关于工件坐标系和图像坐标系的关系以及如何仿射
有时在项目中需要在工件上建立一个工件坐标系来描述需要检测工件的位置,该坐标系通常是由线和点组成,其中线描述X轴,点向该线做垂线作为Y轴,此处的X轴和Y轴即为数学上的X轴和Y轴的关系。通过给出需检测工件的最小外接矩形的五个参数,即中心行坐标,中心列坐标,角度,半长以及半宽(工件坐标),根据相机的精度即可计算出各个工件的像素坐标。然后对拍取的每张图进行定位工件所在区域,再进行抠图和检测,当然,这一切都是建立在每张图中的工件坐标系和工件是一个相对固定的关系,或者他们共同放大或者缩小(即相机的精度改变)。那么需要如何去处理呢
通过将工件坐标转为了图像坐标后,可以将整个工件坐标系的原点先平移到和图像坐标系的原点重合,再将工件坐标系旋转至如下位置:
图中X轴和Y轴构成的红色的为工件坐标系,C和R轴为图像坐标系,这时假设在原工件坐标系中的一个工件如图所示:
假设这个工件在原工件坐标系下的工件坐标为(-300,200,90°,350,250),精度为0.5pixel/mm那么现在将这个工件坐标系和工件坐标全部转换到图像坐标系下,原点不变,工件坐标变为(-400,-600,90°,700,500),不难理解,无论工件坐标系原来处于一个什么角度,工件在工件坐标系下是个什么位置,在将他们都转到图像坐标系下的时候,其实只要将原工件坐标(x,y)改为(-y,x)再乘上精度即可,半长和半宽也乘上精度,其他参数都不用改,即可完成转换。在完成转换后,通过gen_rectangle2算子先绘出这个工件最小外接矩形的位置。然后,在相机拍下一张图片时,先找到定义的工件坐标系的线和点,然后通过projection_pl算子求出线和点的垂足(R,C),通过angle_lx求出当前找到的线和X轴的夹角(注意抓到的线的起始点的顺序要和一开始仿射的工件坐标系的X轴方向一致)P,通过vector_angle_grid(0,0,0,R,C,P,hommat2d),其中0,0,0为前面图中已经完成转换的工件坐标系的图像坐标系下的原点坐标和角度,通过得到的仿射矩阵,对之前绘制的工件的最小外接矩形进行仿射即可得到当前图中目标工件的最小外接矩形的区域。下面通过Halcon程序验证:
为了方便,自己制作了一张工件坐标的图片,省去了乘上精度这一步骤:
该白色工件在工件坐标系下的位置为(-230.5,131.36,90,60,30)
此图为将上面一张图像进行平移和旋转得到的新图,可以理解为相机拍的一张新图,通过如下代码进行仿射:
1 read_image (Image, 'C:/Users/Niqiao/Desktop/test/Image.tif') 2 X := -230.5 3 Y := 131.36 4 Lenth1 := 60 5 Lenth2 := 30 6 Phi := 90 7 8 LineStartCoordinateRow := 342 9 LineStartCoordinateCol := 61 10 LineEndCoordinateRow := 459 11 LineEndCoordinateCol := 229 12 ProjectPointCoordinateRow := 490 13 ProjectPointCoordinateCol := 273 14 affine_coordinate_system (Image, RegionsAff, ImageReduced, LineStartCoordinateRow, LineStartCoordinateCol, LineEndCoordinateRow, LineEndCoordinateCol, ProjectPointCoordinateRow, ProjectPointCoordinateCol, X, Y, Lenth1, Lenth2, rad(Phi), Exception) 15 16 17 18 xArr := [] 19 x := 2 20 y := 3 21 tuple_concat (xArr, x, Concat) 22 tuple_concat (Concat, y, Concat)
仿射结果如下:
可以看到,工件区域被正确仿射,出现的一点点误差是因为图形是通过gen_image_const和paint_region创建的,垂足则是通过在图像中放大近似查找的,所以造成了几个像素的误差,但是不影响这个方法的可行性。