分水岭算法-python-opencv

分水岭算法简单原理:

对于一个图像的灰度值,将图像放平,可以看成是类似与山谷与山顶的图像,灰度值小的就是山底。先找到若干个山底,同时加水,当加到一定程度时候,某些山顶会被淹没,此时在山顶修建大坝,避免两处水汇集在一起。此时这个大坝就是分水岭,即边缘。

原图像:

二值化:

 利用OTSU方法首先进行二值化操作:

详情请看:图像阈值处理-OpenCV_独憩的博客-CSDN博客

import cv2.cv2
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

img = cv.imread(r'XXXXX\water_coins.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)

形态学得到边界区域:

对于分水岭算法,我们首先要得到边界可能存在的区域,你们对于上述图像来说,我们要得到的图像为”圆环“

开始直接我们采用开运算去除噪声;

故我们先需要得到一些确定的”背景“,和一些确定的”内部“,利用两者相减得到边界可能存在的区域,即圆环;

确定的”背景“可以使原二值图像”膨胀“得到,确定的”内部“可以使原二值图像”腐蚀“得到,具体原理见:图像膨胀、腐蚀、开运算、闭运算---python.opencv_独憩的博客-CSDN博客

kernel = np.ones((3,3),np.uint8)
#去除噪声
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 3)
#膨胀得到背景
sure_bg = cv.dilate(opening,kernel,iterations=3)
#腐蚀得到前景
sure_fg = cv2.erode(opening, kernel, iterations=3)
sure_fg = np.uint8(sure_fg)
#两者相减得到边缘可能存在区域
unknown = cv.subtract(sure_bg,sure_fg)

plt.figure()
plt.subplot(1,3,1)
plt.imshow(sure_bg,'gray')
plt.title('sure background area')
plt.xticks([]),plt.yticks([])
plt.subplot(1,3,2)
plt.imshow(sure_fg,'gray')
plt.title('sure foreground area')
plt.xticks([]),plt.yticks([])
plt.subplot(1,3,3)
plt.imshow(unknown,'gray')
plt.title('unknown')
plt.xticks([]),plt.yticks([])
plt.show()


但是从图像看出,unknown图像中由于硬币重叠,有部分边界被抵消,故我们采用另外一种方法:

首先介绍一个函数:

dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)

我们只需要知道,这个函数的作用是得到图像(灰度)中所有非零像素与最近的零像素的距离

 我们可以通过对dist_transform图像进行阈值处理得到确定的”内部“,这样的好处是可以控制圆环的粗细,阈值处理 cv.threshold具体见:图像阈值处理-OpenCV_独憩的博客-CSDN博客

kernel = np.ones((3,3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 3)

sure_bg = cv.dilate(opening,kernel,iterations=3)

dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)
ret, sure_fg = cv.threshold(dist_transform,0.5*dist_transform.max(),255,0)
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg,sure_fg)

plt.figure()
plt.subplot(1,3,1)
plt.imshow(sure_bg,'gray')
plt.title('sure background area')
plt.xticks([]),plt.yticks([])
plt.subplot(1,3,2)
plt.imshow(sure_fg,'gray')
plt.title('sure foreground area')
plt.xticks([]),plt.yticks([])
plt.subplot(1,3,3)
plt.imshow(unknown,'gray')
plt.title('unknown')
plt.xticks([]),plt.yticks([])
plt.show()

背景,前景,边界区域分类:

 然后我们需要对背景,前景(内部),边界区域进行分类:

ret, markers = cv2.connectedComponents(sure_fg)

markers = markers+1 #使得背景为1

markers[unknown==255] = 0  #使得边界区域为0
markers_copy = markers.copy()

markers_copy[markers==0] = 150  # 灰色表示背景
markers_copy[markers==1] = 0    # 黑色表示背景
markers_copy[markers>1] = 255   # 白色表示前景

markers_copy = np.uint8(markers_copy)
plt.figure()
plt.imshow(markers_copy,'gray')
plt.title('markers')
plt.xticks([]),plt.yticks([])
plt.show()

 cv2.watershed():

最后直接调用分水岭算法函数:

markers = cv2.watershed(img, markers)
img=cv.cvtColor(img,cv.COLOR_BGR2RGB)
img[markers==-1] = [255,0,0]
plt.figure()
plt.imshow(img,'gray')

plt.xticks([]),plt.yticks([])
plt.show()

 

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV中的分水岭算法是一种图像分割算法,可以将图像分成不同的区域。它可以用Python编程语言来实现。分水岭算法的基本思想是将图像看作一个地形图,然后通过计算水流的路径来将图像分成不同的区域。在OpenCV中,可以使用cv2.watershed()函数来实现分水岭算法。该函数需要输入一个灰度图像和一个标记图像,标记图像用于指定分割的区域。分水岭算法在图像处理和计算机视觉领域中有广泛的应用。 ### 回答2: OpenCV是一个开源的计算机视觉库,其包含了丰富的图像处理和计算机视觉的功能,可以用于处理各种图像和视频。其中,分水岭算法OpenCV中一个常用的图像分割算法,它可以将图像分成两个或多个不同区域。 分水岭算法的基本思想是以图像中的灰度极值点作为种子点,从这些种子点开始,寻找向外扩展的连通区域。当两个不同的连通区域相遇时,它们将会合并在一起。这样不断重复,直到所有的像素都分配到了某个连通区域中为止。 在使用OpenCV进行分水岭算法时,可以先使用cv2.threshold或cv2.adaptiveThreshold对图像进行二值化处理,然后使用cv2.distanceTransform对二值化后的图像进行距离变换,以获取到分水岭算法的必须参数。最后使用cv2.watershed对距离变换后的图像进行分割,并通过cv2.imshow显示结果即可。 使用分水岭算法可以有效的分割图像中的不同部分,并对分割后的结果进行后续处理,例如提取特定区域中的特征等操作。但是由于算法涉及到较多的参数和复杂的操作,对于新手而言,需要花费一定的时间和精力去学习和掌握算法的使用和优化方法。 ### 回答3: OpenCV是一个流行的开源计算机视觉库,支持各种算法和工具。其中之一是分水岭算法,它是一种用于图像分割的强大算法。在Python中使用OpenCV实现分水岭算法,你需要遵循以下步骤: 1. 读取图像:首先,你需要使用OpenCV的imread函数读取图像,同时将它转换为灰度图像。 2. 图像预处理:在分水岭算法之前,你需要对图像进行预处理。这包括通过高斯模糊去噪,使用形态学操作(如开闭运算)去除图像中的小尺寸噪点,以及寻找合适的阈值来产生二值图像。 3. 计算距离变换:分水岭算法需要距离变换作为输入图像。使用距离变换,可以将二值图像中的每一个像素点转换为其与最近背景像素点的距离。 4. 计算标记:将距离变换图像中的每个局部极大值对应的像素位置提取出来,这些位置就是分割的标记。 5. 进行分水岭分割:使用分水岭函数,将距离变换图像和标记作为输入,进行分水岭算法分割。 6. 可视化:最后,你可以将分割结果可视化显示出来。使用OpenCV的imshow函数,你可以将标记可视化为不同的颜色,而最终的分割结果则会显示为突出的边界线。 总的来说,OpenCV分水岭算法可以很好地用于图像分割。但是,注意到算法的成功与否取决于预处理、距离变换、标记计算等多个因素,需要多次迭代并不断调整参数才能获得最佳结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值