Search code examples
edge-detectionhalcon

Halcon - find edge position, draw line and lineintersection


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


Solution

  • 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