【图像处理】图像分割与Watershed算法

参考《OpenCV4.1中文官方文档》

理论

任何灰度图像都可以看作是一个地形表面,其中高强度表示山峰,低强度表示山谷。

你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。

随着水位的上升,根据附近的山峰(坡度),来自不同山谷的水明显会开始合并,颜色也不同。

为了避免这种情况,你要在水融合的地方建造屏障。

你继续填满水,建造障碍,直到所有的山峰都在水下。

然后你创建的屏障将返回你的分割结果。

这种方法会由于图像中的噪声或其他不规则性而产生过度分割的结果。

因此OpenCV实现了一个基于标记的分水岭算法,

你可以指定哪些是要合并的山谷点,哪些不是。

我们所做的是给我们知道的对象赋予不同的标签。

用一种颜色(或强度)标记我们确定为前景或对象的区域,

用另一种颜色标记我们确定为背景或非对象的区域,

最后用 0 标记我们不确定的区域。

然后应用分水岭算法。然后我们的标记将使用我们给出的标签进行更新,对象的边界值将为 -1 。

代码

在这里插入图片描述

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

img = cv.imread('E:/project/test/test.png') 
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)

kernel = np.ones((3,3),np.uint8) 
#开运算 消除噪音
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)

# 膨胀 确定背景区域 
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.7*dist_transform.max(),255,0) #相当于腐蚀

sure_fg = np.uint8(sure_fg) 
unknown = cv.subtract(sure_bg,sure_fg)

ret, markers = cv.connectedComponents(sure_fg) #创建标记图

markers = markers+1 
markers[unknown==255] = 0

marke=np.uint8(markers)
cv.imshow("markers", marke)
cv.waitKey(0)

markers = cv.watershed(img,markers)
#Watershed算法 第一个参数是图像,第二个参数是标记图
#会根据markers传入的轮廓作为种子(也就是所谓的注水点),
#对图像上其他的像素点根据分水岭算法规则进行判断,
#并对每个像素点的区域归属进行划定,直到处理完图像上所有像素点
#区域与区域之间的分界处的值被置为“-1”,以做区分。

img[markers == -1] = [255,0,0]
cv.imshow("ans", img)
cv.waitKey(0)

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值