如何定义OpenCV中的Watershed的标记? [英] How to define the markers for Watershed in OpenCV?

查看:1485
本文介绍了如何定义OpenCV中的Watershed的标记?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm writing for Android with OpenCV. I'm segmenting an image similar to below using marker-controlled watershed, without the user manually marking the image. I'm planning to use the regional maxima as markers.

minMaxLoc()会给我的价值,我怎么能限制它的blobs这是我感兴趣的?我可以利用 findContours()或cvBlob blob的结果来限制ROI,并对每个blob应用最大值吗?

minMaxLoc() would give me the value, but how can I restrict it to the blobs which is what I'm interested in? Can I utilize the results from findContours() or cvBlob blobs to restrict the ROI and apply maxima to each blob?

推荐答案

首先:函数 minMaxLoc 仅找到给定输入的全局最小值和全局最大值,因此它对于确定区域最小值和/或区域最大值。但是你的想法是正确的,基于区域最小值/最大值提取标记以执行基于标记的流域变换是完全正确的。让我试着澄清什么是流域变换,以及你应该如何正确地使用存在于OpenCV中的实现。

First of all: the function minMaxLoc finds only the global minimum and global maximum for a given input, so it is mostly useless for determining regional minima and/or regional maxima. But your idea is right, extracting markers based on regional minima/maxima for performing a Watershed Transform based on markers is totally fine. Let me try to clarify what is the Watershed Transform and how you should correctly use the implementation present in OpenCV.

处理流域的一些体面的论文描述类似于下面(我可能会错过一些细节,如果你不确定:问)。考虑你知道的一些地区的表面,它包含谷和峰(在这里与我们无关的其他细节)。假设在这个表面下面你所有的是水,有色的水。现在,在你的表面的每个山谷打洞,然后水开始填充所有的区域。在某些时候,不同颜色的水将会遇到,当这种情况发生时,你建造一个水坝,使他们不会互相接触。最后,你有一个水坝的集合,这是分水岭分离所有不同的有色水。

Some decent amount of papers that deal with watershed describe it similarly to what follows (I might miss some detail, if you are unsure: ask). Consider the surface of some region you know, it contains valleys and peaks (among other details that are irrelevant for us here). Suppose below this surface all you have is water, colored water. Now, make holes in each valley of your surface and then the water starts to fill all the area. At some point, differently colored waters will meet, and when this happen, you construct a dam such that they don't touch each other. In the end you have a collection of dams, which is the watershed separating all the different colored water.

现在,如果你在那个表面上做了太多的洞,你结束具有太多的区域:过分割。如果你做得太少,你会得到一个欠分割。因此,几乎任何建议使用分水岭的论文实际上都提供了一些技术来避免这篇论文所涉及的应用程序的这些问题。

Now, if you make too many holes in that surface, you end up with too many regions: over-segmentation. If you make too few you get an under-segmentation. So, virtually any paper that suggests using watershed actually presents techniques to avoid these problems for the application the paper is dealing with.

我写了所有这些(这可能太天真因为它直接反映了你应该如何使用流域实现(当前接受的答案是以一种完全错误的方式做的)。让我们从OpenCV示例开始,使用Python绑定。

I wrote all this (which is possibly too naïve for anyone that knows what the Watershed Transform is) because it reflects directly on how you should use watershed implementations (which the current accepted answer is doing in a completely wrong manner). Let us start on the OpenCV example now, using the Python bindings.

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

The image presented in the question is composed of many objects that are mostly too close and in some instances overlapping. The usefulness of watershed here is to separate correctly these objects, not to group them into a single component. So you need at least one marker for each object and good markers for the background. As an example, first binarize the input image by Otsu and perform a morphological opening for removing small objects. The result of this step is shown below in the left image. Now with the binary image consider applying the distance transform to it, result at right.

利用距离变换结果,我们可以考虑一些阈值,使得我们仅考虑距离背景最远的区域(下图中的左图)。这样,我们可以通过标记早先阈值之后的不同区域来获得每个对象的标记。现在,我们还可以考虑上面左侧图像的扩展版本的边框来构成我们的标记。完整的标记如下所示(一些标记太暗,不能看到,但左侧图像中的每个白色区域都显示在右侧图像中)。

With the distance transform result, we can consider some threshold such that we consider only the regions most distant to the background (left image below). Doing this, we can obtain a marker for each object by labeling the different regions after the earlier threshold. Now, we can also consider the border of a dilated version of the left image above to compose our marker. The complete marker is shown below at right (some markers are too dark to be seen, but each white region in the left image is represented at the right image).

< img src =https://i.stack.imgur.com/Byr6Q.pngalt =enter image description here>

我们这里的标记很有意义。每个彩色水==一个标记将开始填充该区域,分水岭转换将构建水坝,阻止不同的颜色合并。如果我们做变换,我们得到左边的图像。

This marker we have here makes a lot of sense. Each colored water == one marker will start to fill the region, and the watershed transformation will construct dams to impede that the different "colors" merge. If we do the transform, we get the image at left. Considering only the dams by composing them with the original image, we get the result at right.

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)
    # 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)

这篇关于如何定义OpenCV中的Watershed的标记?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