2017-11-12 3 views
-1

Ich benutze Opencv und Python für die Programmierung und ich versuche, eine Linie zwischen zwei Punkten zu zeichnen, die ich kenne ihre Koordinaten, und dann lassen Sie die Linie abgeschlossen, bis es das Ende der Kontur wie im Bild unten erreicht. Die Kontur ist in meinem Fall tatsächlich ein Bildgesicht, aber ich habe hier einen Kreis zur Erklärung bereitgestellt. Also versuche ich, die Kante des Kopfes an dieser Stelle mit der Linie und der Kontur zu schneiden. Gibt es eine Möglichkeit, eine Linie von zwei Punkten aus zu zeichnen und dann die Linie bis zum Erreichen der Kontur zu zeichnen? Wie zeichne ich eine Linie von zwei Punkten und lasse dann die Linie die Zeichnung vervollständigen, bis ich einen Konturpunkt mit opencv, python, erreiche?

+0

Sie OpenCV der LineIterator folgen alle Pixel einer Zeile verwenden könnte, bis Sie ein Konturpixel getroffen. Aber nicht sicher, ob LineIterator existiert in Python-API ... – Micka

+0

Ja, ich glaube nicht, es existiert in Python –

+2

@Micka böse, wusste nicht OpenCV hatte eine solche Funktion! Jemand auf Stack hat tatsächlich eine eigene Version der Funktion für Python erstellt: https://stackoverflow.com/questions/32328179/opencv-3-0-python-lineiterator –

Antwort

0

Ich kann mir eine einfache Methode vorstellen, die das Bild nicht inkrementell aktualisiert: Auf ein leeres Bild zeichnen Sie eine lange Linie, die sich vom ersten Punkt in Richtung Punkt zwei erstreckt Dann UND das resultierende Bild mit dem Bild der einzelnen Kontur gezeichnet (gefüllt). Dies stoppt die Linie am Ende der Kontur. Dann können Sie entweder diese Maske verwenden, um die Linie zu zeichnen, oder die minimalen/maximalen x, y-Koordinaten erhalten, wenn Sie die Koordinaten der Linie wollen.

durch ein Beispiel zu gehen, werden wir zuerst die Kontur finden und es auf ein leeres Bild zeichnen:

contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1] 
contour_img = np.zeros_like(img) 
cv2.fillPoly(contour_img, contours, 255) 

Dann, wenn wir die Punkte p1 und p2 haben, finden Sie die Richtung, die sie hinwollen in und einen Punkt weit weg in dieser Entfernung zu finden und diese Zeile auf ein neues leeres Bild zeichnen (hier habe ich eine Entfernung von 1000 Pixeln von p1):

p1 = (250, 250) 
p2 = (235, 210) 

theta = np.arctan2(p1[1]-p2[1], p1[0]-p2[0]) 
endpt_x = int(p1[0] - 1000*np.cos(theta)) 
endpt_y = int(p1[1] - 1000*np.sin(theta)) 

line_img = np.zeros_like(img) 
cv2.line(line_img, (p1[0], p1[1]), (endpt_x, endpt_y), 255, 2) 

Dann einfach cv2.bitwise_and() die beiden Bildern zusammen

contour_line_img = cv2.bitwise_and(line_img, contour_img) 

Hier ist ein Bild, um die Punkte zeigt, wobei die Leitung über die Kontur erstreckt, und die Linie, an der Kontur abbrach.

Line breaking at contour

Edit: Beachten Sie, dass dies nur funktioniert, wenn Ihre Konturen konvex sind. Wenn es irgendeine Konkavität gibt und die Linie durch diesen konkaven Teil verläuft, wird sie weiterhin auf der anderen Seite davon zeichnen. Für z.B. Wenn in Silencers Antwort beide Punkte innerhalb eines Ohrs liegen und auf das andere Ohr zeigen, möchten Sie, dass die Kontur stoppt, sobald sie auf eine Kante trifft, aber meine wird weiterhin auf das andere Ohr zeichnen. Ich denke, eine iterative Methode wie Silencer ist die beste für den allgemeinen Fall, aber ich mag die Einfachheit dieser Methode, wenn Sie wissen, dass Sie konvexe Konturen haben oder wenn Ihre Punkte an einem Ort sein werden, an dem dieses Problem nicht auftritt.

Edit2: Jemand anders auf Stapel beantwortete ihre eigene Frage über die Linie Iterator Klasse in Python durch eine zu erstellen: openCV 3.0 python LineIterator

+0

Der Code funktioniert tatsächlich, aber warum haben Sie den Wert 1000 festgelegt ist es ein ungefährer Wert für die Bildbreite und -höhe? –

+0

@ Neda'a Ja, es ist nur die Länge der Zeile in Pixeln, Sie können jede beliebige Länge verwenden.Die Diagonale des Bildes ist die längste mögliche Linie in einem Bild, also wäre es vielleicht ein guter Wert, um im Allgemeinen zu verwenden, um sicher zu sein, dass sich die Linie zu den Enden des Bildes erstreckt. Da ich nur die Linie zeichne, ist es egal, ob die Linie über die Bildgrenzen hinaus reicht oder nicht - sie wird nur an den Rand des Bildes gezeichnet. –

+0

Ja, das macht Sinn, danke. –

Verwandte Themen