OpenCV / C ++는 거리를 기준으로 주변 윤곽을 연결합니다


15

윤곽을 연결할지 여부를 지정하는 거리를 기준으로 이미지에서 주변 윤곽을 연결해야합니다.

이제이 질문은 여기에 같은 문제에 이미 /programming/8973017/opencv-c-obj-c-connect-nearby-contours을 그러나 여기에서 그는 하나 하나에 모든 윤곽을 병합합니다. 이것은 원하지 않습니다. 나는 이것을 위해 opencv에 어떤 ​​함수가 있다고 생각하지 않지만 그것에 대한 알고리즘을 제안 할 수 있습니다. 내 응용 프로그램은 다음과 같습니다.

손을 감지하고 있으므로 피부 감지 알고리즘을 사용하여 손을 확인했지만 피부가 하 얗지 않고 어두워서 때때로 팔꿈치의 윤곽이 끊어졌습니다. 그래서 나는 가까운 윤곽선을 연결하고 싶지만 모두가 아닙니다. (두 손이 윤곽선에 있기 때문에.) (손으로 나는 어깨에서 손바닥까지를 의미합니다.)

또한 가장자리 감지 기능을 사용하면 손 경계가 생기고이 경계 내부의 패치 중 일부가 피부로 감지되는지 감지하면이 경계 내의 전체 영역이 피부로 감지되지만 어떻게 해야할지 잘 모르겠습니다. 부품.

도움을 주시면 감사하겠습니다. 미리 감사드립니다

샘플 이미지 :

여기에 이미지 설명을 입력하십시오

이 이미지에서는 거리가 40 픽셀 미만인 포인트 (8 개의 연결성)를 연결하여 왼손을 단일 윤곽으로 가져옵니다.

내 목표는 손의 윤곽 만 얻는 것입니다 (다른 지역은 신경 쓰지 않습니다)


손으로 당신은 실제로 팔을 의미합니다. 피부색과 일치하도록 피부를 감지하는 데 사용하는 색조를 조정할 수 있습니까?
waspinator

나는 그것을했고 그것은 (피부가 밝을 때) 훌륭한 출력을 제공합니다. 따라서 저녁에는 그림과 같이 나타납니다. 어쨌든 근처 블롭을 연결하는 방법이있을 것이라고 생각했습니다.
Roney Island 2016 년


스택 교환에 오신 것을 환영합니다. SE는 포럼이 아닙니다! 이것은 질문에 대한 답변이 아닙니다. 질문에 대해 궁금한 점이 있으면 이것을 의견으로 쓰십시오.
Dipan Mehta

피부는 어떻게 감지합니까?
nkint

답변:


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

귀하의 접근 방식에 감사하고 내 경우에 적용하려고 시도했지만 불행히도 Python에서는 속도가 느립니다 (노트북에는 Core i7QM 및 8GB RAM이 있음). MSER을 사용하여 영역을 감지하고 이제는 "인접한"영역 쌍을 결정해야합니다. 임계 값 10으로 알고리즘을 시도했습니다 ... 인접 영역을 반환하는 데 몇 년이 걸립니다.
Jim Raynor

4

연결 문제를 해결하려면 닫기 작업을 시도하십시오.

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

이것이 당신이 원하는 결과를 낳을지는 의심하지만, 시도해 볼 수는 있습니다.


2

이미지를 "과다 분할"한 것 같습니다. bjnoernz가 제안한 것처럼 형태 학적 조작이 도움이 될 것입니다. 특히, 흘림 접근 방식은 단순히 거리를 확인하는 것보다 원하는 것에 더 가까워 야합니다 (위의 파이썬 예제에서와 같이). http://cmm.ensmp.fr/~beucher/wtshed.html을 참조 하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.