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

信息处理 图像处理 计算机视觉 opencv 形态操作
2022-01-05 03:31:09

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

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

我正在检测手,所以我使用了皮肤检测算法来确定它们,但由于我的皮肤不是白色的,并且可能是因为光照条件有时肘部的轮廓断裂。所以我希望连接附近的轮廓,但不是全部(因为我的两只手都会在轮廓中。)(我的意思是从肩膀到手掌。)

此外,我认为通过使用一些边缘检测,我会得到我的手的边界,并检测这个边界内的一些补丁是否被检测为皮肤,然后这个边界内的整个区域将被检测为皮肤,但我不知道该怎么做部分。

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

示例图片:

在此处输入图像描述

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

我的目标是只得到手的轮廓(我不关心任何其他区域)

3个回答

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

方法是这样的:你取每个轮廓并找到到其他轮廓的距离。如果距离小于 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)

以下是我得到的结果:

在此处输入图像描述

在此处输入图像描述

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

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

我怀疑这会产生你想要的结果,但你可以试一试。

看起来你正在“过度分割”你的形象。正如 bjnoernz 所建议的,形态学操作会有所帮助。特别是,分水岭方法应该更接近您想要的,而不仅仅是检查距离(如上面的 python 示例)。http://cmm.ensmp.fr/~beucher/wtshed.html