2D视觉定位引导系列 3 探讨海康 VisionMaster N点标定的内部原理

前面 2篇文章,
对标定进行了初步探讨,内容涉及9点和12点标定。本篇文章来对海康的N点标定的内部原理进行探讨
但是我不得不吐槽下,关于N点标定的原理的官方说明太少,只有民间有些只言片语的说明。
丛 这篇文章V社区-机器智能技术交流-常规定位引导项目入门必看 (v-club.com)才了解点N点标定得信息,文章作者在评论去说了这么一句话
“第五点拍照位也就是拟合旋转中心的物理坐标,
12点标定得到的标定矩阵是做过旋转归一化的,旋转中心经过标定转换即为(0,0)点,
所有点经过标定转换都是相对于旋转中心的,此时加上这个拍照位坐标也就转换到实际物理坐标系了”
就上面这句话,我相信10个人看了,9个人会迷糊,主要可能下面几方面迷糊
1.第五点拍照位也就是拟合旋转中心的物理坐标   第5点为什么是拟合旋转中心的物理点
2.过旋转归一化 何为旋转归一化,为什么旋转归一化以后旋转中心就是(0,0) 点
3.所有点经过标定转换都是相对于旋转中心的,此时加上这个拍照位坐标也就转换到实际物理坐标系了  物理坐标的获取方式 大家是否理解
以上3点疑问后续为你慢慢说明白
N点标定 中的9点标定,N点标定模块和我们平时做的9点标定 没大的差别,提供9组像素和物理坐标就行了。
N点标定 中12 点标定与我这个系列文章12点标定 < 2D视觉定位引导系列 2 图解12点标定及仿真>没有太大的差别,如果能理解本人12点标定那篇文章内容的同学
理解N点标定将易如反掌。2者的区别 就是这个旋转归一化。
认识下第5个点  第5点是标定的起始点,9点标定物理坐标就是在这个点的基础上进行正负XY偏移得到的,旋转标定也是在这个点完成的,旋转标定时机构XY停在这个点,只动角度部分。
到底何为旋转归一化。一句话总结就是将标定的起始点坐标设定为(0,0),也就是N点标定的第5个物理坐标,设定为(0,0),正常情况下这个坐标不会时(0,0),通过将坐标系的原点移动
到这个第5点就行了,具体操作如下。
假如原始物理坐标为(x1,y1)(x2,y2)..(x5,y5)…(x8,y8)(x9,y9)
则将坐标处理成 (x1-x5,y1-y5)(x2-x5,y2-y5)..(x5-x5,y5-y5)…(x8-x5,y8-y5)(x9-x5,y9-y5). (注意这种是假定相机静止的情况,相机运动的案例,后面再讨论)。
用处理后的物理坐标重新进行一次标定计算的新的标定系数。标定完成后 如何得到像素点的真实物理物理坐标。方法就是像素点经过标定转化后,还得加上标定时的第5点坐标(x5,y5),
因为当初标定的时候所有物理点可是都减去了这个(x5,y5),现在要得到真实的物理坐标就得把这个坐标加上。其实这解释的上面问题的第3点。
上面是理论分析 下面开始标定验证,将我12点标定的数据带入到 海康N点标定中计算
运行参数旋转 上相机静止
   
标定结果
                 
关于N点标定标定结果说3点
1.像素精度为1,符合预期
2.旋转轴图像点,(-1000.487,999.5067)与我12点标定文章中计算的旋转中心 (-1000.69,999.497)非常接近,差别是不同的圆拟合算法造成的。
3.关于标定结果中的旋转中心物理点是(-1000.487,999.5067) 这个我暂时也没法理解。
简单验证下
取2个点验证下结果
1.将旋转轴的图像点对于的物理坐标应该是(0,0),结果基本吻合
2.9点标定最后一个像素点(1499.5,1499.5),这个点在线新的坐标系下 为(2500,500)与 标定转换的结果(2499.987,499.993) 非常接近。
Halcon 代码来模拟这个标定流程
代码还是采用我们上篇文章的halcon 代码只是稍作改动,代码的最后部分 也是对上面2个点进行验证,结果海康的结果也基本也一致,
取物理坐标的地方,修改如下
*模拟九点获取机械坐标,假设此时机械坐标就表示法兰盘中心的坐标
    *tuple_concat(xwolrd,arm_center_row+move9Row[Index]*step,xwolrd)
    *tuple_concat(yworld,arm_center_col+move9Col[Index]*step,yworld)
     *海康12点标定将标定的第5点设定为(0,0),以前是(3000,5000)
     tuple_concat(xwolrd,0+move9Row[Index]*step,xwolrd)
     tuple_concat(yworld,0+move9Col[Index]*step,yworld)

