欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

opencv——分水岭图像分割算法demo思路与应用

程序员文章站 2022-08-05 23:30:53
原理解释: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-BlogCommendFromMachineLearnPa...

原理解释: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将对下面这张罗勒叶子使用分水岭图像分割算法,把罗勒叶部分分割出来:opencv——分水岭图像分割算法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)

效果:
opencv——分水岭图像分割算法demo思路与应用
之后我们使用开操作去除噪声数据:

#开操作去除噪声数据
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2)

opencv——分水岭图像分割算法demo思路与应用
然后通过对开操作变换后的图像进行膨胀操作,可以得到大部分都是背景的区域:


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

opencv——分水岭图像分割算法demo思路与应用
反之,可以通过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)

处理结果:opencv——分水岭图像分割算法demo思路与应用
所得到的前景和背景有重合的部分,怎么办呢?首先要确定这些区域,可从sure_bg与sure_fg的集合相减得到。

sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)  #两图像相减。
cv_show('unknonw',unknown)

处理结果:opencv——分水岭图像分割算法demo思路与应用

有了这些区域,就可以设定栅栏来阻止水汇聚了,通过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)

最终结果:
opencv——分水岭图像分割算法demo思路与应用

完整代码:

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

相关标签: opencv