2015-02-27 10 views
5

Ich arbeite an Retinal fundus images.Das Bild besteht aus einer kreisförmigen Netzhaut auf schwarzem Hintergrund. Mit OpenCV habe ich es geschafft, eine Kontur zu bekommen, die die gesamte kreisförmige Retina umgibt. Was ich brauche ist, die kreisförmige Netzhaut aus dem schwarzen Hintergrund herauszuschneiden.Wie schneidet man den inneren Bereich einer Kontur?

+2

was meinst du mit cropping? Bilder sind immer rechteckig. Sie können also entweder eine Maske erstellen und die folgenden Operationen (Verarbeitung/Rendering) nur auf den maskierten Pixeln ausführen. Oder Sie können das Bild zuschneiden, so dass es durch die Bounding Box der Retina dargestellt wird, die viel kleiner als das Originalbild sein kann, aber immer noch einige schwarze Teile (da die Retina nicht rechteckig ist).Oder Sie können die maximale rechteckige Region INNERHALB der Netzhaut beschneiden, die keine schwarzen Hintergrundpixel mehr enthält, sondern auch Teile der Netzhaut entfernt. Welchen willst du? – Micka

+2

Wenn es das letzte Szenario ist, versuchen Sie es bitte http://stackoverflow.com/questions/21410449/how-do-i-crop-to-largest-interior-bounding-box-in-opencv/21479072#21479072 – Micka

+0

@GauravPatil - Obwohl diese Antwort mehrere Jahre alt ist, werde ich immer wieder auf meine Antwort aufmerksam ... was bedeutet, dass es wahrscheinlich richtig ist. Wenn Ihnen das irgendwie geholfen hat, würde ich mich freuen, wenn Sie die Antwort akzeptieren könnten, dass die Leute wissen, dass Sie in dieser Hinsicht keine Hilfe mehr brauchen. Vielen Dank! – rayryeng

Antwort

17

In Ihrer Frage ist unklar, ob Sie die in der Kontur definierten Informationen tatsächlich ausschneiden oder die Informationen ausblenden möchten, die für die gewählte Kontur nicht relevant sind. Ich werde untersuchen, was in beiden Situationen zu tun ist.


die Informationen Ausblendung

Angenommen, Sie cv2.findContours auf Ihrem Bild lief, haben Sie eine Struktur erhalten, die alle die Konturen in Ihrem Bild auflistet. Ich nehme auch an, dass Sie den Index der Kontur kennen, die verwendet wurde, um das gewünschte Objekt zu umgeben. Angenommen, dies ist in idx gespeichert, zuerst cv2.drawContours verwenden, um eine gefüllte Version dieser Kontur auf ein leeres Bild zu zeichnen, dann verwenden Sie dieses Bild, um in Ihr Bild zu indizieren, um das Objekt zu extrahieren. Diese Logik maskiert irrelevante Informationen und behält nur das, was wichtig ist - was innerhalb der von Ihnen ausgewählten Kontur definiert ist. Der Code, dies zu tun, etwas wie folgt aussehen würde, vorausgesetzt, Ihr Bild wird ein Graustufenbild in img gespeichert:

import numpy as np 
import cv2 
img = cv2.imread('...', 0) # Read in your image 
contours, _ = cv2.findContours(...) # Your call to find the contours 
idx = ... # The index of the contour that surrounds your object 
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise 
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask 
out = np.zeros_like(img) # Extract out the object and place into output image 
out[mask == 255] = img[mask == 255] 

# Show the output image 
cv2.imshow('Output', out) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

Wenn Sie tatsächlich zuschneiden möchten ...

Wenn Sie Ernte wollen Im Bild müssen Sie den minimalen Begrenzungsrahmen des durch die Kontur definierten Bereichs definieren. Sie können die obere linke und untere rechte Ecke der Bounding-Box finden und dann die Indizierung verwenden, um das auszuschneiden, was Sie benötigen. Der Code wird die gleiche wie zuvor, aber es wird ein zusätzlicher Anbau Schritt:

import numpy as np 
import cv2 
img = cv2.imread('...', 0) # Read in your image 
contours, _ = cv2.findContours(...) # Your call to find the contours 
idx = ... # The index of the contour that surrounds your object 
mask = np.zeros_like(img) # Create mask where white is what we want, black otherwise 
cv2.drawContours(mask, contours, idx, 255, -1) # Draw filled contour in mask 
out = np.zeros_like(img) # Extract out the object and place into output image 
out[mask == 255] = img[mask == 255] 

# Now crop 
(x, y) = np.where(mask == 255) 
(topx, topy) = (np.min(x), np.min(y)) 
(bottomx, bottomy) = (np.max(x), np.max(y)) 
out = out[topx:bottomx+1, topy:bottomy+1] 

# Show the output image 
cv2.imshow('Output', out) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 

Das Zuschneiden Code funktioniert so, dass, wenn wir die Maske definieren durch die Kontur definiert den Bereich zu extrahieren, wir die zusätzlich finden kleinste horizontale und vertikale Koordinaten, die die obere linke Ecke der Kontur definieren. Wir finden ebenfalls die größten horizontalen und vertikalen Koordinaten, die die untere linke Ecke der Kontur definieren. Wir verwenden dann die Indizierung mit diesen Koordinaten, um zu schneiden, was wir tatsächlich brauchen. Beachten Sie, dass das Beschneiden auf dem maskierten Bild ausgeführt wird - das ist das Bild, das alles außer der Information entfernt, die in der größten Kontur enthalten ist.

Hinweis mit OpenCV 3.x

Es sollte beachtet werden, dass der obige Code vorausgesetzt, dass Sie OpenCV 2.4.x. verwenden Beachten Sie, dass in OpenCV 3.x die Definition von cv2.drawContours geändert wurde. Insbesondere ist die Ausgabe eine Tupelausgabe mit drei Elementen, wobei das erste Bild das Quellbild ist, während die anderen beiden Parameter dieselben wie in OpenCV 2.4.x sind. Daher ändern Sie einfach die Anweisung in dem obigen Code, um die erste Ausgabe zu ignorieren:

_, contours, _ = cv2.findContours(...) # Your call to find contours 
+0

@RedetGetachew - Nein, die Koordinaten werden nicht vertauscht. Die Ausgabe von "np.where" liefert Zeilenpositionen in "x" und Spaltenpositionen in "y", die nicht Null sind. Daher ist die Indizierung in das Array korrekt. Bitte testen Sie Ihre Änderungen, bevor Sie eine Änderung vorschlagen. – rayryeng

Verwandte Themen