2015-09-05 4 views
5

Ich verwende Hintergrundsubtraktion, um sich bewegende Objekte einer Outdoor-Szene zu analysieren. Wenn die Sonne rauskommt, habe ich ein Problem mit Schatten. Ich verwende Konturen, um die Objekte zu isolieren. Im Moment analysiere ich einfach die obere Hälfte der Kontur, da der Schatten normalerweise in der unteren Hälfte liegt.OpenCV Kontur Mindestmaß Ort in Python

Stellen Sie sich eine Kontur einer Gummiente vor, was ich gerne tun würde, ist die y-Position des Halses der Ente, das ist, wo die Kontur in ihrer minimalen horizontalen Dimension ist. Könnte mir jemand bitte in die richtige Richtung zeigen, wie man den "Hals der Ente" findet?

enter image description here

Im Code binary ein Schwellenwert Bild der sich bewegenden Objekte ist, HIGHTWIDTH und die Höhe und Breite des Bildes sind, ist lab das gleiche Bild in dem LAB-Farbraum.

Ich möchte die half = int(h/2) Zeile mit einer Funktion ersetzen, um die Y-Position einer horizontalen Linie zu finden, um den "Enten Hals" aus zu schneiden.

_,contours,_ = cv2.findContours(binary.copy(), cv2.RETR_EXTERNAL, 
          cv2.CHAIN_APPROX_SIMPLE) 

# loop over the contours 
for i, cnt in enumerate(contours): 

    # compute the bounding box for the contour 
    (x, y, w, h) = cv2.boundingRect(cnt) 

    # reject contours outside size range 
    if w > 250 or w < 30 or h > 250 or h < 30 : 
      continue 

    # make sure the box is inside the frame 
    if x <= 0 or y <= 0 or x+w >= (WIDTH -1) or y+h >= (HIGHT -1): 
      continue 

    # isolate feature 
    half = int(h/2) 
    roi = lab[y:y+half, x:x+w] 
    mask = binary[y:y+half, x:x+w] 

    # calculate the mean of the colour 
    mean = cv2.mean(roi, mask = mask) 
    # note: mean is L a b 
    L = int(mean[0]) 
    a = int(mean[1]) 
    b = int(mean[2]) 
    print L,a,b 

Ich verwende opencv 3 und Python 2.7

P. S. Ich habe den Hintergrund-Subtrahierer MOG2 ausprobiert, der gesagt wird, um Schatten zu identifizieren, aber es ist viel zu laut für meinen Gebrauch und nicht lebensfähig.

+3

Fügen Sie Ihrer Frage ein paar Bilder mit tatsächlichen und erwarteten Ergebnissen hinzu. Klicken Sie auf den Link zum Bearbeiten unter den Tags. Du hast nicht genug Reputation, um ein Bild hinzuzufügen, aber du kannst einen öffentlichen Link von imgur oder ähnlichem posten – Miki

+0

Hallo Miki, ich habe eine Skizze hinzugefügt, die zur Klärung beitragen sollte, bitte fühle dich frei, etwas anderes zu fragen. Ich habe über 3 mögliche Lösungen nachgedacht, 1) Irgendwie Momente, 2) Iterate durch die Konturliste, um Wendepunkte zu finden, 3) Summe Zeilen horizontal, um ein Profil zu erhalten und dann Wendepunkte des Profils zu finden. Die ersten beiden, von denen ich keine Ahnung habe, könnten helfen, wie man Momente benutzt oder wie man auf die Konturliste zugreift und sie interpretiert. Oder jeder andere Vorschlag würde sehr geschätzt werden. – Johno

+0

Sorry, ein Schmerz zu sein, wenn du versuchst zu tun, aber bitte vermeiden Dropbox/andere vorübergehende Links wenn möglich - wir wollen diese Fragen Menschen seit Jahren helfen und wenn Sie Ihre Dropbox-Datei in Zukunft löschen, würde es machen Diese Frage ist weniger wertvoll. SO Haben Sie eine Vereinbarung mit Imgur, um sicherzustellen, dass alle Bilder für die Dauer vorhanden sind. Ich habe es in diesem Fall für dich getan. Hoffe, du findest deine Antwort! – Basic

Antwort

0

Sie können eine Maske definieren, um das Bild zu erodieren, so dass Sie die oberen und unteren Blobs aus dem Tal brechen können. Sie können das auf Ihren Code wie folgend anwenden:

# loop over the contours 
for i, cnt in enumerate(contours): 

    # compute the bounding box for the contour 
    (x, y, w, h) = cv2.boundingRect(cnt) 

    # reject contours outside size range 
    if w > 250 or w < 30 or h > 250 or h < 30 : 
      continue 

    # make sure the box is inside the frame 
    if x <= 0 or y <= 0 or x+w >= (WIDTH -1) or y+h >= (HIGHT -1): 
      continue 

    # --------------- 
    # create a mask for erosion, you can play with the mask size/shape 
    mask = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5)) 
    # erode the original image 
    eroded_img = cv2.erode(binary,mask,iterations = 1) 
    cv2.imshow("Eroded image",eroded_img) 
    # find the middle of the two new contours 
    _,new_contours,_ = cv2.findContours(eroded_img, cv2.RETR_EXTERNAL, 
         cv2.CHAIN_APPROX_SIMPLE) 
    (_, y_t, _, h_t) = cv2.boundingRect(new_contours[0]) 
    (_, y_b, _, h_b) = cv2.boundingRect(new_contours[1]) 
    bottom_top_y = max(y_t, y_b) # highest y of bottom part 
    top_bottom_y = min(y_t+h_t, y_b+h_b) # lowest y of top part 
    half = top_bottom_y + (bottom_top_y - top_bottom_y)/2 
    # ------------ 

    # isolate feature 
    roi = lab[y:y+half, x:x+w] 
    mask = binary[y:y+half, x:x+w] 

    # calculate the mean of the colour 
    mean = cv2.mean(roi, mask = mask) 
    # note: mean is L a b 
    L = int(mean[0]) 
    a = int(mean[1]) 
    b = int(mean[2]) 
    print L,a,b 

Hoffen Sie, dass es hilft! Weitere Beispiele zu morphologischen Operationen auf Binärbildern finden Sie unter here.

+0

Ike, vielen Dank für Ihre Eingabe. Dies ist definitiv eine Möglichkeit, dies zu tun.Ich verwende bereits erode, um die Maskengröße zu reduzieren, so dass die Kanten des Objekts nicht in meinen Erkennungsberechnungen enthalten sind. Vielleicht werde ich in einer Schleife erodieren, bis es zwei Konturen gibt und dann die obere Kontur wieder auf die ursprüngliche Größe wachsen lässt. Prost :-) – Johno