当前位置:   article > 正文

Halcon 3D算子总结整理

halcon 3d

halcon 3D包含以下几个模块:

  • 3D Matching(3D匹配)
  • 3D Object Model(3D模型)
  • 3D Reconstruction(3D重构)
  • 3D Transformations(3D转换)

1. 3D Matching

1.1 3D Box3D盒查找器

不需要对象模型,只需要盒子尺寸,适用于箱子抓取的场景。

算子说明
find_box_3d可输入箱体的形状参数,来查找点云中对应的箱体。在这里插入图片描述

1.2 Shape-Based基于形状的匹配

利用CAD模型,在2D图像上进行物体的空间定位,需要进行相机标定拿到内参。
正如前文《手眼标定》所说:
基于形状匹配是指在二维图像中搜索三维CAD模型实例。通过操作符find_shape_model_3d计算并返回物体空间姿态。这个方法虽然拿不到点云,但它最终还是能计算出物体的空间位姿,挺牛逼的,就是性能、精度都很差。
它是通过一种基于视图的方法来计算的。通过虚拟球面视图的方式,降低算法复杂度:

假设物体置于球心,并对球心进行观测,创建多个位置的虚拟相机,我们可以通过将物体投影到每一个虚拟相机的像平面上获取相机的拍到的视图,注册为模板,在实际匹配时,会在每个虚拟相机的位置进行匹配计算,找到最佳位姿。注意还需计算不同半径下的虚拟相机。

在这里插入图片描述

创建模板的时候,利用CAD三维信息,进行多虚拟相机投影的计算,计算量很大。在后面使用时,需要对数以千计的视图进行匹配计算,很难满足实际的应用需求,还是推荐直接上3D相机获取到点云信息后进行匹配。

因为用的不多,这里不再介绍。

1.3 Surface-Based基于表面的匹配

可通过点云或CAD模型来进行空间定位。

算子说明
clear_surface_matching_result清除找到的结果内存。
clear_surface_model清除模型内存
create_surface_model创建一个surface的模型,来为后面的匹配做准备。该算子输入 xyz_to_object_model_3d或者read_object_model_3d得到的对象。这个算子非常重要,它可以决定后续的匹配是基于表面、边缘还是视角,不同的方法对应不同的要求,比如如果要计算2D/3D的边缘匹配结果来提升精度,则必须要求模型的点法向量向内,并且模型必须包含三角形或多边形网格
find_surface_model查找最佳匹配位姿。分了三个步骤:首先近似匹配,找到大概的位姿;第二步稀疏匹配,提升匹配精度;第三步稠密匹配,找到个更精确的位姿。注意:该算子返回的位姿是模板模型到目标的变换关系,可以通过rigid_trans_object_model_3d(模板,pose, )将模板整体模型转到目标中进行靠模

1.4 Deformable Surface-Based基于表面的形变匹配

用于空间物体扭曲变形下的匹配。

1.5 3D Gripping Point Detection3D夹持点检测

是一种基于深度学习的方法。

2. 3D Object Model

2.1 Creation创建

算子说明
clear_object_model_3d释放3D对象模型的内存
copy_object_model_3d拷贝一个3D模型
deserialize_object_model_3d对序列化的3D模型进行反序列化。
gen_box_object_model_3d创建一个盒子3D对象模型
gen_cylinder_object_model_3d创建一个圆柱3D对象模型
gen_empty_object_model_3d创建一个空的3D对象模型
gen_object_model_3d_from_points从3D点云数据来创建3D对象模型
gen_plane_object_model_3d创建一个平面的3D对象模型
gen_sphere_object_model_3d通过位姿创建一个球形的3D对象模型
gen_sphere_object_model_3d_center通过(xyz)点创建一个球形的3D对象模型
read_object_model_3d从一个CAD文件中读取一个3D对象模型
remove_object_model_3d_attrib移除3D对象模型指定属性信息,例如点向量、三角形等
remove_object_model_3d_attrib_mod移除3D对象模型一些属性信息
serialize_object_model_3d序列化一个3D对象模型
set_object_model_3d_attrib给3D对象模型设置一些属性信息
set_object_model_3d_attrib_mod给3D对象模型设置一些属性信息
read_object_model_3d从一个CAD文件中读取一个3D对象模型
union_object_model_3d将多个3D对象模型合并为一个
write_object_model_3d写3D对象模型到文件

2.2 Features特征

