halcon subpixel definition and measurement fit

process:

Implementation process:

1》Acquisition of images

2》Preprocessing (RoI): Reduce the area of ​​interference

3 "Sub-pixel edge extraction (xld)

edges_sub_pix edge extraction operator

threshold_sub_pix edge extraction operator (pixel based)

Centerline: line_gauss line_color line_facet

Interconversion operator of area and xld

zero_crossing_sub_pix cannot handle grayscale images, only derivative Gaussian difference Gaussian images

4" filter, split, join

filter

 

Segmentation operator for contours: segment_contours_xld

Union operator: there are three (depending on the situation)

union_collinear_contours_xld collinear union

union_colse_contours_xld closed union

union_colse_contours_xld contiguous union

union_cocircular_contours_xld Cocircular union

5" Fitting

Least Squares: fit_line_contour_xld() function to fit straight lines to subpixels

fit_circle_contour_xld() function for subpixel fit circle

fit_ellipse_contour_xld() function for subpixel fitting circles

fit_rectangle2_contour_xld() function to fit j rectangles to subpixels

6" Calculation (pixel value)

7" Introduce internal parameters and external parameters to convert pixel values ​​into shooting boundary coordinates (mm)

1. Edge extraction

Halcon operator edges_sub_pix subpixel definition and filter (1) - Running Zheng's Blog - CSDN Blog_edges_sub_pix

Subpixel:


The minimum unit of the imaging surface of an area scan camera is a pixel. For example, the pixel pitch of a certain chip is 5.2 microns. When the camera is shooting, the continuous images in the physical world are discretized; each pixel on the imaging surface is only The color that represents its vicinity, as to how "nearby" is? It's hard to explain. There is a distance of 5.2 microns between two pixels, which can be seen as connected on a macroscopic level, but on a microscopic level, there are infinitely smaller things between them, and this smaller thing we call it "Sub-pixel"; in fact, "sub-pixel" should exist, but there is no subtle sensor on the hardware to detect it. So the software calculates it approximately.


Subpixel accuracy:


Sub-pixel accuracy refers to the subdivision between two adjacent pixels, and the input value is usually one-half, one-third or one-quarter. This means that each pixel will be divided into smaller units to perform interpolation algorithms on these smaller units. For example, if you choose quarter, it is equivalent to each pixel being counted as four pixels both horizontally and vertically.
Application of sub-pixel:
In machine vision, sub-pixel is a relatively common concept. In many functions, you can choose whether to use sub-pixel, and in measurement, such as position, line, circle, etc., sub-pixel will appear. Such as measuring the diameter of a circle is 100.12 pixels. The 0.12 behind this is subpixel. Because it can be understood from the pixels that the smallest physical unit of an industrial camera is actually a pixel, but the value after the decimal point is still obtained in the machine vision measurement. This is calculated by the software. In fact, in the real situation, it is not necessarily very precise. This value is usually easier to reflect in grayscale images, and in binary images, because the values ​​are only 0, 1. So many functions do not necessarily compute subpixels.
 

Edge detection definition:


Edge detection is a basic tool in graphics and image processing, computer vision and machine vision. It is usually used for feature extraction and feature detection. It aims to detect edges or discontinuous areas with obvious changes in a digital image, in one-dimensional space. In , a similar operation is called step detection. The edge is the boundary line between different Quyuans in an image, usually an edge image is a binary image. The purpose of edge detection is to capture areas with sharp changes in brightness, which are usually of interest to us. Two -degree discontinuities in an image are usually one of the following:
     (1) discontinuities in image depth
     (2) discontinuities in image (gradient) orientation
     (3) discontinuities in image illumination (intensity)
     ( 4) Where the texture changes
Ideally, applying an edge detector to a given image results in a series of continuous curves that represent the boundaries of objects. Therefore, the result obtained by applying the edge detection algorithm will greatly reduce the amount of image data, thereby filtering out a lot of information that we do not need, leaving the important structure of the image, and the work to be processed is greatly simplified. However, the edges extracted from ordinary pictures are often corrupted by the segmentation of the image, that is, the detected curves are usually not continuous, there are some edge curve segments open, the edge segments will be lost, and there will be some that we are not interested in. the edge of. This requires the accuracy of edge detection algorithms

 Halcon operator segment_contours_xld_Running Zheng's blog-CSDN blog_segment_contours_xld

