2012-04-20 11 views
7

Obecnie pracuję nad projektem przetwarzania obrazu. Używam Opencv2.3.1 z VC++. Napisałem kod w taki sposób, że obraz wejściowy jest filtrowany tylko na kolor niebieski i konwertowany na obraz binarny. Obraz binarny ma kilka małych obiektów, których nie chcę. Chciałem wyeliminować te małe obiekty, więc użyłem metody openCV do wykrywania konturów w obrazie binarnym. ale problem polega na tym, że nie mogę wyeliminować małych obiektów w obrazie wyjściowym. Użyłem funkcji cvContourArea(), ale nie działałem poprawnie ..., funkcja erodująca również nie działała poprawnie.Kontury opencv: Jak wyeliminować małe kontury na obrazie binarnym

Więc proszę mi ktoś pomóc z tym problemem ..

binarny obraz który uzyskałam:

enter image description here

Wynik/wyjścia obrazu, które chcę w celu uzyskania:

enter image description here

Odpowiedz

1

Czy na pewno filtrowanie za pomocą małego obszaru konturu nie działa? To zawsze działa dla mnie. Czy widzimy twój kod?

Ponadto, jak wspomniano, wskazane jest, aby używać zarówno erodowania, jak i rozszerzania, aby w przybliżeniu zachować obszar. Aby usunąć małe, hałaśliwe fragmenty, najpierw użyj żródła i wypełnij otwory, najpierw użyj rozszerzenia.

A drugi bok, może chcesz sprawdzić nową C++ wersje cv * funkcji, jeśli nie wiedzieli o nich już (documentation dla findContours). Są one, moim zdaniem, znacznie łatwiejsze w użyciu.

+0

Dzięki za sugestię, ale nie wiem, jak napisać kod, aby znaleźć obszar każdego wykrytego plamki/konturu. Kod, który napisałem, znajduje się pod poniższym linkiem. Czy możesz go poprawić i odpowiedzieć. : http://textuploader.com/?p=6&id=YwRl. –

+0

oh! Właśnie zapomniałem, nagłówek i plik cpp dla cvutility można znaleźć w tych linkach: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Proszę uwzględnić je w katalog źródłowy i dołącz ścieżki. –

+0

Nie jestem zbyt obeznany z C api, ale wygląda na to, że właśnie obliczasz obszar pierwszego konturu. Musisz wykonać iterację poprzez kontury i narysować tylko te z obszarem> pewnym progiem. Jeśli próbujesz znaleźć ten obiekt, powinieneś narysować kontur z największym obszarem. – fferen

0

Sądząc po obrazach przed i po, należy określić obszar wszystkich białych obszarów lub obiektów typu blob, a następnie zastosować wartość obszaru progowego. To wyeliminowałoby wszystkie obszary mniejsze niż wartość i pozostawiło tylko duży biały obszar, który jest widoczny na drugim obrazie. Po użyciu funkcji cvFindContours spróbuj użyć momentów rzędu 0. Zwróciłoby to obszar obszarów typu BLOB na obrazie. Ten link może być pomocny w implementacji tego, co właśnie opisałem. http://www.aishack.in/2010/07/tracking-colored-objects-in-opencv/

+0

Dzięki za sugestię, ale nie mam sposobu, aby napisać kod, aby znaleźć obszar każdego blob/kontur, który został wykryty. –

+0

Dzięki za sugestię, ale nie wiem, jak napisać kod, aby znaleźć obszar każdego wykrytego plamki/konturu. Kod, który napisałem, znajduje się pod poniższym linkiem. Czy możesz go poprawić i odpowiedzieć. : http://textuploader.com/?p=6&id=YwRl. –

+0

oh! Właśnie zapomniałem, nagłówek i plik cpp dla cvutility można znaleźć w tych linkach: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Proszę uwzględnić je w katalog źródłowy i dołącz ścieżki. –

10

Ok, wierzę problem mógłby być rozwiązany z the bounding box demo niedawno wprowadzonej przez OpenCV.

enter image description here

Jak już zapewne zauważyliście, obiekt jesteś zainteresowany co powinno być wewnątrz największy prostokąt rysować na zdjęciu. Na szczęście ten kod nie jest zbyt skomplikowany i jestem pewien, że możesz to wszystko zrozumieć, badając i eksperymentując z nim.

+0

thnx .. Sprawdzę to. –

7

Oto moje rozwiązanie w celu wyeliminowania małych konturów. Podstawową ideą jest sprawdzenie długości/powierzchni dla każdego konturu, a następnie usunięcie mniejszego z kontenera wektorowego.

normalnie dostaniesz kontury jak ten

Mat canny_output; //example from OpenCV Tutorial 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
Canny(src_img, canny_output, thresh, thresh*2, 3);//with or without, explained later. 
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

Z Canny() wstępnego przetwarzania, dostaniesz segmenty konturu, jednak każdy segment jest przechowywany z brzegowych pikseli jako zamknięty pierścień.W tym przypadku można sprawdzić długość i usunąć mały jak

for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end();) 
{ 
    if (it->size()<contour_length_threshold) 
     it=contours.erase(it); 
    else 
     ++it; 
} 

Bez Canny() wyprzedzającym, dostaniesz kontury przedmiotów. Podobieństwo, można również użyć obszar zdefiniować próg, aby wyeliminować drobne przedmioty, jak samouczek OpenCV pokazanego

vector<Point> contour = contours[i]; 
double area0 = contourArea(contour); 

to contourArea() jest liczba niezerowych pikseli

0

wierzę można użyć morfologiczne operatory takie jak erozja i rozszerzanie (czytaj więcej here)

Musisz dokonać erozji o wielkości jądra w pobliżu promienia koła po prawej (ten, który chcesz wyeliminować). , a następnie rozszerzenie za pomocą tego samego jądra, aby wypełnić luki utworzone przez krok erozji.

Erykcja FYI, a następnie rozszerzenie za pomocą tego samego jądra nazywa się otwarciem.

kod będzie coś takiego

int erosion_size = 30; // adjust with you application 
Mat erode_element = getStructuringElement(MORPH_ELLIPSE, 
         Size(2*erosion_size + 1, 2*erosion_size+1), 
         Point(erosion_size, erosion_size)); 
erode(binary_img, binary_img, erode_element); 
dilate(binary_img, binary_img, erode_element); 
0

Nie jest to szybki sposób, ale może być przydatna w niektórych przypadkach. W OpenCCV 3.0 jest nowa funkcja - connectedComponentsWithStats. Dzięki niemu możemy uzyskać obszar połączonych komponentów i wyeliminować niepotrzebne. Możemy więc łatwo usunąć krąg z dziurami, z tą samą ramką ograniczającą, co pełne kółko.

Powiązane problemy