OpenCV / C ++根据它们之间的距离连接附近的轮廓


15

我必须根据它们之间的距离连接图像中的附近轮廓,该距离指定是否要连接轮廓。

现在这里已经有一个关于同一问题的问题,https://stackoverflow.com/questions/8973017/opencv-c-obj-c-connect-nearby-contours,但是在这里他将所有轮廓合并为一个轮廓。这个我不要 我认为opencv中没有为此功能,但是您可以为此建议一个算法。我的应用程序如下所示:

我正在检测手,因此我使用皮肤检测算法来确定它们,但是由于我的皮肤不是白色,可能是由于某些情况下的照亮情况导致肘部轮廓破裂。因此,我希望连接附近的轮廓,但不要全部连接(因为我的两只手都在轮廓中。)(我的意思是从肩膀到手掌。)

此外,我认为通过使用一些边缘检测,我将获得我的手的边界,并检测该边界内的某些补丁是否被检测为皮肤,然后将该边界内的整个区域检测为皮肤,但是我不确定如何执行此操作部分。

任何帮助将不胜感激。提前致谢

样本图片:

在此处输入图片说明

在此图像中,我想连接距离(小于40像素)的点(8个连接点),以便将左手作为单个轮廓

我的目的是只获得手的轮廓(我不在乎其他任何区域)


用手实际上是指武器。您是否可以仅调整用于检测皮肤的色相来匹配您的肤色?
waspinator 2012年

我做到了,它可以提供很好的输出(当我的皮肤被照亮时)。因此,在晚上,如图所示。无论如何,我认为可能有某种方法可以连接附近的Blob。
罗尼岛


欢迎进行堆栈交换。SE不是论坛!这不是问题的答案。如果您对此问题有疑问,请将其作为评论。
Dipan Mehta 2012年

您如何检测皮肤?
nkint

Answers:


10

如果您不担心手的速度或精确轮廓,下面是一个简单的解决方案。

方法是这样的:您获取每个轮廓并找到与其他轮廓的距离。如果距离小于50,则它们在附近,您将它们放在一起。如果不是,则将它们放在不同的位置。

因此,检查到每个轮廓的距离是一个耗时的过程。需要几秒钟。因此,您无法实时进行操作。

另外,为了连接轮廓,我将它们放在一个集合中,并为该集合绘制了一个凸包。因此,您得到的结果实际上是凸形的手壳,而不是真实的手。

以下是我在OpenCV-Python中的代码。我还没有进行任何优化,只是希望它能正常工作,仅此而已。如果它解决了您的问题,请进行优化。

import cv2
import numpy as np

def find_if_close(cnt1,cnt2):
    row1,row2 = cnt1.shape[0],cnt2.shape[0]
    for i in xrange(row1):
        for j in xrange(row2):
            dist = np.linalg.norm(cnt1[i]-cnt2[j])
            if abs(dist) < 50 :
                return True
            elif i==row1-1 and j==row2-1:
                return False

img = cv2.imread('dspcnt.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,0)
contours,hier = cv2.findContours(thresh,cv2.RETR_EXTERNAL,2)

LENGTH = len(contours)
status = np.zeros((LENGTH,1))

for i,cnt1 in enumerate(contours):
    x = i    
    if i != LENGTH-1:
        for j,cnt2 in enumerate(contours[i+1:]):
            x = x+1
            dist = find_if_close(cnt1,cnt2)
            if dist == True:
                val = min(status[i],status[x])
                status[x] = status[i] = val
            else:
                if status[x]==status[i]:
                    status[x] = i+1

unified = []
maximum = int(status.max())+1
for i in xrange(maximum):
    pos = np.where(status==i)[0]
    if pos.size != 0:
        cont = np.vstack(contours[i] for i in pos)
        hull = cv2.convexHull(cont)
        unified.append(hull)

cv2.drawContours(img,unified,-1,(0,255,0),2)
cv2.drawContours(thresh,unified,-1,255,-1)

以下是我得到的结果:

在此处输入图片说明

在此处输入图片说明


如何在C ++中完成?我已经完成了findContour部分,但是在那之后我似乎无法将轮廓包裹在如上所示的多边形中(而不是边界矩形)。
Elionardo Feliciano 2013年

我感谢您的方法,并尝试将其应用于我的案例,但是不幸的是,它在Python上非常慢(尽管我的笔记本电脑具有Core i7QM和8GB RAM)。我使用MSER来检测区域,现在需要确定哪些区域是“相邻”的,我尝试使用阈值为10的算法...返回相邻区域需要花费数年的时间。
Jim Raynor 2014年

4

要解决连接问题,您可以尝试关闭操作:

cv::Mat structuringElement = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(40, 40));
cv::morphologyEx( inputImage, outputImage, cv::MORPH_CLOSE, structuringElement );

我怀疑这会产生您想要的结果,但是您可以尝试一下。


2

您好像在“过度细分”您的图片。正如bjnoernz所建议的,形态学操作会有所帮助。特别是,分水岭方法应该比仅检查距离更接近您想要的方法(如上面的python示例)。参见http://cmm.ensmp.fr/~beucher/wtshed.html

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.