基于Halcon的三维点云处理(鞋点胶)


基于Halcon的三维点云处理(鞋点胶)

1.点云介绍

点云(Point Cloud)是一种用于表示三维空间中大量点的数据结构。每个点通常由其在三维空间中的坐标值(x、y、z)以及可能的其他属性(如颜色、法线、强度等)组成。点云通常用于描述物体的表面几何形状或场景的空间信息。

点云数据可以通过各种方式获取,包括激光扫描、结构光扫描、摄影测量等技术。处理点云数据通常涉及到点云的采样、滤波、配准、分割、特征提取等操作,以便进行后续的分析和应用。

2.点云处理

因为目前我正在学习Halcon三维点云处理,所以我采用的是Halcon中的三维点云处理算子,并没有使用PCL库

Halcon是一种功能强大的机器视觉库,广泛用于工业视觉系统和机器视觉应用中。Halcon也提供了对点云数据进行处理和分析的功能,可以帮助用户处理三维点云数据并应用于各种视觉任务中。

Halcon用于点云处理的功能和方法:

  1. 点云的读取和显示:Halcon提供了读取和显示点云数据的功能,可以从文件中读取点云数据并在视觉界面中显示。
  2. 点云的滤波:Halcon支持对点云数据进行滤波操作,如高斯滤波、中值滤波等,以去除噪音或平滑点云数据。
  3. 点云的配准:Halcon可以进行点云的配准操作,将两个或多个点云数据对齐,以便进行后续的比较和分析。
  4. 点云的分割:Halcon可以对点云数据进行分割操作,将点云分为不同的部分或对象,以便进行单独的分析或处理。
  5. 点云的特征提取:Halcon支持从点云数据中提取特征,如边缘、表面法向量、曲率等,用于后续的目标识别或建模。
  6. 点云的三维重建:Halcon可以通过点云数据进行三维重建,生成三维模型或表面网格模型,用于可视化或其他应用。

3.Halcon中点云处理的主要算子

3.1 点云的读取算子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
*读取点云文件
read_object_model_3d( : : FileName, Scale, GenParamName, GenParamValue : ObjectModel3D, Status)

*参数
FileName (输入控制):要读取的文件的文件名。
数据类型:字符串
文件扩展名:.off, .ply, .dxf, .om3, .obj, .stl

Scale (输入控制):文件中数据的比例尺。
数据类型:字符串/实数/整数
默认值:'m'
建议取值:'m', 'cm', 'mm', 'microns', 'µm', 'nm', 'km', 'in', 'ft', 'yd', 1.0, 0.01, 0.001, 1.0e-6, 0.0254, 0.3048, 0.9144

GenParamName (输入控制):通用参数的名称。
数据类型:字符串数组
默认值:[]
可选值:'convert_to_triangles', 'file_type', 'invert_normals', 'max_approx_error', 'min_num_points', 'xyz_map_height', 'xyz_map_width'
GenParamValue (输入控制):通用参数的值。
数据类型:字符串/实数/整数
默认值:[]
建议取值:'true', 'false', 1, 0, 'om3', 'off', 'ply', 'dxf', 'obj', 'stl', 'stl_binary', 'stl_ascii'
--------------------------------
convert_to_triangles:指定是否将对象转换为三角形。可能的取值为 'true'(转换为三角形)或 'false'(不转换为三角形)。
file_type:文件类型。可能的取值包括 'om3', 'off', 'ply', 'dxf', 'obj', 'stl', 'stl_binary', 'stl_ascii',分别表示不同类型的3D文件格式。
invert_normals:指定是否反转法线。可能的取值为 'true'(反转法线)或 'false'(不反转法线)。
max_approx_error:最大近似误差。可以是实数,用于指定在读取对象模型时允许的最大近似误差。
min_num_points:最小点数。可以是整数,用于指定对象模型中允许的最小点数。
xyz_map_height:XYZ映射高度。可以是字符串/实数/整数,用于指定XYZ映射的高度值。
xyz_map_width:XYZ映射宽度。可以是字符串/实数/整数,用于指定XYZ映射的宽度值。
--------------------------------

ObjectModel3D (输出控制):3D对象模型的句柄。
数据类型:整数

