9点标定

2D视觉定位引导系列 1 图解9点标定及仿真

相机标定是视觉引导的第一个课,此课不过关,后面难以为继,出了问题可能都不好找。我当初这块也是疑惑了很久,
经过理论和实验算是总结了一点小经验。关于标定这块没有想好如何规划,先想到哪里写哪里,后面在慢慢整理。视觉定位太
需要实践了,个人感觉理论就是那些初中知识,但是要想完全用好,需要用丰富的现场实验经验。
本系列标定文章大概覆盖以下几点内容

1.9点标定
2.12 点标定
3.坐标归一化
4.海康VM 单点标定原理和测试
5.相机静止运动标定的区别
6.相机轴标定

为了更生动描述9/12点标定,也为了大家能更容易理解坐标系转换关系,只引入机械坐标系和相机坐标系,其他的坐标系就不提了,免得大家混。
特意通过Halcon写了一段模拟机械手运动进行标定的程序。先简单介绍下这个模拟程序。下图就是模拟的一个简单使用场景,XYZθ轴,上相机固定。
可以想象一下吸盘上吸玻璃片,玻璃片上有容易定位识别的边或者线。相机通过识别边线的交点来作为标定的特征点
分几步将机构做了简化示意图

 

 

 

1.机械坐标系 在Halcon中定义了机械坐标系 10000*10000,原点位于左上角,为了方便计算,原点往下为X轴,原点往右边为Y轴。

             

 

2.XYZθ 模组,只留了末端法兰盘和其连接的治具。以下图简化XYZθ模组

 

     3.相机  蓝色框表示相机视野 2000*2000 像素。像素坐标尺寸和机械坐标尺寸是1:1,且相机视野的2个轴与机械坐标对齐,现实世界很难做倒,

这里只是模拟仿真,便于计算和理解。这样只要计算下图小圆圈的中心坐标,减去相机视野左角坐标 就可以得出像素坐标。

在此之前我们不妨思考一下如下问题
1.9点标定的意义是什么,为什么要进行9点标定
2.12点标定的意义是什么,为什么要进行12点标定。12点标定 放到下篇文章再讲
对于9点标定 应该很好理解,将相机坐标系映射到机械坐标系,这样像素坐标就可以转换为机械坐标,将像素的偏移数据转换为机械坐标的偏移 引导机械补偿偏移。
如果需要补偿旋转偏移基本的都需要12点标定。12点标定就比9点标定多了一个3点旋转标定
关于机械坐标的疑问
有一个疑问,就是XYZθ 设备读取的机械坐标到底表示的是设备那个点的坐标,这个容易引起困惑。其实这个容易理解,这个坐标可以表示Z轴上任意一点的坐标。
一旦确定这个坐标表示的是Z轴上的那个点,机械坐标系就被锚定了,在这之前 这个机械坐标系像是飘忽不定一样。对于有旋转轴的设备,此机械坐标一般表示的是末端法兰盘中心的坐标。
对于Scara 水平多关节机器人 对应的就是第四轴 中心点,对于普通6轴机器人就是末端旋转轴的中心。但是对于没有旋转轴的设备,标定时候的机械坐标表示哪个机械位置似乎显的不
太重要,应为绝大多数情况下计算的都是相对偏移量。绝对位置也可以通过示教位置加上相对偏移来获取。
标定的流程为,机构带着标定物,移动9次,相机在标定物上方拍9次照,这样共得到9组像素和机械坐标数据。联立方程组可解出像素坐标到机械坐标的转移矩阵。下面视频演示9点标定流程

仿真流程看如下代码 基于Halcon

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

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


*定义相机视野长宽
camstartrow:=5000
camstartcol:=5000
cam_width:=1000
cam_degre:=0
*定义相机左上角坐标,后面计算像素坐标用
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:=[ 0, 1, 1, 0, -1, -1, -1, 0, 1 ]
move9Col:=[ 0, 0, 1, 1, 1, 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)
     
    *模拟移动机械臂
    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
disp_cross(WindowHandle, row_pixel, col_pixel, 10,0)

*上面模拟九点标定以后 计算标定数据,HomMat2D 就是9点标定的转移矩阵
vector_to_hom_mat2d(row_pixel, col_pixel, xwolrd, yworld, HomMat2D)

*验算Qx1 Qy1 与 xwolrd,yworld 可以说完全一致
affine_trans_point_2d(HomMat2D, row_pixel, col_pixel, Qx1, Qy1)

*模拟X Y 移动(800,800)
hom_mat2d_identity(HomMat2DIdentity)
hom_mat2d_translate(HomMat2DIdentity, 800, 800, HomMat2DTranslate)
affine_trans_region(Tool_ARM, RegionAffineTrans, HomMat2DTranslate, 'nearest_neighbor')
dev_set_color ('green')
dev_display(RegionAffineTrans)

*取像素坐标
area_center(RegionAffineTrans, Area, Row, Column)
px:=Row[2]-cam_origin_row
py:=Column[2]-cam_origin_col

*通过像素坐标计算机械坐标
affine_trans_point_2d(HomMat2D,px,py,qx,qy)
dev_set_color ('green')
disp_cross(WindowHandle, px, px, 80, 0)
dev_set_color ('red')
disp_cross(WindowHandle, qx, qy, 80, 0)

 

上面代码 模拟了9点标定的过程。机械坐标表示的是法兰盘中心坐标也就是图中那个大圈圆心坐标。
代码最后模拟XY 分别移动(800,800),来验证标定是否正确。蓝色表示移动后的位置。(qx,qy)(3800,5800) 在下图用红色十字标出,在大圆中心,符合预期。
9点标定
此处有一个疑问:像素空间中的一个点的像素坐标,经过上面标定数据转换后,得到坐标是否能对应此像素坐标在机械坐标空间的真实坐标。很显然,不一定,这取决与标定时 机械坐标指的是哪机械点的坐标。
如上图 点2的像素坐标(px,py) (1799.5,1799.5),  经过标定转化后的坐标 应该为  (5800,5800),但是实际情况是(3800,5800),偏移到了点1。理论和实际存在(2000,0)的固定偏移。   为何会出现这种情况,
这种偏移是在标定时引入的。因为标定时像素对应机械坐标就是大圆圈的坐标,如果取的时小圆圈的坐标就不存在偏移。实际场景也是很难取得像素点对应的真实机械坐标。对于没有角度偏移的使用场景,这种
固定偏差的存在不影响我们引导定位。因为应为绝大多数情况下计算的都是相对偏移量。绝对位置也可以通过示教位置加上相对偏移来得到。
系列文章
疑问留言 或者 添加下面2种方式 交流 加群(277957302)

暂无评论

发表回复

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