勇哥的实验:halcon阈值分割算子细谈(一)dyn_threshold

阈值分割引言

阈值分割有非常多的算法,大体上分为全局和局部算法。
全局算法包括全局固定阈值和基于图像直方图的阈值,局部算法包括局部动态阈值分割。
基于图像直方图阈值分割的方法也有很多,比如常规的高斯滤波双峰法,OTSU大津法。
但是这类所有的法都基于一个假设:图像是有前景和背景的,待分割目标处于背景中,即图像直方图是双峰的。
如果因为非均匀光照导致待分割目标不处于背景或前景中,即图像直方图无双峰,
那么基于图像直方图的所有法都是不甚理想的
只能在此基础上进行一定的变换,例如nbl算法等,这些都属于局部算法。

任何算法,都会基于假设空间的。没有假设空间,所有算法性能一致。包括经典算法和深度学习算法。

本系列的贴子勇哥通过实验来细品它们之间的差别,以求以后可以精准应用。


先提供各类阈值分割算子的基础资料如下:

http://47.98.154.65/?id=683



 dyn_threshold


先来段理论介绍,后面我们开始实验:


dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset, LightDark : )
——局部动态阈值分割 Dynamic Threshold

  • ThresholdImage:是我们用来作为灰度值参考的另外一幅图像,在实际使用过程中通常都是对原图像OrigImage进行一次平滑处理,然后用平滑处理之后得到的图像作为参考图像。

  • Offset:其实是在设定一个比较的区间范围。

  • LightDark:是问我们提取亮?暗?还是相似的区域?(当然,这是相对于ThresholdImage)


dyn_threshold 这个算子就是根据一套灰度值比较规则来选择原图像中那些灰度值符合这个公式的像素点。

g_{o} = g_{OrigImage}; 代表原图中的像素点的灰度值
g_{t} = g_{ThresholdImage};代表参考图中的像素点的灰度值

我们的做法是把参考图像的灰度值加上(减去)一个Offset,然后去和原图的像素点逐像素对应地进行比较。

下面看Halcon中给出的这些公式:

在这里插入图片描述

  • 当参数 LightDark = ‘light’ 时,
    既然选择light,那就代表提取相对参考图来说亮一些的地方,那么自然要选择那些灰度值比 gt + Offset 要大的像素点。
    在这里插入图片描述

  • 当参数 LightDark = ‘dark’ 时:
    如果要提取的是比参考图要暗一些的区域,那么自然要选择比g_t的灰度值要小的那些像素点,
    但是这样直接比较的话提取的小区域太多了,并没有很好地提取出相对参考图来说很明显有差别的那部分,
    所以我们才给定Offset这个参数用来修正。这样给参考图的灰度值一减掉Offset,提取出来的和参考的之间的差距就会很明显。
    在这里插入图片描述

  • 当参数 LightDark = ‘equal’ 时,
    选择equal的意思是选择那些和参考图的差不多的,只要在这个合理的范围内的都算。
    在这里插入图片描述

  • 最后, 当 LightDark = 'not_equal’时
    反正只要不是差不多的就不选,亮的暗的无所谓。
    在这里插入图片描述

通常,阈值图像是原始图像的平滑版本(例如,通过应用mean_image、binomial_filter、gauss_filter等)。
然后dyn_threshold 的效果类似于将 threshold 应用到经过高通滤波的原始图像上(参见highpass_image)。
dyn_threshold可以提取出物体的轮廓,其中物体的大小(直径)由低通滤波器的掩码大小和物体边缘的振幅决定:

所选择的模板越大,找到的region就会越大。一般来说,模板的大小应该是我们要提取的物体直径大小的两倍左右。
还有很重要的一点是最好不要把Offset这个变量设置为0,因为这样会导致最后找到太多很小的regions,而这基本上都是噪声。
所以这个值最好是在5-40之间,值选择的越大,提取出来的regions就会越小。

在这里插入图片描述
在这里插入图片描述


示例一:划痕


read_image (Image, 'surface_scratch')
get_image_size (Image, Width, Height)
dev_set_draw ('margin')
dev_set_line_width (4)


mean_image (Image, ImageMean, 7, 7)
dyn_threshold (Image, ImageMean, DarkPixels, 5, 'dark')


gauss_filter(Image, ImageGauss, 11)
dyn_threshold (Image, ImageGauss, DarkPixels1, 9, 'dark')


原图

image.png

mean_image 中值滤波算子(7,7)的效果

image.png

中值滤波后dyn_threshold 的效果:

image.png


gauss_filter高斯滤波(11)的效果。

image.png

高斯滤波后dyn_threshold的效果:

image.png



示例2: 选择渐变色的对象


image.png


dyn_threshold (Image, ImageMean, RegionDynThresh, 15, 'not_equal')的效果

image.png

gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, 6.28318, 'positive', 1)后的效果

image.png



dev_update_off ()

read_image (Image, 'photometric_stereo/embossed_01')
get_image_size (Image, Width, Height)
dev_get_window (WindowHandle)
if (is_handle_elem(WindowHandle) == true)
    dev_resize_window_fit_image (Image, 0, 0, -1, -1)
else
    dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
endif
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (2)

dev_display (Image)
Message := 'Original image'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

mean_image (Image, ImageMean, 59, 59)

dev_display (ImageMean)
Message := 'Mean filtered image'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

dyn_threshold (Image, ImageMean, RegionDynThresh, 15, 'not_equal')

dev_display (Image)
dev_display (RegionDynThresh)
Message := 'Regions segmented with dyn_threshold'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

closing_circle (RegionDynThresh, RegionClosing, 8.5)
opening_circle (RegionClosing, RegionOpening, 6.5)
connection (RegionOpening, ConnectedRegions)
smallest_circle (ConnectedRegions, Row, Column, Radius)
gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, 6.28318, 'positive', 1)

dev_display (Image)
dev_set_color ('green')
dev_display (ContCircle)
Message := 'Results of braille segmentation after morphology'
disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')

dev_update_on ()


示例3:纹理检测


下面这个例子的图片经常在分类器功能中做演示。

其实直接用dyn_threshold效果很好!


原图

image.png

中值滤波

 image.png

dyn_threshold (Image, ImageMean, RegionDynThresh, 5, 'dark') 后的效果

image.png

面积选择

 image.png

dev_update_window ('off')
read_image (Image, 'plastic_mesh/plastic_mesh_01')
dev_close_window ()
get_image_size (Image, Width, Height)
dev_open_window_fit_image (Image, 0, 0, Width, Height, WindowHandle)
set_display_font (WindowHandle, 18, 'mono', 'true', 'false')
dev_set_draw ('margin')
dev_set_line_width (3)

for J := 1 to 14 by 1
    read_image (Image, 'plastic_mesh/plastic_mesh_' + J$'02')
    mean_image (Image, ImageMean, 49, 49)
    dyn_threshold (Image, ImageMean, RegionDynThresh, 5, 'dark')
    connection (RegionDynThresh, ConnectedRegions)
    select_shape (ConnectedRegions, ErrorRegions, 'area', 'and', 500, 99999)
    count_obj (ErrorRegions, NumErrors)
    dev_display (Image)
    dev_set_color ('red')
    dev_display (ErrorRegions)

    if (NumErrors > 0)
        disp_message (WindowHandle, 'Mesh not OK', 'window', 24, 12, 'black', 'true')
    else
        disp_message (WindowHandle, 'Mesh OK', 'window', 24, 12, 'black', 'true')
    endif

    if (J < 14)
        disp_continue_message (WindowHandle, 'black', 'true')
        stop ()
    endif
endfor



--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!


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

发表评论:

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

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 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