opencv库(7)

图像的分割之基于形态学分水岭的分割

基于标记的形态学分水岭算法

import cv2 as cv
import numpy as np

# 标准形态学分水岭算法
# 针对灰度图像,使用灰度值最低的像素点作为起始点,从起始点开始淹没
# 基于标记的形态学分水岭算法
# 使用灰度值最低的像素点作为起始点,也可以将相对较高的灰度值像素作为标记点,从标记点和起始点开始进行淹没
img = cv.imread("watershed.jpg")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 转换成二值图片
ret, th = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
# 后面的运算都使用一个3×3的中心结构体
kernel = cv.getStructuringElement(cv.MORPH_CROSS, (3, 3))
# 进行开运算
opening = cv.morphologyEx(th, cv.MORPH_OPEN, kernel)
# 进行膨胀腐蚀操作,确定图像的背景、前景以及不确定区域,用不确定区域通过分水岭算法来找到确定的边界
sure_bg = cv.dilate(opening, kernel)
sure_fg = cv.erode(opening, kernel)
# 由于图片之间是彼此接触的,可以使用带阈值的距离变换来得到图像的前景。
# 其中每个像素的值为其到最近的背景像素(灰度值为0)的距离,可以看到硬币的中心像素值最大(中心离背景像素最远)。
# 对其进行二值处理就得到了分离的前景图
dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)
ret, sure_fg = cv.threshold(dist_transform, 0.3 * dist_transform.max(), 255, cv.THRESH_BINARY)
sure_fg = np.array(sure_fg, np.uint8)
unknown = cv.subtract(sure_bg, sure_fg)
# cv.connectedComponents()将背景标记为0,前景标记为大于0的数
ret, marker = cv.connectedComponents(sure_fg)
# 由于cv.watershed()将不确定区域标记为0,背景标记为1,前景标记为大于1的数,故要对marker进行+1操作
marker = marker + 1
# 将不确定区域标记为0
marker[unknown == 255] = 0
# 使用cv.watershed()得到的边界标记为-1
marker = cv.watershed(img, marker)
img[marker == -1] = [255, 0, 0]

# 常用的形态学运算
# 使用一个3×3的中心窗口
kernel = cv.getStructuringElement(cv.MORPH_CROSS, (3, 3))
# 腐蚀运算
# 用于细化图像,去除噪声
cv.erode(img, kernel)
cv.morphologyEx(img, cv.MORPH_ERODE, kernel)
# 膨胀运算
# 消除目标区域内的孔洞
cv.dilate(img, kernel)
cv.morphologyEx(img, cv.MORPH_DILATE, kernel)
# 开运算
# 先腐蚀后膨胀,消除外部噪声
cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
# 闭运算
# 先膨胀后腐蚀,消除内部孔洞
cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)
# 梯度运算
# 相当于膨胀-腐蚀,可以得到图像的轮廓
cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)
# 顶帽运算
# 相当于原始图像-开运算,获取图像外部噪声点
cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
# 黑帽运算
# 相当于闭运算-原始图像,获取图像内部的孔洞
cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)


Guess you like

Origin blog.csdn.net/weixin_49346755/article/details/121052877