halcon模板匹配和rake直线测量结合

这里用的模板匹配是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)


无论图片怎么跑偏,都可以找到直线。

在这里插入图片描述
在这里插入图片描述

记得把上面三个函数都替换成改动后的程序就可以了

有不会的可以在下面留言,有指教的也可以留言,我学习一下。

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在 Qt 中使用 Halcon 进行模板匹配测量可以通过以下步骤实现: 1. 在 Qt 中创建一个 Halcon 的窗口,用于显示图像和测量结果。 2. 加载要匹配模板图像和待匹配的目标图像。 3. 定义模板匹配的参数,如匹配算法和匹配区域等。 4. 调用 Halcon模板匹配函数,对待匹配的目标图像进行匹配,并得到匹配结果。 5. 根据匹配结果,计算出目标物体的测量值,如位置、角度、长度等。 6. 将测量结果显示在 Halcon 窗口中。 以下是一个简单的示例代码,演示了如何在 Qt 中使用 Halcon 进行模板匹配测量: ```c++ // 加载模板图像和目标图像 HImage tplImg("template.jpg"); HImage tgtImg("target.jpg"); // 创建 Halcon 窗口 HTuple winId; QHBoxLayout *layout = new QHBoxLayout(); HalconQtWidget *halconWidget = new HalconQtWidget(this); layout->addWidget(halconWidget); setLayout(layout); halconWidget->getHalconWidget()->GetWindowHandle(&winId); // 显示图像 disp_image(tgtImg, winId); // 定义模板匹配参数 HTuple hvMetric = "use_polarity"; // 使用极性信息 HTuple hvSubPixel = "none"; // 不使用亚像素精度 HTuple hvNumMatches = 1; // 只找一个匹配 HTuple hvGreediness = 0.5; // 匹配贪婪度 HTuple hvRow1 = 0, hvCol1 = 0, hvRow2, hvCol2; get_image_size(tplImg, &hvRow2, &hvCol2); // 匹配区域为整个模板图像 // 进行模板匹配 HTuple hvRow, hvCol, hvScore; find_template(tgtImg, tplImg, hvMetric, hvSubPixel, hvNumMatches, hvGreediness, &hvRow, &hvCol, &hvScore); // 计算测量结果 HTuple hvX, hvY, hvAngle, hvScale, hvScoreMax; vector_to_tuple(hvRow[0], &hvY); vector_to_tuple(hvCol[0], &hvX); tuple_max(hvScore, &hvScoreMax); tuple_length(hvScore, &hvNumMatches); if (hvNumMatches > 0) { vector_to_tuple(hvScore[0], &hvScoreMax); hvScoreMax *= 100; hvRow1 = hvY - hvRow2 / 2; hvCol1 = hvX - hvCol2 / 2; hvAngle = 0; hvScale = 1; } // 显示测量结果 set_color("green"); disp_message(winId, "Score: " + tuple_string(hvScoreMax), "window", 20, 20, "false"); disp_rectangle1(winId, hvRow1, hvCol1, hvRow1 + hvRow2, hvCol1 + hvCol2); ``` 这只是一个简单的示例,实际应用中需要根据具体需求进行更详细的参数设置和测量结果计算。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值