图像分割
图像分割就是把图像分成若干个特定的、具有独特性质的区域并提出感兴趣目标的技术和过程。它是由图像处理到图像分析的关键步骤。现有的图像分割方法主要分以下几类:基于阈值的分割方法、基于边缘的分割方法、基于区域的分割方法以及基于特定理论的分割方法等。
阈值法的基本思想是基于图像的灰度特征来计算一个或多个灰度阈值,并将图像中每个像素的灰度值与阈值相比较,最后将像素根据比较结果分到合适的类别中。因此,该类方法最为关键的一步就是按照某个准则函数来求解最佳灰度阈值。
Otsu分割算法原理简介
Otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之内的灰度差异最小,通过方差的计算来寻找一个合适的灰度级别 来划分。 所以 可以在二值化的时候 采用Otsu算法来自动选取阈值进行二值化。Otsu算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。因此,使类间方差最大的分割意味着错分概率最小。
设t为设定的阈值。
wo: 分开后 前景像素点数占图像的比例
uo: 分开后 前景像素点的平均灰度
w1: 分开后 后景像素点数占图像的比例
u1: 分开后 后景像素点的平均灰度
u=wo*uo + w1*u1 :图像总平均灰度
从L个灰度级遍历t,使得t为某个值的时候,前景和后景的方差最大,则这个 t 值便是我们要求得的阈值。
其中,方差的计算公式如下:
g=wo*(uo-u)*(uo-u)+w1*(u1-u)*(u1-u)
此公式计算量较大,可以采用:g=wo*w1*(uo-u1)*(uo-u1)
由于Otsu算法是对图像的灰度级进行聚类,因此,在执行Otsu算法之前,需要计算该图像的灰度直方图。
上一篇,我们用diblook示例成功显示了bmp图像,在加入算法之前,我们先分析一下diblook的结构,仔细看一下官方diblook的示例,我们会发现以下描述信息:
原来,我们是从文件中读取的DIB,然后为其准备调色板对象CPalette。再利用Ondraw调用Windows例程::PaintDIB显示DIB,而这些相关的API在Dibapi.cpp文件中。
我们可以打开来看一看:
可以看到这个文件提供的函数接口,下面还有具体的函数实现,另外我们也可以看一下图中其他几个cpp文件。
接下来,我们就要往里面加入算法了!
这一次,我们先实现两个相对简单的算法,我会尽量把MFC的创建消息的过程写清楚。
首先我们打开资源视图1->2->3,然后就会在左边窗口出现4
这个界面是不是很熟悉,没错,我们上一篇文章就是用这个界面显示的bmp,这里就是MFC的界面啦,我们在4的窗口下输入一个新的菜单项image processing,并在其下加入两个子菜单Invert(反色)和Otsu(大津分割),注意,不要用中文菜单名,编译后运行会出现乱码。最后如图所示:
添加完成之后,我们可以点击看看这两个子菜单的ID值:ID_IMAGEPROCESSING_INVERT和ID_IMAGEPROCESSING_OTSU
然后我们添加类向导:
在类向导页面,我们设置类名为CDibView,对象ID为ID_IMAGEPROCESSING_INVERT,点击消息COMMAND,最后点击添加处理程序,如下图所示:
上面添加的只是反色的消息,请自行添加OTSU的消息。
添加完成之后,我们会发现程序自动跳转到了dibview.cpp文件下,并创建了两个消息机制
void CDibView