算子说明
area_object_model_3d计算3D对象模型所有面的面积 ,次模型必须具有面,比如box模型
distance_object_model_3d计算两个点云间的距离
get_object_model_3d_params获取3D对象模型的属性
max_diameter_object_model_3d计算3D对象模型的最大凸包直径
moments_object_model_3d计算3D对象模型的二阶平均矩或中心矩
select_object_model_3d根据一些全局特征从一堆3D对象模型中选择指定特征的模型,这些特征比如平均x坐标、矩信息,面数、点数等.注意和后面点云分割select_points_object_model_3d的区别。下面是从多个对象模型中选择出的。在这里插入图片描述
smallest_bounding_box_object_model_3d最小外接方框。smallest_sphere_object_model_3d
smallest_sphere_object_model_3d最小内接球
volume_object_model_3d_relative_to_plane获取3D对象模型相对于一个平面的体积

2.3 Segmentation分割

算子说明
segment_object_model_3d将一个3D点集按照指定的特征分割成特征相似的子集,并进行基本形状拟合(可选),这些特征例如点的最大法向量差、子集所需最小点数等。如果选择基本形状拟合,则可拟合成基本形状(圆柱、球、箱)。如果不选择拟合,则生成的指示一堆子集,后续也可通过fit_primitives_object_model_3d来拟合为基本形状。最终可输出多个拟合的模型。
fit_primitives_object_model_3d将3D对象模型拟合为基本的形状,可拟合成圆柱、球、箱,一旦拟合成功,就可以拿到这些形状的基本信息,比如球半径等
select_points_object_model_3d根据一些特征分割出想要的点云,这些特征比如指定的x坐标、z坐标、邻域距离范围等等。下图按z范围去掉了底面。注意该它的对象模型还是1个。connection之后会产生多个模型,这时候就得配合select_object_model_3d在这里插入图片描述
reduce_object_model_3d_by_view将3D对象模型的点投影到相机的图像平面坐标系中,此时变为了2D图像,然后在2D图像上给定一个region,只保留该region内的3D对象模型。注意需要提供相机内参,不常用。

2.4 Transformations

算子说明
affine_trans_object_model_3d进行3D对象模型的仿射变换。
connection_object_model_3d按照给定的特征条件,进行点云筛选,比如点之间的距离、法向量夹角等等。注意会构建多个点云模型下图是按照点之间的距离进行的筛选。。在这里插入图片描述
convex_hull_object_model_3d创建给定3D对象模型的凸包模型。
edges_object_model_3d查找3D对象模型的边缘轮廓。在这里插入图片描述
fuse_object_model_3d将3D对象模型进行曲面拟合。在这里插入图片描述
intersect_plane_object_model_3d计算一个平面和3D模型的界面轮廓。在这里插入图片描述
object_model_3d_to_xyz3D对象模型转为xyz数值,可选参数如果是’from_xyz_map’,仅在 xyz_to_object_model_3d算子转的模型后使用。注意如果对模型进行了刚体变换或投影变换,虽然模型xyz坐标变了,但’from_xyz_map’后还是同样的xyz图!此时可通过’point_coord_x’等拿到新的坐标
xyz_to_object_model_3dxyz转为3D对象模型。
prepare_object_model_3d调用其他算子如create_shape_model_3d/ segment_object_model_3d/distance_object_model_3d等等接口的点云预操作,如果后续要多次调用相关算子,可通过预处理运算来提速,减少重复的操作。当然该算子也可以不使用。
project_object_model_3d将3D对象模型先转换到相机坐标系下,再根据内参投影到像平面上。
projective_trans_object_model_3d用一个使用vector_to_hom_mat3d.创建的转换矩阵(刚性/仿射/相似/投影矩阵),对3D对象模型进行空间变换。
rigid_trans_object_model_3d只对3D对象模型进行刚性变换。
register_object_model_3d_global对多个相似3D对象模型进行点云融合重构,这个不需要进行标定,挺有意思。下图为第一个模型:后面是多个模型通过重叠部分迭代计算,融合在一起,可以看到模型更加完整了:在这里插入图片描述
register_object_model_3d_pair通过比对两个3D对象模型的重叠程度,计算位姿变换关系。
affine_trans_object_model_3d将3D对象模型的一个视角下的位姿模型转到图片格式。
sample_object_model_3d对3D对象模型进行采样,注意原始点云的点可能会被修改,比如’accurate’模式会遍历所有点,在指定半径的球内寻找其他点,如果有,则保留球内所有点的重心。在这里插入图片描述
smooth_object_model_3d点云平滑滤波,包含两种方式:基于3D空间曲面多项式拟合的mls算法和基于2D深度图的图像滤波算法。后者速度更快。在这里插入图片描述在这里插入图片描述在这里插入图片描述
surface_normals_object_model_3d为3D对象模型生成三角面的表面。

3. 3D重构

包含双目、深度聚焦、多2d相机视角重建、线激光重构四种方法。这里就不罗列了。

4. Transformations

4.1 Pose

pose位姿数组,描述的是刚性三维变换。形式为 [ T x , T y , T z , R x , R y , R z , C o d e ] [Tx,Ty,Tz,Rx,Ry,Rz,Code] [Tx,Ty,Tz,Rx,Ry,Rz,Code],分别对应了平移、旋转还有类型编码。可通过create_pose算子创建。

