OpenCV / C ++ з'єднують довколишні контури на основі відстані між ними


15

Я повинен з'єднати контури, розташовані поруч із зображенням, виходячи з відстані між ними, яка визначає, чи потрібно контури підключати.

Тепер вже є питання щодо тієї ж проблеми тут /programming/8973017/opencv-c-obj-c-connect-nearby-contours, але тут він об'єднує всі контури в єдиний. Цього я не хочу. Я не думаю, що для цього є якась функція у opencv, але ви можете запропонувати для цього алгоритм. Моя заявка виглядає так:

Я виявляю руки, тому використовував алгоритм виявлення шкіри, щоб визначити їх, але оскільки моя шкіра не біла і, можливо, через світліші умови колись обрив контуру в лікті. Тому я хочу, щоб контури довкола були з'єднані, але не всі вони (тому що обидві мої руки будуть там у контурах.) (Я маю на увазі від плеча до долоні.)

Більше того, я думаю, що за допомогою деякого виявлення ребер я отримаю межі своїх рук і виявляю, чи знайдеться якийсь цей патч всередині цієї межі як шкіра, то вся область в межах цієї межі буде виявлена ​​як шкіра, але я не впевнений, як це зробити частина.

Будь-яка допомога буде вдячна. Спасибі заздалегідь

Зразок зображення:

введіть тут опис зображення

На цьому зображенні я хочу з'єднати точки (8 підключень), менші за 40 пікселів відстані, так що я отримаю ліву руку як єдиний контур

Моя мета - отримати лише контур руки (мені не цікавий жоден інший регіон)


під руками ви насправді маєте на увазі зброю. Ви не могли б просто відрегулювати відтінок, який використовуєте для виявлення шкіри, відповідно до вашого кольору шкіри?
waspinator

Я це зробив, і це дає прекрасний вихід (Коли моя шкіра освітлена). Тож під час вечора це відбувається як показано. У будь-якому разі я думав, що може бути якийсь метод підключення сусідніх крапок.
Острів Роні

Пов’язано з dsp.stackexchange.com/q/2588/590
Кріс

Ласкаво просимо до обміну стеками. SE - це не форум! Це не відповідь на запитання. Якщо у вас є питання щодо цього питання - поставте це як коментар.
Діпан Мехта

як ви виявляєте шкіру?
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, але після цього я не можу отримати контури, щоб загорнутись у багатокутник, як показано вище (на відміну від обмежуючого прямокутника).
Еліонардо Фелісіано

Я ціную ваш підхід і намагався застосувати до моєї справи, але, на жаль, на Python це надзвичайно повільно (хоча мій ноутбук має Core i7QM та 8 ГБ ОЗУ). Я використовую MSER для виявлення регіонів і тепер мені потрібно визначити, яка пара регіонів є "сусідніми", я спробував ваш алгоритм із порогом 10 ... На повернення сусідніх регіонів потрібні роки.
Джим Рейнор

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 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.