【分水岭算法实现过程】

本文详细解析了OpenCV中的分水岭算法实现过程,从初始化mark矩阵到递归注水,阐述了如何通过像素灰度差值进行区域标记和边界检测,最终得到分水岭边界。博客通过实例展示了算法步骤,并强调了算法如何确保最小灰度差的邻域像素参与标记。
摘要由CSDN通过智能技术生成

在做项目中用到了有种子像素的图像分割问题,找到了古老的分水岭算法,看了很多博客,都是直接调用了opencv的函数,对原算法的原理实现与原理解释的很不到位。因此,研究了opencv中分水岭函数的实现原理,参考了阿里云开发者麦克老狼的博客。

原始图像和Mark图像,它们的大小都是32*32,分水岭算法的结果是得到两个连通域的轮廓图。

  

 

初始的mark图像数据如下,黄色的部分为我们的第一个mark区域,值为255,用来标记背景区域,第二个区域为褐红色的区域,值为128,第三个绿色的区域,值为64

 opencv分水岭算法描述如下:

初始化mark矩阵,生成最初的注水区域。

1.设置mark图像的边框值为-1(标记背景区域)

2. 标记每个mark区域的边界为-2(初始填充点)

3. 对于mark图像一个像素值,如果它本身值为0,但上下左右四邻域有一个像素值不为0,则把该点按照(最小邻域灰度差值)放入相应的队列。

      举例说明:如下图像素点,它的mark值为0,但左和上像素值不为0,此时,我们求原始图像中对应像素的灰度差值,计算方式如下面公式,其中I原图像的灰度值,彩色图像为三个颜色值,OpenCV中使用三个通道差分的最大值,下标L表示左,R表示右,T表示上,B表示下,abs表示取绝对值

min(abs(I-IL),abs(I-IT)abs(I-RR),abs(I-IB)

 上图中指定的像素,它的高度值显然为0,所以我们把(22)点放入高度为0的队列中(总共有256个队列,对应0-255的高度)

    初始化阶段完成后,我们得到下面的mark图,并把-2对应的边界像素点,按照其对应的灰度差值放入相应的队列。

  之后就进入了递归注水过程,递归过程描述如下:

for(; ; )

{

    1、从0255扫描灰度差值队列,找到一个像素,则弹出该标记,并退出扫描。从低处填充,邻域像素的高度用与已标记点的灰度差表示,故优先填充所有种子点差值最小的像素。

    2、如果该像素的四邻域中存在两个不同的非0值,表示该点为两个注水盆地的边缘,即分水岭线,在mark图像中标记该点为-1。(两个区域的交汇处,标记为区域之间的分界线)

3、扫描该点的四邻域,是否存在为0mark域,存在的话这把该邻域点按照与该点的灰度差值,放入相应的队列。

4、直到队列中无像素,退出。

}

经过上述的递归过程,最后我们得到的mark图像如下所示,其中绿色格子的-1即为所有的分水岭边界: 

上述递归过程总是从最小的灰度差0到最大255扫描的,因此总能够保证与已标记像素灰度差最小的邻域像素参与标记。 

参考:

OpenCV学习(9) 分水岭算法(3)-阿里云开发者社区 (aliyun.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值