欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV与图像处理学习十一——分水岭算法(含代码)

发布时间:2024/7/23 编程问答 61 豆豆
生活随笔 收集整理的这篇文章主要介绍了 OpenCV与图像处理学习十一——分水岭算法(含代码) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

OpenCV与图像处理学习十一——分水岭算法(含代码)

  • 一、分水岭算法概要
  • 二、分水岭算法步骤
  • 三、代码应用

一、分水岭算法概要

任意的灰度图像可以被看做是地质学表面,高亮度的地方是山峰,低亮度的地方是山谷。

给每个孤立的山谷(局部最小值)不同颜色的水(标签),当水涨起来,根据周围的山峰(梯度),不同的山谷也就是不同的颜色会开始合并,要避免山谷合并,需要在水要合并的地方建立分水岭,直到所有山峰都被淹没,所创建的分水岭就是分割边界线,这个就是分水岭的原理。

二、分水岭算法步骤

  • 将白色背景变成黑色背景——目的是为了后面的变换做准备
  • 使用filter2D与拉普拉斯算子实现图像对比度的提高
  • 转为二值图像
  • 距离变换
  • 对距离变换结果进行归一化[0-1]之间
  • 使用阈值,在此二值化,得到标记
  • 腐蚀每个peak erode
  • 发现轮廓 findContours
  • 绘制轮廓 drawContours
  • 分水岭变换 watershed
  • 对每个分割区域着色输出结果
  • 三、代码应用

    """ 完成分水岭算法步骤: 1、加载原始图像 2、阈值分割,将图像分割为黑白两个部分 3、对图像进行开运算,即先腐蚀在膨胀 4、对开运算的结果再进行 膨胀,得到大部分是背景的区域 5、通过距离变换 Distance Transform 获取前景区域 6、背景区域sure_bg 和前景区域sure_fg相减,得到即有前景又有背景的重合区域 7、连通区域处理 8、最后使用分水岭算法 """import cv2 import numpy as np# Step1. 加载图像 img = cv2.imread('image/yezi.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Step2.阈值分割,将图像分为黑白两部分 ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) cv2.imshow("thresh", thresh)# Step3. 对图像进行“开运算”,先腐蚀再膨胀 kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) cv2.imshow("opening", opening)# Step4. 对“开运算”的结果进行膨胀,得到大部分都是背景的区域 sure_bg = cv2.dilate(opening, kernel, iterations=3) cv2.imshow("sure_bg", sure_bg)# Step5.通过distanceTransform获取前景区域 dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) # DIST_L1 DIST_C只能 对应掩膜为3 DIST_L2 可以为3或者5 ret, sure_fg = cv2.threshold(dist_transform, 0.1 * dist_transform.max(), 255, 0)cv2.imshow("sure_fg", sure_fg)# Step6. sure_bg与sure_fg相减,得到既有前景又有背景的重合区域 #此区域和轮廓区域的关系未知 sure_fg = np.uint8(sure_fg) unknow = cv2.subtract(sure_bg, sure_fg) cv2.imshow("unknow", unknow)# Step7. 连通区域处理 ret, markers = cv2.connectedComponents(sure_fg, connectivity=8) # 对连通区域进行标号 序号为 0 - N-1 markers = markers + 1 # OpenCV 分水岭算法对物体做的标注必须都 大于1 ,背景为标号 为0 因此对所有markers 加1 变成了 1 - N # 去掉属于背景区域的部分(即让其变为0,成为背景) # 此语句的Python语法 类似于if ,“unknow==255” 返回的是图像矩阵的真值表。 markers[unknow==255] = 0# Step8.分水岭算法 markers = cv2.watershed(img, markers) # 分水岭算法后,所有轮廓的像素点被标注为 -1 print(markers)img[markers == -1] = [0, 0, 255] # 标注为-1 的像素点标 红 cv2.imshow("dst", img) cv2.waitKey(0) cv2.destroyAllWindows()

    原图为:

    使用大津阈值法二值化后的结果:

    开运算消除一些噪声(本例不明显):

    做膨胀操作,那么得到的背景区域一定是背景区域:

    做距离变换操作(或腐蚀),那么得到的前景一定为真正的前景:

    中间是既有前景又有背景的重合区域,此区域和轮廓区域的关系未知:

    分水岭算法之后的效果为:

    总结

    以上是生活随笔为你收集整理的OpenCV与图像处理学习十一——分水岭算法(含代码)的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。