Halcon - 找到边缘位置,画线和线交点

Halcon - find edge position, draw line and lineintersection

我从头开始使用 Halcon,但无法解决问题。我有一个对象,需要从这个对象中提取边缘,沿着边界画一条线,并在线的交点上画一个点。

我已经尝试过阈值处理、边缘、颜色边缘,但它会在所有地方提取边界,除了我需要的那些之外..

这只是我正在做的一个测试,因为它与我稍后在实际项目中必须做的类似。但是两天没解决..

这是基础图像,以及想要的结果图像:

我目前拥有的:

open_framegrabber ('GigEVision', 0, 0, 0, 0, 0, 0, 'default', -1, 'default', -1, 'false', 'default', 'S1204667', 0, -1, AcqHandle)
set_framegrabber_param (AcqHandle, 'Gain', 1.0)
set_framegrabber_param (AcqHandle, 'ExposureTime', 20000)
set_framegrabber_param (AcqHandle, 'timerDuration', 1)
set_framegrabber_param (AcqHandle, 'BalanceWhiteAuto', 'Off')
set_framegrabber_param (AcqHandle, 'BalanceRatioSelector', 'Red')
set_framegrabber_param (AcqHandle, 'BalanceRatio', 1.22)
set_framegrabber_param (AcqHandle, 'BalanceRatioSelector', 'Green')
set_framegrabber_param (AcqHandle, 'BalanceRatio', 1.00)
set_framegrabber_param (AcqHandle, 'BalanceRatioSelector', 'Blue')
set_framegrabber_param (AcqHandle, 'BalanceRatio', 1.95)


grab_image (Image, AcqHandle)

threshold (Image, Region, 0, 128)
expand_region (Region, Region, RegionExpanded, 15, 'image')

close_framegrabber (AcqHandle)

Halcon 有很多方法可以根据需要来完成。检测线的最常用技术之一是使用霍夫变换。我附上了一个小的 HDevelop 脚本,展示了如何获得图像中两条线的交点。其他的也可以用同样的原理。

Halcon 中最重要的概念之一是区域。示例程序首先允许您通过在两条线的顶部绘制矩形来创建两个区域。下图中的区域是黑色的。在程序的第 8 行 (draw_rectangle2...),您需要在第一行周围绘制一个边界框。完成后右击。第 10 行(绘制矩形 2...)将要求您在第二行周围绘制一个边界框。完成后再次右键单击。

然后在第 13-16 行通过连接将这些区域组合在一起。在第 19 行 (reduce_domain) 中,图像的域被缩减为连接区域。你可以把它想象成一个面具。现在当我们搜索线条时,我们将只搜索我们创建区域的图像部分。 强调文字

read_image (Image, 'C:/Users/Jake/Documents/Stack Overflow/Halcon/Find Edge Position, 
Draw Line and Line Intersection/FMuX1.jpg')

get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_display(Image)

*Use the mouse to draw region 1 around first line. Right click when finished. 
draw_rectangle2(WindowHandle, Reg1Row, Reg1Column, Reg1Phi, Reg1Length1, Reg1Length2)
*Use the mouse to draw region 2 around second line. Right click when finished. 
draw_rectangle2(WindowHandle, Reg2Row, Reg2Column, Reg2Phi, Reg2Length1, Reg2Length2)

*Generate a single region to search for two lines
gen_rectangle2(Rectangle1, Reg1Row, Reg1Column, Reg1Phi, Reg1Length1, Reg1Length2)
gen_rectangle2(Rectangle2, Reg2Row, Reg2Column, Reg2Phi, Reg2Length1, Reg2Length2)
concat_obj(Rectangle1, Rectangle2, Regions)
union1(Regions, RegionUnion)

*Reduce the domain of the image to the region created in lines 13-16
reduce_domain(Image, RegionUnion, ImageReduced)

* Detect edges (amplitude) using the Sobel operator
sobel_amp (ImageReduced, EdgeAmplitude1, 'thin_sum_abs', 3)
dev_set_color ('red')
threshold (EdgeAmplitude1, Region1, 100, 255)
hough_lines (Region1, 4, 50, 5, 5, Line1Angle, Line1Dist)
dev_set_color ('blue')
* Store input lines described in HNF
gen_region_hline (LineRegions, Line1Angle, Line1Dist)

*Select Line1
select_obj(LineRegions, Line1, 1)
*Select Line2
select_obj(LineRegions, Line2, 2)

*Calculate and display intersection
intersection(Line1, Line2, Line1Line2Intersection)
area_center(Line1Line2Intersection, Line1Line2IntersectArea, Line1Line2IntersectRow, 
Line1Line2IntersectCol)
disp_circle (WindowHandle, Line1Line2IntersectRow, Line1Line2IntersectCol, 6)

基于最初的 poster 担心位置移动,我 posting 另一个更复杂的答案。对于这种情况,此策略可能不是最简单的,但它是适用于很多情况的通用策略。通常,此类问题的解决方法如下:

1) 对零件进行粗略定位。这通常涉及斑点检测或匹配策略(相关性、基于形状等)。此步骤的输出是描述对象位置(平移、方向)的转换。

