点云处理,点云滤波,求点云DEM
程序员文章站
2022-06-02 22:02:50
...
点云处理,点云滤波,求点云DEM
##作业:点云数据预处理软件,具体功能包括:
1,数据的自适应导入;
2,统计点云的范围、中值、均值、直方图;
3,对点云进行滤波,剔除明显的错误噪声点(自己找资料,实现算法);
4,基于点云高度,给其赋予颜色(自己找资料,
5,利用滤波后的点云,内插DEM(可选,自己找资料,实现算法);
6,上述2~5功能支持将结果输出为文本文件或者其他格式文件。
要求: 1,要使用C++语言完成软件开发;
2,要有完整的类定义,实现接口与实现的相分离;
3,要有类的继承与封装;
4,要有标准的注释及规范的代码风格;
5,有能力的同学,可以设计相关的交互界面。 提交:
1,完整的代码工程;
2,作业实验报告(双面打印),内容包括:实验目的、逻辑设计、代码实现、结果分析、作业总结。
//head.h
#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<windows.h>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iomanip>
struct point3D
{
point3D();
~point3D();
int id;
int use;
double xyz[3];
int rgb[3];
int Dis;
//重载point3D,使得可以用优先队列进行point3D类型的比较
friend bool operator<(point3D a, point3D b)
{
return a.Dis > b.Dis;
}
};
class Get_Filename
{
public:
//将一个LPCWSTR转换为string
std::string Lpcwstr2String(LPCWSTR list);
//新建一个对话窗口,选择文件
std::string get_path();
public:
//导入文件路径
const std::string filename = get_path().c_str();
};
class CloudManger:public Get_Filename
{
public:
CloudManger();
~CloudManger();
public:
//打开文件,点云的自适应导入
void open_file();
//点云滤波,并导出滤波文件
void point_filter();
//求范围,中值,均值,直方图,并输出相应的
void point_Manger();
//给点云赋颜色,并保存到D:\\point_Cloud_rgb.txt
void point_rgb();
//求DEM并保存到D:\\DEM.txt
void DEM_Grid();
public:
//保存原始点云
std::vector<point3D>point_3D;
//存滤波后的点云
std::vector<point3D> point3D_filter;
public:
//保存点云的x,y,z最大,最小值
double Max_x, Max_y, Max_z;
double Min_x, Min_y, Min_z;
};
//head.cpp
#include"head.h"
#define cell 100//大网格的边长
#define cell_ 5//DEM网格的边长
point3D::point3D()
{
id = 0;
use = 0;
xyz[0] = 0; xyz[1] = 0; xyz[2] = 0;
rgb[0] = 0; rgb[1] = 0; rgb[2] = 0;
Dis = 0;
}
point3D::~point3D()
{
}
//将一个LPCWSTR转换为string
std::string Get_Filename::Lpcwstr2String(LPCWSTR list)
{
int len = WideCharToMultiByte(CP_ACP, 0, list, -1, NULL, 0, NULL, NULL);
if (len <= 0) {
return "";
}
else {
char* dest = new char[len];
WideCharToMultiByte(CP_ACP, 0, list, -1, dest, len, NULL, NULL);
dest[len - 1] = 0;
std::string str(dest);
delete[] dest;
return str;
}
}
//新建一个对话窗口,选择文件
std::string Get_Filename::get_path()
{
OPENFILENAME ofn;
char szFile[300];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = (LPWSTR)szFile;
ofn.lpstrFile[0] = '\0';
ofn.nFilterIndex = 1;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"ALL\0*.*\0Text\0*.TXT\0";
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
std::string path_image = "";
if (GetOpenFileName(&ofn)) {
path_image = Lpcwstr2String(ofn.lpstrFile);
return path_image;
}
else {
return "";
}
}
CloudManger::CloudManger()
:Max_x(0.0), Max_y(0.0), Max_z(0.0), Min_x(0.0), Min_y(0.0), Min_z(0.0)
{
}
CloudManger::~CloudManger()
{
}
//打开点云文,点云的自适应导入
void CloudManger::open_file()
{
point3D store;
std::ifstream OpenFile;
std::string line;
OpenFile.open(filename, std::ios::in);
if (OpenFile.fail())//文件打开失败:返回0
{
std::cerr << "open error" << std::endl;
exit(1);
}
while (!OpenFile.eof() /*&& !line.empty()*/)
{
double X, Y, Z;
X = Y = Z = -99999;
OpenFile >> X >> Y >> Z;
if (Z == -99999) continue;
store.xyz[0] = X;
store.xyz[1] = Y;
store.xyz[2] = Z;
store.id++;
point_3D.push_back(store);
}
std::cout << "Original point cloud points:" << point_3D.size() << "\n";
OpenFile.close();
return;
}
//点云滤波---统计滤波
void CloudManger::point_filter()
{
std::vector<point3D> poilt;
std::vector<double> d;
d.clear();
//取当前点与下一个点的距离为最小临近距离
//(由于点云数据量太大,求最小k临近距离所需时间复杂度O(n^2),耗时太大)
double d_x = 0, d_y = 0, d_z = 0, d_d;
for (size_t i = 0; i < point_3D.size() - 1; i++)
{
d_x = abs(point_3D[i].xyz[0] - point_3D[i + 1].xyz[0]);
d_y = abs(point_3D[i].xyz[1] - point_3D[i + 1].xyz[1]);
d_z = abs(point_3D[i].xyz[2] - point_3D[i + 1].xyz[2]);
d_d = sqrt(pow(d_x, 2) + pow(d_y, 2) + pow(d_z, 2));
d.push_back(d_d);
}
double d_ave = 0.0, d_var = 0.0;
//距离的平均值
for (size_t m = 0; m < d.size(); m++)
{
d_ave += d[m] / d.size();
}
//方差
for (size_t i = 0; i < d.size(); i++)
{
d_var += pow(abs(d[i] - d_ave), 2) / (d.size() - 1);
}
d_var = sqrt(d_var);
for (size_t i = 0; i < d.size(); i++)
{
//这里的1.4是通过调试得到的最佳过滤情况
if (abs(d[i] - d_ave) / d_var < 1.4)
{
point_3D[i].use = 1;
poilt.push_back(point_3D[i]);
}
}
//点云高差的均值
double avg = 0.0;
std::vector<point3D>::iterator it;
for (it = poilt.begin(); it != poilt.end(); it++)
{
avg += it->xyz[2] / poilt.size();
}
//超过一定范围的点就舍弃
for (it = poilt.begin(); it != poilt.end(); it++)
{
if (abs(it->xyz[2] - avg - 150) < 450)
{
point3D Pt;
Pt.xyz[0] = it->xyz[0];
Pt.xyz[1] = it->xyz[1];
Pt.xyz[2] = it->xyz[2];
point3D_filter.push_back(Pt);
}
}
//保存滤波后的文件到D:\\point3D_filter.txt
std::ofstream save_filter("D:\\point3D_filter.txt", std::ios::out);
if (save_filter.fail())//文件打开失败:返回0
{
std::cerr << "open point3D_filter.txt error" << std::endl;
}
for (size_t i = 0; i < point3D_filter.size(); i++)
{
if (point3D_filter[i].xyz[0] != 0)
{
save_filter << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< point3D_filter[i].xyz[0] << " " << point3D_filter[i].xyz[1] <<
" " << point3D_filter[i].xyz[2] << std::endl;
}
}
std::cout << "The number of filtered points:" << point3D_filter.size() << "\n";
std::cout << "Save the points filtered file to D:\\point3D_filter.txt" << std::endl;
save_filter.close();
return;
}
//求范围,中值,均值,直方图,并输出相应的txt文件
void CloudManger::point_Manger()
{
std::vector <double> flt_pts_x, flt_pts_y, flt_pts_z;
for (size_t i = 0; i < point3D_filter.size(); i++)
{
flt_pts_x.push_back(point3D_filter[i].xyz[0]);
flt_pts_y.push_back(point3D_filter[i].xyz[1]);
flt_pts_z.push_back(point3D_filter[i].xyz[2]);
}
sort(flt_pts_x.begin(), flt_pts_x.end());
sort(flt_pts_y.begin(), flt_pts_y.end());
sort(flt_pts_z.begin(), flt_pts_z.end());
Max_x = flt_pts_x[flt_pts_x.size() - 1];
Max_y = flt_pts_y[flt_pts_y.size() - 1];
Max_z = flt_pts_z[flt_pts_z.size() - 1];
Min_x = flt_pts_x[0];
Min_y = flt_pts_y[0];
Min_z = flt_pts_z[0];
//范围
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe range of point x: " << Min_x << "--" << Max_x << std::endl;
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The range of point y: " << Min_y << "--" << Max_y << std::endl;
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The range of point z: " << Min_z << "--" << Max_z << std::endl;
//中值
if (flt_pts_x.size() % 2 != 0)
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe median of point x: " << flt_pts_x[flt_pts_x.size() / 2] << std::endl;
else std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe median of point x: " << (flt_pts_x[flt_pts_x.size() / 2]
+ flt_pts_x[flt_pts_x.size() / 2 - 1]) / 2 << std::endl;
if (flt_pts_y.size() % 2 != 0)
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point y: " << flt_pts_y[flt_pts_y.size() / 2] << std::endl;
else std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point y: " << (flt_pts_y[flt_pts_y.size() / 2]
+ flt_pts_y[flt_pts_y.size() / 2 - 1]) / 2 << std::endl;
if (flt_pts_z.size() % 2 != 0)
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point z: " << flt_pts_z[flt_pts_z.size() / 2] << std::endl;
else std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point z: " << (flt_pts_z[flt_pts_z.size() / 2]
+ flt_pts_z[flt_pts_z.size() / 2 - 1]) / 2 << std::endl;
//均值
double avg_x = 0.0, avg_y = 0.0, avg_z = 0.0;
for (size_t i = 0; i < point3D_filter.size(); i++)
{
avg_x += point3D_filter[i].xyz[0] / point3D_filter.size();
avg_y += point3D_filter[i].xyz[1] / point3D_filter.size();
avg_z += point3D_filter[i].xyz[2] / point3D_filter.size();
}
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe mean of the point cloud x: " << avg_x << std::endl;
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The mean of the point cloud y: " << avg_y << std::endl;
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The mean of the point cloud z: " << avg_z << std::endl;
//直方图
double range_x = (flt_pts_x[flt_pts_x.size() - 1] - flt_pts_x[0]) / 10;//间隔
double range_y = (flt_pts_y[flt_pts_y.size() - 1] - flt_pts_y[0]) / 10;
double range_z = (flt_pts_z[flt_pts_z.size() - 1] - flt_pts_z[0]) / 10;
int a[10] = {}, b[10] = {}, c[10] = {};//统计每个区间的点云数,a,b,c,分别对应x,y,z
//分别统计x,y,z,值在10个分段的个数
for (size_t i = 0; i < point3D_filter.size(); i++)
{
for (double k = flt_pts_x[0], j = 0; k < flt_pts_x[flt_pts_x.size() - 1] && j < 10; k += range_x, j++)
{
if ((point3D_filter[i].xyz[0] > k || point3D_filter[i].xyz[0] == k) && point3D_filter[i].xyz[0] < k + range_x)
a[(int)j]++;
}
for (double k = flt_pts_y[0], j = 0; k < flt_pts_y[flt_pts_y.size() - 1] && j < 10; k += range_y, j++)
{
if ((point3D_filter[i].xyz[1] > k || point3D_filter[i].xyz[1] == k) && point3D_filter[i].xyz[1] < k + range_y)
b[(int)j]++;
}
for (double k = flt_pts_z[0], j = 0; k < flt_pts_z[flt_pts_z.size() - 1] && j < 10; k += range_z, j++)
{
if ((point3D_filter[i].xyz[2] > k || point3D_filter[i].xyz[2] == k) && point3D_filter[i].xyz[2] < k + range_z)
c[(int)j]++;
}
}
//根据区间内点的个数按比例输出*,作为直方图高度
std::cout << "\n";
for (double i = flt_pts_x[0], j = 0; i < flt_pts_x[flt_pts_x.size() - 1] && j < 10; i += range_x, j++)
{
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "X: " << i << " - " << i + range_x << "\t\t" << a[(int)j];
for (int k = 0; k < a[(int)j] / 2500; k++)
{
std::cout << "*";
}
std::cout << std::endl;
}
std::cout << "\n";
for (double i = flt_pts_y[0], j = 0; i < flt_pts_y[flt_pts_y.size() - 1] && j < 10; i += range_y, j++)
{
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "Y: " << i << " - " << i + range_y << "\t\t" << a[int(j)];
for (int k = 0; k < a[int(j)] / 2500; k++)
{
std::cout << "*";
}
std::cout << std::endl;
}
std::cout << "\n";
for (double i = flt_pts_z[0], j = 0; i < flt_pts_z[flt_pts_z.size() - 1] && j < 10; i += range_z, j++)
{
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "Z: " << i << " - " << i + range_z << "\t\t\t" << a[int(j)];
for (int k = 0; k < a[int(j)] / 2500; k++)
{
std::cout << "*";
}
std::cout << std::endl;
}
//保存点的范围,中值,均值,直方图
std::ofstream save_point_Manger("D:\\point_Manger.txt", std::ios::out);
if (save_point_Manger.fail())//文件打开失败:返回0
{
std::cerr << "open point3D_filter.txt error" << std::endl;
}
//保存范围
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe range of point x: " << flt_pts_x[0] << "--" << flt_pts_x[flt_pts_x.size() - 1] << std::endl;
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The range of point y: " << flt_pts_y[0] << "--" << flt_pts_y[flt_pts_y.size() - 1] << std::endl;
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3) << "The range of point z: "
<< flt_pts_z[0] << "--" << flt_pts_z[flt_pts_z.size() - 1] << std::endl;
//保存中值
if (flt_pts_x.size() % 2 != 0)
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe median of point x: " << flt_pts_x[flt_pts_x.size() / 2] << std::endl;
else save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "\nThe median of point x: " << (flt_pts_x[flt_pts_x.size() / 2]
+ flt_pts_x[flt_pts_x.size() / 2 - 1]) / 2 << std::endl;
if (flt_pts_y.size() % 2 != 0)
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point y: " << flt_pts_y[flt_pts_y.size() / 2] << std::endl;
else save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point y: " << (flt_pts_y[flt_pts_y.size() / 2]
+ flt_pts_y[flt_pts_y.size() / 2 - 1]) / 2 << std::endl;
if (flt_pts_z.size() % 2 != 0)
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point z: " << flt_pts_z[flt_pts_z.size() / 2] << std::endl;
else save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The median of point z: " << (flt_pts_z[flt_pts_z.size() / 2]
+ flt_pts_z[flt_pts_z.size() / 2 - 1]) / 2 << std::endl;
//保存均值
save_point_Manger << "\n";
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The mean of the point cloud x: " << avg_x << std::endl;
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The mean of the point cloud y: " << avg_y << std::endl;
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "The mean of the point cloud z: " << avg_z << std::endl;
//保存直方图
save_point_Manger << "\n";
for (double i = flt_pts_x[0], j = 0; i < flt_pts_x[flt_pts_x.size() - 1] && j < 10; i += range_x, j++)
{
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "X: " << i << " - " << i + range_x << "\t\t\t" << a[(int)j];
for (int k = 0; k < a[(int)j] / 2500; k++)
{
save_point_Manger << "*";
}
save_point_Manger << std::endl;
}
save_point_Manger << "\n";
for (double i = flt_pts_y[0], j = 0; i < flt_pts_y[flt_pts_y.size() - 1] && j < 10; i += range_y, j++)
{
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "Y: " << i << " - " << i + range_y << "\t\t" << a[int(j)];
for (int k = 0; k < a[int(j)] / 2500; k++)
{
save_point_Manger << "*";
}
save_point_Manger << std::endl;
}
save_point_Manger << "\n";
for (double i = flt_pts_z[0], j = 0; i < flt_pts_z[flt_pts_z.size() - 1] && j < 10; i += range_z, j++)
{
save_point_Manger << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< "Z: " << i << " - " << i + range_z << "\t\t\t\t\t" << a[int(j)];
for (int k = 0; k < a[int(j)] / 2500; k++)
{
save_point_Manger << "*";
}
save_point_Manger << std::endl;
}
save_point_Manger.close();
std::cout << "Save point cloud range, mean, median, histogram file to D:\\point_Manger.txt" << std::endl;
}
//给点云赋颜色,并保存到D:\\point_Cloud_rgb.txt
void CloudManger::point_rgb()
{
std::vector <double> flt_pts_z;
for (size_t i = 0; i < point3D_filter.size(); i++)
{
flt_pts_z.push_back(point3D_filter[i].xyz[2]);
}
sort(flt_pts_z.begin(), flt_pts_z.end());
//给点云赋四个大颜色段
double range_Z = (flt_pts_z[flt_pts_z.size() - 1] - flt_pts_z[0]) / 4;
//每个大颜色段分成256小段,分别给点云赋颜色
double range_rgb = range_Z / 256;
for (double j = flt_pts_z[0], k = 1; j < flt_pts_z[flt_pts_z.size() - 1], k < 5; j += range_Z, k++)
{
for (size_t i = 0; i < point3D_filter.size(); i++)
{
for (double m = j, n = 0; m < (j + 5 * range_Z) && n < 256; m += 5 * range_rgb, n += 5)
{
if ((point3D_filter[i].xyz[2] > m || point3D_filter[i].xyz[2] == m)
&& point3D_filter[i].xyz[2] < m + 5 * range_rgb)
{
if (k == 1)
{
point3D_filter[i].rgb[0] = 0;
point3D_filter[i].rgb[1] = int(n);
point3D_filter[i].rgb[2] = 255;
}
if (k == 2)
{
point3D_filter[i].rgb[0] = 0;
point3D_filter[i].rgb[1] = 255;
point3D_filter[i].rgb[2] = 255 - int(n);
}
if (k == 3)
{
point3D_filter[i].rgb[0] = int(n);
point3D_filter[i].rgb[1] = 255;
point3D_filter[i].rgb[2] = 0;
}
if (k == 4)
{
point3D_filter[i].rgb[0] = 255;
point3D_filter[i].rgb[1] = 255 - int(n);
point3D_filter[i].rgb[2] = 0;
}
}
}
}
}
std::ofstream rgb("D:\\point_Cloud_rgb.txt", std::ios::out);
if (!rgb)
{
std::cout << "Open point_Cloud_rgb.txt error" << std::endl;
}
for (size_t i = 0; i < point3D_filter.size(); i++)
{
if (point3D_filter[i].xyz[0] != 0)
{
rgb << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< point3D_filter[i].xyz[0] << " " << point3D_filter[i].xyz[1]
<< " " << point3D_filter[i].xyz[2] << " " << point3D_filter[i].rgb[0]
<< " " << point3D_filter[i].rgb[1] << " " << point3D_filter[i].rgb[2] << std::endl;
}
}
rgb.close();
std::cout << "Save the dot cloud color file to D:\\point_Cloud_rgb.txt" << std::endl;
}
//求DEM
void CloudManger::DEM_Grid()
{
std::vector<double> point_d_s;
std::vector<std::vector<std::vector<point3D>>> grid_map;
std::vector<std::vector<int>>gridpoint_counts;
int M, N;
double Dx, Dy;
double d_x = 0.0, d_y = 0.0, d_z = 0.0, d_d = 0.0;
Dx = Max_x - Min_x;
Dy = Max_y - Min_y;
M = int(Dx / cell) + 1;
N = int(Dy / cell) + 1;
int n = M * N;
//给网格vectorgrid_map和网格中的计数容器gridpoint_counts赋网格空间
grid_map.resize(M);
gridpoint_counts.resize(M);
for (int i = 0; i < M; i++)
{
grid_map[i].resize(N);
gridpoint_counts[i].resize(N);
}
//先给计数的容器中每个值赋0
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
gridpoint_counts[i][j] = 0;
}
}
std::vector<point3D> grid_s;
grid_s.resize(n);
std::vector<int> grid_count;
grid_count.resize(n);
std::vector<int> Index;
Index.resize(n);
for (int i = 0; i < n; i++)
{
grid_count[i] = 0;
}
//分网格
for (size_t i = 0; i < point3D_filter.size(); i++)
{
int xCell = int((point3D_filter[i].xyz[0] - Min_x) / cell);
int yCell = int((point3D_filter[i].xyz[1] - Min_y) / cell);
//把对应点放入对应的网格中
grid_map[xCell][yCell].push_back(point3D_filter[i]);
//为每个网格计数
gridpoint_counts[xCell][yCell] ++;
}
double grid_x = 0.0, grid_y = 0.0, dd_x = 0.0, dd_y = 0.0, dd_pow = 0.0;
int grid_count_x = 0, grid_count_y = 0;
//DEM网格的行数与列数x,y
grid_count_x = int(Dx / cell_) + 1;
grid_count_y = int(Dy / cell_) + 1;
grid_x = Min_x;
//总的DEM网格数
int DEM_Grid_counts = grid_count_x * grid_count_y;
std::vector<std::vector<std::vector<double>>> DEM_grid_point;
//存最小的三个距离点
std::vector<std::vector<std::vector<point3D>>>nearst_3point3;
std::vector < std::vector<point3D>>dempoint;
//给DEM网格赋空间,给存三个最近点的容器赋空间
DEM_grid_point.resize(grid_count_x);
nearst_3point3.resize(grid_count_x);
dempoint.resize(grid_count_x);
for (int i = 0; i < grid_count_x; i++)
{
DEM_grid_point[i].resize(grid_count_y);
nearst_3point3[i].resize(grid_count_y);
}
//把DEM网格的x,y坐标赋进DEM_grid_point
for (int i = 0; i < grid_count_x; i++)
{
grid_y = Min_y;
for (int j = 0; j < grid_count_y; j++)
{
DEM_grid_point[i][j].push_back(grid_x);
DEM_grid_point[i][j].push_back(grid_y);
grid_y += cell_;
}
grid_x += cell_;
}
//大栅格是小栅格的倍数
int H = int(cell / cell_);
存最小的三个距离点
//std::vector<std::vector<std::vector<point3D>>>nearst_3point3;
//求DEM网格点坐标与大网格点的距离
for (int i = 0; i < grid_count_x; i++)
{
for (int j = 0; j < grid_count_y; j++)
{
if (gridpoint_counts[int(i / H)][int(j / H)] == 0)
{
continue;
}
//把最短的三个距离的点找出
std::priority_queue< point3D > Min_d_3;
for (int k = 0; k < gridpoint_counts[int(i / H)][int(j / H)]; k++)
{
dd_x = abs(DEM_grid_point[i][j][0] - grid_map[int(i / H)][int(j / H)][k].xyz[0]);
dd_y = abs(DEM_grid_point[i][j][1] - grid_map[int(i / H)][int(j / H)][k].xyz[1]);
dd_pow = sqrt(pow(dd_x, 2.0) + pow(dd_y, 2.0));
grid_map[int(i / H)][int(j / H)][k].Dis = int(dd_pow);
//把每个距离点放入Min_d_3,排好序,求出3个小的距离点
Min_d_3.push(grid_map[int(i / H)][int(j / H)][k]);
}
//nearst_3point3里面存了最小的三个距离点
if (Min_d_3.size() < 3)
continue;
else
{
nearst_3point3[i][j].push_back(Min_d_3.top());
Min_d_3.pop();
nearst_3point3[i][j].push_back(Min_d_3.top());
Min_d_3.pop();
nearst_3point3[i][j].push_back(Min_d_3.top());
}
}
}
//到比较最小的三个距离值的时候了,明天要改重载
double A = 0.0, a0 = 0.0, a1 = 0.0, a2 = 0.0, x = 0.0, y = 0.0, z = Min_z - 1.0;
double z1 = 0.0, z2 = 0.0, z3 = 0.0, z4, z5, z6;
double d1 = 0.0, d2 = 0.0, d3 = 0.0;
std::ofstream save_DEM("D:\\DEM.txt", std::ios::out);
if (!save_DEM)
{
std::cout << "Open point_Cloud_rgb.txt error" << std::endl;
}
point3D Pt;
for (int i = 0; i < grid_count_x; i++)
{
for (int j = 0; j < grid_count_y; j++)
{
if (nearst_3point3[i][j].size() == 0)
{
x = DEM_grid_point[i][j][0];
y = DEM_grid_point[i][j][1];
z = Min_z - 1.0;
Pt.xyz[0] = x;
Pt.xyz[1] = y;
Pt.xyz[2] = z;
dempoint[i].push_back(Pt);
continue;
}
x = DEM_grid_point[i][j][0];
y = DEM_grid_point[i][j][1];
z1 = nearst_3point3[i][j][0].xyz[2];
z2 = nearst_3point3[i][j][1].xyz[2];
z3 = nearst_3point3[i][j][2].xyz[2];
z4 = nearst_3point3[i][j][0].xyz[2];
z5 = nearst_3point3[i][j][0].xyz[2];
z6 = nearst_3point3[i][j][0].xyz[2];
d1 = nearst_3point3[i][j][0].Dis;
d2 = nearst_3point3[i][j][1].Dis;
d3 = nearst_3point3[i][j][2].Dis;
z = (z1 * d1 + z2 * d2 + z3 * d3) / (d1 + d2 + d3);
Pt.xyz[0] = x;
Pt.xyz[1] = y;
Pt.xyz[2] = z;
if (!(z > Min_z && z < Max_x))
{
z = z1;
Pt.xyz[2] = z;
}
dempoint[i].push_back(Pt);
}
}
for (int i = 1; i < grid_count_x - 1; i++)
{
for (int j = 1; j < grid_count_y - 1; j++)
{
double z = (dempoint[i - 1][j].xyz[2] + dempoint[i + 1][j].xyz[2]
+ dempoint[i][j - 1].xyz[2] + dempoint[i][j + 1].xyz[2]) / 4;
save_DEM << std::setiosflags(std::ios::fixed) << std::setprecision(3)
<< dempoint[i][j].xyz[0] << " " << dempoint[i][j].xyz[1] << " " << z << std::endl;
}
}
save_DEM.close();
std::cout << "Save point cloud DEM file to D : \\DEM.txt" << std::endl;
}
//main.cpp
#include"head.h"
int main()
{
CloudManger p;
//导入点云数据
p.open_file();
//点云滤波并导出滤波文件D:\\point3D_filter.txt
p.point_filter();
//求范围,中值,均值,直方图,并保存到D:\\point_Manger.txt
p.point_Manger();
//给点云赋颜色,并保存到D:\\point_Cloud_rgb.txt
p.point_rgb();
//求DEM并保存到D:\\DEM.txt
p.DEM_Grid();
system("pause");
return 0;
}
点云处理,点云滤波,求点云DEM
作业:点云数据预处理软件,具体功能包括:
1,数据的自适应导入;
2,统计点云的范围、中值、均值、直方图;
3,对点云进行滤波,剔除明显的错误噪声点(自己找资料,实现算法);
4,基于点云高度,给其赋予颜色(自己找资料,实现算法);
5,利用滤波后的点云,内插DEM(可选,自己找资料,实现算法);
6,上述2~5功能支持将结果输出为文本文件或者其他格式文件。
要求:
1,要使用C++语言完成软件开发;
2,要有完整的类定义,实现接口与实现的相分离;
3,要有类的继承与封装;
4,要有标准的注释及规范的代码风格;
5,有能力的同学,可以设计相关的交互界面。
提交:
1,完整的代码工程;
2,作业实验报告(双面打印),内容包括:实验目的、逻辑设计、代码实现、结果分析、作业总结。
上一篇: Ubuntu 网卡多设置