分水岭算法和距离变换函数

  • 分水岭算法原理
  • 算法流程
  • 距离变换函数
  • 区域标记
  • 结果
  • 分割示例
  • 代码
    • 分水岭分割
    • 距离函数

分水岭算法原理

在地理学中,分水岭是一个山脊,该山脊通过不同的水系来区分排水区域。集水盆地是把水排入河流或水库的地理区域。分水岭变换把这些概念应用到灰度图像处理中,从而解决许多图像分割问题。
我们把灰度图像视为一个拓扑表面,表面中f(x,y)的值被解释为高度。例如,我们可以把下图中的简单图像形象化为下图中的三维表面。如果雨水降落到该表面上,那么雨水明显会流人集水盆地中。正好降落到分水岭脊线上的雨水会等概率地流到集水盆地中。分水岭变换将找到灰度图像中的集水盆地和脊线。在解决图像分割问题方面,关键概念是把起始图像变为另一幅图像,在变换后的图像中,集水盆地就是我们要识别的物体或区域。

其核心思路是每一张灰度图都可以表示为一个地形图,比如:

如果我们从它的最小值开始淹没这个形状,我们将图像分割成两个不同的集合:集水区和分水岭。

算法流程

  1. 对图像进行二值化
  2. 降噪去除干扰
  3. 使用距离变换函数完成距离变换
  4. 获得边界区域
  5. 标记区域
  6. 使用分水岭算法进行分割
  7. 与原图结合显示

距离变换函数

距离变换函数(opencv中的cv2.distanceTransform函数):
用于计算图像中每一个非零点像素与其最近的零点像素之间的距离,输出的是保存每一个非零点与最近零点的距离信息。
比如构造一200x200大小的图片,其中在(50,60)和(120,120)处,分别有半径为15和12的圆,如下图所示:

对其进行距离变换,得到如下所示图像:

越亮代表距离最近的零点像素之间的距离越大,越暗代表距离越小,对其进行伪彩色增强更加的直观,得到如下图所示图像:

距离变换再加上合适的阈值。接下来我们要找到肯定不是目标的区域。膨胀可以将对象的边界延伸到背景中去。剩下的区域就是我们不知道该如何区分的了。这就是分水岭算法要做的。这些区域通常是前景与背景的交界处(或者两个前景的交界)。我们称之为边界。

区域标记

现在知道哪些是背景那些是目标了。那我们就可以创建标签(一个与原图像大小相同的数组),并标记其中的区域了。对我们已经确定分类的区域(无论是前景还是背景)使用不同的正整数标记,对我们不确定的区域使用 0 标记。我们可以使用函数 cv2.connectedComponents() 来做这件事。它会把将背景标记为 0,其他的对象使用从 1 开始的正整数标记。 但是,我们知道如果背景标记为 0,那分水岭算法就会把它当成未知区域了。所以我们想使用不同的整数标记它们。而对不确定的区域(函数 cv2.connectedComponents 输出的结果中使用 unknown 定义未知区域)标记为 0。
深蓝色区域为未知区域。肯定是目标的区域 使用不同的颜色标记。得到如下图所示的标记,图中的黄色部分,即肯定是目标区域的部分。

结果

再进行分水岭算法,即可得到结果:

分割示例

对如图所示图像进行分割:

对其进行二值化,以及腐蚀操作得到:

用得到的图像进行距离变换,得到如下图所示:

再加上合适的阈值。接下来我们要找到肯定不是目标的区域。用假彩色显示标签,蓝色为目标区域,在与原图进行叠加得到最终的分割区域如图所示:

再对其他图片进行测试得到:


从以上的测试结果,可以看出分水岭分割算法,对于目标背景简单的物体图片进行分割,可以得到较好的效果,但是对于复杂的目标,比如lina图像,分割效果不好。

代码

分水岭分割

import numpy as np
import cv2
from matplotlib import pyplot as pltsrc = cv2.imread('up.jpg')
img = src.copy()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)gray = cv2.GaussianBlur(gray, (5,5), 2)ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)# thresh=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)# 消除噪声
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)# 膨胀
sure_bg = cv2.dilate(opening, kernel, iterations=3)# 距离变换
dist_transform = cv2.distanceTransform(opening, 2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.8*dist_transform.max(), 255, 0)# 获得未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)# 标记
ret, markers1 = cv2.connectedComponents(sure_fg)# 确保背景是1不是0
markers = markers1 + 1# 未知区域标记为0
markers[unknown == 255] = 0markers3 = cv2.watershed(img, markers)
img[markers3 == -1] = [0, 0, 255]plt.subplot(131), plt.imshow(cv2.cvtColor(src, cv2.COLOR_BGR2RGB)),
plt.title('Original'), plt.axis('off')
plt.subplot(132), plt.imshow(np.abs(markers), cmap='jet'),
plt.title('Markers'), plt.axis('off')
plt.subplot(133), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)),
plt.title('Result'), plt.axis('off')
plt.show()

距离函数

