2011-12-09 23 views
14

Podczas pobierania konturów z obrazu, powinieneś uzyskać 2 kontury na blob - jeden wewnętrzny i jeden zewnętrzny. Rozważ krąg poniżej - ponieważ koło jest linią o szerokości piksela większej niż jedna, powinieneś być w stanie znaleźć dwa kontury na obrazie - jeden z wewnętrznej części koła i jeden z zewnętrznej.Znaleźć kontury w OpenCV?

Korzystając z OpenCV, chcę odzyskać kontury INNER. Jednak kiedy używam findContours(), wydaje mi się, że uzyskuję tylko zewnętrzne kontury. W jaki sposób odzyskać wewnętrzne kontury obiektu typu blob za pomocą OpenCV?

Używam C++ API, nie C, dlatego sugeruję tylko funkcje korzystające z API C++. (to znaczy findContours() zamiast cvFindContours())

Dzięki.

enter image description here

+0

Czy możesz pokazać nam kod? – SSteve

+0

Nie mam żadnego unikalnego kodu. Po prostu mam Matę, którą pobieram z kamery. Uruchomę na nim detektor krawędzi, a następnie znajduję kontury za pomocą findContours(). Wszystkie znalezione kontury są przechowywane w wektorze >. To w zasadzie wszystko, co mam, więc nie ma sensu umieszczać prawdziwego kodu - to tylko tradycyjny proces znajdowania konturów. – fdh

+0

Pracowałem trochę z konturami, choć moje zainteresowanie było tylko zewnętrznymi konturami. Próbowałem kolorować kontur, z "drawContours()". Który wyszukuje coś w rodzaju hierachy. Próbka na "drawContours()", której użyłem, nie pokolorowała wewnętrznych konturów. Próbuję się tu dostać, jest to, że prawdopodobnie musisz użyć hierarchii z "findContours()", aby je posortować. (Powodem, dla którego nie zamieszczam odpowiedzi jest to, że moja wiedza na temat tej hierachy jest ograniczona, nie chciałbym wprowadzać w błąd w tej sprawie.) Przeprowadziłem trochę testów na tych i mogłem wyjaśnić moje zrozumienie do tej pory, jeśli żądasz.) – Sonaten

Odpowiedz

19

Pobiegłem ten kod na obrazie i wrócił wewnętrzny i zewnętrzny kontur.

#include <iostream> 
#include "opencv2/core/core.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 

int main(int argc, const char * argv[]) { 

    cv::Mat image= cv::imread("../../so8449378.jpg"); 
    if (!image.data) { 
     std::cout << "Image file not found\n"; 
     return 1; 
    } 

    //Prepare the image for findContours 
    cv::cvtColor(image, image, CV_BGR2GRAY); 
    cv::threshold(image, image, 128, 255, CV_THRESH_BINARY); 

    //Find the contours. Use the contourOutput Mat so the original image doesn't get overwritten 
    std::vector<std::vector<cv::Point> > contours; 
    cv::Mat contourOutput = image.clone(); 
    cv::findContours(contourOutput, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); 

    //Draw the contours 
    cv::Mat contourImage(image.size(), CV_8UC3, cv::Scalar(0,0,0)); 
    cv::Scalar colors[3]; 
    colors[0] = cv::Scalar(255, 0, 0); 
    colors[1] = cv::Scalar(0, 255, 0); 
    colors[2] = cv::Scalar(0, 0, 255); 
    for (size_t idx = 0; idx < contours.size(); idx++) { 
     cv::drawContours(contourImage, contours, idx, colors[idx % 3]); 
    } 

    cv::imshow("Input Image", image); 
    cvMoveWindow("Input Image", 0, 0); 
    cv::imshow("Contours", contourImage); 
    cvMoveWindow("Contours", 200, 0); 
    cv::waitKey(0); 

    return 0; 
} 

Oto kontury to znaleziono:

findContour result image

+0

Dzięki. Czy zdarzy ci się wiedzieć, jak uzyskać dostęp tylko do wewnętrznych konturów? Jak w granicach dziury? – fdh

+2

Jeśli ustawisz tryb na 'CV_RETR_TREE' zamiast' CV_RETR_LIST' otrzymasz hierarchiczne drzewo konturów, dzięki czemu kontur wewnętrzny będzie znajdował się poniżej konturu zewnętrznego. Nie rozróżnia konturów wewnętrznych od zewnętrznych, więc jeśli wewnątrz okręgu znajduje się okrąg, oba te kontury znajdowałyby się poniżej wewnętrznego obrysu zewnętrznego koła. Samouczek [OpenCV findContour] (http://opencv.itseez.com/doc/tutorials/imgproc/shapedescriptors/find_contours/find_contours.html#find-contours) używa 'CV_RETR_TREE'. – SSteve

3

myślę co Farhad jest pytaniem jest, aby przyciąć kontur z oryginalnego obrazu.

Aby to zrobić, musisz znaleźć kontur, jak wyjaśniono powyżej, a następnie użyć maski, aby uzyskać wnętrze z oryginału, a następnie przyciąć wynik do obrazu o takim samym rozmiarze jak kontur.

0

Funkcja findcontours przechowuje wszystkie kontury w różnych wektorach, w kodzie podanym, że wszystkie kontury są rysowane, wystarczy narysować kontur odpowiadający konturowi wewnętrznemu, idx jest zmienną, która określa, który kontur jest narysowany.

Powiązane problemy