create_pose( : : TransX, TransY, TransZ, RotX, RotY, RotZ, OrderOfTransform, OrderOfRotation, ViewOfTransform : Pose)
OrderOfTransform可以是Rp+T’和Rp-T’,这里R是旋转,p是点,T是平移。
OrderOfRotation可选’gba’‘abg’‘rodriguez’,其中gba表示RxRyRz的顺序,按新旧轴可以选择从左往右还是从右往左读,后面会有说明。abg对应RzRyRx。这里rodriguez表示罗德里格旋转公式,此时3个旋转量对应了向量的方向,向量的长度定义为了在这里插入图片描述
ViewOfTransform可选为’point’和 ‘coordinate_system’,后者将旋转的角度取了反!(名称容易误导)

标准的位姿变换(Rp+T,gba,point),推荐用这种:
在这里插入图片描述
注意这里是Ht*Hr,顺序不能错了。
对于一个点的转换公式:
在这里插入图片描述
不标准的Rp-T,这里T取了负值,并且RT矩阵反过来了!:在这里插入图片描述
类型编码如下:
在这里插入图片描述

算子说明
convert_pose_type改变Pose的类型,即改为不同code下的表达方式。
**get_pose_type **获取pose对应type类型。
create_pose创建Pose。
deserialize_pose反序列化Pose。
serialize_pose序列化Pose。
dual_quat_to_pose对偶四元数转位姿。
pose_to_dual_quatPose转对偶四元数。
pose_to_quatPose转四元数。
quat_to_pose四元数转Pose。
get_circle_pose计算标定板上亚像素圆的位姿。
get_rectangle_pose计算亚像素矩形框的位姿。
pose_average计算一堆Pose旋转和平移的带权平均值。
pose_compose两个Pose转为矩阵后相乘。
proj_hom_mat2d_to_pose函数根据描述2D世界坐标(单位为米)和2D图像坐标之间关系的单应性矩阵Homography计算姿态。
write_pose写Pose到文件。
read_pose从文件读取Pose。
set_origin_pose按照自身坐标系,平移该Pose的原点位置。
vector_to_posePNP算法,PnP算法通过一组3D点和它们对应的2D图像点来估计相机的姿态。

4.3 3D Transformations

homMat3D变换矩阵形式

在这里插入图片描述

算子说明
affine_trans_point_3d对一个3D点进行仿射变换,比如通过 hom_mat3d_identity, hom_mat3d_scale, hom_mat3d_rotate, hom_mat3d_translate和pose_to_hom_mat3d创建的变换矩阵。
deserialize_hom_mat3d将一个SerializedItemHandle反序列化为hommat3D矩阵。
serialize_hom_mat3d将HomMat3D序列化
hom_mat3d_compose实现两个homMat3D矩阵相乘。
hom_mat3d_transpose转置
point_pluecker_line_to_hom_mat3d普吕克坐标下转换
pose_to_hom_mat3dpose位姿数组转HomMat3D矩阵
vector_to_hom_mat3d根据两个坐标系下的3D点数组,拟合homMat3D矩阵在这里插入图片描述
hom_mat3d_determinant创建一个3D齐次变换阵在这里插入图片描述
hom_mat3d_invert求逆
hom_mat3d_rotate绕一个固定点(Px,Py,Pz)进行旋转,注意R在homMat3D矩阵左边!绕旧轴旋转在这里插入图片描述
hom_mat3d_rotate_local绕HomMat3D自身进行转,R乘到后面了!绕新轴旋转在这里插入图片描述
hom_mat3d_scale绕一个固定点,乘以一个缩放系数矩阵在这里插入图片描述等价于(左边):在这里插入图片描述
hom_mat3d_scale_localhomMat3D直接进行缩放,右边:在这里插入图片描述
hom_mat3d_to_poseHomMat3D矩阵转pose位姿数组
hom_mat3d_translateHomMat3D左乘一个平移矩阵,按旧轴平移在这里插入图片描述
hom_mat3d_translate_localHomMat3D右乘平移矩阵,按新轴平移,最终结果:在这里插入图片描述
projective_trans_hom_point_3d对一个3D点待Pw进行投影变换 在这里插入图片描述
projective_trans_hom_point_3d对一个3D点进行投影变换在这里插入图片描述

4.4 新/旧轴总结

对于hom_mat3d_rotate/hom_mat3d_rotate_local等旧轴和新轴的区别,这里用2d下的类似算子进行验证,这样比较直观。