edges_sub_pix (ImageROI, Edges, 'lanser2', 0.3, 10, 30)  利用Deriche、Lanser、Shen和Canny滤波器提取亚像素精度边缘
  提取图像精确边缘 (精确边缘就是亚像素边缘)   一阶导数  (10,30,这两个越小,边缘越多,越细腻,越大,边缘越少)
   Image: // 输入图像
   Edges:  //输出边缘轮廓
   Filter: //边缘提取算法的名称 (canny,lanser1 )
    Alpha: // 高斯平滑系数,  0.3 参数指定值越小,平滑越强大,会减少边缘细节。(canny刚好相反,值越大,边缘细节越少,当有多段边缘的时候可以调大这个值来是的其平滑)  
   Low:   // 低阈值   (边缘幅度值  像素)
   High: //  高阈值    (边缘幅度值  像素)
     canny的原理: 1.高斯平滑滤波
                  2.利用sobel其梯度(即有大小,又有方向)
                  3.费极大值抑制(越大  越小)
                  4.高低阈值控制(如果线是段的,要连起来,可以将这个值变大)中间看8领域





滞后性:简单的说就是延迟,落后;一个现象与另一密切相关的现象相对而言的落后迟延,尤其指物理上的果没有及时跟着因而出现;
 

滞后性阈值的描述:
 使用边缘滤波,得到的边缘都是大于一个像素的轮廓,因此要对所得到的图像进行骨架化,从而得到比较清晰的边缘轮廓。有时候还需要进行非最大抑制处理
 这样,经过先对边缘幅度进行阈值分割,然后对分割出的区域进行骨架化处理,再进行非最大抑制处理,一般就可得到清晰的边缘。但是,有时候我们选择高的阈值以保证只将相关边缘选出时,边缘通常被割裂成诺干段;另一方面,如果选择低的阈值以保证边缘不会断裂成一段一段时,我们最终的分割结果中又会包含很多不相关边缘。针对这种情况,Canny提出来一种特殊的阈值分割算法来分割边缘:滞后阈值分割。
       滞后阈值分割使用两个阈值----高阈值和低阈值。边缘幅度比高阈值大的那些点立即作为安全边缘点被接受。边缘幅度比低阈值小的那些点被立即剔除。边缘幅度在高阈值和低阈值之间的那些点按如下原则处理:只有在这些点能按某一路径和安全边缘点相连时,他们才作为边缘点被接受。组成这一路径的所有点的边缘幅度都比低阈值要大。我们也能把这个过程理解为,首先边缘幅度大于高阈值的所有边缘点,然后在边缘幅度大于低阈值的情况下尽可能延长边缘。

Edge detection algorithms are basically based on the mathematical basis of differentiation. Generally, the image is filtered first, and then thresholded. Since the first-order differential only needs to use a filter to meet the requirements, the first-order differential is generally used to read the edge. Because sometimes there is too much noise on the section, which affects the quality of the image, the image of the section should be filtered. There are two convolution operations involved here: one is the filter convolution calculation for image smoothing; the other is the filter convolution calculation for derivation of the image.

There are three criteria for edge filter selection:
       first, the output signal-to-noise ratio generated by the edge filter should be maximized, so that the possibility of false detection and missed detection of an edge point should be lower;
       second, the extracted position variance should be minimized , so that the extracted edge is closer to the real edge;
       the third is to maximize the distance between the extracted edge positions, so that the edge detector only returns a unique edge for each real edge, which can avoid multiple responses
 

2. Contour segmentation 

segment_contours_xld(Contours : ContoursSplit : Mode, SmoothCont, MaxLineDist1, MaxLineDist2 : )
*Contours  Edges:待分割的轮廓
*ContoursSplit:分割后的轮廓
* Mode :
    * 如果Mode='lines'则将输入轮廓分割成线条,
    * 如果Mode='lines_circles'则将其分割成线条和圆弧,
    * 如果Mode='lines_ellipses'则将其分割成线条和椭圆弧;
*SmoothCont 平滑轮廓系数  不能等于0  最好大于等于3并且是奇数 ,建议值是5
*MaxLineDist1 轮廓线和近似线之间的最大距离(第一次迭代)   最大线距需要大于等于0.0;
*MaxLineDist2 轮廓线和近似线之间的最大距离(第二次迭代)   最小线距需要大于等于0.0

