2017-01-11 5 views
2

Mit Python und OpenCV Ich Erkennung Konturen einer binären Maske:eine binäre Maske Contouring mit OpenCV/Python

import numpy as np 
import cv2 
import matplotlib.pyplot as plt 

mask = np.zeros(20000, dtype=np.uint8).reshape(100, 200) 
mask[5:-5,5:-5] = 255 
mask[10:70,40:80] = 0 
plt.subplot(121) 
plt.imshow(mask, cmap='Greys_r', interpolation='none') 

_, contours, hierarchy = cv2.findContours(mask.copy(), 
              cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE, 
              offset=(0, 0)) 

in einem erwarteten Verhalten Resultierende:

plt.subplot(122) 
cv2.drawContours(mask, contours, -1, (127, 127, 127), 2) 
plt.imshow(mask, cmap='Greys_r', interpolation='none') 
plt.show() 

Simple opencv contouring

jedoch Ich kann das Ergebnis einer vollständig aktivierten Maske anscheinend nicht verstehen:

mask = np.ones(20000, dtype=np.uint8).reshape(100, 200) 
mask *=255 
_, contours, hierarchy = cv2.findContours(mask.copy(), 
              cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE, 
              offset=(0, 0)) 

print contours[0] 

Welche produziert:

(1 1), (1 98), (198 98), (198 1) 

statt (0 0), (0 99), (199, 99), (199, 0)

Warum ist opencv findcontours so verhalten, mit einem Versatz von 1?

+0

Durch genau Ausführung Dein letzter Codeschnipsel bekomme ich (0 0), (0 99), (199, 99), (199, 0) – Soltius

Antwort

3

Bis OpenCV 3.1 findContours hat this wierd behaviour auf Grenzen, auch im documentation erklärte:

Quelle Bild wird durch diese Funktion geändert. Außerdem berücksichtigt die Funktion nicht die 1-Pixel-Grenze des Bildes (sie ist mit Nullen gefüllt und wird für die Nachbaranalyse im Algorithmus verwendet), daher werden die Konturen, die den Bildrand berühren, abgeschnitten.

Dies hat been corrected in OpenCV 3.2, which also doesn't modify the source image:

Da opencv 3.2 Quellbild durch diese Funktion nicht geändert wird.


für frühere Versionen Als Abhilfe können Sie copyMakeBorder verwenden, um eine schwarz (0) Grenze von 1 Pixel zu erzeugen und verwenden findContours mit einem Versatz von (-1,-1):

border = cv2.copyMakeBorder(mask, 1, 1, 1, 1, cv2.BORDER_CONSTANT, value=0) 
_, contours, hierarchy = cv2.findContours(border, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE, offset=(-1, -1)) 
+0

Danke für beide Ansätze. Ich freue mich auf opencv3.2 auf Python und bleibe bei deinem ersten Ansatz in der Zwischenzeit – bold