其他
OpenCV基于标记控制的分水岭分割算法演示
点击上方↑↑↑“OpenCV学堂”关注我
常见图像分割算法之一
分水岭分割
图像分水岭分割是基于图像形态学的语义分割算法,常见的算法实现主要基于标记的分水岭分割方法,图示如下:
算法就是要找到分水岭线,对图像完成分水岭分割,这个在生物与医学图像处理中特别有用。主要原因是常见的分水岭算法是基于灰度基本与距离变换结果寻找分割线,很容易导致过度分割,过度分割的合并有比较复杂,而基于标记(marker)的分水岭分割算法就比较稳定,一般情况下不会产生过度分割问题。所以OpenCV中也完成了基于标记(marker)的分水岭分割算法。
图像分水岭分割流程
正常对于输入图像首先需要转换为灰度图像、然后二值图像,通过距离变换生成标记,然后使用分水岭变换算法得到输出结果,可视化输出即可。其中距离变换是很重要的一个环节,另外在输入图像质量不佳的情况下,通常会通过高斯或者非局部均值进行去噪以后在完成上述一系列操作,完整的流程图示如下:
代码实现与各步输出
代码实现与各步输出
输入图像如下:
二值化之后
开操作与膨胀操作
距离变换
前景图像
分水岭分割结果
完整的演示代码如下:
import cv2 as cv
import numpy as np
src = cv.imread("D:/images/water_coins.jpg")
cv.imshow("input", src)
gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)
cv.imshow("binary", binary)
# 形态学操作
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
open_img = cv.morphologyEx(binary, cv.MORPH_OPEN, se, iterations=2)
# sure background area
sure_bg = cv.dilate(open_img,se,iterations=3)
cv.imshow("sure_bg", sure_bg)
# 距离变换
dist_transform = cv.distanceTransform(open_img, cv.DIST_L2, 5)
ret, sure_fg = cv.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
cv.imshow("distance transform", dist_transform/50)
cv.imshow("sure_fg", sure_fg)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg, sure_fg)
# 连通组件标记 - 发现markers
ret, markers = cv.connectedComponents(sure_fg)
markers = markers+1
# 设定边缘待分割区域
markers[unknown==255] = 0
# 分水岭分割
markers = cv.watershed(src,markers)
src[markers == -1] = [0,0,255]
cv.imshow("result", src)
cv.waitKey(0)
cv.destroyAllWindows()
OpenVINO系列文章
扫码加入OpenCV研习社
系统化学习OpenCV4,解锁更多技能!