python_分水岭算法

def img_huizhi_lunkuo_tongji():
    """
    识别小物体数量
    :return:
    """
    def watershed_algorithm(image):
        src = image.copy()
        blur = cv2.pyrMeanShiftFiltering(image, sp=21, sr=55) # 边缘保留滤波  去噪
        cv2.imshow("灰度", blur)

        gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)# 转成灰度图像
        ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 得到二值图像区间阈值
        cv2.imshow('二值图像thres', binary)


        # 距离变换
        dist = cv2.distanceTransform(binary, cv2.DIST_L2, 3) #反映像素与背景(值为 0的像素点)的距离关系
        #uint8类型的图片归一化处理
        dist_out = cv2.normalize(dist, 0, 1.0, cv2.NORM_MINMAX)
        cv2.imshow('距离转换distance-Transform', dist_out * 100)

        #再次进行阈值转换
        ret, surface = cv2.threshold(dist_out, 0.5 * dist_out.max(), 255, cv2.THRESH_BINARY)
        cv2.imshow('前景图', surface)
        sure_fg = np.uint8(surface)  # 转成8位整型
        cv2.imshow('背景图Sure foreground', sure_fg)

        # image = np.hstack((gray, sure_fg))#水平合并显示
        # cv2.imshow('hstack', image)

        # Marker labelling
        ret, markers = cv2.connectedComponents(sure_fg)  # 连通区域
        print(ret)
        markers = markers + 1  # 整个图+1  确保背景是1不是0

        # 未知区域标记(不能确定是前景还是背景)
        kernel = np.ones((3, 3), np.uint8)#内核
        #类形态学的变化
        op=cv2.MORPH_DILATE  # op = cv2.MORPH_OPEN
        binary = cv2.morphologyEx(binary, op, kernel, iterations=1)#腐蚀一次

        # cv2.MORPH_OPEN 开运算--先腐蚀--膨胀,分开
        # cv2.MORPH_CLOSE 闭运算--膨胀-腐蚀--合并
        # MORPH_GRADIENT - 形态学梯度(Morphological gradient)就是膨胀图与俯视图之差,用于保留物体的边缘轮廓
        # MORPH_TOPHAT - 顶帽(Top  hat)     原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
        # MORPH_BLACKHAT - 黑帽(Black hat)  闭运算与原图像之差,用于分离比邻近点暗一些的斑块。
        # MORPH_ERODE        腐蚀,去毛刺
        # MORPH_DILATE        膨胀,去小孔
        # 形状:表核的形状,矩形MORPH_RECT; 交叉形MORPH_CROSS;  椭圆形MORPH_ELLIPSE;

        unknown = binary - sure_fg # #腐蚀-背景
        cv2.imshow('unknown', unknown)

        markers[unknown == 255] = 0 #未标记区域
        markers_show = np.uint8(markers)## 区域标记结果转换
        cv2.imshow('markers', markers_show * 100)

        # 分水岭算法分割
        markers = cv2.watershed(image, markers=markers)  # 标签图像将会被修改,边界区域的标记将变为 -1

        # src[markers == -1] = [0, 0, 255]  # 红色# 获得到的边界值为-1
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(markers)
        markers_8u = np.uint8(markers)
        # print(max_val)
        colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),
                  (255, 0, 255), (0, 255, 255), (255, 128, 0), (255, 0, 128),
                  (128, 255, 0), (128, 0, 255), (255, 128, 128), (128, 255, 255)]
        for i in range(2, int(max_val + 1)):
            ret, thres1 = cv2.threshold(markers_8u, i - 1, 255, cv2.THRESH_BINARY)
            ret2, thres2 = cv2.threshold(markers_8u, i, 255, cv2.THRESH_BINARY)
            mask = thres1 - thres2
            cv2.imshow('mask', mask)
            # color = (rd.randint(0,255), rd.randint(0,255), rd.randint(0,255))
            # image[markers == i] = [rd.randint(0,255), rd.randint(0,255), rd.randint(0,255)]
            # image[markers == i] = [colors[i-2]]

            contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
            cv2.drawContours(image, contours, -1, colors[(i - 2) % 12], -1)
            # cv2.drawContours(src,contours,-1,colors[(i-2)%12],-1)
            M = cv2.moments(contours[0])
            cx = int(M['m10'] / M['m00'])
            cy = int(M['m01'] / M['m00'])  # 轮廓重心
            cv2.drawMarker(image, (cx, cy), (0, 0, 255), 1, 10, 2)
            cv2.drawMarker(src, (cx, cy), (0, 0, 255), 1, 10, 2)

        cv2.putText(src, "count=%d" % (int(max_val - 1)), (220, 30), 0, 1, (0, 255, 0), 2)
        cv2.putText(image, "count=%d" % (int(max_val - 1)), (220, 30), 0, 1, (0, 255, 0), 2)
        cv2.imshow('regions', image)
        result = cv2.addWeighted(src, 0.6, image, 0.5, 0)  # 图像权重叠加
        cv2.imshow('result', result)

    src = cv2.imread('./douzi.bmp')
    # src = cv2.imread('./99.bmp')
    cv2.imshow('src', src)
    watershed_algorithm(src)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值