Status (输出控制):状态信息。
数据类型:字符串数组

3.2 点云的显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
*点云的显示
visualize_object_model_3d( : : WindowHandle, ObjectModel3D, CamParam, PoseIn, GenParamName, GenParamValue, Title, Label, Information : PoseOut)

*参数
WindowHandle (输入控制):窗口标识符。
数据类型:整数
ObjectModel3D (输入控制):3D对象模型的句柄。
数据类型:整数数组
CamParam (输入控制):场景的相机参数。
数据类型:实数数组
默认值:[]
PoseIn (输入控制):对象的3D姿势。
数据类型:实数/整数数组
默认值:[]
GenParamName (输入控制):通用参数的名称。可以传递所有disp_object_model_3d的通用参数。
数据类型:字符串数组
默认值:[]
建议值:'alpha', 'attribute', 'color', 'colored', 'disp_lines', 'disp_normals', 'disp_pose', 'light_position', 'light_ambient', 'light_diffuse', 'line_color', 'line_width', 'normal_color', 'point_size', 'intensity', 'intensity_red', 'intensity_green', 'intensity_blue', 'lut', 'disp_background', 'inspection_mode'
GenParamValue (输入控制):通用参数的值。可以传递所有disp_object_model_3d的通用参数。
数据类型:任意类型数组
默认值:[]
建议值:'true', 'false', 'coord_x', 'coord_y', 'coord_z', 'red', 'green', 'blue', 'auto', 'faces', 'primitive', 'points', 'lines', 'normal_x', 'normal_y, 'normal_z', 'standard', 'surface'
--------------------------------------------
attribute:明确选择对象模型可视化的方式,可以是自动选择、面、基元、点或线。默认为自动选择。
color:对象的颜色,可以是预设颜色(使用query_color操作符查询)或以#rrggbb形式指定的RGB三元组。默认为白色。
alpha:对象的透明度,取值范围为0.0(完全透明)到1.0(完全不透明)。默认为1.0
disp_lines:是否显示对象多边形的轮廓。默认为false
disp_normals:是否显示3D对象模型的表面法线。默认为false
line_color:当disp_lines设置为true时,线的颜色。默认为color的值。
line_width:线的宽度(以像素为单位)。默认为1.0
normal_color:当disp_normals设置为true时,可视化法线的颜色。默认为color的值。
intensity, intensity_red, intensity_green, intensity_blue:描述显示点或面强度的属性。默认为none。
lut:将强度转换为颜色的查找表(LUT)。默认为default
point_size:点的直径(以像素为单位)。默认为3.5
inspection_mode:影响交互式修改姿势的方式,可选standard或surface。默认为standard。
--------------------------------------------
Title (输入控制):要显示在输出图形窗口左上角的文本。
数据类型:字符串数组
默认值:[]
Label (输入控制):要显示在每个显示对象模型位置的文本。
数据类型:字符串数组
默认值:[]
Information (输入控制):要显示在输出图形窗口左下角的文本。
数据类型:字符串数组
默认值:[]
PoseOut (输出控制):所有可能由用户交互更改的对象模型的姿势。
数据类型:姿势数组

image-20240922134956742

3.3 求点云表面法向量

1
2
3
4
5
6
7
8
9
*用于计算3D对象模型的表面法线。
surface_normals_object_model_3d( : : ObjectModel3D, Method, GenParamName, GenParamValue : ObjectModel3DNormals)

*参数
ObjectModel3D:输入参数,包含3D点数据的3D对象模型的句柄。
Method:输入参数,法线计算方法。目前仅支持Moving Least Squares (MLS,方法为'mls') 法线估计方法。
GenParamName:输入参数,通用平滑参数的名称列表。包括'mls_abs_sigma', 'mls_force_inwards', 'mls_kNN', 'mls_order', 'mls_relative_sigma'等。
GenParamValue:输入参数,通用平滑参数的值列表。可以根据具体需求设置各个参数的值。
ObjectModel3DNormals:输出参数,包含计算出的3D法线的3D对象模型句柄。

3.3 三维重建

将离散的点重建成一个聚合的面

