halcon 阈值分割

前言

图像二值化是图像分析与处理中最常见最重要的处理手段,二值处理方法也非常多。越精准的方法计算量也越大。参考博客:

1.threshold-全局固定阈值分割

threshold(Image : Region : MinGray, MaxGray : )
——使用全局固定阈值分割图像
阈值从输入图像中选取灰度值g满足以下条件的像素点
在这里插入图片描述
满足条件的图像的所有点作为一个区域返回。如果传递多个灰度值间隔(MinGray和MaxGray的元组),则每个间隔返回一个单独的区域。对于向量场图像,阈值不应用于灰度值,而是应用于向量的长度。

应用一:利用灰度直方图确定阈值进行图像分割。一般是物体与背景之间存在一个明显的灰度差,直方图会存在两个波峰一个是目标一个是背景,那么阈值就是物体与背景之间的最小值。

read_image (Image, 'clip')
*计算直方图
gray_histo (Image, Image, AbsoluteHisto, RelativeHisto)
*将直方图转换为区域(包含直方图的区域;输入的直方图;直方图中心的行/列坐标;直方图的比例因子)
gen_region_histo (Region, AbsoluteHisto, 255, 255, 1)
*利用直方图获取阈值
histo_to_thresh (AbsoluteHisto,10, MinThresh, MaxThresh)
*期望阈值
TarGetGray:=23
for Index := |MinThresh|-1 to 0 by -1
 if(MinThresh[Index]<=TarGetGray)
 	 	 MinThresh:= MinThresh[Index]
  	 break
  	 endif
 endfor
 for Index1 := 0 to |MaxThresh|-1 by 1
 	  if (MaxThresh[Index1]>=TarGetGray)
  	  		 MaxThresh:=MaxThresh[Index1]
 	  break
      endif
 endfor
*全局阈值分割
threshold (Image, Region1, MinThresh, MaxThresh)

    
    
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

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

2.Binary Threshold-自动全局阈值分割

参考: 阈值分割算子之OSTU算法(binary_threshold)
binary_threshold(Image : Region : Method, LightDark : UsedThreshold)
——自动全局阈值分割(自动确定的全局阈值分割单通道图像,并在区域中返回分割后的区域)
输入:

  • Image:需要进行阈值的图像
  • Region:处理后的区域

输出:

  • Method:分割方法(‘max_separability’:最大限度的可分性, ‘smooth_histo’:直方图平滑)
  • LightDark:提取的是黑色部分还是白色部分
  • UsedThreshold:自动阈值使用的阈值值
	read_image (Image, 'clip')
	binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold)

    
    
    
    
  • 1
  • 2

例如,分割均匀照明的背景上有用的字符。binary_threshold还返回UsedThreshold中使用的阈值。
使用的阈值由方法中给出的方法确定。目前,该操作符提供了以下两个方法:
’max_separability’:最大限度的可分性, ‘smooth_histo’:直方图平滑
这两种方法只能用于具有双峰直方图的图像。(如下图)

smooth_histo方法提供的功能与操作符bin_threshold提供的功能相同。方法’max_separability’倾向于为UsedThreshold确定较小的值。此外,它对柱状图中的稀疏孤立峰不那么敏感,而且通常比‘smooth_histo’更快。

最大限度的可分性(max_separability):
通过选择Method= ’ max_separability ',根据“灰度直方图的阈值选择方法”的灰度直方图自动阈值调用。该算法首先计算图像的直方图,然后利用统计矩找到将像素分割为前景和背景的最优阈值,并最大化这两个类之间的可分性。此方法仅适用于byte和uint2图像
如果LightDark = ‘light’,则选中所有灰度值大于或等于"T*"的像素。
如果LightDark = ‘dark’,则选中所有灰色值小于"T*"的像素。

直方图平滑(smooth_histo):
通过选择Method = 'smooth_histo ’ binary_threshold可以通过以下方式确定阈值:首先确定灰度值的相对直方图。然后,从直方图提取相关的最小值,作为阈值操作的参数。为了减少最小值,直方图被平滑处理为一个高斯函数,就像在auto_threshold中一样。在平滑直方图中,掩模尺寸增大,直到最小值。然后,阈值设置为这个最小值的位置。
如果LightDark = ‘light’,则选中所有灰度值大于或等于"T*"的像素。
如果LightDark = ‘dark’,则选中所有灰色值小于"T*"的像素。

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

3.dyn_threshold-局部动态阈值分割