计算标定偏移的地方修改如下

*计算标定偏移
*Dx:=arm_center_row-Qx
*Dy:=arm_center_col-Qy
Dx:=0-Qx
Dy:=0-Qy

完整代码如下,可复制 到halcon 直接运行

*窗口坐标 宽度
dev_update_window('off')

winw:=10000 
winh:=10000
dev_open_window(0, 0, 1000, 1000, 'black', WindowHandle)
dev_set_part(0,0,winw,winh)
set_system ('clip_region', 'false')
dev_clear_window()
dev_set_draw ('margin')
gen_region_line(xaxis, 0, 0, 0, winw)
gen_region_line(yaxis, 0, 0, winw, 0)
dev_set_color ('red')
dev_display(xaxis)
dev_display(yaxis)


*定义相机视野长宽
camstartrow:=5000
camstartcol:=5000
cam_width:=1000
cam_degre:=0
*定义相机左上角坐标,后面计算像素坐标用
   *以Cam的左上角为0,0 坐标 相机原点在机械坐标系中的位置是 (arm_center_row-cam_width),(camstartcol-cam_width)
cam_origin_row:=camstartrow-cam_width
cam_origin_col:=camstartcol-cam_width
*生成相机区域
gen_rectangle2(camrect, camstartrow, camstartcol, cam_degre, cam_width, cam_width)


dev_set_color ('blue')
dev_set_draw ('margin')
dev_display(camrect)

*定义 Arm 法兰盘位置,旋转标定的物理中心
arm_center_row:=3000
arm_center_col:=5000
gen_circle(arm_center, arm_center_row, arm_center_col, 200) 
*定义末端工具 可以理解为一更长杆一端连接在法兰盘中心,一端带着吸盘 ,初始将吸盘的中心也放到相机中心
gen_region_line(tool,arm_center_row,arm_center_col,camstartrow,camstartcol)
*定义吸盘
gen_circle(tool_center, camstartrow, camstartcol, 100)

concat_obj(arm_center,tool,ObjectsConcat)
concat_obj(ObjectsConcat, tool_center, Tool_ARM)

dev_set_color ('pink')
dev_set_draw ('margin')
dev_display(Tool_ARM)

*定义2个轴的移动步长系数
move9Row:=[ -1,  0,  1, 1, 0, -1, -1,  0,  1 ]
move9Col:=[ -1, -1, -1, 0, 0,  0,  1,  1,  1 ]


*机械坐标
xwolrd:=[]
yworld:=[]
*像素坐标
row_pixel:=[]
col_pixel:=[]
*每次移动补偿
step:=500.0
for Index := 0 to 8 by 1
    
    *构建每次平移矩阵
    hom_mat2d_identity(HomMat2DIdentity)
    hom_mat2d_translate(HomMat2DIdentity, move9Row[Index]*step, move9Col[Index]*step, HomMat2DTranslate)
    
    *模拟九点获取机械坐标,假设此时机械坐标就表示法兰盘中心的坐标
  
    *tuple_concat(xwolrd,arm_center_row+move9Row[Index]*step,xwolrd)
    *tuple_concat(yworld,arm_center_col+move9Col[Index]*step,yworld)
     *海康12点标定将标定的第5点设定为(0,0),以前是(3000,5000)
     tuple_concat(xwolrd,0+move9Row[Index]*step,xwolrd)
     tuple_concat(yworld,0+move9Col[Index]*step,yworld)
     
    *模拟移动机械臂
    affine_trans_region(Tool_ARM, RegionAffineTrans, HomMat2DTranslate, 'nearest_neighbor')
    *计算移动后机械臂的坐标,这里(Row[2],Column[2]),刚好是吸盘(小圆圈)的坐标
    area_center(RegionAffineTrans, Area, Row, Column)
    *模拟取吸盘的像素坐标
    tuple_concat(row_pixel,Row[2]-(cam_origin_row), row_pixel)
    tuple_concat(col_pixel,Column[2]-(cam_origin_col), col_pixel)
    dev_display(RegionAffineTrans)
