欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

点云处理,点云滤波,求点云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,作业实验报告(双面打印),内容包括:实验目的、逻辑设计、代码实现、结果分析、作业总结。