勇哥的这个项目是整盘物料机器人视觉取料。
由于该项目有两个相机,一个是整盘入料相机,用于判断物料有无和粗定位。
另外还有一个下相机,用于精定位后物料入转盘机。
本篇说的就是整盘入料相机的粗定位算法。
这里勇哥使用的是halcon的形态学算法,相比找边的方式来说,其意义是速度快,能满足视觉一键换型的需要。
read_image(backImg, 'C:/Users/hackpig/Desktop/蓝牙撕膜机黑料盘问题/20191106_141224_PS_1_OK.tif.bmp') read_image(inputImg, 'C:/Users/hackpig/Desktop/蓝牙撕膜机黑料盘问题/20191106_141155_PS_1_OK.tif.bmp') get_image_size(inputImg, Width, Height) gen_empty_obj(resultImg) gen_empty_obj(resultImg2) abs_diff_image(inputImg, backImg, ImageAbsDiff,2) threshold (ImageAbsDiff, Regions, 211, 255) fill_up(Regions, RegionFillUp) connection(RegionFillUp, ConnectedRegions) select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 5000, 99999999) count_obj(SelectedRegions, Number) areaAry:=[] area_center(SelectedRegions, Area, Row, Column) tuple_max(Area, Max) gen_empty_obj(EmptyObject) for Index := 0 to Number-1 by 1 if(Area[Index]>(Max*0.6)) select_obj(SelectedRegions, ObjectSelected, Index+1) concat_obj(EmptyObject, ObjectSelected, EmptyObject) endif endfor dev_set_draw('margin') orientation_region(EmptyObject, Phi) inner_rectangle1(EmptyObject, Row1, Column1, Row2, Column2) gen_rectangle1(Rectangle, Row1, Column1, Row2, Column2) area_center(Rectangle, Area1, Row3, Column3) hom_mat2d_identity(HomMat2DIdentity) Number1:=|Row1| len1:=[] len2:=[] for Index1 := 0 to Number1-1 by 1 len1[Index1]:=(Row2[Index1]-Row1[Index1])/2 len2[Index1]:=(Column2[Index1]-Column1[Index1])/2 endfor for Index1 := 0 to Number1-1 by 1 hom_mat2d_rotate(HomMat2DIdentity, Phi[Index1], Row3[Index1], Column3[Index1], HomMat2DRotate1) endfor for Index1 := 0 to Number1-1 by 1 affine_trans_point_2d(HomMat2DRotate1, Row1[Index1], Column1[Index1], qx,qy) Row1[Index1]:=qx Column1[Index1]:=qy affine_trans_point_2d(HomMat2DRotate1, Row2[Index1], Column2[Index1], qx1,qy1) Row2[Index1]:=qx1 Column2[Index1]:=qy1 endfor gen_rectangle2(Rectangle1,Row3, Column3,Phi, len1, len2) disp_obj(backImg,200000) disp_obj(EmptyObject,200000) disp_obj(Rectangle1, 200000) tuple_cos (Phi, Cos) tuple_sin (Phi, Sin) i:=0 for i := 0 to Number1-1 by 1 a:= -len1[i]*Cos[i] - len2[i]*Sin[i] b := -len1[i]*Sin[i] + len2[i]*Cos[i] gen_cross_contour_xld(Cross1, Row3[i]-b, Column3[i]+a, 6, Phi[i]) c := len1[i]*Cos[i] - len2[i]*Sin[i] d := len1[i]*Sin[i] + len2[i]*Cos[i] gen_cross_contour_xld(Cross2, Row3[i]-d, Column3[i]+c, 6, Phi[i]) e:= len1[i]*Cos[i] + len2[i]*Sin[i] f := len1[i]*Sin[i] - len2[i]*Cos[i] gen_cross_contour_xld(Cross3, Row3[i]-f, Column3[i]+e, 6, Phi[i]) g := -len1[i]*Cos[i] + len2[i]*Sin[i] h := -len1[i]*Sin[i] - len2[i]*Cos[i] gen_cross_contour_xld(Cross4, Row3[i]-h, Column3[i]+g, 6, Phi[i]) projection_pl(Row3[i],Column3[i],Row3[i]-d, Column3[i]+c,Row3[i]-f, Column3[i]+e,RowProj, ColProj) disp_arrow(200000, Row3[i], Column3[i], RowProj, ColProj, 4) endfor *右 * disp_line(200000, Row3[i]-b, Column3[i]+a, Row3[i]-d, Column3[i]+c) *底 * disp_line(200000, Row3[i]-d, Column3[i]+c,Row3[i]-f, Column3[i]+e) *左 * disp_line(200000, Row3[i]-f, Column3[i]+e, Row3[i]-h, Column3[i]+g) *顶 * disp_line(200000, Row3[i]-h, Column3[i]+g, Row3[i]-b, Column3[i]+a)
勇哥解释一下代码:
(1)abs_diff_image算子运算结果见ImageAbsDiff。我们把有料料盘减去空料盘做差异化处理,目的是让背景更“干净一些”。
(backImg)
(inputImg)
(ImageAbsDiff)
(2)按面积筛选出电池的本体
(SelectedRegions)
(EmptyObject)
(4)算子orientation_region是用于确定region的方向,这里我们用EmptyObject来确定方向。
算子inner_rectangle1用于确定EmptyObject的内接矩形。
orientation_region(EmptyObject, Phi) inner_rectangle1(EmptyObject, Row1, Column1, Row2, Column2) gen_rectangle1(Rectangle, Row1, Column1, Row2, Column2)
然后把矩形Rectangle旋转,角度为Phi,最后画出箭头。
(内接矩形)
(内接矩形通过旋转矩阵后的效果)
(最后画出箭头方向)
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!