描述:segment_contours_xld在分割时,
           如果Mode='lines'则将输入轮廓分割成线条,
           如果Mode='lines_circles'则将其分割成线条和圆弧,
           如果Mode='lines_ellipses'则将其分割成线条和椭圆弧;
          (1)、segment_contours_xld首先通过折线来逼近输入的轮廓,这样,在弯曲的地方轮廓就会被过度的分割,如果用圆弧可以更好地逼近轮廓,则用圆弧或椭圆弧分别代替相邻的线段。如果SmoothCont设置为> 0,则首先对输入的轮廓进行平滑,这是必要的,因为平滑抑制了轮廓上的异常值,所以一方面可以防止在分割特别短的线的时后带来的异常,另一方面,在使用圆或椭圆分割时,可以实现更稳健的分割;
          (2)、最初的折线逼近是使用Ramer算法通过MaxLineDist1的最大距离来完成的,在此之后,圆形或椭圆形的弧被匹配到相邻的线段中,如果所产生的弧线到轮廓线的最大距离小于两条线段的最大距离,两个线段被替换为圆弧,迭代此过程,直到不再发生更改;
          (3)、在此之后,仍然由线段逼近的轮廓部分再次用最大距离MaxLineDist2的多边形逼近进行分割,并且新创建的线段在可能的情况下合并为圆形或椭圆弧。显然,这只会在MaxLineDist2 < MaxLineDist1时更改输出,这种两步方法比使用MaxLineDist2的一步方法更有效,由于在第一步中生成的线段较少,因此必须较少地进行圆或椭圆拟合。因此,使用长圆弧逼近部分输入轮廓会更高效;之后,再用短圆弧去逼近输入的轮廓,最后再细化使用过长圆弧逼近的轮廓的末端;
          (4)、所述所得轮廓长度至少为3像素,并且包含所述输入轮廓的至少6个连续点;所有输入的长度小于3像素或少于6个轮廓点的轮廓线将被复制到输出轮廓线,不做任何修改。
 

参数设置注意事项:
SmoothCont (input_control)   
(1)、不能等于0;
(2)、最好大于等于3并且是奇数;
(3)、建议值是5;
 
MaxLineDist1 (input_control)    MaxLineDist2 (input_control)  
(1)、需要大于等于0.0;
MaxLineDist1这个第一次分割,MaxLineDist2是第二次分割,第一次分割为主,第二次在第一次的基础上逼近理想值)
 

Union operator: there are three (depending on the situation)

union_collinear_contours_xld collinear union

union_colse_contours_xld closed union

union_colse_contours_xld contiguous union

union_cocircular_contours_xld Cocircular union

 

 3. Fitting

Least Squares:

fit_line_contour_xld() function for fitting lines to subpixels

fit_circle_contour_xld() function for subpixel fit circle

fit_ellipse_contour_xld() function for subpixel fitting circles

fit_rectangle2_contour_xld() function to fit j rectangles to subpixels

Halcon operator segment_contours_xld_Running Zheng's blog-CSDN blog_segment_contours_xld 

    *get_contour_global_attrib_xld(Contour : : Name : Attrib)获得轮廓的全局属性   
	*	属性名(Name)包含如下:
	*				'regr_norm_row', 回归线单位法向量的行坐标,法向量从原点指向该线
	*				'regr_norm_col', 回归线单位法向量的列坐标,法向量从原点指向该线。
	*				'regr_mean_dist', 包含每个等高线点到回归线之间的欧式距离的平均值
	*				'regr_dev_dist', 轮廓线点与回归线之间(欧几里得)距离的标准差
	*				'cont_approx',  如果'cont_approx'=-1,这一部分轮廓最适合被拟合为直线段。
    *                               如果'cont_approx'=0,这一部分轮廓最适合被拟合为椭圆弧。
    *                               如果'cont_approx'=1,这一部分轮廓最适合被拟合为圆弧。
	*				 'bright_dark', 建立整流网各网格点之间的连接
	*				'is_hole'      判断是否是包含孔的边界,'is_hole'设置为1,是包含孔的边界;否则设置为0
	*	如果Attrib是 -1 是适合拟合成直线,
    *                 1 说明适合拟合成圆  ,
    *                 0说明适合拟合出椭圆 

measure_metal_part

* measure_metal_part.hdev: inspects metal part by fitting lines and circles
* 
dev_close_window ()
dev_update_window ('off')
* ****
* step: acquire image
* ****
read_image (Image, 'metal-parts/metal-parts-01')
get_image_size (Image, Width, Height)
dev_open_window_fit_image (Image, 0, 0, Width, Width, WindowID)
set_display_font (WindowID, 14, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (3)
dev_display (Image)
disp_continue_message (WindowID, 'black', 'true')
stop ()
* ****
* step: create contours
* ****


* edges_sub_pix :边缘提取算子:利用Deriche、Lanser、Shen和Canny滤波器提取亚像素精度边缘
  *Image:  输入图像
  *Edges:  输出边缘轮廓
  *Filter: 边缘提取算法的名称 (canny,lanser1 )
  *Alpha:  高斯平滑系数,  0.3 参数指定值越小,平滑越强大,会减少边缘细节。(canny刚好相反,值越大,边缘细节越少,当有多段边缘的时候可以调大这个值来是的其平滑)  
  *Low:    低阈值   (边缘幅度值  像素)
  *High:   高阈值    (边缘幅度值  像素)
edges_sub_pix (Image, Edges, 'canny', 1.9, 40, 90)

dev_display (Edges)
disp_continue_message (WindowID, 'black', 'true')
stop ()
* ****
* step: process contours
* ****
segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 6, 4, 4)
*segment_contours_xld(Contours : ContoursSplit : Mode, SmoothCont, MaxLineDist1, MaxLineDist2 : )
*Contours  Edges:待分割的轮廓
*ContoursSplit:分割后的轮廓
* Mode :
    * 如果Mode='lines'则将输入轮廓分割成线条,
    * 如果Mode='lines_circles'则将其分割成线条和圆弧,
    * 如果Mode='lines_ellipses'则将其分割成线条和椭圆弧;
