小白学python(opencv分水岭算法)

分水岭算法需要很多方面知识,我这里仅仅是简单实现基本功能而已,希望大家多多指教。

watershed()

#原理: 
#灰度图像可以被看成拓扑平面,灰度值高的区域可以看出山峰,灰度值低的区域可以看成是山谷。
向每一个山谷当中灌不同颜色的水。水位升高,不同山谷的水会汇#合,为防止不同山谷的水汇合
,小在汇合处建立起堤坝。然后继续灌水,然后再建立堤坝,直到山峰都掩模。构建好的堤坝就是图像的分割。

#此方法通常会得到过渡分割的结果,因为图像中的噪声以及其他因素。为了减少此影响,opencv使用基于标记的分水岭算法,
此算法要设置哪些山谷中的汇合点,哪些不是。这是一种交互式的图像分割算法那。我们要给已知对象打上不同表情。
如果某个区域肯定是前景或对象,就使用某个颜色或灰度值标签标记它。如果是背景那么使用其他颜色进行标记,
其余不能确定的部分用0标记。然后使用分水岭算法,每次灌水,标签会被更新,当两个不同颜色的标签相遇就会构建堤坝,知道所有山峰掩模,
最后得到的边界对象值是-1

先一步一步开始做吧,我们先开始对图像进行处理:

import cv2 as cv
import numpy as np
def main():
    pitcurepath = "C:/Users/POG/Desktop/49d2d78cd115011da7c9b4aa54f5460b.jpg"
    global src
    src = cv.imread(pitcurepath)
    cv.imshow("image",src)
    watershed_demo()
    cv.waitKey(0)
    cv.destroyAllWindows()



def watershed_demo():
    print(src.shape)
    #cv.pyrMeanShiftFiltering()  边缘保留滤波
    blurred = cv.pyrMeanShiftFiltering(src,10,100)
    #灰度处理
    gray = cv.cvtColor(src,cv.COLOR_BGR2GRAY)
    #函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
    cv.imshow("binaryimage",binary)




if __name__ =="__main__":
    main()

这里仅仅是先对图像进行灰度处理和二值处理(把灰度图像变成非黑即白),结果:
(这里献上我的霉霉)

那我们要是再来对图像进行边缘保留滤波处理呢?
(仅仅改下cv.cvtColor参数)

iimport cv2 as cv
import numpy as np
def main():
    pitcurepath = "C:/Users/POG/Desktop/49d2d78cd115011da7c9b4aa54f5460b.jpg"
    global src
    src = cv.imread(pitcurepath)
    cv.imshow("image",src)
    watershed_demo()
    cv.waitKey(0)
    cv.destroyAllWindows()



def watershed_demo():
    print(src.shape)
    #cv.pyrMeanShiftFiltering()  边缘保留滤波
    blurred = cv.pyrMeanShiftFiltering(src,10,100)
    #灰度处理
    gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
    #函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
    cv.imshow("binaryimage",binary)




if __name__ =="__main__":
    main()

小白学python(opencv分水岭算法)_第1张图片
肉眼可见边缘变模糊了,变得好处理了。
下面我们进行形态学操作函数morphologyEx和距离变换来看看结果:

import cv2 as cv
import numpy as np
def main():
    pitcurepath = "C:/Users/POG/Desktop/u=1730442960,1387670636&fm=26&fmt=auto&gp=0.jpg"
    global src
    src = cv.imread(pitcurepath)
    cv.imshow("image",src)
    watershed_demo()
    cv.waitKey(0)
    cv.destroyAllWindows()



def watershed_demo():
    print(src.shape)
    #cv.pyrMeanShiftFiltering()  边缘保留滤波
    blurred = cv.pyrMeanShiftFiltering(src,10,100)
    #灰度处理
    gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
    #函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
    cv.imshow("binaryimage",binary)
    #getStructuringElement函数会返回指定形状和尺寸的结构元素
    kenrnel = cv.getStructuringElement(cv.MORPH_RECT,(3,3))
    #形态学操作函数morphologyEx
    mb = cv.morphologyEx(binary,cv.MORPH_OPEN,kenrnel,iterations=2)
    sure_bg = cv.dilate(mb,kenrnel,iterations=3)
    cv.imshow("mor-pot",sure_bg)
    #距离变换
    dist = cv.distanceTransform(mb,cv.DIST_L2,3)
    dest_output = cv.normalize(dist,0,1.0,cv.NORM_MINMAX)
    cv.imshow("distince",dest_output*100)




if __name__ =="__main__":
    main()

(突然到这发现霉霉的照片用不成了,没法进行区分区域。。)
小白学python(opencv分水岭算法)_第2张图片
完整代码:
(这里用到很多形态学知识和操作,我也只是跟着视频和书做的,很多都不熟练,这个分水岭算法我会经常更新的)

import cv2 as cv
import numpy as np
def main():
    pitcurepath = "C:/Users/POG/Desktop/u=1730442960,1387670636&fm=26&fmt=auto&gp=0.jpg"
    global src
    src = cv.imread(pitcurepath)
    cv.imshow("image",src)
    watershed_demo()
    cv.waitKey(0)
    cv.destroyAllWindows()



def watershed_demo():
    print(src.shape)
    #cv.pyrMeanShiftFiltering()  边缘保留滤波
    blurred = cv.pyrMeanShiftFiltering(src,10,100)
    #灰度处理
    gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
    #函数 cvThreshold 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
    cv.imshow("binaryimage",binary)
    #getStructuringElement函数会返回指定形状和尺寸的结构元素
    kenrnel = cv.getStructuringElement(cv.MORPH_RECT,(3,3))
    #形态学操作函数morphologyEx
    mb = cv.morphologyEx(binary,cv.MORPH_OPEN,kenrnel,iterations=2)
    sure_bg = cv.dilate(mb,kenrnel,iterations=3)
    cv.imshow("mor-pot",sure_bg)
    #距离变换
    dist = cv.distanceTransform(mb,cv.DIST_L2,3)
    dest_output = cv.normalize(dist,0,1.0,cv.NORM_MINMAX)
    cv.imshow("distince",dest_output*50)

    ret,surface = cv.threshold(dist,dist.max()*0.6,255,cv.THRESH_BINARY)
    cv.imshow("surface",surface)

    surface_fg = np.uint8(surface)
    unknown = cv.subtract(sure_bg,surface_fg)
    ret,markers = cv.connectedComponents(surface_fg)
    print(ret)

    #watershed transform
    markers = markers+1
    markers[unknown==255]=0
    markers = cv.watershed(src,markers=markers)
    src[markers==-1]=[0,0,255]
    cv.imshow("result",src)



if __name__ =="__main__":
    main()

效果如图:
小白学python(opencv分水岭算法)_第3张图片

你可能感兴趣的:(小白python,计算机视觉)