• 【OpenCV】 - 图像分割之分水岭算法,watershed()函数的输出,对marker和image的改变


    一、背景

    最近在学分水岭算法的opencv函数watershed()时,对函数执行完后image和marker的变化一无所知、懵懵懂懂。

    于是便结合网上资料和自己现身说法,给大家分享一下【watershed函数的执行效果】。

    OpenCV: Image Segmentation with Watershed Algorithm 

    OpenCV: Image Segmentation

    首先说明一点:

    传入watershed函数的marker参数可以有三种成分:背景、不确定、前景(也即object)。

    比如背景像素填充1,而object1填充2,不确定像素填充0。

    下文的“种子数值”代表Object成分的编号。

    因此,object1的种子数值是2。

    二、直接给结论

    watershed函数一旦执行,就会改变marker,但是image不变。

    改变A:从基点开始向外填充种子数值,直到边界。

    例如下面的第2个硬币对应的种子数值是2,原marker中只有硬币最中间才是填充了2

    函数执行后,整个硬币所处区域全被填充2。

     

    改变B:向外填充时,若即将与另一个山谷的积水相涉就停止扩展,最外围便是边界线,marker中的边界线区域填充-1。

    还是以第二个硬币为例,第二个硬币的边界像素点填充-1。

    也就是说,最后得到的marker想比原marker是更加完善的;原marker的object像素点只需要至少填充一个种子数值,而新marker是将object的所有像素全部填充种子数值,更加精确和点对点。

     

    三、测试(现身说法)

    测试用到的图片

    测试用到的代码

    1. import cv2 as cv
    2. import numpy as np
    3. from matplotlib import pyplot as plt
    4. def watershed_demo():
    5. # remove noise if any
    6. print(src.shape)
    7. blurred = cv.pyrMeanShiftFiltering(src, 10, 100)
    8. # gray\binary image
    9. gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
    10. ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    11. cv.imshow("binary-image", binary)
    12. # morphology operation
    13. kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
    14. mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)
    15. sure_bg = cv.dilate(mb, kernel, iterations=3)
    16. cv.imshow("mor-opt", sure_bg)
    17. # distance transform
    18. dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
    19. dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
    20. cv.imshow("distance-t", dist_output*50)
    21. ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)
    22. surface_fg = np.uint8(surface)
    23. cv.imshow("surface-bin", surface_fg)
    24. unknown = cv.subtract(sure_bg, surface_fg)
    25. ret, markers = cv.connectedComponents(surface_fg)
    26. # watershed transform
    27. markers = markers + 1
    28. markers[unknown == 255] = 0
    29. print(type(markers))
    30. print(np.sum(markers==2))
    31. markers = cv.watershed(src, markers=markers)
    32. print(np.unique(markers))
    33. print(np.sum(markers==2))
    34. src[markers==-1] = [0, 0, 255]
    35. cv.imshow("result", src)
    36. markers = markers + 1
    37. plt.imshow(markers)
    38. plt.show()
    39. src = cv.imread("D:\BaiduNetdiskDownload\pycv-learning\pythonProject\images\coins.jpg")
    40. cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
    41. cv.imshow("input image", src)
    42. watershed_demo()
    43. cv.waitKey(0)
    44. cv.destroyAllWindows()

     

    cv.imshow("surface-bin", surface_fg)的输出如下。

    这十个白圆块的区域,对应marker填充种子数值的范围。

    cv.imshow("result", src)的输出如下。

    硬币的边界上绘制了一个红圈,正是利用了上文第二部分的改变B。

     

    plt.imshow(markers)的输出如下。

    我们可以看到新得到的marker真正做到对各个硬币进行像素级别的标注,不同硬币object对应不同填充色。

     

  • 相关阅读:
    安装ora2pg遇到如下问题
    SpringCloud Alibaba微服务第2章之Nacos
    MapStruct,降低无用代码的神器
    给 K8s 中的 Operator 添加 Webhook 功能【保姆级】
    持续持续集成部署-k8s-配置与存储-配置管理:Secret 的应用
    git仓库推送错误
    行业下滑,海尔智家继续逆增双11全网第一
    【模拟电路建模与控制系统分析】01Laplace变换
    【机器学习】回归的原理学习与葡萄酒数据集的最小二乘法线性回归实例
    python 并发、并行处理、分布式处理
  • 原文地址:https://blog.csdn.net/PSpiritV/article/details/125994413