1

I'm starting from scratch with Halcon, and I'm not able to solve a problem. I have a Object, need to extract edges from this object, draw a line along the borders and draw a point on the intersection of the lines.

I've tried tresholding, edge, color edge, but It extracts borders everywhere, except the ones I need..

Its just a test i am doing as it is similar to what I have to do later on a real project. But in two days I didnt manage to solve it..

Here is the base image, and the desired result image:

enter image description here enter image description here

what I have so far:

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)

enter image description here

sharkyenergy
  • 3,842
  • 10
  • 46
  • 97

2 Answers2

3

Based off the original poster being worried about positional movement, I'm posting another answer which is more involved. This strategy might not be the easiest for this case but it is a general strategy that works for a lot of cases. Typically problems like this are solved as follows:

1) Perform a rough location of the part. This usually involves either a blob detection or a matching strategy (correlation, shape based etc). The output of this step is a transformation describing the location of the object (translation, orientation).

2) Based off the found location in step 1, the search regions for detecting features (lines, holes etc) are transformed or updated to new locations. Or the entire image is transformed.

I couldn't post all the code since it was too large. You will have to personal message me if you want me to email you the full HDevelop script. Here are some snippets to give you an idea:

Step 1: Threshold the image and setup search regions where the lines should be found. Only posting code for the first two regions but code is identical for the other three

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)

The search regions look like this:

enter image description here

Step 2: Calculate the intersection of the lines. Only posting code for the first two lines but code is identical for the other three

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

This produces the following output: enter image description here

Step 3: Create a normalized cross correlation model for finding the object when it undergoes translation or rotation. Here I choose a simple region on the bottom

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)

Output Imageenter image description here

Step 4: Now we consider what happens when the object is moved. To simulate this I warped the image using a affine transform. I then searched for the normalized cross correlation model created in step 3. Below you can see the object was found. The output is a row, column and angle where it was found. This is converted to a matrix called AlignmentHomMat2D

Some of the code:

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 

The output is as follows: enter image description here

Step 5: Finally the search regions for locating the original lines are updated based off where the cross-correlation model was found.

Here is the code. Again I'm only showing the first two line segments:

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

This produces the following output:

enter image description here

Jake Chittle
  • 316
  • 1
  • 2
  • 4
  • WOW! that was a whole load of effort you took to make this.. thank you very much.. there is a lot to learn for me here. If you could mail me the full sample it would be great! sending you over a reward also for the effort tomorrow as soon as it is enabled on this post.. posting my email in another comment so i can delete it after you have it. Thank you! – sharkyenergy May 15 '20 at 05:17
  • @Jake Chittle Can you please share your code – Dominota Nov 24 '21 at 03:29
  • sure what is your email? – Jake Chittle Nov 25 '21 at 16:31
1

Halcon has a lot of ways this can be accomplished depending on the requirements. One of the most common techniques for detecting lines is to use the Hough Transform. I've attached a small HDevelop script showing how to get the intersection of two of the lines in your image. The same principle can be used for the others.

One of the most important concepts in Halcon is Regions. The example program first allows you to create two regions by drawing rectangles over top of two of the lines. The regions are black in the image below. On line 8 of the program (draw_rectangle2...) you will need to draw a bounding box around the first line. Right click when you are finished. Line 10 (draw rectangle2...) will expect you to draw a bounding box around the second line. Again right click when finished.

The regions are then combined on lines 13-16 by concatenation. On line 19 (reduce_domain) the domain of the image is reduced to the concatenated regions. You can think of this as a mask. Now when we search for the lines we will only search the part of the image where we created the regions. emphasized text

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)

generated intersection in HDevelop

Jake Chittle
  • 316
  • 1
  • 2
  • 4
  • thank you very much for your answer.. I think that i was not clear enough in my post. This would be on an automated system, and would need to make this evaluation once per second.. It would have to be automated,, i have a tolerance of 10 cm for the position of the box, so it could be shifted in all directions.. – sharkyenergy May 14 '20 at 13:59
  • Hey you can have an automated system by hard-coding the values generated by draw_rectangle2 into gen_rectangle 2. That was only included to show you how to set the regions up easily at first. If the regions in the program above are not meeting your 10cm tolerance, you can make them slightly larger. I do automated systems all the time. It is usually better to only search for features in a region where they are expected to be, which in your case is only 10cm of movement. – Jake Chittle May 14 '20 at 14:23
  • Is the shape of the black piece going to be similar every time? If it is, I would first use matching to locate the black piece. Then I would setup 4 fixtured search regions to locate the corners or lines. Let us know if you are interested in this solution. – Jake Chittle May 14 '20 at 14:47
  • I have a quick question.. If you connected the regions on this sample, and it is finding the external edge (one "L" shaped line) why is it creating 2 distinct lines, and none in the "curve"? – sharkyenergy May 15 '20 at 14:21
  • The Hough transform has a few different variants. In this case it is trying to detect lines only. There is also a variant of the Hough transform that searches for circles. It is not a plain edge or contour detector. Try changing the thresholds in "hough_lines" to see what happens. Also if you search the help file for "lines" in Hdeveop you will find many ways to detect lines. Just play with them until you find something that works. In the other example I provided, I showed how you could also use regression to fit a line from edge contours. So you have many options. – Jake Chittle May 15 '20 at 20:37