第3章:点云数据基础——从结构到文件,再到Halcon读写
点云是什么?说白了,就是一堆三维空间里的点。每个点都带着自己的坐标信息(X, Y, Z)。有些点还带着颜色(R, G, B)。这就是我们常说的XYZ和XYZRGB。
我刚开始接触3D视觉时,觉得点云不就是一堆点嘛,有什么好学的?后来在项目里被文件格式坑过几次,才明白——数据结构搞不清楚,后面所有处理都是空中楼阁。
3.1 点云数据结构:XYZ与XYZRGB
先看最基本的。一个点云数据,核心就是点的集合。每个点至少有三个坐标值。
| 数据类型 | 字段 | 说明 | 典型场景 |
|---|---|---|---|
| XYZ | X, Y, Z | 三维空间坐标,单位通常为毫米或米 | 激光扫描、结构光深度图 |
| XYZRGB | X, Y, Z, R, G, B | 坐标 + 颜色信息,颜色值0-255 | RGB-D相机(如Kinect、RealSense) |
| XYZI | X, Y, Z, Intensity | 坐标 + 反射强度 | 激光雷达(LiDAR) |
核心理解:Halcon内部统一用3D对象模型(ObjectModel3D)来管理点云。不管你读进来的是XYZ还是XYZRGB,最终都变成一个object_model_3d句柄。颜色信息存储在属性里,不是单独的数据结构。
我在一个3C检测项目里遇到过这种情况:客户给的PLY文件带颜色,但我们的算法只需要坐标。一开始我傻傻地读了全部数据,内存直接爆了。后来才学会——读文件时可以指定只加载坐标,颜色不要。嗯,这个后面会讲。
3.2 点云文件格式:PLY、OBJ、CSV
市面上点云格式很多,但工业项目里最常见的就是这三种。我按自己的经验排个序:PLY > OBJ > CSV。
3.2.1 PLY格式(Polygon File Format)
这是我最推荐的格式。为什么?因为它既能存点云,又能存三角网格。而且支持ASCII和二进制两种编码。
- 优点:结构清晰,支持XYZRGB,支持顶点法向量,文件头可读
- 缺点:二进制版本跨平台有时字节序不对
- Halcon支持:完美支持,读写速度最快
我的习惯:项目里所有中间结果都存PLY二进制格式。文件小,读写快。只有需要人工查看时才转ASCII。
3.2.2 OBJ格式(Wavefront OBJ)
OBJ是3D建模界的通用格式。它主要存网格,但也能存点云。
- 优点:几乎所有3D软件都能打开,支持材质(MTL)
- 缺点:点云数据量大时文件很臃肿,不支持直接存颜色
- Halcon支持:支持读写,但速度比PLY慢
注意:OBJ格式里,颜色通常存在关联的MTL文件里。如果你只拿OBJ文件,颜色信息可能会丢。我曾经因为这个被坑过一次,调试了半天才发现是文件格式的问题。
3.2.3 CSV格式(Comma-Separated Values)
CSV就是纯文本表格。每一行一个点,列之间用逗号分隔。
- 优点:人类可读,Excel直接打开,方便调试
- 缺点:文件巨大,没有标准头信息,读写慢
- Halcon支持:不直接支持,需要自己解析
你想想看,一个100万个点的点云,CSV文件可能有几十MB。而同样的数据用PLY二进制,可能只有10MB。所以CSV我只在调试阶段用,正式项目从来不用。
3.3 Halcon中读取与保存点云
终于到实操环节了。Halcon提供了两个核心算子:read_object_model_3d 和 write_object_model_3d。
3.3.1 读取点云:read_object_model_3d
这个算子的签名是这样的:
read_object_model_3d( : : FileName, Scale, GenParamName, GenParamValue : ObjectModel3D, Status)
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| FileName | string | 文件路径,支持.ply、.obj、.dxf、.stl等 |
| Scale | real | 缩放因子,默认1.0。单位转换时用 |
| GenParamName | tuple | 控制参数名称,如'ply_type' |
| GenParamValue | tuple | 控制参数值 |
| ObjectModel3D | handle | 输出:3D对象模型句柄 |
| Status | integer | 输出:状态码,0表示成功 |
来个实际例子:
* 读取PLY文件,保持原始尺寸
read_object_model_3d ('pointcloud.ply', 1.0, [], [], ObjectModel3D, Status)
* 读取时只加载坐标,不加载颜色(节省内存)
read_object_model_3d ('pointcloud.ply', 1.0, ['load_color'], ['false'], ObjectModel3D, Status)
* 读取OBJ文件,并缩放到毫米单位
read_object_model_3d ('mesh.obj', 0.001, [], [], ObjectModel3D, Status)
避坑指南:我曾经在读取一个大型PLY文件时,程序直接卡死了。后来发现是文件里包含了三角网格信息,而我只想要点云。解决方案是加上参数 'ply_type' 设为 'point_cloud',只读点云部分。
3.3.2 保存点云:write_object_model_3d
保存的算子同样简洁:
write_object_model_3d( : : ObjectModel3D, FileType, FileName, GenParamName, GenParamValue : )
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| ObjectModel3D | handle | 输入:3D对象模型句柄 |
| FileType | string | 输出格式,如'ply'、'obj'、'dxf' |
| FileName | string | 输出文件路径 |
| GenParamName | tuple | 控制参数,如'ply_encoding' |
| GenParamValue | tuple | 控制参数值 |
实际保存示例:
* 保存为PLY二进制格式(推荐)
write_object_model_3d (ObjectModel3D, 'ply', 'output.ply', ['ply_encoding'], ['binary'])
* 保存为OBJ格式
write_object_model_3d (ObjectModel3D, 'obj', 'output.obj', [], [])
* 保存为PLY ASCII格式(方便调试)
write_object_model_3d (ObjectModel3D, 'ply', 'output_ascii.ply', ['ply_encoding'], ['ascii'])
重要提醒:保存时如果点云包含颜色信息,Halcon会自动写入。但OBJ格式不支持颜色,颜色会丢失。所以如果你需要保留颜色,一定要用PLY格式。
3.4 知识体系结构图
下面这张图帮你理清本章的核心逻辑:
3.5 本章小结
这一章我们走了三个台阶:
- 数据结构:XYZ是骨架,XYZRGB是血肉。理解它们,你才知道读进来的数据是什么。
- 文件格式:PLY是首选,OBJ是备选,CSV是调试工具。选对格式,事半功倍。
- Halcon读写:两个算子搞定一切。但参数细节决定了你的程序是跑得飞快还是卡死。
一句话总结:点云数据基础,就是搞清楚「数据长什么样、存在什么文件里、怎么用Halcon搬进来搬出去」。这三件事搞定了,后面的点云处理才有根基。