2) 基于在步骤 1 中找到的位置,用于检测特征(线、孔等)的搜索区域被转换或更新到新位置。或者整个图像被转换。

我无法 post 所有代码,因为它太大了。如果您希望我通过电子邮件将完整的 HDevelop 脚本发送给您,您必须私信我。这里有一些片段可以给你一个想法:

第 1 步:设定图像阈值并设置应找到线条的搜索区域。前两个区域只有 posting 代码,其他三个区域的代码相同

threshold(Image, RegionThreshold, 0, 100)
region_to_bin(RegionThreshold, ImageBinary, 255, 0, Width, Height)
dev_display(ImageBinary)

*Use the mouse to draw region 1 around first line. Right click when finished. 
draw_rectangle2(WindowHandle, Reg1Row, Reg1Column, Reg1Phi, Reg1Length1, Reg1Length2)
gen_rectangle2(Rectangle1, Reg1Row, Reg1Column, Reg1Phi, Reg1Length1, Reg1Length2)

*Use the mouse to draw region 2 around second line. Right click when finished. 
draw_rectangle2(WindowHandle, Reg2Row, Reg2Column, Reg2Phi, Reg2Length1, Reg2Length2)
gen_rectangle2(Rectangle2, Reg2Row, Reg2Column, Reg2Phi, Reg2Length1, Reg2Length2)

搜索区域如下所示:

第 2 步:计算直线的交点。前两行只有 posting 代码,其他三行的代码相同

*get line segment 1
reduce_domain(ImageBinary, Rectangle1, ImageReduced)
edges_sub_pix (ImageReduced, EdgesLine1, 'lanser2', 0.1, 20, 40)
fit_line_contour_xld (EdgesLine1, 'regression', -1, 0, 5, 2, RowBeginLine1, \
                  ColBeginLine1, RowEndLine1, ColEndLine1, Nr, Nc, Dist)

*get line segment 2
reduce_domain(ImageBinary, Rectangle2, ImageReduced)
edges_sub_pix (ImageReduced, EdgesLine2, 'lanser2', 0.1, 20, 40)
fit_line_contour_xld (EdgesLine2, 'regression', -1, 0, 5, 2, RowBeginLine2, \
                  ColBeginLine2, RowEndLine2, ColEndLine2, Nr, Nc, Dist)

*Calculate and display intersection line 1 to line 2
intersection_lines(RowBeginLine1, ColBeginLine1, RowEndLine1, ColEndLine1, \
                  RowBeginLine2, ColBeginLine2, RowEndLine2, ColEndLine2, \
                  Line1Line2IntersectRow, Line1Line2IntersectCol, 
IsOverlappingLine1Line2)

这会产生以下输出:

