OpenCV / C ++ verbindet nahegelegene Konturen basierend auf dem Abstand zwischen ihnen


15

Ich muss in der Nähe befindliche Konturen in einem Bild basierend auf dem Abstand zwischen ihnen verbinden, der angibt, ob die Konturen verbunden werden sollen.

Jetzt gibt es hier bereits eine Frage zum gleichen Problem: /programming/8973017/opencv-c-obj-c-connect-nearby-contours, aber hier führt er alle Konturen zu einer einzigen zusammen. Das will ich nicht. Ich glaube nicht, dass es dafür eine Funktion in opencv gibt, aber Sie können einen Algorithmus dafür vorschlagen. Meine Bewerbung sieht folgendermaßen aus:

Ich erkenne Hände, also habe ich einen Hauterkennungsalgorithmus verwendet, um sie zu bestimmen, aber da meine Haut nicht weiß ist und möglicherweise aufgrund von Aufhellungsbedingungen manchmal die Kontur am Ellbogen bricht. Ich möchte also, dass die nahe gelegenen Konturen verbunden werden, aber nicht alle (weil beide Hände in Konturen vorhanden sind.) (Mit Händen meine ich von der Schulter bis zur Handfläche.)

Darüber hinaus denke ich, dass ich durch die Verwendung einer Kantenerkennung meine Handgrenzen erhalte und erkenne, ob ein Teil dieses Patches innerhalb dieser Grenze als Haut erkannt wird, dann wird der gesamte Bereich innerhalb dieser Grenze als Haut erkannt, aber ich bin mir nicht sicher, wie ich das tun soll Teil.

Jede Hilfe wird geschätzt. Danke im Voraus

Beispielbild:

Geben Sie hier die Bildbeschreibung ein

In diesem Bild möchte ich Punkte (8 Konnektivitäten) verbinden, die weniger als 40 Pixel entfernt sind, damit ich meine linke Hand als einzelne Kontur bekomme

Mein Ziel ist es, nur die Handkontur zu erhalten (mir ist keine andere Region wichtig)


Mit Händen meinst du eigentlich Arme. Könnten Sie nicht einfach den Farbton anpassen, mit dem Sie die Haut erkennen, um sie an Ihre Hautfarbe anzupassen?
Waspinator

Ich habe das getan und es gibt eine feine Ausgabe (wenn meine Haut beleuchtet ist). Abends kommt es also wie gezeigt. Wie auch immer, ich dachte, dass es eine Methode geben könnte, um in der Nähe befindliche Blobs zu verbinden.
Roney Island


Willkommen beim Stapelaustausch. SE ist kein Forum! Dies ist keine Antwort auf die Frage. Wenn Sie eine Frage zu dieser Frage haben, geben Sie diese als Kommentar ein.
Dipan Mehta

Wie erkennt man die Haut?
nkint

Antworten:


10

Wenn Sie sich keine Gedanken über die Geschwindigkeit oder die genaue Kontur der Hand machen, finden Sie unten eine einfache Lösung.

Die Methode ist wie folgt: Sie nehmen jede Kontur und finden Abstand zu anderen Konturen. Wenn die Entfernung weniger als 50 beträgt, sind sie in der Nähe und Sie setzen sie zusammen. Wenn nicht, werden sie als unterschiedlich eingestuft.

Das Überprüfen des Abstands zu jeder Kontur ist daher ein zeitaufwändiger Vorgang. Dauert einige Sekunden. Sie können es also auf keinen Fall in Echtzeit tun.

Um Konturen zu verbinden, habe ich sie in einem einzigen Satz zusammengefasst und einen konvexen Rumpf für diesen Satz gezeichnet. Das Ergebnis, das Sie erhalten, ist also tatsächlich eine konvexe Handhülle, keine echte Hand.

Unten ist mein Code in OpenCV-Python. Ich habe keine Optimierung vorgenommen, wollte nur, dass es funktioniert, das ist alles. Wenn es Ihr Problem löst, gehen Sie zur Optimierung.

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)

Unten sind die Ergebnisse, die ich bekommen habe:

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein


Wie geht das in c ++? Ich habe bis zum findContour-Teil, aber danach kann ich die Konturen nicht mehr wie oben gezeigt in ein Polygon einbinden (im Gegensatz zu einem Begrenzungsrechteck).
Elionardo Feliciano

Ich schätze Ihren Ansatz und habe versucht, ihn auf meinen Fall anzuwenden, aber leider ist er unter Python extrem langsam (obwohl mein Laptop über Core i7QM und 8 GB RAM verfügt). Ich verwende MSER, um Regionen zu erkennen, und muss nun bestimmen, welches Paar von Regionen "benachbart" ist. Ich habe Ihren Algorithmus mit dem Schwellenwert 10 ausprobiert. Es dauert Jahre, bis die benachbarten Regionen zurückgegeben werden.
Jim Raynor

4

Um das Verbindungsproblem zu beheben, können Sie einen Abschlussvorgang versuchen:

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

Ich bezweifle, dass dies zu den gewünschten Ergebnissen führt, aber Sie können es versuchen.


2

Es sieht so aus, als würden Sie Ihr Image "übersegmentieren". Morphologische Operationen, wie bjnoernz vorgeschlagen hat, würden helfen. Insbesondere sollte ein Wassereinzugsgebietsansatz näher an das heranrücken, was Sie möchten, als nur die Entfernung zu überprüfen (wie im obigen Python-Beispiel). Sehen http://cmm.ensmp.fr/~beucher/wtshed.html .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.