2013-06-14 17 views
23

Proszę spojrzeć na następujący kodRóżnica między „detekcja krawędzi” i „Obraz Kontury”

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

using namespace std; 
using namespace cv; 

Mat src, grey; 
int thresh = 10; 

const char* windowName = "Contours"; 

void detectContours(int,void*); 

int main() 
{ 
    src = imread("C:/Users/Public/Pictures/Sample Pictures/Penguins.jpg"); 

    //Convert to grey scale 
    cvtColor(src,grey,CV_BGR2GRAY); 

    //Remove the noise 
    cv::GaussianBlur(grey,grey,Size(3,3),0); 

    //Create the window 
    namedWindow(windowName); 

    //Display the original image 
    namedWindow("Original"); 
    imshow("Original",src); 

    //Create the trackbar 
    cv::createTrackbar("Thresholding",windowName,&thresh,255,detectContours); 

    detectContours(0,0); 
    waitKey(0); 
    return 0; 

} 

void detectContours(int,void*) 
{ 
    Mat canny_output,drawing; 

    vector<vector<Point>> contours; 
    vector<Vec4i>heirachy; 

    //Detect edges using canny 
    cv::Canny(grey,canny_output,thresh,2*thresh); 

    namedWindow("Canny"); 
    imshow("Canny",canny_output); 

    //Find contours 
    cv::findContours(canny_output,contours,heirachy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0)); 

    //Setup the output into black 
    drawing = Mat::zeros(canny_output.size(),CV_8UC3); 



    //Draw contours 
    for(int i=0;i<contours.size();i++) 
    { 
     cv::drawContours(drawing,contours,i,Scalar(255,255,255),1,8,heirachy,0,Point()); 
    } 

    imshow(windowName,drawing); 

} 

Teoretycznie Contours wykrywają krzywe. Edge detection oznacza wykrywanie krawędzi. W powyższym kodzie wykonałem wykrywanie krawędzi za pomocą Canny i wykrywanie krzywej przez findContours(). Poniżej przedstawiono wynikowe obrazy

Canny Obraz

enter image description here

Kontury Obraz

enter image description here

OK, więc teraz, jak widać, nie ma żadnej różnicy! Jaka jest rzeczywista różnica między tymi 2? W samouczkach OpenCV podano tylko kod. Znalazłem wyjaśnienie na temat tego, co jest Contours, ale nie rozwiązuje tego problemu.

Proszę pomóc!

+0

Proponuję użyć cv :: GaussianBlur() przed cv :: Canny(). To może pozbyć się większości bałaganu przy zachowaniu głównych krawędzi. – Bull

Odpowiedz

38

Krawędzie są obliczane jako punkty ekstremy gradientu obrazu w kierunku gradientu. jeśli to pomaga, możesz myśleć o nich jako o punktach minimalnych i maksymalnych w funkcji 1D. Chodzi o to, że piksele brzegowe są pojęciem lokalnym: wskazują tylko znaczącą różnicę między sąsiednimi pikselami.

kontury często uzyskane z krawędzi, ale służą one jako obiektów kontury. Muszą więc być zamknięte krzywe. Możesz myśleć o nich jako o granicach (niektóre algorytmy przetwarzania obrazu nazywają je w ten sposób). Po uzyskaniu krawędzi należy połączyć krawędzie w celu uzyskania zamkniętego konturu.

+0

Dziękuję bardzo za odpowiedź. Naprawdę to doceniam :) –

+0

Nie ma za co :) – sansuiso

3

Kontury mogą zrobić coś więcej niż "tylko" wykrycie krawędzi. Algorytm rzeczywiście znajduje krawędzie obrazów, ale także umieszcza je w hierarchii. Oznacza to, że możesz zażądać zewnętrznych granic obiektów wykrytych na obrazach. Takie rzeczy nie byłyby (bezpośrednio) możliwe, gdybyś sprawdzał tylko krawędzie.

Jak można przeczytać w dokumentacji, kontury są najczęściej używane do rozpoznawania obiektów, w których wykrywacz krawędzi jest bardziej "globalną" operacją. Nie zdziwiłbym się, gdyby algorytm konturu użył jakiejś wykrywalnej krawędzi.

+0

odkąd findContours() działa na obrazach binarnych, byłbym bardzo zaskoczony, gdyby użył detektora krawędzi Canny. – Bull

+0

Bardzo dziękuję za odpowiedź, już dałem ci +1 –

6

Główna różnica między znajdowaniem krawędzi i zliczeń polega na tym, że po wyszukaniu krawędzi wyjście jest nowym obrazem. W tym nowym obrazie (krawędziowym) będą podświetlone krawędzie. Istnieje wiele algorytmów do wykrywania krawędzi look at wiki see also.

Na przykład operator Sobela daje gładkie "mgliste" wyniki. W twoim szczególnym przypadku, chwyt polega na tym, że używasz detektora krawędzi Canny. Ten wykonuje kilka kroków dalej niż inne czujki. W rzeczywistości prowadzi dalsze kroki doskonalenia krawędzi. Wyjście detektora Canny'ego jest zatem obrazem binarnym, z liniami o szerokości 1 px zamiast krawędzi.

Z drugiej strony algorytm przetwarza dowolny obraz binarny. Więc jeśli włożysz biały wypełniony kwadrat na czarnym tle. Po uruchomieniu algorytmu Contours otrzymasz biały pusty kwadrat, tylko granice.

Inną dodatkową zaletą wykreślania konturów jest to, że zwraca zestaw punktów! To świetnie, ponieważ możesz wykorzystać te punkty do dalszej obróbki.

W twoim przypadku, to tylko zbieg okoliczności, że oba obrazy pasują do siebie. Nie rządzi, aw twoim przypadku jest to spowodowane unikalną właściwością algorytmu Canny'ego.

+2

Sobel tak naprawdę nie jest wykrywaczem krawędzi, tylko daje gradient. Canny jednak znajduje maksymalny gradient, tj. Pik w gradiencie. Implementacja OpenCV Canny'ego() w rzeczywistości używa Sobel() w jego interfejsie. – Bull

+0

Bardzo dziękuję za odpowiedź, już dałem ci +1 –

2

Pojęcie konturów służy jako narzędzie do pracy na danych krawędziowych. Nie wszystkie krawędzie są takie same. Ale w wielu przypadkach, np. obiekty z jednomodalnym rozkładem kolorów (tj. jeden kolor), krawędzie są rzeczywistymi konturami (obrysem, kształtem).

  1. Wykryj nie tylko krzywe, ale wszystko, co jest połączone na krawędzi mapy. (analiza połączonych komponentów) [1]
  2. Przydatna dla obiektów z jednomodalnym rozkładem kolorów (maska ​​pierwszego planu jest łatwo dostępna z prostym progiem). Twój przykładowy obraz nie jest odpowiedni.

[1] topologiczne Structural Analysis zdigitalizowanych Binary obrazy Granicy brzmienie Satoshi Suzuki, 1985.

+0

Bardzo dziękuję za odpowiedź, już dałem ci +1 –