第 3 步:创建归一化互相关模型,用于在对象进行平移或旋转时找到对象。这里我选择底部的简单区域

gen_rectangle1 (ModelRegion, 271.583, 200, 349.083, 530)
reduce_domain (ImageBinary, ModelRegion, TemplateImage)
create_ncc_model (TemplateImage, 'auto', rad(0), rad(360), 'auto', 'use_polarity', 
ModelID)
area_center (ModelRegion, ModelRegionArea, RefRow, RefColumn)

输出图像

第四步:现在我们考虑对象移动时会发生什么。为了模拟这一点,我使用仿射变换扭曲了图像。然后,我搜索了在步骤 3 中创建的归一化互相关模型。您可以在下面看到找到了对象。输出是找到它的行、列和角度。这被转换为一个名为 AlignmentHomMat2D

的矩阵

部分代码:

threshold(TransImage, RegionThreshold, 0, 100)
region_to_bin(RegionThreshold, ImageBinaryScene, 255, 0, Width, Height)

* Matching 01: Find the model
find_ncc_model (ImageBinaryScene, ModelID, rad(0), rad(360), 0.8, 1, 0.5, 'true', 0, 
Row, Column, Angle, Score)

* Matching 01: Display the centers of the matches in the detected positions
dev_display (TransImage)
set_line_width(WindowHandle, 3)

for I := 0 to |Score| - 1 by 1
    * Matching 01: Display the center of the match
    gen_cross_contour_xld (TransContours, Row[I], Column[I], 20, Angle)
    dev_set_color ('green')
    dev_display (TransContours)
    hom_mat2d_identity (AlignmentHomMat2D)
    hom_mat2d_translate (AlignmentHomMat2D, -RefRow, -RefColumn, AlignmentHomMat2D)
    hom_mat2d_rotate (AlignmentHomMat2D, Angle[I], 0, 0, AlignmentHomMat2D)
    hom_mat2d_translate (AlignmentHomMat2D, Row[I], Column[I], AlignmentHomMat2D)
    * Matching 01: Display the aligned model region
    affine_trans_region (ModelRegion, RegionAffineTrans, AlignmentHomMat2D, 
    'nearest_neighbor')
    dev_display (RegionAffineTrans)
endfor 

输出结果如下:

第 5 步:最后,根据找到互相关模型的位置更新用于定位原始线的搜索区域。

这是代码。同样,我只显示前两条线段:

*transform initial search regions
affine_trans_region(Rectangle1, Rectangle1Transformed, 
AlignmentHomMat2D,'nearest_neighbor')
affine_trans_region(Rectangle2, Rectangle2Transformed, 
AlignmentHomMat2D,'nearest_neighbor')

*get line segment 1
reduce_domain(ImageBinaryScene, Rectangle1Transformed, ImageReduced)
edges_sub_pix (ImageReduced, EdgesLine1, 'lanser2', 0.5, 20, 40)
fit_line_contour_xld (EdgesLine1, 'regression', -1, 0, 5, 2, RowBeginLine1, \
                  ColBeginLine1, RowEndLine1, ColEndLine1, Nr, Nc, Dist)

*get line segment 2
reduce_domain(ImageBinaryScene, Rectangle2Transformed, ImageReduced)
edges_sub_pix (ImageReduced, EdgesLine2, 'lanser2', 0.5, 20, 40)
fit_line_contour_xld (EdgesLine2, 'regression', -1, 0, 5, 2, RowBeginLine2, \
                  ColBeginLine2, RowEndLine2, ColEndLine2, Nr, Nc, Dist)

*Calculate and display intersection line 1 to line 2
intersection_lines(RowBeginLine1, ColBeginLine1, RowEndLine1, ColEndLine1, \
                  RowBeginLine2, ColBeginLine2, RowEndLine2, ColEndLine2, \
                  Line1Line2IntersectRow, Line1Line2IntersectCol, 
IsOverlappingLine1Line2)

这会产生以下输出: