1

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

在此处输入图像描述

4

2 回答 2

3

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

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

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

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

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

搜索区域如下所示:

在此处输入图像描述

第二步:计算线的交点。仅发布前两行的代码,但其他三行的代码相同

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

这会产生以下输出:

在此处输入图像描述

于 2020-05-14T22:47:34.930 回答
1

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

在 HDevelop 中生成交集

于 2020-05-14T13:40:12.677 回答