endfor
*上面模拟九点标定以后计算标定数据,HomMat2D 就是9点标定的转移矩阵
vector_to_hom_mat2d(row_pixel, col_pixel, xwolrd, yworld, HomMat2D)



*3点旋转 标定起点 旋转3此
rotate3Point:=[20,0,-20]
arc_row:=[]
arc_col:=[]
for Index1 := 0 to 2 by 1
   hom_mat2d_identity(HomMat2DIdentity)
   *标定起点 选择
   hom_mat2d_rotate(HomMat2DIdentity, rad(rotate3Point[Index1]), arm_center_row, arm_center_col, HomMat2DRotate)
     *模拟移动机械臂
   affine_trans_region(Tool_ARM, RegionAffineTrans, HomMat2DRotate, 'nearest_neighbor')
    *计算移动后机械臂的坐标,这里(Row[2],Column[2]),刚好是吸盘(小圆圈)的坐标,
   area_center(RegionAffineTrans, Area, Row, Column)
   *模拟取吸盘的像素坐标
   tuple_concat(arc_row, Row[2]-(cam_origin_row), arc_row)
   tuple_concat(arc_col,Column[2]-(cam_origin_col), arc_col)
   
   dev_set_color ('turquoise')
   dev_display(RegionAffineTrans)
endfor

*通过上面的3点  计算圆心
gen_contour_polygon_xld(Contour, arc_row, arc_col)
get_part(WindowHandle, Row11, Column11, Row2, Column2)
fit_circle_contour_xld(Contour, 'algebraic', -1, 0, 0, 3, 2, Row1, Column1, Radius, StartPhi, EndPhi, PointOrder)
*Row1,Column1 就是圆心的像素坐标,当前值(-1000,1000),
gen_cross_contour_xld(Cross, Row1,Column1, 100, 0)
set_system ('clip_region', 'false')
dev_set_color ('red')
dev_display(Cross)

affine_trans_point_2d(HomMat2D, Row1, Column1, Qx, Qy)
dev_set_color ('blue')
gen_cross_contour_xld(Cross1, Qx,Qy, 200, 0)
*显示旋转标定中心坐标
dev_display(Cross1)
*计算偏移
*Dx:=arm_center_row-Qx
*Dy:=arm_center_col-Qy
*现在物理旋转中心被设定为(0,0),所以计算偏移不用(arm_center_row,arm_center_col)这个数据了,希望能理解
Dx:=0-Qx
Dy:=0-Qy
*修正9点标定的机械坐标
xwolrd1:=xwolrd+Dx
ywolrd1:=yworld+Dy
*重新计算标定矩阵
vector_to_hom_mat2d(row_pixel, col_pixel, xwolrd1, ywolrd1, HomMat2D1)
*重新验算标定的旋转中心是否与法兰中心重合

*旋转中心验证
affine_trans_point_2d(HomMat2D1, Row1, Column1, Qx1, Qy1)

*(1499.5,1499.5 )
affine_trans_point_2d(HomMat2D1, 1499.5,1499.5 , Qx2, Qy2)
总结:
本文通过分析了,海康N点标定的内部原理,带大家了解了何为旋转归一化。  海康N点标定模块采用12点标定,
1.如果相机静止,需要记住第五代物理坐标,以后计算像素的物理坐标要把第五点坐标值加上。怎么感觉这类似于相对标定。
2.如果相机运动(后续文章会讲),就有个拍照位置的问题,最终的物理坐标是像素经过标定转换后加上拍照位置的物理坐标得到最终物理坐标
3.这个N点标定的优点是什么,我的理解是旋转中心的坐标未(0,0),计算旋转造成的XY偏移就会比较简单。
4.N点标定与我的12点标定有何区别,主要区别是N点标定模块标定转换后得到的是相对坐标,需要经过上面1,2 处理,而我的12点标定后得到
的就是真实的物理坐标。二者各有优点,你们自己研究研究(特别是相机运动的模式下,海康N点标定比较灵活)
转载本文需要标明出处。疑问留言 或者 添加下面2种方式 交流
加群(277957302)交流

1 条评论

  • 442999791@qq.com 2024-06-04 回复

    写的不错

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注