阈值分割引言
阈值分割有非常多的算法,大体上分为全局和局部算法。 全局算法包括全局固定阈值和基于图像直方图的阈值,局部算法包括局部动态阈值分割。 基于图像直方图阈值分割的方法也有很多,比如常规的高斯滤波双峰法,OTSU大津法。 但是这类所有的法都基于一个假设:图像是有前景和背景的,待分割目标处于背景中,即图像直方图是双峰的。 如果因为非均匀光照导致待分割目标不处于背景或前景中,即图像直方图无双峰, 那么基于图像直方图的所有法都是不甚理想的 只能在此基础上进行一定的变换,例如nbl算法等,这些都属于局部算法。 任何算法,都会基于假设空间的。没有假设空间,所有算法性能一致。包括经典算法和深度学习算法。 本系列的贴子勇哥通过实验来细品它们之间的差别,以求以后可以精准应用。
先提供各类阈值分割算子的基础资料如下:
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')
原图
mean_image 中值滤波算子(7,7)的效果
中值滤波后dyn_threshold 的效果:
gauss_filter高斯滤波(11)的效果。
高斯滤波后dyn_threshold的效果:
示例2: 选择渐变色的对象
dyn_threshold (Image, ImageMean, RegionDynThresh, 15, 'not_equal')的效果
gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, 6.28318, 'positive', 1)后的效果
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效果很好!
原图
中值滤波
dyn_threshold (Image, ImageMean, RegionDynThresh, 5, 'dark') 后的效果
面积选择
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
版权声明:本文为博主原创文章,转载请附上博文链接!