from scipy.ndimage.morphology import distance_transform_edt
import numpy as np
import cv2l = 200x, y = np.indices((l, l))center1 = (50, 60)center2 = (120, 120)radius1, radius2 = 15, 12circle1 = (x - center1[0])**2 + (y - center1[1])**2 < radius1**2circle2 = (x - center2[0])**2 + (y - center2[1])**2 < radius2**2# 3 circlesimg = circle1 + circle2
img = ~img
ig = img
img = np.uint8(img*255)
cv2.imshow("0", img)
cv2.imwrite("0.jpg", img)kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)sure_bg = cv2.dilate(opening, kernel, iterations=3)
# img = distance_transform_edt(img)
img = cv2.distanceTransform(img, 2, 5)ret, sure_fg = cv2.threshold(img, 0.7*img.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)# 标记
ret, markers1 = cv2.connectedComponents(sure_fg)# 确保背景是1不是0
markers = markers1 + 1# 未知区域标记为0
markers[unknown == 255] = 0
im_color1=cv2.applyColorMap(cv2.convertScaleAbs(markers,alpha=150),cv2.COLORMAP_JET)
cv2.imshow("4", im_color1)
cv2.imwrite("4.jpg", im_color1)markers3 = cv2.watershed(ig, markers)
img[markers3 == -1] = [255]
cv2.imshow("5", img)img_max = np.max(img)
img = np.uint8(img*255/img_max)
cv2.imwrite("3.jpg", img)im_color=cv2.applyColorMap(cv2.convertScaleAbs(img,alpha=1),cv2.COLORMAP_JET)
cv2.imshow("1", im_color)
cv2.imwrite("1.jpg", im_color)
cv2.waitKey(0)

分水岭算法和距离变换函数相关推荐

  1. opencv进阶学习笔记14:分水岭算法 实现图像分割

    基础版学习笔记目录: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 分水岭算法原理 分水岭算法 ...

  2. OpenCV(26)图像分割 -- 距离变换与分水岭算法(硬币检测、扑克牌检测、车道检测)

    目录 一.基础理论 1.思想 2.原理 二.分水岭实战:硬币 步骤归纳 1.把原图像转二值图 2.开运算去噪 3.确定背景区域(膨胀)(得到背景/最大连通域) 4.确定前景区域(距离变换) (分离)( ...

  3. 分水岭算法(学习笔记)

    分水岭算法watershed 进行图像分割 基本的步骤 通过形态学开运算对原图像O去噪 通过膨胀操作获取"确定背景B" 利用距离变换函数对图像进行运算,并对其进行阈值处理,得到&q ...

  4. c++实现分水岭算法

    水岭算法是一种基于图论的图像分割算法,它将图像看做一个拓扑图,利用水位不断上升的过程将图像中的区域分割出来.以下是使用 C++ 实现分水岭算法的步骤及讲解: 导入必要的头文件: #include &l ...

  5. 使用分水岭算法对米粒进行精准分割(2)

    背景:(https://blog.csdn.net/qq_36623595/article/details/109250114)因为本篇帖子中对米粒中黏连的部分没有精确分割,经过探索得出了以下结论 本 ...

  6. OpenCV+python:分水岭算法

    1,概念简介 现实中我们可以或者说可以想象有山有湖的景象,那么那一定是水绕 山,山围水的情形.当然在需要的时候,要人工构筑分水岭,以防集水盆之间的互相穿透.而区分高山(plateaus)与水的界线,以 ...

  7. Python OpenCV分水岭算法分割和提取重叠或有衔接的图像中的对象

    本文将介绍如何使用分水岭算法对触摸和重叠的图像中的对象进行分割和提取. 参考:https://www.pyimagesearch.com/2015/11/02/watershed-opencv/ 分水 ...

  8. pythonopencv算法_python opencv之分水岭算法示例

    本文介绍了python opencv之分水岭算法示例,分享给大家,具体如下: 目标 使用分水岭算法对基于标记的图像进行分割 使用函数cv2.watershed() 原理: 灰度图像可以被看成拓扑平面, ...

  9. 分水岭算法分割图像的原理概述及OpenCV代码实现

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 前面博文中提到的图像阈值化,图像边缘检测,图像轮 ...

最新文章

  1. 一个好用的C++的json库
  2. 修改python plot折线图的坐标轴刻度
  3. 计算机文献读后感,论文读后感
  4. tensorflow去掉某一维度_在Python中解压缩(取消堆栈)一个输入(占位符),在tensorflow中有一个None维度...
  5. pywin32 获取窗口句柄_Excel VBA | 这个窗口居然关不掉
  6. 1909升级卡64_【春节配置推荐】第3期:设计娱乐万元配置推荐、四代升级建议参考...
  7. 手机txt拆分器_TXT文本分割器
  8. 背包九讲Java版本
  9. 约瑟夫问题 c语言数组,约瑟夫问题的数组实现
  10. uni-app生成pdf,依赖html2canvas和jspdf
  11. 浅议初中语文微写作(语文教师论文)
  12. 基于OpenHarmony的智慧牧场
  13. 很久以前某位大仙对petri网的总结
  14. C语言停车场管理系统
  15. Eclipse-CDT
  16. chmod授权sh文件执行权限
  17. 大学的计算机证书,大学必拿的几个证书是什么?
  18. 飞行控制系统大讲堂系列五(下洗气流和下洗角)
  19. 有什么靠谱的Python培训机构
  20. 数学模型在计算机科学与技术,科学计算与数学建模

热门文章

  1. VIGA--病毒基因组注释
  2. OpenAI gym Atari游戏的环境设置
  3. nginx安全漏洞(CVE-2021-23017)修复
  4. openwrt mesh网络设置
  5. python怎么去掉换行符_python去除空格和换行符的实现方法(推荐)
  6. 小米手机开机自启动软件及定时开关机
  7. 如何获取注册高德Key使用的SHA1值
  8. 20行代码制作字符画版小黄鸭表情包 | 文末送书抽奖结果
  9. 2021年中国嵌入式系统软件业务收入及业务收入结构分析[图]
  10. RabbitMQ可视化界面登录不了,报错:Login failed