这里用的模板匹配是halcon形状模板匹配,直线测量就是鸟叔的rake算子里面的三个,经过了一些改动,因为完整的rake算子里面主要含三个算子,我要加入模板匹配的功能,所以经过了改动,主要是要把模板和检测图生成的转置矩阵要应用到函数里面
我贴在下面:
read_image(Image, '矩形.png')
dev_get_window (WindowHandle)
dev_set_color ('dark olive green')
* 1. 创建ROI draw_rake函数
Elements:=20
DetectHeight:=50
DetectWidth:=5
draw_rake (Regions, WindowHandle, Elements, DetectHeight, DetectWidth, Row1, Column1, Row2, Column2)
stop()
* 2. 边缘测量 rake函数
Sigma:=8
Threshold:=30
Transition:='all'
Select:='all'
rake (Image, Regions1, Elements, DetectHeight, DetectWidth, Sigma, Threshold, Transition, Select, Row1, Column1, Row2, Column2, ResultRow, ResultColumn)
stop()
* 3. 拟合直线 pts_to_best_line函数
ActiveNum:=5
pts_to_best_line (Line, ResultRow, ResultColumn, ActiveNum, Row1, Column1, Row2, Column2)
angle_lx(Row1, Column1, Row2, Column2, Angle)
degree:=deg(Angle)
dev_set_color ('blue')
dev_set_line_width (3)
dev_display (Line)
这三个完整函数可以自己去网上搜,我仔细看了后有重复,就进行了更改。
但还是保留了原函数名,只是内容改了,参数也改了,如下
draw_rake (RegionLines1, WindowHandle, Elements, DetectHeight, DetectWidth, Row_1, Column_1, Row_2, Column_2)改成了下面的代码
* 提示
disp_message (WindowHandle, '点击鼠标左键画一条直线,点击右键确认', 'window', 12, 12, 'red', 'false')
* 产生一个空显示对象,用于显示
gen_empty_obj (Regions)
* 画矢量检测直线
draw_line (WindowHandle, Row1, Column1, Row2, Column2)
* 产生直线xld
gen_contour_polygon_xld (RegionLines, [Row1,Row2], [Column1,Column2])
rake (Image, Regions, Elements, DetectHeight, DetectWidth, Sigma, Threshold, Transition, Select, RowTrans1, ColTrans1, RowTrans2, ColTrans2, ResultRow, ResultColumn)
改成了下面的代码:
SelectOut := Select
TransitionOut := Transition
* 获取图像尺寸
get_image_size (Image, Width, Height)
* 产生一个空显示对象,用于显示
gen_empty_obj (Regions)
* 初始化边缘坐标数组
ResultRow := []
ResultColumn := []
* 产生直线xld
gen_contour_polygon_xld (RegionLines, [Row1,Row2], [Column1,Column2])
* 存储到显示对象
concat_obj (Regions, RegionLines, Regions)
* 计算直线与x轴的夹角,逆时针方向为正向
angle_lx (Row1, Column1, Row2, Column2, ATan)
*
* 边缘检测方向垂直由于检测直线:直线方向正向旋转90°为边缘检测方向
ATan := ATan+rad(90)
*
* 根据检测直线按顺序产生测量区域矩形,并存储到显示对象
for i := 1 to Elements by 1
* 如果只有一个测量矩形,作为卡尺工具,宽度为检测直线的长度
if (Elements == 1)
RowC := (Row1+Row2)*0.5
ColC := (Column1+Column2)*0.5
* 判断是否超出图像,超出不检测边缘
if (RowC>Height-1 or RowC<0 or ColC>Width-1 or ColC<0)
continue
endif
distance_pp (Row1, Column1, Row2, Column2, Distance)
DetectWidth := Distance
gen_rectangle2_contour_xld (Rectangle, RowC, ColC, ATan, DetectHeight/2, Distance/2)
else
* 如果有多个测量矩形,产生该测量矩形xld
RowC := Row1+(((Row2-Row1)*(i-1))/(Elements-1))
ColC := Column1+(Column2-Column1)*(i-1)/(Elements-1)
* 判断是否超出图像,超出不检测边缘
if (RowC>Height-1 or RowC<0 or ColC>Width-1 or ColC<0)
continue
endif
gen_rectangle2_contour_xld (Rectangle, RowC, ColC, ATan, DetectHeight/2, DetectWidth/2)
endif
*
* 把测量矩形xld存储到显示对象
concat_obj (Regions, Rectangle, Regions)
if (i==1)
* 在第一个测量矩形绘制一个箭头xld,用于指示边缘检测方向
RowL2 := RowC+DetectHeight/2*sin(-ATan)
RowL1 := RowC-DetectHeight/2*sin(-ATan)
ColL2 := ColC+DetectHeight/2*cos(-ATan)
ColL1 := ColC-DetectHeight/2*cos(-ATan)
gen_arrow_contour_xld (Arrow1, RowL1, ColL1, RowL2, ColL2, 25, 25)
* 把xld存储到显示对象
concat_obj (Regions, Arrow1, Regions)
endif
* 产生测量对象句柄
gen_measure_rectangle2 (RowC, ColC, ATan, DetectHeight/2, DetectWidth/2, Width, Height, 'nearest_neighbor', MeasureHandle)
*
* 设置极性
if (TransitionOut=='negative')
TransitionOut := 'negative'
elseif (TransitionOut=='positive')
TransitionOut := 'positive'
else
TransitionOut := 'all'
endif
* 设置边缘位置。最强点是从所有边缘中选择幅度绝对值对大点,需要设置为'all'
if (SelectOut=='first')
SelectOut := 'first'
elseif (SelectOut=='last')
SelectOut := 'last'
else
SelectOut := 'all'
endif
* 检测边缘
measure_pos (Image, MeasureHandle, Sigma, Threshold, TransitionOut, SelectOut, RowEdge, ColEdge, Amplitude, Distance)
* 清除测量对象句柄
close_measure (MeasureHandle)
*
* 临时变量初始化
* 保存找到指定边缘的坐标
tRow := 0
tCol := 0
* 保存边缘的幅度绝对值
t := 0
* 找到的边缘必须至少为1个
tuple_length (RowEdge, Number)
if (Number<1)
continue
endif
*
* 有多个边缘时,选择幅度绝对之后最大的边缘
for j := 0 to Number-1 by 1
if (abs(Amplitude[j])>t)
tRow := RowEdge[j]
tCol := ColEdge[j]
t := abs(Amplitude)
endif
endfor
* 把找到的边缘保存在输出数组
if (t>0)
ResultRow := [ResultRow,tRow]
ResultColumn := [ResultColumn,tCol]
endif
endfor
*
return ()
pts_to_best_line (Line, ResultRow, ResultColumn, ActiveNum, Row1, Column1, Row2, Column2)改成了下面的代码
* 初始化
Row1 := 0
Column1 := 0
Row2 := 0
Column2 := 0
* 产生一个空的直线对象,用于保存拟合后的直线
gen_empty_obj (Line)
* 计算边缘数量
tuple_length (Cols, Length)
* 当边缘数量不小于有效点数时进行拟合
if (Length>=ActiveNum and ActiveNum>1)
* halcon的拟合是基于xld的,需要把边缘连接成xld
gen_contour_polygon_xld (Contour, Rows, Cols)
* 拟合直线。使用的算法是'tukey',其他算法参考fit_line_contour_xld的描述
fit_line_contour_xld (Contour, 'tukey', -1, 0, 5, 2, Row1, Column1, Row2, Column2, Nr, Nc, Dist)
* 判断拟合结果是否有效:如果拟合成功,数组中元素的数量大于0
tuple_length (Dist, Length1)
if (Length1 < 1)
return ()
endif
* 根据拟合结果,产生直线xld
gen_contour_polygon_xld (Line, [Row1,Row2], [Column1,Column2])
endif
return ()
以上就是改动的代码,但没有加入模板匹配,下面是加入了模板匹配的代码,用的图片就是halcon自带的
list_image_files ('halogen_bulb', [], 'recursive', ImageFiles)
tuple_regexp_select (ImageFiles, 'good', ImageFilesGood)
read_image (Image, ImageFiles[0])
dev_update_off ()
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, 640, 640, WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_color ('lime green')
dev_set_line_width (3)
*
* Create the shape model
gen_rectangle1 (Rectangle, 400, 300, 900, 1000)
reduce_domain (Image, Rectangle, ImageReduced)
create_shape_model (ImageReduced, 'auto', -0.39, 0.78, 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID)
area_center (Rectangle, Area,Row_m, Column_m)
dev_clear_window ()
dev_display (Image)
dev_display_shape_matching_results (ModelID, 'lime green',Row_m, Column_m, 0.0, 1.0, 1.0, 0)
disp_message (WindowHandle, 'The model edges used for the matching', 'window', 12, 12, 'lime green', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
*gen_region_line(RegionLines, 146, 1029, 571, 991)
* 1. 创建ROI draw_rake函数(以及显示测量的矩阵)
Elements:=20
DetectHeight:=80
DetectWidth:=5
draw_rake (RegionLines1, WindowHandle, Elements, DetectHeight, DetectWidth, Row_1, Column_1, Row_2, Column_2)
dev_set_color ('red')
*
for Index := 0 to |ImageFiles| - 1 by 1
if (regexp_match(ImageFiles[Index],'none') == 'none')
continue
endif
read_image (Image, ImageFiles[Index])
dev_display (Image)
count_seconds (Seconds1)
find_shape_model (Image, ModelID, -0.39, 0.78, 0.7, 1, 0.5, 'least_squares', [0,-1], 0.9, Row, Column, Angle, Score)
vector_angle_to_rigid(Row_m, Column_m, 0, Row, Column, Angle, HomMat2D)
affine_trans_pixel(HomMat2D, Row_1, Column_1, RowTrans1, ColTrans1)
affine_trans_pixel(HomMat2D, Row_2, Column_2, RowTrans2, ColTrans2)
count_seconds (Seconds2)
dev_display_shape_matching_results (ModelID, 'lime green', Row, Column, Angle, 1.0, 1.0, 0)
dev_set_color ('red')
disp_message (WindowHandle, |Row| + ' Match found in ' + ((Seconds2 - Seconds1) * 1000.0)$'.1f' + ' ms', 'window', 12, 12, 'lime green', 'false')
* 2. 边缘测量 rake函数
Sigma:=8
Threshold:=30
Transition:='all'
Select:='all'
rake (Image, Regions, Elements, DetectHeight, DetectWidth, Sigma, Threshold, Transition, Select, RowTrans1, ColTrans1, RowTrans2, ColTrans2, ResultRow, ResultColumn)
dev_display(Regions)
* 3. 拟合直线 pts_to_best_line函数
ActiveNum:=5
pts_to_best_line (Line, ResultRow, ResultColumn, ActiveNum, Row1, Column1, Row2, Column2)
angle_lx( Row1, Column1, Row2, Column2, Angle)
degree:=deg(Angle)
dev_set_color ('blue')
dev_set_line_width (3)
dev_display (Line)
stop()
endfor
clear_shape_model (ModelID)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/dadb137c164f4047a853088fd07c5cb7.png#pic_center)
无论图片怎么跑偏,都可以找到直线。
记得把上面三个函数都替换成改动后的程序就可以了
有不会的可以在下面留言,有指教的也可以留言,我学习一下。