勇哥的这个项目是整盘物料机器人视觉取料。
由于该项目有两个相机,一个是整盘入料相机,用于判断物料有无和粗定位。
另外还有一个下相机,用于精定位后物料入转盘机。
本篇说的就是整盘入料相机的粗定位算法。
这里勇哥使用的是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
版权声明:本文为博主原创文章,转载请附上博文链接!