在这里插入图片描述
dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset, LightDark : )
——局部动态阈值分割 Dynamic Threshold

  • ThresholdImage:是我们用来作为灰度值参考的另外一幅图像,在实际使用过程中通常都是对原图像OrigImage进行一次平滑处理,然后用平滑处理之后得到的图像作为参考图像。
  • LightDark:是问我们提取亮?暗?还是相似的区域?(当然,这是相对于ThresholdImage)
  • Offset:其实是在设定一个比较的区间范围,因为在图像处理这个主观性本来就比较强的领域中“绝对”这个科学名次实在有点太过分,所以什么事情,只要在一个合理的范围内,我们都是可以接受的,而不是死死抓住一个点不放,最后也得不到想要的结果。

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就会越小。
在这里插入图片描述
在这里插入图片描述

经过dyn_threshold这个算子处理之后,我们就可以提取一个物体的轮廓了,具体提取的方法当然要用到什么类似select_shape之类的算子,当然,这里最重要的是gen_contour_region_xld这个算子,用你刚才提取出来的这些区域生成XLD轮廓线,这样就达到了提取物体轮廓的目的。 注意,我们这样提取出来的所有符合条件的像素点都会被返回到一个region中去,所以如果你要分开的区域的话,就用connection这个算子再计算一下就好啦。

小结:

threshold是最简单的阈值分割算子,理解最为简单;binary_threshold是自动阈值算子,它可以自动选出暗(dark)的区域,或者自动选出亮(light)的区域,理解起来也没有难度。
动态阈值算子dyn_threshold理解起来稍微复杂一点,使用dyn_threshold算子的步骤基本是这样的:

① 将原图进行滤波模糊处理。

② 用原图和模糊后的图逐个像素做比较,它可以根据参数分割出原图比模糊后的图灰度高(或者低)若干个灰度值的区域。
举例如下:
在这里插入图片描述
处理代码:

read_image (Image, ‘C:/Users/happy xia/Desktop/dynPic.png‘)
mean_image (Image, ImageMean, 9, 9)
dyn_threshold (Image, ImageMean, RegionDynThresh, 10, ‘dark‘)

    
    
    
    
  • 1
  • 2
  • 3

程序分析:本例中,将图片模糊后,点阵字的黑色扩散了,随之就是字的黑色不如原图那么黑了,那么通过给定的限值“10”和“dark”,就可以将原图比模糊后的图暗10个灰阶以上的区域(即黑色文字部分)选出来了。

4.var_threshold算子-均值和标准偏差局部阈值分割

Halcon阈值化算子dual_threshold和var_threshold的理解

var_threshold(Image : Region : MaskWidth, MaskHeight, StdDevScale, AbsThreshold, LightDark : )
——均值和标准偏差局部阈值分割,能够较好的分开目标和背景,对不适合的参数设置不敏感。

  • MaskWidth、 MaskHeight 是用于滤波平滑的掩膜单元;
  • StdDevScale 是标准差乘数因子(简称标准差因子);
  • AbsThreshold 是设定的绝对阈值;
  • LightDark 有4个值可选,’light’、’dark’、’equal’、’not_equal’。

var_threshold图像灰度值在均值与方差之和以上或在均值与方差之差以下

1)应用示例

var threshold (Image, Region, 4, 4, 0.2, 12, 'dark' )

    
    
    
    
  • 1

在该程序中,先用4x4的掩膜在图像上逐像素游走,用原图中的当前像素和对应掩膜中16个像素的灰度均值对比,找出暗(dark)的区域。当原图像素灰度比对应的掩膜灰度均值低(0.2,12)个灰阶时(本程序中StdDevScale = 0.2, AbsThreshold = 12),该区域被分割出来。
问题的关键就是理解如何通过StdDevscale和AbsThreshold来确定用于分割的阈值。

2)var_threshold的帮助文档
在这里插入图片描述

  • 1)d(x,y)指的是遍历每个像素时,掩膜覆盖的那些像素块(本例中是4×4 = 16个像素)灰度的标准差;StdDevScale 是标准差因子;
  • 2)当标准差因子StdDevscale>=0时, v(x.y)取(StdDevscale x 标准差)和AbsThreshold中较大的那个 ;
  • 3)当标准差因子StdDevScale<= 0时, v(xy)取(StdDevscale x 标准差)和AbsThreshold中较小的那个。