对图像先旋转30度,再沿x轴平移100个像素。

  • 套用hom_mat2d_rotate_local 和hom_mat2d_translate_local,因为是对新轴进行的,所以平移是按照旋转之后的坐标系沿x平移。
  • 套用hom_mat2d_rotate和hom_mat2d_translate,因为是对旧轴进行的,所以平移还是按照之前的图像坐标系平移。

上代码,local模式:

read_image (Image, 'forest_road')
hom_mat2d_identity (HomMat2DIdentity) //这里先创建默认齐次矩阵,在这个基础上添加平移或旋转量
hom_mat2d_rotate_local (HomMat2DIdentity, rad(30), HomMat2DRotate_local)
affine_trans_image (Image, ImageAffineTrans, HomMat2DRotate_local, 'nearest_neighbor', 'false')
hom_mat2d_translate_local(HomMat2DRotate_local, 100, 0, HomMat2DTranslate_local)
affine_trans_image (Image, ImageAffineTrans, HomMat2DTranslate_local, 'nearest_neighbor', 'false')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以看到,原图像被旋转了30度,左上角的点坐标变为了(86,50),由三角形斜边长度为50/sin30=100,正好和平移的100匹配上了。
在这里插入图片描述
在这里插入图片描述
非local模式,这里固定点是(0,0),和上面的local默认旋转轴中心一致,方便对比:

hom_mat2d_rotate (HomMat2DIdentity, rad(30), 0, 0, HomMat2DRotate)
affine_trans_image (Image, ImageAffineTrans, HomMat2DRotate, 'nearest_neighbor', 'false')
hom_mat2d_translate (HomMat2DRotate, 100, 0, HomMat2DTranslate)
affine_trans_image (Image, ImageAffineTrans, HomMat2DTranslate, 'nearest_neighbor', 'false')
  • 1
  • 2
  • 3
  • 4

可以看出,旋转之后,由沿垂直x方向平移了100,也就是原始的图像坐标系为“旧轴”。
在这里插入图片描述

在这里插入图片描述
还有如下结论:

  1. 想对已知的点或者图像进行空间变换,首先使用hom_mat2d_identity创建一个齐次基本矩阵,然后将平移和旋转往上加
  2. 当旋转中心一样时,连续旋转一个角度,比如旋转1次再旋转1次,local和非local结果都是一样的。带上平移就不一样了。
  3. 相机外参的位姿Pose中的,旋转和平移用的是旧轴还是新轴的方式呢?根据halcon给出的create_pose关于Rgba帮助文档:

在这里插入图片描述

If you start from the right, the rotations are always performed relative to the global (i.e., fixed or “old”) coordinate system. Thus, can be read as follows: First rotate around the z-axis, then around the “old” y-axis, and finally around the “old” x-axis. In contrast, if you read from the left to the right, the rotations are performed relative to the local (i.e., “new”) coordinate system. Then, corresponds to the following: First rotate around the x-axis, the around the “new” y-axis, and finally around the “new(est)” z-axis.
如果您从右边开始读取,旋转始终相对于全局(即固定或“旧”)坐标系执行。因此,可以按照以下方式解读:首先绕z轴旋转,然后绕“旧” y轴旋转,最后绕“旧” x轴旋转。相反,如果您从左到右阅读,则旋转相对于局部(即“新”)坐标系执行。然后,对应于以下操作:首先绕x轴旋转,然后绕“新” y轴旋转,最后绕“最新的”z轴旋转。

从右到左读取对应于以下算子调用顺序:

 hom_mat3d_identity (HomMat3DIdent)
  hom_mat3d_rotate (HomMat3DIdent, RotZ, 'z', 0, 0, 0, HomMat3DRotZ)
  hom_mat3d_rotate (HomMat3DRotZ, RotY, 'y', 0, 0, 0, HomMat3DRotYZ)
  hom_mat3d_rotate (HomMat3DRotYZ, RotX, 'x', 0, 0, 0, HomMat3DXYZ)
  • 1
  • 2
  • 3
  • 4

相反,从左向右读取对应于以下算子调用顺序:

  hom_mat3d_identity (HomMat3DIdent)
  hom_mat3d_rotate_local (HomMat3DIdent, RotX, 'x', HomMat3DRotX)
  hom_mat3d_rotate_local (HomMat3DRotX, RotY, 'y', HomMat3DRotXY)
  hom_mat3d_rotate_local (HomMat3DRotXY, RotZ, 'z', HomMat3DXYZ)
  
  • 1
  • 2
  • 3
  • 4
  • 5

也就是说,在使用Pose和点或图像进行变换时,因为点都是乘在变换矩阵左边,直接计算即可,不必区分新旧轴,只有对homMat3D变换时,才需要考虑新旧轴。但Pose下的阅读顺序,可以帮助我们“观察”点或图像是如何变过去的,有助于拿到一个Pose,肉眼大概分析出是否正确。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/460192
推荐阅读
相关标签
  

闽ICP备14008679号