OpenCV的分水岭算法

本文使用python实现

import cv2 as cv
import numpy as np


def watershed_demo(src):
    print(src.shape)
    blurred = cv.pyrMeanShiftFiltering(src, 10, 100)    # 去噪声
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)      # 转为灰度
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY|cv.THRESH_OTSU)   # 二值化
    cv.imshow("binary_image", binary)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))    # 产生一个kernel
    '''
    def getStructuringElement(shape: Any,   # 形状
                          ksize: Any,       # kernel尺寸
                          anchor: Any = None) -> None
    '''
    mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)   # 形态学操作
    '''
    def morphologyEx(src: Any,          # 原图像
                 op: Any,               # 操作类型
                                        # MORPH_ERODE    = 0, //腐蚀
                                        # MORPH_DILATE   = 1, //膨胀
                                        # MORPH_OPEN     = 2, //开操作
                                        # MORPH_CLOSE    = 3, //闭操作
                                        # MORPH_GRADIENT = 4, //梯度操作
                                        # MORPH_TOPHAT   = 5, //顶帽操作
                                        # MORPH_BLACKHAT = 6, //黑帽操作
                                        # MORPH_HITMISS  = 7  
                 kernel: Any,           # 用于膨胀操作的结构元素,kernel
                 dst: Any = None,
                 anchor: Any = None,    # 参考点
                 iterations: Any = None,
                 borderType: Any = None,
                 borderValue: Any = None) -> None
    MORPH_OPEN(开),内部就是进行了先腐蚀后膨胀的操作。
    MORPH_CLOSE(闭),其实内部就是进行了先膨胀后腐蚀的操作。
    MORPH_GRADIENT(梯度),内部是膨胀减去腐蚀。
    '''
    sure_bg = cv.dilate(mb, kernel, iterations=3)   # 对输入图像用特定结构元素进行膨胀操作
    '''
    def dilate(src: Any,
           kernel: Any,
           dst: Any = None,
           anchor: Any = None,
           iterations: Any = None,
           borderType: Any = None,
           borderValue: Any = None) -> None
    '''
    cv.imshow("mor_opt", sure_bg)

    # 距离变换
    dist = cv.distanceTransform(mb, cv.DIST_L2, 3)  # 距离变换
    '''
    def distanceTransform(src: Any,         # 二值化图像
                      distanceType: Any,    # 计算距离的类型,CV_DIST_L1、CV_DIST_L2 、CV_DIST_C
                      maskSize: Any,        # 距离变换掩码矩阵的大小
                      dst: Any = None,
                      dstType: Any = None) -> None
    '''
    dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    cv.imshow("distance_t", dist_output*50)
    ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)
    cv.imshow("surface_bin", surface)
    surface_fg = np.uint8(surface)
    unknown = cv.subtract(sure_bg, surface_fg)  # 图像的相减操作
    '''
    def subtract(src1: Any,
             src2: Any,
             dst: Any = None,
             mask: Any = None,  # 可选操作掩码; 这是一个8位单通道数组,用于指定要更改的输出数组的元素。 
             dtype: Any = None) -> None # 输出阵列的可选深度
    '''
    ret, markers = cv.connectedComponents(surface_fg)   # 连通域标识
    '''
    def connectedComponents(image: Any,             # image是threshold得到的二值图
                        labels: Any = None,
                        connectivity: Any = None,
                        ltype: Any = None) -> None
    '''
    print(ret)

    # 分水岭
    markers = markers + 1
    markers[unknown == 255] = 0
    markers = cv.watershed(src, markers=markers)
    '''
    def watershed(image: Any,
              markers: Any) -> None
    第二个入参markers必须包含了种子点信息。
    在执行分水岭函数watershed之前,必须对第二个参数markers进行处理,它应该包含不同区域的轮廓,
    每个轮廓有一个自己唯一的编号,轮廓的定位可以通过Opencv中findContours方法实现,这个是执行
    分水岭之前的要求。接下来执行分水岭会发生什么呢?算法会根据markers传入的轮廓作为种子(也就是
    所谓的注水点),对图像上其他的像素点根据分水岭算法规则进行判断,并对每个像素点的区域归属进行划
    定,直到处理完图像上所有像素点。而区域与区域之间的分界处的值被置为“-1”,以做区分。
    '''
    src[markers == -1] = [0, 0, 255]
    cv.imshow("result_image", src)


src = cv.imread("C:/Users/admin/Desktop/21.jpg")  # 打开一张图片
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 设置图片尺寸,自动
cv.imshow("input image", src)  # 显示图像
watershed_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

结果

OpenCV的分水岭算法_第1张图片

你可能感兴趣的:(python)