实测发现,这里的比较大小是带符号比较,由于标准差是非负数,当StdDevscale <0时,(StdDevscalex标准差) <=0恒成立,所以此时的取值就是(StdDevScale x标准差) 。

  • 帮助文档中StdDevscale的推荐值范围是-1-1,一般通过上面的例子可知,一般的明显的黑白过度处的在50左右,StdDevScale即-50 ~50 ,50的灰度差异,对于一般分割来说足够。

  • 标准差文档还说:推荐的值是0.2,如果参数StdDevScale太大,可能分割不出任何东西;如果参数StdDevScale太小(例如-2) ,可能会把整个图像区域全部输出,也就说达不到有效分割的目的。一般推荐使用该算子时,StdDevScale取正值。

  • 需要强调的是:在黑白过渡处,一般掩膜覆盖的像素的标准差较大,而在其他平缓的地方,标准差较小;因此最终采用的分割值随着掩膜在不断遍历像素的过程中,在(StdDevScale x 标准差)和AbsThreshold之间不断切换。

3)var_threshold和dyn_threshold的区别和联系:

  • var_threshold算子和dyn_threshold算子极为类似,不同的是var threshold集成度更高,并且加入了"标准差x标准差因子"这一变量。可以有效地减少噪声对分割的影响
  • dyn_threshold是将原图和滤波平滑后的图对比, var_threshold是将原图和对应像素掩膜覆盖的像素的平均,灰度值对比,在算子var_threshold中,如果参数StdDevScale=0,那么就可以用动态阈值的方式非常近似地模拟,以上两种算法的效果,极为类似。
  • 那么当StdDevScale > 0 时,var_threshold对比dyn_threshold还存在什么优点呢?我认为是在黑白过渡处能减少分割出不需要的区域的概率。(因为黑白过渡处标准差大,当然前提是StdDevScale 不能设置得太小)
    在这里插入图片描述

5.dual_threshold-双重阈值分割(有符号图像的阈值算子)

dual_threshold(Image : RegionCrossings : MinSize, MinGray, Threshold : )

  • MinSize 表示分割出来的区域的最小面积(即分割出来的面积要大于MinSize);
  • MinGray 表示分割出来的区域对应的原图中图像像素的最高灰度大于MinGray设定值。
  • threshold 灰度值小于阈值(或大于阈值)的区域被抑制;
  • dual_threshold算子的缺陷:它只能分割出灰度值高的亮区域,不能分割出灰度值低的暗区域
read_image (Image, ‘C:/Users/happy xia/Desktop/2.png‘)
dual_threshold (Image, RegionCrossings1, 174, 200, 180)
dual_threshold (Image, RegionCrossings2, 176, 200, 180)
dual_threshold (Image, RegionCrossings3, 176, 216, 180)

* MinGray = Threshold 时,即为单阈值分割:选取灰度值大于180的区域
dual_threshold (Image, RegionCrossings4, 176, 180, 180)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

源图:
在这里插入图片描述
RegionCrossings1
在这里插入图片描述
RegionCrossings2
在这里插入图片描述
RegionCrossings3(齿轮右下角灰度值未超过216,故无法选取)
在这里插入图片描述
RegionCrossings4()
在这里插入图片描述

6.auto_threshold-自动全局阈值分割

auto_threshold(Image : Regions : Sigma : )
——根据直方图确定阈值自动全局阈值分割

  • 运行原理,
  • 第一,计算灰度直方图。
  • 第二,高斯平滑后从直方图提取最小值。
  • 第三,根据提取的最小值进行阈值分割。sigma越大提取区域越少。
	read_image (Image, 'fabrik')
	median_image (Image, Median, 'circle', 3, 'mirrored')
	auto_threshold (Median, Regions, 3)

 
 
 
 
  • 1
  • 2
  • 3

7.fast_threshold-快速全局阈值分割

fast_threshold(Image : Region : MinGray, MaxGray, MinSize : )
——快速全局阈值分割

  • 灰度值满足MinGray<=g<=MaxGra聚合为一个区域,为了节省时间按两步执行。
  • 第一,先处理行列间隔Minsize的所有像素点。
  • 第二,处理上一步选择点的领域。和threshold相比分割速度快。

8.watersheds-分水岭算法分割

watersheds(Image : Basins, Watersheds : : )
——分水岭图像分割。可以分割出分水岭和盆地。
watersheds_threshold(Image : Basins : Threshold : )
——通过阈值实现图像的分水岭算法分割

	read_image (Br2, 'particle')
	gauss_filter (Br2, ImageGauss, 9)
	invert_image (ImageGauss, ImageInvert)
	watersheds (ImageInvert, Basins, Watersheds)
	dev_set_draw ('margin')
	dev_set_colored (12)
	dev_display (Br2)
	dev_display (Basins)

 
 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

第1步:
通过分水岭算法watersheds()获取图像的盆地。
第2步:
根据第一步分水岭算法分离结果,若盆地部分的灰度**< threshold**,则被合并到一起。设B1和B2分别为相邻盆地的最小灰度值,W为将盆地分割为两个盆地的最小灰度值。则分割结果为:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值