由于阈值处理直观,实现简单且计算速度快,因此阈值处理再图像分割应用处于核心地位
假设一个图像的灰度直方图对应于图像的$f(x,y)$,而该图像由暗色背景上的较亮物体组成,那么,就可以设置一个全局阈值T,然后对于每一个$f(x,y)>T$的点称之为对象点,其余的称之为背景点,从而达到了分割图像的目的。
基本的全局阈值处理
当物体的背景像素的灰度分布十分明显时,可以用适用于整个图像的单个(全局)阈值。通常图像之间有较大的变化,使用手动设置的全局阈值是一种方法,当然也有着对图像进行自动阈值估算的算法
迭代法
1,为全局阈值$T_{0}$选择一个初始估计值(一般为中位数)
2,使用 把图像分割成两个部分 和,并计算其平均灰度 和$m_{2}$
3,计算新阈值
4,重复步骤2到4,直到$T_{0} <\Delta T$
这样就可以计算出一个比较合适的阈值$T_{0}$
实现
1 | void thresholdByIterate(const ImageUtil::ImageData& data) |
Otsu法
阈值处理可以视为一种统计决策理论问题。其目的在于把像素分为两个或多个组,使得分组的时候引入的平均误差最小。
而Otsu法则是一种很好的方案,他的思想在于,使得分组之间的类间方差最大化,这么,也就是相当于每一个类里面的方差是最小的,从而达成了一个比较好的分割的目的。
Otsu方法还有一个特性,就是他可以完全在一个图片上的直方图进行运算。
由于Otsu方法的思想在于取得最大的类间方差,那么,我们需要做的就是计算出每一个类里的平均灰度值,以及他们之间的方差即可。
证明
以下证明来自于冈萨雷斯的《数字图像处理(第三版)》
首先,我们选择一个阈值,然后把输入的图像分为两类和,那么当中所有的所有的点由所有灰度值在内的像素组成,而同理。
那么我们可以得知,类的概率可以这样得到
类同理
而分配到类的平均灰度值为
同样同理。
而我们同样可以根据直方图计算出全局的平均灰度值
我们可以这样验证这个公式
在拥有了每一个类的平均灰度值与全局灰度值之后,我们就可以计算类间的方差了。
由于只需要计算一次,所以,我们只需要对应每一个选定的阈值k
都计算其P_1,m_k
既可以计算出所有阈值下的方差了。
最后,我们只需要寻找到方差最大的一个阈值,设置为最终阈值即可。(若有多个相同大小的最大阈值,就取其平均值)。
实现
根据公式,即可以写出其中的算式实现。
1 | //计算方差 |
然后,我们就可以开始利用这些公式计算了。
1,输入归一化的直方图
2,计算出全局灰度
3,对于每一个灰度分量阈值k都计算出其类间方差
4,选出其中的方差最大的作为阈值k,若有相同的,取平均值
从而既可以实现Ostu方法了。
1 |
|
基于边缘的灰度分割
由于直方图很少依赖物体与背景的大小,因此,有时候会出现阈值处理失败的情况。比如,一个大的背景当中有很多噪点,这样会污染了直方图。
因此,在直方图的处理上有一种改进就是利用图像的边缘。因为图像的边缘四周是背景或者是前景图的概率是很高的。
这种算法的思想在于
1,计算图像的边缘(拉普拉斯算子之类的)
2,设置阈值T,将边缘图当中所有大于T的像素点设为1,否则为0
3,根据像素图当中1的点的位置,只使用这些位置的点,计算出原图的直方图
4,对直方图进行全局分割(例如Otsu方法)
Laplace + Otsu 实现
1 | void laplaceOstu(const ImageUtil::IMGDATA& data) |