Halcon算子学习:图像阈值分割-threshold、binary_threshold、dyn_threshold算子
Halcon算子学习:图像阈值分割算子
前言
1.threshold-全局固定阈值分割
2.Binary Threshold-自动全局阈值分割
3.dyn_threshold-局部动态阈值分割
小结:
4.var_threshold算子-均值和标准偏差局部阈值分割
5.dual_threshold-双重阈值分割(有符号图像的阈值算子)
6.auto_threshold-自动全局阈值分割
7.fast_threshold-快速全局阈值分割
8.watersheds-分水岭算法分割
前言
图像二值化是图像分析与处理中最常见最重要的处理手段,二值处理方法也非常多。越精准的方法计算量也越大。参考博客:
图像处理之常见二值化方法汇总
Halcon阈值化算子dual_threshold和var_threshold的理解
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)
2.Binary Threshold-自动全局阈值分割
参考: 阈值分割算子之OSTU算法(binary_threshold)
binary_threshold(Image : Region : Method, LightDark : UsedThreshold)
——自动全局阈值分割(自动确定的全局阈值分割单通道图像,并在区域中返回分割后的区域)
输入:
Image:需要进行阈值的图像
Region:处理后的区域
输出:
Method:分割方法(‘max_separability’:最大限度的可分性, ‘smooth_histo’:直方图平滑)
LightDark:提取的是黑色部分还是白色部分
UsedThreshold:自动阈值使用的阈值值
例如,分割均匀照明的背景上有用的字符。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-局部动态阈值分割
小结:
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为将盆地分割为两个盆地的最小灰度值。则分割结果为: