【问题标题】:Watershed Transform of Distance Image with OpenCV使用 OpenCV 对距离图像进行分水岭变换
【发布时间】:2014-09-12 07:37:47
【问题描述】:

在Matlab中,我们可以对距离变换进行分水岭变换,将两个接触的物体分开:

上面的第一张图片是我们希望分离的带有触摸对象的图片。第二张图是它的距离变换。

所以,如果黑白图像被称为img,在Matlab中我们可以这样做:

D = -bwdist(~img); 
L = watershed(D);

现在用 openCV 做同样的事情: OpenCV 具有基于标记的分水岭分割功能。似乎要执行使用 openCV 分离两个触摸对象的相同任务,需要为对象和背景提供标记。

img = np.zeros((400, 400), np.uint8)
cv2.circle(img, (150, 150), 100, 255, -1)
cv2.circle(img, (250, 250), 100, 255, -1)

dist = cv2.distanceTransform(img, cv2.cv.CV_DIST_L2, cv2.cv.CV_DIST_MASK_PRECISE)
dist3 = np.zeros((dist.shape[0], dist.shape[1], 3), dtype = np.uint8)
dist3[:, :, 0] = dist
dist3[:, :, 1] = dist
dist3[:, :, 2] = dist

markers = np.zeros(img.shape, np.int32)
markers[150,150] = 1 # seed for circle one
markers[250, 250] = 2 # seed for circle two
markers[50,50] =  3 # seeds for background

cv2.watershed(dist3, markers)

在下图中,您可以看到执行分水岭后的markers 图像。原来的黑白img用红色叠加在上面。 问题是生成的markers 图像中的对象边界与原始图像不同。如何确保对象边界保持不变?

【问题讨论】:

    标签: python opencv distance image-segmentation watershed


    【解决方案1】:

    您会更好地了解分水岭功能中可能发生的情况。 它开始用种子泛滥,并将其邻居的坐标和梯度放入优先队列中。

    如你所知,当你在img上应用distanceTransform时,圆的梯度变成0或1,但背景总是0;

    所以,现在你有 3 个种子,并且泛洪开始工作:背景(种子 3)、邻居(种子 1)、邻居(种子 2),它们可以依次工作,直到种子 1 或种子 2 满足它们的梯度 1;那么只要seed3就可以继续工作了。

    当seed3遇到圆的边界时,它的梯度变为1,现在它们又可以轮流工作了。

    所以如果要保证物体边界不变,最好在seed3遇到圆的边界时加大梯度。

    就像:

    dist = cv2.distanceTransform(img, cv2.cv.CV_DIST_L2, cv2.cv.CV_DIST_MASK_PRECISE)
    dist[dist > 0] += 2.0
    

    这里是result

    ...里面有一些问题(当队列中所有的梯度都是1时,先弹出哪个先弹出,后弹出哪个)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 2019-01-21
      • 2022-01-12
      • 2012-07-11
      • 2013-11-29
      相关资源
      最近更新 更多