opencv——分水岭图像分割算法demo思路与应用
原理解释:https://blog.csdn.net/ChangWei_wenzhou/article/details/83583230?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.channel_param
demo将对下面这张罗勒叶子使用分水岭图像分割算法,把罗勒叶部分分割出来:
首先第一步,图像读取,这就不废话了。
img = cv2.imread(r'C:\Users\Owen\Pictures\luoleye2.jpg')
然后是转换为灰度图,随后二值化。
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
效果:
之后我们使用开操作去除噪声数据:
#开操作去除噪声数据
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2)
然后通过对开操作变换后的图像进行膨胀操作,可以得到大部分都是背景的区域:
sure_bg = cv2.dilate(opening,kernel,iterations=3)
反之,可以通过distanceTransform来获取确定的前景区域。也就是说这是图像中最可能是前景的区域,越是远离背景区域的边界的点越可能属于前景。
在得到distanceTransform操作的结果后,应用一个阈值来决定哪些区域是前景,这样得到正确结果的概率很高:
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret,sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
处理结果:
所得到的前景和背景有重合的部分,怎么办呢?首先要确定这些区域,可从sure_bg与sure_fg的集合相减得到。
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg) #两图像相减。
cv_show('unknonw',unknown)
处理结果:
有了这些区域,就可以设定栅栏来阻止水汇聚了,通过connectedComponents函数完成。
ret,markers = cv2.connectedComponents(sure_fg)
在背景区域上+1,将unknown区域设为0
markers = markers +1
markers[unknown==255] = 0
打开门,让水漫进来并把栅栏绘成红色
markers = cv2.watershed(img,markers)
img[markers == -1] = [0,0,255]
img = img.astype(np.uint8) #数值转化为uint8,不然报错。 ?
cv_show('img',img)
最终结果:
完整代码:
import numpy as np
import cv2
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img = cv2.imread(r'C:\Users\Owen\Pictures\luoleye2.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化
ret,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
cv_show('thresh',thresh)
#开操作去除噪声数据
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2)
cv_show('opening',opening)
#通过对开操作变换后的图像进行膨胀操作,可以得到大部分都是背景的区域:
sure_bg = cv2.dilate(opening,kernel,iterations=3)
cv_show('sure_bg',sure_bg)
#反之,可以通过distanceTransform来获取确定的前景区域。也就是说这是图像中最可能是前景的区域,越是远离背景区域的边界的点越可能属于前景。
#在得到distanceTransform操作的结果后,应用一个阈值来决定哪些区域是前景,这样得到正确结果的概率很高。
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
ret,sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
cv_show('sure_fg',sure_fg)
#所得到的前景和背景有重合的部分,怎么办呢?首先要确定这些区域,可从sure_bg与sure_fg的集合相减得到。
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg) #两图像相减。
cv_show('unknonw',unknown)
#有了这些区域,就可以设定栅栏来阻止水汇聚了,通过connectedComponents函数完成。
ret,markers = cv2.connectedComponents(sure_fg)
#在背景区域上+1,将unknown区域设为0
markers = markers +1
markers[unknown==255] = 0
#打开门,让水漫进来并把栅栏绘成红色
markers = cv2.watershed(img,markers)
img[markers == -1] = [0,0,255]
img = img.astype(np.uint8) #数值转化为uint8,不然报错。 ?
cv_show('img',img)
本文地址:https://blog.csdn.net/qq_37957854/article/details/107625954