2013-06-14 18 views
23

Si prega di dare un'occhiata al seguente codice didifferenza tra "Rilevamento dei bordi" e "Immagine Contorni"

#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); 

} 

Teoricamente, Contours mezzi di rilevamento curve. Edge detection significa rilevare i bordi. Nel mio codice precedente, ho eseguito il rilevamento dei fronti utilizzando Canny e il rilevamento delle curve tramite findContours(). Di seguito sono riportate le immagini risultanti

Canny Immagine

enter image description here

contorni dell'immagine

enter image description here

OK, ora, come si può vedere, non v'è alcuna differenza! Quindi, qual è la differenza effettiva tra questi 2? Nelle esercitazioni OpenCV, viene fornito solo il codice. Ho trovato una spiegazione su ciò che è Contours ma non sta affrontando questo problema.

Si prega di aiuto!

+0

vi suggerisco di utilizzare cv :: GaussianBlur() prima cv :: Canny(). Questo può sbarazzarsi della maggior parte del disordine mantenendo i bordi principali. – Bull

risposta

38

I bordi sono calcolati come punti che sono estremi del gradiente di immagine nella direzione del gradiente. se aiuta, puoi considerarli come i punti minimo e massimo in una funzione 1D. Il punto è, i pixel del bordo sono una nozione locale: indicano solo una differenza significativa tra i pixel vicini.

contorni sono spesso ottenuti dai bordi, ma sono finalizzate a essere contorni dell'oggetto. Quindi, devono essere curve chiuse. Puoi considerarli come confini (alcuni algoritmi di Image Processing & li chiamano in questo modo). Quando si ottengono dai bordi, è necessario collegare i bordi per ottenere un contorno chiuso.

+0

Grazie mille per la risposta. Lo apprezzo davvero :) –

+0

Prego :) – sansuiso

3

I contorni possono effettivamente fare un po 'di più che "solo" rilevare i bordi. L'algoritmo trova infatti i bordi delle immagini, ma le colloca anche in una gerarchia. Ciò significa che è possibile richiedere i bordi esterni degli oggetti rilevati nelle immagini. Una cosa del genere non sarebbe (direttamente) possibile se controlli solo i bordi.

Come si può leggere nella documentazione, i contorni sono utilizzati principalmente per il riconoscimento di oggetti, in cui il rilevatore di bordo canny è un'operazione più "globale". Non mi sorprenderebbe se l'algoritmo di contorno utilizzasse una sorta di rilevamento dei bordi canny.

+0

dal momento che findContours() funziona su immagini binarie, sarei estremamente sorpreso se usasse un rilevatore di bordo Canny. – Bull

+0

Grazie mille per la risposta, ti ho già dato un +1 –

6

La differenza principale tra la ricerca di spigoli e contorni è che se si esegue la ricerca di spigoli l'uscita è una nuova immagine. In questa nuova immagine (immagine del bordo) avrai dei bordi evidenziati. Esistono molti algoritmi per il rilevamento dei bordi look at wiki see also.

Ad esempio, l'operatore Sobel fornisce risultati "nebbiosi" uniformi. Nel tuo caso particolare, il problema è che stai usando il rilevatore di bordo Canny. Questo fa pochi passi in più rispetto ad altri rivelatori. Effettua attualmente ulteriori passaggi di rifinitura del bordo. L'uscita del rivelatore Canny è quindi un'immagine binaria, con linee larghe 1 px al posto dei bordi.

D'altra parte l'algoritmo Contours elabora un'immagine binaria arbitraria. Quindi se metti quadrati bianchi pieni su sfondo nero. Dopo aver eseguito l'algoritmo Contours, si otterrebbe un quadrato vuoto bianco, solo i bordi.

Altro bonus aggiuntivo del rilevamento del contorno è, in realtà restituisce un insieme di punti! È fantastico, perché puoi utilizzare questi punti più avanti per qualche elaborazione.

Nel tuo caso particolare, è solo una coincidenza che entrambe le immagini coincidano. Non regola, e nel tuo caso, è a causa della proprietà unica dell'algoritmo Canny.

+2

Sobel non è proprio un rilevatore di bordi, ma dà solo il gradiente. Canny tuttavia trova il gradiente massimo, cioè i picchi nel gradiente. L'implementazione OpenCV di Canny() utilizza infatti Sobel() nella sua front-end. – Bull

+0

Grazie mille per la risposta, ti ho già dato un +1 –

2

La nozione di contorni viene utilizzata come strumento per lavorare sui dati dei bordi. Non tutti i bordi sono uguali. Ma in molti casi, ad es. gli oggetti con distribuzione dei colori unimodale (ad esempio un colore), i bordi sono i contorni effettivi (contorno, forma).

  1. Rileva non solo le curve, ma tutto ciò che è connesso sulla mappa dei bordi. (analisi dei componenti collegati) [1]
  2. Utile per oggetti con distribuzione dei colori unimodale (una maschera in primo piano si trova facilmente con una soglia semplice). La tua immagine di esempio non è adatta.

[1] topologico Analisi Strutturale del Digitized Binary Immagini di frontiera seguito da Satoshi Suzuki, 1985.

+0

Grazie mille per la risposta, ti ho già dato un +1 –

Problemi correlati