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

Posted

技术标签:

【中文标题】Halcon - 找到边缘位置,画线和线交点【英文标题】:Halcon - find edge position, draw line and lineintersection 【发布时间】:2020-08-30 17:11:44 【问题描述】:

我是从头开始使用 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)

【问题讨论】:

【参考方案1】:

基于原始海报担心位置移动,我发布了另一个涉及更多的答案。对于这种情况,这种策略可能不是最简单的,但它是一种适用于很多情况的通用策略。通常这样的问题是这样解决的:

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

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

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

第 1 步:设置图像阈值并设置应找到线条的搜索区域。仅发布前两个地区的代码,但其他三个地区的代码相同

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 步:计算线的交点。仅发布前两行的代码,但其他三行的代码相同

*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)

输出图片

第 4 步:现在我们考虑移动对象时会发生什么。为了模拟这一点,我使用仿射变换扭曲了图像。然后我搜索了在步骤 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)

这会产生以下输出:

【讨论】:

哇!你付出了很大的努力才能做到这一点.. 非常感谢.. 我在这里有很多东西要学。如果你能把完整的样品寄给我,那就太好了!一旦在这篇文章上启用它,明天也会为你的努力发送奖励.. 在另一条评论中发布我的电子邮件,这样我可以在你拥有它后将其删除。谢谢! @Jake Chittle 你能分享你的代码吗 确定你的邮箱是什么?【参考方案2】:

根据要求,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)

【讨论】:

非常感谢您的回答。我认为我的帖子不够清楚。这将在一个自动化系统上,并且需要每秒进行一次评估。它必须是自动化的,我对盒子的位置有 10 厘米的公差,所以它可以向各个方向移动.. 嘿,您可以通过将 draw_rectangle2 生成的值硬编码到 gen_rectangle 2 中来拥有一个自动化系统。最初只是为了向您展示如何轻松设置区域。如果上述程序中的区域不符合您 10 厘米的容差,您可以将它们稍大一些。我一直在做自动化系统。通常最好只在预期的区域中搜索特征,在您的情况下只有 10 厘米的移动。 黑块的形状每次都会相似吗?如果是,我会首先使用匹配来定位黑色块。然后我会设置 4 个固定搜索区域来定位角或线。如果您对此解决方案感兴趣,请告诉我们。 我有一个简单的问题.. 如果您连接了此示例上的区域,并且它正在寻找外部边缘(一条“L”形线),为什么它会创建 2 条不同的线,而在“曲线”? 霍夫变换有几个不同的变体。在这种情况下,它只尝试检测线条。 Hough 变换还有一个变体,用于搜索圆。它不是普通的边缘或轮廓检测器。尝试更改“hough_lines”中的阈值,看看会发生什么。此外,如果您在 Hdeveop 中搜索“线条”的帮助文件,您会发现许多检测线条的方法。和他们一起玩,直到你找到有用的东西。在我提供的另一个示例中,我展示了如何使用回归从边缘轮廓拟合一条线。所以你有很多选择。

以上是关于Halcon - 找到边缘位置,画线和线交点的主要内容,如果未能解决你的问题,请参考以下文章

Core Graphics 触摸时画线和删除

CGContextRef画线和点,如何清屏?

Java画线和按键改变颜色

利用Halcon寻找出边缘突出的部分

R中多边形和线的复杂裁剪(空间交点?)

通过 3D 向量拟合线并找到与平面的交点