1、什么是点云
点云是一个数据集,数据集中的每个点代表一组X、Y、Z几何坐标和一个强度值,这个强度值根据物体表面反射率记录返回信号的强度。当这些点组合在一起时,就会形成一个点云,即空间中代表3D形状或对象的数据点集合。点云也可以自动上色,以实现更真实的可视化。
2、点云的获取
生成点云的数据可以通过多种方式采集, 其中包括全站仪、地面和机载激光扫描仪、无人机、移动测绘系统、快照图像,从手簿中采集到的视频,还有智能手机和生成表面和结构模型的CAD程序。
3、点云数据的解析
点云体量可以大到超过数百GB,这需要强大的软件来进行高效的处理、分析和数据导出。数据安全存储和共享对于成功的项目协作也是必不可少的。这就是基于云的解决方案发挥作用的地方,它提供了可视化的便捷访问,并以富有成效的方式与点云进行交互。
4、点云的应用
点云可用于多个方向,包括可视化、动画、渲染和CAD建模。在地理空间工作流中,利用点云交付的成果可包括地形和测深地图、数字高程模型、数字地形模型、3D CAD和BIM模型、点云、图像浏览器以及动画和虚拟现实等。
精准的地理空间数据可以高效地利用在以下方面:
- 监测及竣工验收
- 建筑物、厂房及民用基础设施的重建或翻修
- 在外部环境不受干扰的情况下对犯罪现场进行司法调查,呈现的证据允许在法庭上使用
- 快速实现事故重建,大大减少道路封闭的时间
- 文化遗产的保护和修复以及更多可能的应用
因此,从最基本的意义上说,点云是用数字化的方式对物理世界的真实表达,它在诸多应用中起到的作用是无与伦比的。
5、点云数据的特点
- 无序性:只是点而已,排序顺序不受影响
- 近密远梳:扫码与视角不同导致的
- 非结构化数据:直接CNN比较难
- 要解决的任务就是如果对点云数据信息特征提取
1
2
3
4
5
a.无序性:点云数据是点的集合,点之间进行相互调换,其自身带有的位置信息也就会随之进行改变,调换后和未调换前一致。
b.近密远疏:拍摄的距离近一些表示的点云很多稠密,远部分的则表示的很稀疏。如上图座椅的点云数据图所示。
c.点云数据是文本形式的,处理起来麻烦,也就是非结构化。
6、点云数据结构
- 点云存储格式:*.pts; *.asc ; *.dat; .stl ; [1] .imw;.xyz;.las。LAS格式文件已成为LiDAR数据的工业标准格式,LAS文件按每条扫描线排列方式存放数据,包括激光点的三维坐标、多次回波信息、强度信息、扫描角度、分类信息、飞行航带信息、飞行姿态信息、项目信息、GPS信息、数据点颜色信息等。

1
2
3
4
5
6
7
8
C–class(所属类)
F一flight(航线号)
T一time(GPS时间)
I一intensity(回波强度)
R一return(第几次回波)
N一number of return(回波次数)
A一scan angle(扫描角)
RGB一red green blue(RGB颜色值)
- 点云的数据类型
(1)pcl::PointCloudpcl::PointXYZ
PointXYZ 成员:float x,y,z;表示了xyz3D信息,可以通过points[i].data[0]或points[i].x访问点X的坐标值
(2)pcl::PointCloudpcl::PointXYZI
PointXYZI成员:float x, y, z, intensity; 表示XYZ信息加上强度信息的类型。
(3)pcl::PointCloudpcl::PointXYZRGB
PointXYZRGB 成员:float x,y,z,rgb; 表示XYZ信息加上RGB信息,RGB存储为一个float。
(4)pcl::PointCloudpcl::PointXYZRGBA
PointXYZRGBA 成员:float x , y, z; uint32_t rgba; 表示XYZ信息加上RGBA信息,RGBA用32bit的int型存储的。
(5) PointXY 成员:float x,y;简单的二维x-y点结构
(6)Normal结构体:表示给定点所在样本曲面上的法线方向,以及对应曲率的测量值,用第四个元素来占位,兼容SSE和高效计算。
7、基于C#操作点云数据
7.1 基于VTK和PCL搭建点云数据操作环境
需引用Kitware.mummy.Runtime.dll,Kitware.VTK.dll,PclCSharp.dll,PointCloudSharpDll.dll
7.2 点云数据操作的UI界面添加点云控件并初始化
private RenderWindowControl renderWindowControl;
// 创建VTK渲染点云数据控件对象 renderWindowControl = new RenderWindowControl(); // 设置控件已填充方式添加到父容器中 renderWindowControl.Dock = DockStyle.Fill; // 将创建的控件对象添加到父容器中 pl_container.Controls.Add(renderWindowControl);
7.3 加载点云的PCD文件及编写对应的代码
// 创建XZY点云对象 private PointCloudXYZ cloud = new PointCloudXYZ(); // 创建一个文件资源对话框对象 var dialog = new OpenFileDialog(); // 设置对话框能打开的类型 dialog.Filter = "点云文件|*.pcd"; // 编写标题 dialog.Title = "请选择点云文件"; // 判断是否打开对话框 if (dialog.ShowDialog() == DialogResult.OK) { // 获取选择的点云文件的路径 var url = dialog.FileName; // 加载pcd文件,并存储到了cloud的PointCloudXYZPointer Io.loadPcdFile(url, cloud.PointCloudXYZPointer); // 把点云数据进行渲染到控件中进行显示 var render = RenderCloudData(cloud); // 获取点云控件上面的渲染窗体对象 var renderWindow = renderWindowControl.RenderWindow; // 将渲染器添加到Render并渲染 renderWindow.AddRenderer(render); // 刷新填充控件的容器 pl_container.Refresh(); }
7.4 点云对象转换为vtkRender
/// <summary> /// 处理点云对象中点云并返回对应渲染对象 /// </summary> /// <param name="cloud"></param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> private vtkRenderer RenderCloudData(PointCloudXYZ cloud) { // 创建存cloud中xyz数据点云对象 var points = vtkPoints.New(); // 把点云对象中的点依次放入点云数据对象中 for (int i = 0; i < cloud.Size; i++) { points.InsertNextPoint(cloud.GetX(i), cloud.GetY(i), cloud.GetZ(i)); } // 创建每个点的属性属性,这里代表颜色 var pclColor = SetPclDataColor(cloud); // 创建多数据对象 var polyData = vtkPolyData.New(); // 把points对象设置到多数据对象中 polyData.SetPoints(points); // 设置颜色到对应点 polyData.GetPointData().SetScalars(pclColor); // 创建过滤器 var glyphFilter = vtkVertexGlyphFilter.New(); // 连接多数据对象管道 glyphFilter.SetInputConnection(polyData.GetProducerPort()); // 创建制图器 var mapper = vtkPolyDataMapper.New(); // 设置缩放显示比例 mapper.SetScalarVisibility(1); // 连接过滤器对象的管道 mapper.SetInputConnection(glyphFilter.GetOutputPort()); // 创建制图的角色 var actor = vtkActor.New(); // 设置制图器到对应角色中 actor.SetMapper(mapper); // 创建渲染器对象 var render = vtkRenderer.New(); // 把角色添加到渲染器中 render.AddActor(actor); // 设置viewport render.SetViewport(0,0,1,1); // 设置背景渐变 render.GradientBackgroundOn(); // 设置渐变的前景和背景 render.SetBackground(0.2, 0.6, 0.3); render.SetBackground2(0.9,0.9,0.9); // 返回创建渲染对象 return render; }
7.5 显示点云模型问题及给点云数据着色
/// <summary> /// 给点云数据xyz几何点着色 /// </summary> /// <param name="cloud"></param> /// <returns></returns> /// <exception cref="NotImplementedException"></exception> private vtkUnsignedCharArray SetPclDataColor(PointCloudXYZ cloud) { var color = vtkUnsignedCharArray.New(); // 求点云数据各个轴对应极值 var minMax = new double[6]; cloud.GetMinMaxXYZ(minMax); // 求Z轴的差值 double z = minMax[5] - minMax[4]; // 求Z轴的差值 double y = minMax[3] - minMax[2]; // 求Z轴的差值 double x = minMax[1] - minMax[0]; // 求中间值 double zMedian = z / 2; double yMedian = y / 2; double xMedian = x / 2; // 设置颜色分组,因为是rgb需要分给三组 color.SetNumberOfComponents(3); double r = 0; double g = 0; double b = 0; for (int i = 0; i < cloud.Size; i++) { if (cloud.GetZ(i) - minMax[4] > zMedian) { // 判断r,g,b值不能超过255 r = (255 * ((cloud.GetZ(i) - minMax[4] - zMedian) / zMedian)); g = (255 * (1 - ((cloud.GetZ(i) - minMax[4] - zMedian) / zMedian))); b = 0; color.InsertNextTuple3(r, g, b); } else { r = 0; g = (255 * ((cloud.GetZ(i) - minMax[4] - zMedian) / zMedian)); b = (255 * (1 - ((cloud.GetZ(i) - minMax[4] - zMedian) / zMedian))); ; color.InsertNextTuple3(r, g, b); } } return color; }
浙公网安备 33010602011771号