一、简介
找边的方式有很多种halcon 里面本来就有找边的算子,然后在拟合成直线或者其他的几何形状,例如edges_sub_pix算子,如下
但是如果要找上面的这条边问题就不好找了,当然还是有办法的,可以先做一些预处理,然后再找用上面的那个算子,但是这样做的话稳定性如何?在现场做出的实验结果是并不好(就这个项目来说),算法的稳定性是决定一个项目的决定因素,而且面对的是各种复杂多样的面料,这种问题就很难解决了,所以今天提出的是找边的方法有两种,第一就是采用二维测量的卡尺来找,第二就是采用灰度投影的方法来找。
每个算法都有自己的局限性,那么面对什么样的情况,兼容性稳定性最强才是我们做最重要的事情
二、算法介绍
为了考虑到兼容性,所以我们将卡尺测量和灰度投影写到一个方法里面用参数来控制调用,首先出入的参数是imge ,param(控制参数),输出: contour,row,col,edge等,具体思路如下
1、从控制参数中获得gen_rectangle2的参数,就是把那条边的大概区域框出来
2、由于reduce_domain()中的图像处理的速度是比较慢的,为了加快CT,所以会将图像从原来的图像中crop_domain() 中抠出来,但是这样的话像素的坐标系就转换了,就需要做坐标转换,如下
reduce_domain (Image, Rectangle, ImageReduced)
crop_domain (ImageReduced, ImagePart)
get_image_size (ImagePart, Width, Height)
area_center (ImagePart, Area1, Row1, Column1)
gen_cross_contour_xld (Cross, Row1, Column1, 6, 0.785398)
* 获得坐标转换矩阵
vector_angle_to_rigid (Row1, Column1, 0,round(Params[0]), round(Params[1]), 0, HomMat2D)
3、图像的预处理
图像自乘 mult_image
affine_trans_image (Image, ImageAffineTrans, HomMat2D, 'constant', 'true')
gray_opening_rect
gray_closing_rect
4、将图像进行卡尺找边
get_image_size (ImagePart, Width, Height)
create_metrology_model (MetrologyHandle)
set_metrology_model_image_size (MetrologyHandle, Width, Height)
gen_cross_contour_xld (Cross5, LineRowStart_Measure_01_0, LineColumnStart_Measure_01_0, 60, 0.785398)
gen_cross_contour_xld (Cross6, LineRowEnd_Measure_01_0, LineColumnEnd_Measure_01_0, 60, 0.785398)
add_metrology_object_line_measure (MetrologyHandle, LineRowStart_Measure_01_0, LineColumnStart_Measure_01_0, LineRowEnd_Measure_01_0, LineColumnEnd_Measure_01_0, MeasureLength1, RoiWidthLen/2.0, Params[18], Params[19],\
[ 'num_measures','measure_transition','measure_select'], [round(Params[17]),Params[5], Params[6]], Index1)
set_metrology_object_param (MetrologyHandle, 'all', 'min_score', 0.1)
* Create region of interest for the alignment
apply_metrology_model (ImagePart, MetrologyHandle)
get_metrology_object_result (MetrologyHandle, 'all', 'all', 'result_type', 'all_param', LineParameter)
get_metrology_object_measures (MeasuresContour, MetrologyHandle, 'all', 'all', rows, cols)
affine_trans_contour_xld (MeasuresContour, MeasuresContour, HomMat2D)
SetDictObject (MeasuresContour, IntermediateObjects, '卡尺ROI')
clear_metrology_model (MetrologyHandle)
gen_cross_contour_xld (Cross1, rows, cols, 10, 0.78)
affine_trans_contour_xld (Cross1, ContoursAffineTrans2, HomMat2D)
SetDictObject (ContoursAffineTrans2, IntermediateObjects, '原始边缘点')
5、帅选出合格点,然后将这些拟合得到的图像开始拟合直线
gen_contour_polygon_xld (Contour, [RowBegin2, RowEnd2 ], [ ColBegin2, ColEnd2])
affine_trans_contour_xld (Contour, ContoursAffineTrans2, HomMat2D)
concat_obj (Contours, ContoursAffineTrans2, Contours)
4.1、使用投影来找边
gen_empty_obj (EmptyObject)
stdRow := []
stdCol := []
* 将一张图片分成两个
for Index1 := 0 to 1 by 1
if(Params[4] == 'H')
row := Height/2
col := [Width/4,Width*3/4][Index1]
Phi := 0
len1 := Width/4
len2 := Height/2
else
row := [Height/4,Height*3/4][Index1]
col := Width/2
Phi := rad(90)
len1 := Height/4
len2 := Width/2
endif
gen_rectangle2 (Rectangle2, row, col, Phi, len1, len2)
reduce_domain (ImagePart, Rectangle2, ImageReduced2)
gray_projections (ImageReduced2, ImageReduced2, 'simple', HorProjection, VertProjection)
if(Params[4] == 'H')
data := HorProjection
else
data := VertProjection
endif
create_funct_1d_array (data, Function)
smooth_funct_1d_mean (Function, 1, 1, SmoothedFunction)
derivate_funct_1d (SmoothedFunction, 'first', Derivative)
local_min_max_funct_1d (Derivative, 'plateaus_center', 'false', Min, Max)
funct_1d_to_pairs (Derivative, XValues, YValues)
smallest_rectangle1 (Rectangle2, Row11, Column11, Row21, Column21)
if(Params[4] == 'H')
if(Index1==0)
gen_contour_polygon_xld (Contour2, XValues, YValues)
else
gen_contour_polygon_xld (Contour2, XValues, YValues+Column11)
endif
gen_contour_polygon_xld (Contour3, [Row11-10,Row21+10], [Column11,Column11])
else
if(Index1==0)
gen_contour_polygon_xld (Contour2, YValues, XValues)
else
gen_contour_polygon_xld (Contour2, YValues+Row11, XValues)
endif
gen_contour_polygon_xld (Contour3, [Row11,Row11], [Column11-10,Column21+10])
endif
gen_empty_obj (Contourprojection)
concat_obj (Contour3, Contour2, Contourprojection)
affine_trans_contour_xld (Contourprojection, ContoursAffineTrans, HomMat2D)
SetDictObject (ContoursAffineTrans, IntermediateObjects, '灰度投影曲线'+(Index1+1))
*开始选边
if(Params[5] == 'positive')
extreme := Max
else
extreme := Min
endif
if(Params[6] == 'first')
sIndex := 0
eIndex := |extreme|-1
step1 := 1
else
sIndex := |extreme|-1
eIndex := 0
step1 := -1
endif
LineIndex := 0
for Index := sIndex to eIndex by step1
if(Params[5] == 'positive')
if(YValues[extreme [Index]] > Params[16])
LineIndex := extreme [Index]
break
endif
else
if(YValues[extreme [Index]] < -Params[16])
LineIndex := extreme [Index]
break
endif
endif
endfor
if(LineIndex == 0)
failFlag := 1
break
endif
if(Params[4] == 'H')
stdRow := [stdRow,LineIndex]
stdCol := [stdCol,col]
else
stdRow := [stdRow,row]
stdCol := [stdCol,LineIndex]
endif
gen_cross_contour_xld (Cross4, stdRow, stdCol, 20, 0)
concat_obj (EmptyObject, Cross4, EmptyObject)
endfor
rows := []
cols := []
count := Params[17]*1.0
if(failFlag==1)
if(Params[4] == 'H')
Row1 := (Height-1)/2
Col1 := 0
Row2 := (Height-1)/2
Col2 := Width-1
len1 := Height/2
len2 := (Width-1)/count/2
else
Row2 := 0
Col2 := (Width-1)/2
Row1 := (Height-1)
Col1 := (Width-1)/2
len1 := Width/2
len2 := (Height-1)/count/2
endif
create_metrology_model (MetrologyHandle)
set_metrology_model_image_size (MetrologyHandle, Width, Height)
add_metrology_object_generic (MetrologyHandle, 'line', [Row1,Col1,Row2,Col2], len1, len2, Params[18], Params[19], [], [], temp)
set_metrology_object_param (MetrologyHandle, 'all', ['measure_transition','num_measures','measure_select'], [Params[5], round(Params[17]), Params[6]])
apply_metrology_model (ImagePart, MetrologyHandle)
get_metrology_object_measures (Contoursrect, MetrologyHandle, 'all', 'all', rows, cols)
clear_metrology_model (MetrologyHandle)