OpenCV / C ++ collega i contorni vicini in base alla distanza tra loro


15

Devo collegare i contorni vicini in un'immagine in base alla distanza tra loro che specifica se i contorni devono essere collegati.

Ora c'è già una domanda sullo stesso problema qui /programming/8973017/opencv-c-obj-c-connect-nearby-contours ma qui unisce tutti i contorni in uno solo. Questo non lo voglio. Non penso che ci sia una funzione in opencv per questo, ma puoi suggerire un algoritmo per quello. La mia applicazione va così:

Sto rilevando le mani, quindi ho usato un algoritmo di rilevamento della pelle per determinarle, ma dato che la mia pelle non è bianca e forse a causa delle condizioni di alleggerimento a volte i contorni del gomito si rompono. Quindi voglio che i contorni vicini siano collegati ma non tutti (perché entrambe le mie mani saranno lì in contorni.) (Per mani intendo dalla spalla al palmo.)

Inoltre penso che usando un po 'di rilevamento dei bordi otterrò i confini delle mie mani e rileverò se parte di questa patch all'interno di questo confine viene rilevata come skin, quindi l'intera regione all'interno di questo confine verrà rilevata come skin ma non sono sicuro di come farlo parte.

Qualsiasi aiuto sarà apprezzato. Grazie in anticipo

Immagine di esempio:

inserisci qui la descrizione dell'immagine

In questa immagine voglio collegare punti (8 connettività) che sono meno di 40 pixel di distanza in modo da ottenere la mia mano sinistra come un singolo contorno

Il mio obiettivo è quello di ottenere solo il contorno della mano (non mi interessa nessun'altra regione)


per mano intendi davvero le armi. non potresti semplicemente regolare la tonalità che usi per rilevare la pelle in modo che corrisponda al colore della tua pelle?
waspinator

L'ho fatto e dà un risultato eccellente (quando la mia pelle è illuminata). Quindi durante la sera arriva come mostrato. Ad ogni modo, ho pensato che potesse esserci un metodo per connettere BLOB nelle vicinanze.
Roney Island,


Benvenuto nello scambio di stack. SE non è un forum! Questa non è una risposta alla domanda. Se hai una domanda sulla domanda, inseriscila come commento.
Dipan Mehta,

come si rileva la pelle?
nkint

Risposte:


10

Se non sei preoccupato per la velocità o il contorno esatto della mano, di seguito è una soluzione semplice.

Il metodo è così: prendi ogni contorno e trovi la distanza da altri contorni. Se la distanza è inferiore a 50, sono vicini e li metti insieme. In caso contrario, sono messi come diversi.

Quindi controllare la distanza da ciascun contorno è un processo che richiede tempo. Ci vogliono pochi secondi Quindi non puoi farlo in tempo reale.

Inoltre, per unire i contorni, li ho messi in un unico set e ho disegnato uno scafo convesso per quel set. Quindi il risultato che stai ottenendo è in realtà uno scafo convesso della mano, non una mano reale.

Di seguito è riportato il mio pezzo di codice in OpenCV-Python. Non ho optato per alcuna ottimizzazione, volevo solo che funzionasse, tutto qui. Se risolve il problema, scegli l'ottimizzazione.

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)

Di seguito sono riportati i risultati che ho ottenuto:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Come può essere fatto in c ++? Ho fino alla parte findContour ma dopo non riesco a far avvolgere i contorni in un poligono come mostrato sopra (al contrario di un rettangolo di delimitazione).
Elionardo Feliciano,

Apprezzo il tuo approccio e ho provato ad applicare il mio caso, ma purtroppo su Python è estremamente lento (anche se il mio laptop ha Core i7QM e 8 GB di RAM). Uso MSER per rilevare le regioni e ora ho bisogno di determinare quale coppia di regioni è "adiacente", ho provato il tuo algoritmo con soglia 10 ... Ci vogliono anni per restituire le regioni adiacenti.
Jim Raynor,

4

Per risolvere il problema di connettività, puoi provare un'operazione di chiusura:

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

Dubito che questo produrrà i risultati desiderati, ma puoi provarlo.


2

Sembra che tu stia "sovradimensionando" la tua immagine. Le operazioni morfologiche, come ha suggerito Bjnoernz, sarebbero di aiuto. In particolare, un approccio di spartiacque dovrebbe avvicinarsi a ciò che desideri piuttosto che controllare la distanza (come nell'esempio di Python sopra). Vedi http://cmm.ensmp.fr/~beucher/wtshed.html .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.