2017-01-11 9 views
2

с Python и OpenCV Я обнаруживать контуры бинарной маски:Контурная двоичную маску с 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)) 

, выражающееся в ожидаемое поведение:

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

Однако , Я не могу понять результат полной активированной маски:

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] 

Который производит:

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

вместо (0 0), (0 99), (199, 99), (199, 0)

Почему OpenCV findcontours ведет себя так, со смещением на 1?

+0

Выполнив точно ваш последний фрагмент кода, я получаю (0 0), (0 99), (199, 99), (199, 0) – Soltius

ответ

3

До OpenCV 3.1 findContours имеет this wierd behaviour на границах, также указывается в documentation:

Источник изображения изменяется с помощью этой функции. Кроме того, функция не учитывает 1-пиксельную границу изображения (она заполнена 0 и используется для анализа соседей в алгоритме), поэтому контуры, затрагивающие границу изображения, будут обрезаны.

Это имеет been corrected in OpenCV 3.2, which also doesn't modify the source image:

Так как OpenCV 3.2 исходного изображения не изменяется с помощью этой функции.


В качестве обходного пути для предыдущих релизов, вы можете использовать copyMakeBorder создать черный (0) границы 1 пиксел, и использовать findContours со смещением (-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

Спасибо за оба подхода. Я с нетерпением жду opencv3.2 на python и придерживаюсь вашего первого подхода – bold

Смежные вопросы