玻璃瓶口的缺陷检测

inspect_bottle_mouth.hdev

巧妙运用了极坐标变换法,细节很精细,值得学习

* tuning parameters
SmoothX := 501
ThresholdOffset := 25
MinDefectSize := 50
* 
* initialization
PolarResolution := 640
RingSize := 70
get_system ('store_empty_region', StoreEmptyRegion)
set_system ('store_empty_region', 'false')
read_image (Image, 'bottles/bottle_mouth_01')
dev_update_off ()
dev_close_window ()
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, 640, 512, WindowHandle1)
set_display_font (WindowHandle1, 16, 'mono', 'true', 'false')
dev_display (Image)
dev_set_draw ('margin')
dev_set_line_width (3)
dev_open_window_fit_size (0, 648, RingSize, PolarResolution, 150, 512, WindowHandle)
dev_set_draw ('margin')
dev_set_line_width (3)
dev_set_color ('red')
* 
* Main loop
* 
* Detect defects in bottle necks
for Index := 1 to 16 by 1
    read_image (Image, 'bottles/bottle_mouth_' + Index$'.02')
    * 
    * Part 1: Use basic morphology to detect bottle
    *自动阈值分割图像
    auto_threshold (Image, Regions, 2)
    *选择第一的区域,没明白
    select_obj (Regions, DarkRegion, 1)
    *用3.5的圆做开运算(先腐蚀后膨胀),消除小物体
    opening_circle (DarkRegion, RegionOpening, 3.5)
    *用25.5的圆做闭运算(先膨胀后腐蚀),排除小型黑洞,可以把里面的小圆滤除掉,只保留大圆
    closing_circle (RegionOpening, RegionClosing, 25.5)
    *填补区域的漏洞,让区域更完整
    fill_up (RegionClosing, RegionFillUp)
    *向外扩散一个区域后,计算区域内的轮廓,(计算轮廓啥意思?)
    boundary (RegionFillUp, RegionBorder, 'outer')
    *内外各以3.5的像素扩大区域
    dilation_circle (RegionBorder, RegionDilation, 3.5)
    *选择了上面扩大后的区域,提取这个区域(不是裁剪)
    reduce_domain (Image, RegionDilation, ImageReduced)
    * 
    * Find the bottle center by fitting a circle to extracted edges
    *使用累计直方图计算两个阀值。凡是大于高阀值的一定是边缘; 凡是小于低阀值的一定不是边缘;
    *如果检测结果大于低阀值但又小于高阀值,那就要看这个像素的邻接像素中有没有超过高阀值的边缘像素:如果有的话那么它就是边缘了,否则他就不是边缘;
    *但我仍然有疑惑
    edges_sub_pix (ImageReduced, Edges, 'canny', 0.5,20, 40)
    *利用直线和圆去分割原有的轮廓,导致更容易拟合
    segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 5, 4, 2)
    *利用上面分割的结果,用直线或者圆弧拟合轮廓
    union_cocircular_contours_xld (ContoursSplit, UnionContours, 0.9, 0.5, 0.5, 200, 50, 50, 'true', 1)
    length_xld (UnionContours, Length)
    select_obj (UnionContours, LongestContour, sort_index(Length)[|Length| - 1] + 1)
    *用一个完整圆拟合上面那个轮廓,返回圆心坐标和半径
    fit_circle_contour_xld (LongestContour, 'ahuber', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
    * 
    * Part 2: Transform the ring-shaped bottle neck region to a rectangle
    *根据圆心坐标和半径产生一个圆
    gen_circle (Circle, Row, Column, Radius)
    *向外以5的像素扩大区域
    dilation_circle (Circle, RegionDilation, 5)
    *向内以(70-5=65)的像素扩大区域
    erosion_circle (Circle, RegionErosion, RingSize - 5)
    *得到一个圆环,两个圆之间的区域
    difference (RegionDilation, RegionErosion, RegionDifference)
    *提取上面的圆环区域(不是裁剪)
    reduce_domain (Image, RegionDifference, ImageReduced)
    *极坐标变换算子,圆形图变方形图
    *参数(输入图像,输出图像,圆心横坐标,圆心纵坐标
    *,要映射到输出图像第一列的射线角度,要映射到输出图像最后一列的射线角度
    *,要映射到输出图像第一行的圆的半径,要映射到输出图像最后一行的圆的半径
    *,输出图的宽,输出图的高,类插值方法)
    polar_trans_image_ext (ImageReduced, ImagePolar, Row, Column, 0, rad(360), Radius - RingSize, Radius, PolarResolution, RingSize, 'nearest_neighbor')
    * 
    * Part 3: Find defects with a dynamic threshold
    * Note the strong smoothing in x-direction in the transformed image.
    *将图像中像素最小和最大之间的像素值均匀映射到0-255之间,增强对比度。
    scale_image_max (ImagePolar, ImageScaleMax)
    *均值滤波
    mean_image (ImageScaleMax, ImageMean, SmoothX, 3)
    *动态阈值分割
    dyn_threshold (ImageScaleMax, ImageMean, Regions1, 55, 'not_equal')
    *将分割后的各区域分隔开
    connection (Regions1, Connection)
    *根据高度选择9个像素以上的区域
    select_shape (Connection, SelectedRegions, 'height', 'and', 9, 99999)
    * ignore noise regions
    *封闭的矩形框,边界被平滑
    closing_rectangle1 (SelectedRegions, RegionClosing1, 10, 20)
    union1 (RegionClosing1, RegionUnion)
    * re-transform defect regions for visualization
    *极坐标反变换
    polar_trans_region_inv (RegionUnion, XYTransRegion, Row, Column, 0, rad(360), Radius - RingSize, Radius, PolarResolution, RingSize, 1280, 1024, 'nearest_neighbor')
    * 
    * Part 4: Display results
    * display original image with results
    dev_set_window (WindowHandle1)
    dev_display (Image)
    dev_set_color ('blue')
    dev_display (RegionDifference)
    dev_set_color ('red')
    dev_display (XYTransRegion)
    * display polar transformed inspected region with results
    * The image and resulting region are rotated by 90 degrees
    * only for visualization purposes! (I.e. to fit better on the screen)
    * The rotation is NOT necessary for the detection algorithm.
    dev_set_window (WindowHandle)
    rotate_image (ImagePolar, ImageRotate, 90, 'constant')
    dev_display (ImageRotate)
    count_obj (RegionUnion, Number)
    if (Number > 0)
        mirror_region (RegionUnion, RegionMirror, 'diagonal', PolarResolution)
        mirror_region (RegionMirror, RegionMirror, 'row', PolarResolution)
        dev_display (RegionMirror)
        disp_message (WindowHandle1, 'Not OK', 'window', -1, -1, 'red', 'false')
    else
        disp_message (WindowHandle1, 'OK', 'window', -1, -1, 'forest green', 'false')
    endif
    if (Index < 16)
        disp_continue_message (WindowHandle1, 'black', 'true')
        stop ()
    endif
endfor
* Reset system parameters
set_system ('store_empty_region', StoreEmptyRegion)

image.png


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864