1
2
3
4
5
6
7
8
9
10
11
12
*用于为3D对象模型创建表面三角化(三角网格重建)
triangulate_object_model_3d( : : ObjectModel3D, Method, GenParamName, GenParamValue : TriangulatedObjectModel3D, Information)
-------------------------------------------
ObjectModel3D (输入参数):包含3D点数据的3D对象模型的句柄。
Method (输入参数):三角化方法。可选值有'greedy''implicit''polygon_triangulation'。默认值为'greedy'。其中:
'polygon_triangulation':是将多边形转换为三角形面表示的简单方法。
'greedy''implicit':这两种方法是用于从未知表面拓扑的纯3D点数据计算三角形面的复杂算法。
GenParamName (输入参数):通用三角化参数的名称列表。例如,'greedy_fix_flips', 'greedy_hole_filling'等。默认为空列表。
GenParamValue (输入参数):通用三角化参数的值列表。例如,6, 8, 'true', 'false'等。默认为空列表。
TriangulatedObjectModel3D (输出参数):包含三角化表面的3D对象模型句柄。
Information (输出参数):关于三角化过程的附加信息,以数字或字符串形式返回
-------------------------------------------

重建前:

image-20240922135412985

重建后:

image-20240922135817408

3.4 点云的筛选

筛选掉点云中的无关杂质(不感兴趣的位置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*筛选孤立散点特征的算子
select_points_object_model_3d( : : ObjectModel3D, Attrib, MinValue, MaxValue : ObjectModel3DThresholded)
*参数
ObjectModel3D (输入参数):3D对象模型的句柄数组,即要应用阈值处理的对象模型集合。
Attrib (输入参数):要应用阈值处理的属性名称。默认值为'point_coord_z',可选的属性包括:
'mapping_col': 映射列
'mapping_row': 映射行
'point_coord_x': 点的X坐标
'point_coord_y': 点的Y坐标
'point_coord_z': 点的Z坐标
'point_normal_x': 点的法线向量X分量
'point_normal_y': 点的法线向量Y分量
'point_normal_z': 点的法线向量Z分量
MinValue (输入参数):指定属性的最小阈值。默认值为0.5
MaxValue (输入参数):指定属性的最大阈值。默认值为1.0
ObjectModel3DThresholded (输出参数):经过阈值处理后的3D对象模型的句柄数组。这些句柄指向经过属性阈值处理后的减少的3D对象模型。

筛选前:

image-20240922135922762

筛选后:

image-20240922135940477

3.5连通域断开处理

只有进行断开操作之后 才可以继续进行筛选操作

1
2
3
4
5
6
7
8
9
10
11
connection_object_model_3d( : : ObjectModel3D, Feature, Value : ObjectModel3DConnected)
*参数
ObjectModel3D (输入参数):3D对象模型的句柄数组,即要处理的3D对象模型。
Feature (输入参数):用于计算连通组件的属性。默认值为'distance_3d',可选的属性包括:
'angle': 角度
'distance_3d': 3D距离
'distance_mapping': 距离映射
'lines': 线
'mesh': 网格
Value (输入参数):两个连通组件之间的最大距离值。默认值为1.0。可选的值包括1.0, 1.1, 1.5, 10.0, 100.0等。
ObjectModel3DConnected (输出参数):代表连通组件的3D对象模型的句柄数组。这些句柄指向表示连接的部分的3D对象模型。

3.6 求点云的最下外界Box

1
2
3
4
5
6
7
8
9
smallest_bounding_box_object_model_3d( : : ObjectModel3D, Type : Pose, Length1, Length2, Length3)

*各参数的解释:
ObjectModel3D (输入参数):3D对象模型的句柄。用于指定要计算最小边界框的3D对象模型。
Type (输入参数):用于估计最小边界框的方法。可以选择'axis_aligned'(轴对齐)或'oriented'(定向)。'oriented'的算法在计算上要昂贵得多,它返回的是定向边界框的近似值。请注意,定向边界框的算法是随机的,每次调用可能返回不同的边界框。
Pose (输出参数):描述生成的边界框的姿势,包括位置和方向。姿势的原点位于边界框的中心,x轴与边界框的最长边对齐。
Length1 (输出参数):边界框最长边的长度。
Length2 (输出参数):边界框第二长边的长度。
Length3 (输出参数):边界框第三长边的长度。

如下图,灰色部分即为最小的外界box,这个外界box是为了便于确认点云的Pose和坐标

image-20240922140238356

3.7 求物体的外边界

我采用的是一个简单粗暴的方法—做切平面

我做了一个竖直的切平面,不断沿着x轴进行移动,求出竖直的切平面与物体之间的交集,然后映射到二维平面,求出XLD线段,这样就可以得到交集线段的起点和终点坐标,这样就可以得到物体的边界

这个方法可以参考例程 inspect_3d_surface_intersections.hdev

image-20240915171921441

4.Halcon源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
*读取点云数据
path:='./2020-01-14-16832.om3'
read_object_model_3d (path, 'm', [], [], ObjectModel3D, Status)

*显示点云数据
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
visualize_object_model_3d (WindowHandle, ObjectModel3D, [], [], ['lut','intensity','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

*筛选去除噪声(通过点云之间的距离进行断开)
connection_object_model_3d (ObjectModel3D, 'distance_3d', 1, ObjectModel3DConnected)
get_object_model_3d_params (ObjectModel3DConnected, 'num_points', ParamValue)
select_object_model_3d (ObjectModel3DConnected, 'num_points', 'and', 20000, 2e7, ObjectModel3DSelected)
visualize_object_model_3d (WindowHandle, ObjectModel3DSelected, [], [], ['lut','intensity','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

*将鞋点云变换到原始坐标系上主轴-x y z
moments_object_model_3d (ObjectModel3DSelected, 'principal_axes', Moments)
*将pose进行翻转
pose_invert (Moments, PoseInvert)
*点云模型刚体变换模型
rigid_trans_object_model_3d (ObjectModel3DSelected, PoseInvert, ObjectModel3DRigidTrans)
visualize_object_model_3d (WindowHandle, ObjectModel3DRigidTrans, [], [], ['lut','intensity','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

*三角曲面重建
triangulate_object_model_3d (ObjectModel3DRigidTrans, 'greedy', [], [], TriangulatedObjectModel3D, Information)
*visualize_object_model_3d (WindowHandle, TriangulatedObjectModel3D, [], [], ['lut','intensity','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

stop()

*这一步是为了更好的将物体移动到主轴的位置(继续转正)-
*求出物体的外接box
smallest_bounding_box_object_model_3d (TriangulatedObjectModel3D, 'oriented', Pose, Length1, Length2, Length3)
*翻转姿态
pose_invert (Pose, PoseInvert1)
*刚体变换
rigid_trans_object_model_3d (TriangulatedObjectModel3D, PoseInvert1, ObjectModel3DRigidTrans1)
*visualize_object_model_3d (WindowHandle, ObjectModel3DRigidTrans1, [], [], ['lut','intensity','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

*生成物体的外接box
smallest_bounding_box_object_model_3d (ObjectModel3DRigidTrans1, 'oriented', PoseBox, Length11, Length21, Length31)
gen_box_object_model_3d (PoseBox, Length11, Length21, Length31, ObjectModel3D1)

*将物体和box一起显示(显示的时候 加'_0'代表第一个Object 加'_1'代表第二个Object)
visualize_object_model_3d (WindowHandle, [ObjectModel3DRigidTrans1,ObjectModel3D1], [], [], ['color_0','color_1','alpha_1','disp_pose'], ['green','gray',0.5,'true'], [], [], [], PoseOut)
objectsOut:=[]
Index_S:=[]
Index_E:=[]
color_S:=[]
color_E:=[]
colorsOut:=[]
colorvaluesOut:=[]
all_x:=[]
all_y:=[]
*做切平面与鞋子的点云相交
for index:=0 to 45 by 1
cutplanePose := PoseBox
cutplanePose[0]:=PoseBox[0] - Length11/2 + (index)*4+3
cutplanePose[3]:=0
cutplanePose[4]:=90
cutplanePose[5]:=0
*产生平面
gen_plane_object_model_3d (cutplanePose, [-1,-1,1,1]* 90, [-1,1,1,-1] * 90, GenPlane)
*visualize_object_model_3d (WindowHandle, [ObjectModel3DRigidTrans1,GenPlane], [], [], ['color_0','color_1','alpha_1','disp_pose'], ['green','gray',0.5,'true'], [], [], [], PoseOut)

*求交线
intersect_plane_object_model_3d (ObjectModel3DRigidTrans1, cutplanePose, ObjectModel3DIntersection)
*visualize_object_model_3d (WindowHandle, ObjectModel3DIntersection, [], [], ['lut','intensity','disp_pose'], ['color1','coord_z','true'], [], [], [], PoseOut)

*变换到二维xld
*翻转姿态
pose_invert (cutplanePose, poseInvert)
*确认投影平面在前面
*获得box外接主轴的直径
get_object_model_3d_params (ObjectModel3DIntersection, 'diameter_axis_aligned_bounding_box', Diameter)
poseInvert[2]:=poseInvert[2]+Diameter
*用平行于投影平面的相机(1:1的比例)
Scale:=1
CamParam := [0,0,1.0/Scale, 1.0/Scale, 0, 0, 500,500]
project_object_model_3d (ModelContours, ObjectModel3DIntersection, CamParam, poseInvert, 'data', 'lines')
count_obj(ModelContours,Number)

Rows:=[]
Columns:=[]
Row:=[]
Column:=[]
for I:=1 to Number by 1
select_obj (ModelContours, EdgeContour, I)
get_contour_xld(EdgeContour, Row,Column)
Rows:=[Rows,Row]
Columns:=[Columns,Column]
endfor
*从上到下依次进行排序
tuple_sort_index (Rows, Indices)
tuple_length(Rows,Length)
OrderRow:=[]
OrderColumn:=[]
if(Length>=1)
for Row_Index:=0 to Length-1 by 1
OrderRow:=[OrderRow,Rows[Indices[Row_Index]]]
OrderColumn:=[OrderColumn,Columns[[Row_Index]]]
endfor
endif

*求最大和最小点(行方向)
tuple_sort_index (OrderRow, Indices)
tuple_length(OrderRow,Length)
*起点(xld)
StartRow:=OrderRow[Indices[0]]
StartColumn:=OrderColumn[Indices[0]]
*终点(xld)
EndRow:=OrderRow[Indices[Length-1]]
EndColumn:=OrderColumn[Indices[Length-1]]

*在起点和终点位置生成 x 图标
gen_cross_contour_xld(StartXP, StartRow, StartColumn, 6, 0.795296)
gen_cross_contour_xld(EndXP, EndRow,EndColumn, 6, 0.795296)
dev_display(ModelContours)

*转换成点云坐标
StartPose:=[cutplanePose[0],StartRow,-StartColumn, 0,0,0,0]
EndPose :=[cutplanePose[0],EndRow,-EndColumn, 0,0,0,0]

*生成球体的点云
gen_sphere_object_model_3d (StartPose, 2, StartPoint)
gen_sphere_object_model_3d (EndPose , 2, EndPoint )

*所有对点的边界点集合
objectsOut := [objectsOut,StartPoint]
objectsOut := [objectsOut,EndPoint ]
*显示时的颜色
Index_S:= 0+index*2
Index_E:= 0+index*2+1
color_S:='color_'+Index_S
color_E:='color_'+Index_E

colorsOut := [colorsOut,color_S]
colorsOut := [colorsOut,color_E]

colorvaluesOut := [colorvaluesOut,'blue']
colorvaluesOut := [colorvaluesOut,'blue']


all_x:=[all_x,cutplanePose[0]]
all_y:=[all_y,StartRow]

all_x:=[all_x,cutplanePose[0]]
all_y:=[all_y,EndRow]
endfor

*显示外边界模型点云
visualize_object_model_3d (WindowHandle,[objectsOut,ObjectModel3DRigidTrans1], [],[],[colorsOut,'color_88'],[colorvaluesOut,'red'], [], '', [], Pose)
*2二维显示
dev_open_window (0, 0, 512, 512, 'black', WindowHandle1)
dev_set_color('red')
gen_cross_contour_xld(Start,all_x,all_y, 3, 0.885398)



文章作者: Yolo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yolo !
评论
  目录