2014-12-04 11 views
10

Użyłem adaptacyjnej techniki progowej, aby utworzyć obraz jak ten poniżej:Uzyskanie powierzchni w obrębie konturów Opencv Python?

enter image description here

Kod Kiedyś było:

image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 45, 0) 

Potem wykorzystać ten kod, aby uzyskać kontury:

cnt = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] 

Moim celem jest wygenerowanie maski przy użyciu wszystkich pikseli w obrysie zewnętrznym, więc chcę wypełnić wszystkie piksele w obiekcie mają być białe. Jak mogę to zrobić?

Próbowałem kodu poniżej, aby utworzyć maskę, ale uzyskany maska ​​wydaje się nie różni, to obraz po zastosowaniu adaptacyjnego progu

mask = np.zeros(image.shape[:2], np.uint8) 
cv2.drawContours(mask, cnt, -1, 255, -1) 

Odpowiedz

10

co masz jest prawie poprawne. Jeśli przyjrzeć się obrazowi z progiem, przyczyną jego braku jest fakt, że obiekt butów ma luki na obrazie. W szczególności chodzi o to, że spodziewasz się, że but ma obwód, który ma być połączony wszystkie. Jeśli tak się stanie, to jeśli wyodrębnisz najbardziej zewnętrzny kontur (co robi twój kod), powinieneś mieć tylko jeden kontur, który reprezentuje zewnętrzny obwód obiektu. Po wypełnieniu konturu but powinien być całkowicie solidny.

Ponieważ obwód buta nie jest kompletny i zepsuty, powoduje to rozłączenie białych obszarów. Jeśli użyjesz findContours, aby znaleźć wszystkie kontury, będzie on znajdował tylko kontury każdego z białych kształtów, a nie najbardziej zewnętrznego obwodu. W związku z tym, jeśli spróbujesz użyć wartości findContours, uzyskasz taki sam efekt, jak oryginalny obraz, ponieważ po prostu znajdujesz obwód każdego białego obszaru wewnątrz obrazu, a następnie wypełniasz te obszary wartością findContours.


Co trzeba zrobić, to upewnić się, że obraz jest całkowicie zamknięte. Polecam, aby użyć morphology, aby zamknąć wszystkie rozłączone regiony razem, a następnie uruchomić wywołanie findContours na tym nowym obrazie. W szczególności wykonaj binarne zamknięcie morfologiczne. To, co to robi, polega na tym, że pobiera rozłączone białe obszary, które są blisko siebie i zapewnia, że ​​są połączone. Użyj morfologicznego zamknięcia i być może użyj czegoś podobnego do kwadratowego elementu struktury 7 x 7, aby zamknąć but. Ten element strukturyzacji można uznać za minimalny podział między białymi regionami, aby uznać je za połączone.

Jako takie coś jak to zrobić:

import numpy as np 
import cv2 
image = cv2.imread('...') # Load your image in here 
# Your code to threshold 
image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 45, 0)  

# Perform morphology 
se = np.ones((7,7), dtype='uint8') 
image_close = cv2.morphologyEx(image, cv2.MORPH_CLOSE, se) 

# Your code now applied to the closed image 
cnt = cv2.findContours(image_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] 
mask = np.zeros(image.shape[:2], np.uint8) 
cv2.drawContours(mask, cnt, -1, 255, -1) 

Ten kod zasadniczo bierze swój progowaniu obrazu morfologicznego i dotyczy zamknięcia do tego obrazu. Następnie odnajdujemy zewnętrzne kontury tego obrazu i wypełniamy je białym kolorem. FWIW, pobrałem twój obraz z progiem i spróbowałem tego na własną rękę. To co mam z obrazka:

enter image description here

+0

To jest niesamowite, nie mogę uwierzyć, że to działa! Pewnego popołudnia udało mi się zamazać tło obrazu. Opencv jest całkiem fajny. – emschorsch

+0

@emschorsch - dzięki za awans :) Tak, OpenCV to niesamowita platforma. Używam go codziennie do pracy. Baw się dobrze! – rayryeng

+0

@rayryeng Próbowałem tego kodu, ale w ostatnim wierszu zgłasza następujący błąd 'drawing.cpp: 2380: error: (-215) npoints> 0 w funkcji cv :: drawContours' - Używam OpenCV 3.1 i Python 2.7 . Jakieś pomysły? – g491