*SmoothCont 平滑轮廓系数  不能等于0  最好大于等于3并且是奇数 ,建议值是5
*MaxLineDist1 轮廓线和近似线之间的最大距离(第一次迭代)   最大线距需要大于等于0.0;
*MaxLineDist2 轮廓线和近似线之间的最大距离(第二次迭代)   最小线距需要大于等于0.0;

sort_contours_xld (ContoursSplit, SortedContours, 'upper_left', 'true', 'column')
dev_clear_window ()
dev_set_colored (12)
dev_display (SortedContours)
disp_continue_message (WindowID, 'black', 'true')
stop ()
* ****
* step: perform fitting
* ****
ROI := [115,225,395,535]
dev_open_window (0, round(Width / 2), (ROI[3] - ROI[1]) * 2, (ROI[2] - ROI[0]) * 2, 'black', WindowHandleZoom)

dev_set_part (round(ROI[0]), round(ROI[1]), round(ROI[2]), round(ROI[3]))

set_display_font (WindowHandleZoom, 14, 'mono', 'true', 'false')
count_obj (SortedContours, NumSegments)
dev_display (Image)
NumCircles := 0
NumLines := 0
for i := 1 to NumSegments by 1
    select_obj (SortedContours, SingleSegment, i)
    *get_contour_global_attrib_xld返回XLD轮廓的全局属性值
    get_contour_global_attrib_xld (SingleSegment, 'cont_approx', Attrib)
    *get_contour_global_attrib_xld(Contour : : Name : Attrib)获得轮廓的全局属性   
	*	属性名(Name)包含如下:
	*				'regr_norm_row', 回归线单位法向量的行坐标,法向量从原点指向该线
	*				'regr_norm_col', 回归线单位法向量的列坐标,法向量从原点指向该线。
	*				'regr_mean_dist', 包含每个等高线点到回归线之间的欧式距离的平均值
	*				'regr_dev_dist', 轮廓线点与回归线之间(欧几里得)距离的标准差
	*				'cont_approx',  如果'cont_approx'=-1,这一部分轮廓最适合被拟合为直线段。
    *                               如果'cont_approx'=0,这一部分轮廓最适合被拟合为椭圆弧。
    *                               如果'cont_approx'=1,这一部分轮廓最适合被拟合为圆弧。
	*				 'bright_dark', 建立整流网各网格点之间的连接
	*				'is_hole'      判断是否是包含孔的边界,'is_hole'设置为1,是包含孔的边界;否则设置为0
	*	如果Attrib是 -1 是适合拟合成直线,
    *                 1 说明适合拟合成圆  ,
    *                 0说明适合拟合出椭圆 
    if (Attrib == 1)
        NumCircles := NumCircles + 1
        *拟合圆 
        fit_circle_contour_xld (SingleSegment, 'atukey', -1, 2, 0, 5, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
       * 生产椭圆的
        gen_ellipse_contour_xld (ContEllipse, Row, Column, 0, Radius, Radius, 0, rad(360), 'positive', 1.0)
        dev_set_color ('white')
        dev_display (ContEllipse)
        set_tposition (WindowHandleZoom, Row - Radius - 10, Column)
        write_string (WindowHandleZoom, 'C' + NumCircles)
        ResultText := 'C' + NumCircles + ': radius = ' + Radius
    else
        NumLines := NumLines + 1
        fit_line_contour_xld (SingleSegment, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
        gen_contour_polygon_xld (Line, [RowBegin,RowEnd], [ColBegin,ColEnd])
        dev_set_color ('yellow')
        dev_display (Line)
        distance_pp (RowBegin, ColBegin, RowEnd, ColEnd, Length)
        set_tposition (WindowHandleZoom, (RowBegin + RowEnd) / 2 - Nr * 10, (ColBegin + ColEnd) / 2)
        write_string (WindowHandleZoom, 'L' + NumLines)
        ResultText := 'L' + NumLines + ': length = ' + Length
    endif
    set_tposition (WindowHandleZoom, 275 + i * 10, 230)
    write_string (WindowHandleZoom, ResultText)
endfor
disp_continue_message (WindowID, 'black', 'true')
stop ()
dev_set_window (WindowHandleZoom)
dev_close_window ()
dev_clear_window ()

Guess you like

Origin blog.csdn.net/weixin_39354845/article/details/123218089