首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在OpenCV中定义分水岭的标记?

如何在OpenCV中定义分水岭的标记?
EN

Stack Overflow用户
提问于 2012-07-02 21:37:56
回答 1查看 70.8K关注 0票数 75

我正在用OpenCV为Android编写代码。我正在使用标记控制的分水岭分割类似于下图的图像,而不需要用户手动标记图像。我计划使用区域最大值作为标记。

minMaxLoc()会给我这个值,但是我怎么才能把它限制在我感兴趣的blobs上呢?我是否可以利用findContours()或cvBlob斑点的结果来限制投资回报率并将最大值应用于每个斑点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-01-31 10:15:02

首先:函数minMaxLoc只找到给定输入的全局最小值和全局最大值,因此它对于确定区域最小值和/或区域最大值几乎没有用处。但是你的想法是正确的,基于区域最小值/最大值来提取标记来执行基于标记的分水岭变换是完全可以的。让我试着阐明什么是分水岭转换,以及您应该如何正确使用OpenCV中的实现。

一些相当多的关于分水岭的论文对它的描述类似于下面的描述(如果你不确定,我可能会遗漏一些细节:询问)。考虑一些你知道的区域的表面,它包含谷和峰(以及其他与我们无关的细节)。假设在这个表面下,你所拥有的是水,有色的水。现在,在你表面的每个谷地上打洞,然后水开始填满所有的区域。在某一时刻,不同颜色的水会相遇,当这种情况发生时,你可以建造一个水坝,使它们不会相互接触。最后,你得到了一个水坝的集合,它是分隔所有不同颜色的水的分水岭。

现在,如果你在曲面上打了太多的洞,你最终会得到太多的区域:过度分割。如果你做得太少,你会得到分割不足的结果。因此,几乎任何建议使用分水岭的论文实际上都提出了避免这些问题的技术,以供论文处理的应用程序使用。

我写了所有这些(对于任何知道分水岭转换是什么的人来说,这可能太天真了),因为它直接反映了您应该如何使用分水岭实现(目前公认的答案是以完全错误的方式进行的)。现在让我们开始使用OpenCV绑定的Python示例。

问题中呈现的图像由许多对象组成,这些对象大多太近,在某些情况下是重叠的。分水岭在这里的用处在于正确地分离这些对象,而不是将它们分组到单个组件中。因此,对于每个对象,您至少需要一个标记,并且需要良好的背景标记。例如,首先通过Otsu对输入图像进行二值化,并执行形态学打开以删除小对象。这一步的结果如下图所示。现在,对于二进制图像,考虑对其应用距离变换,结果在右侧。

对于距离变换结果,我们可以考虑一些阈值,以便我们只考虑距离背景最远的区域(下图左图)。这样做,我们可以通过标记较早阈值之后的不同区域来获得每个对象的标记。现在,我们还可以考虑上面左侧图像的放大版本的边界来组成我们的标记。完整的标记如右下图所示(有些标记太暗而看不见,但左侧图像中的每个白色区域显示在右侧图像中)。

我们这里的这个标记很有意义。每个colored water == one marker将开始填充该区域,分水岭转换将构建水坝以阻止不同的“颜色”合并。如果我们做变换,我们得到左边的图像。只考虑与原始图像合成的水坝,我们得到了正确的结果。

代码语言:javascript
复制
import sys
import cv2
import numpy
from scipy.ndimage import label

def segment_on_dt(a, img):
    border = cv2.dilate(img, None, iterations=5)
    border = border - cv2.erode(border, None)

    dt = cv2.distanceTransform(img, 2, 3)
    dt = ((dt - dt.min()) / (dt.max() - dt.min()) * 255).astype(numpy.uint8)
    _, dt = cv2.threshold(dt, 180, 255, cv2.THRESH_BINARY)
    lbl, ncc = label(dt)
    lbl = lbl * (255 / (ncc + 1))
    # Completing the markers now. 
    lbl[border == 255] = 255

    lbl = lbl.astype(numpy.int32)
    cv2.watershed(a, lbl)

    lbl[lbl == -1] = 0
    lbl = lbl.astype(numpy.uint8)
    return 255 - lbl


img = cv2.imread(sys.argv[1])

# Pre-processing.
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)    
_, img_bin = cv2.threshold(img_gray, 0, 255,
        cv2.THRESH_OTSU)
img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,
        numpy.ones((3, 3), dtype=int))

result = segment_on_dt(img, img_bin)
cv2.imwrite(sys.argv[2], result)

result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
cv2.imwrite(sys.argv[3], img)
票数 127
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11294859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档