2016-08-24 2 views
0

Ich suche nach einem Algorithmus, der externe und interne Konturerkennung an einem idealen Bild mit nur zwei verschiedenen RGB-Werten durchführen kann.Externe und interne Kantenerkennung für ideales Bild

Unten ist ein typisches Beispiel für das Bild (das erste), das ich bearbeiten möchte, das nächste Bild ist eines, das ich selbst gemacht habe und das Ergebnis zeige, das ich erwarte.

Der letzte ist ein Ergebnis von OpenCV Canny Erkennung durch die Demo-Software zur Verfügung gestellt unter OpenCV demo Software.

Der schlaue Algorithmus ist nicht befriedigend, da er die Formen (besonders Ecken) zu sehr glättet.

Gibt es einen eleganten Algorithmus, der die gleichen Ergebnisse liefert wie im zweiten Bild?

Original Image
My own brain's contour detection and expected result
OpenCV -> Contour algorithm result

+0

Verwendung cv :: Schwelle oder andere Methode, um die perfekte Maske zu erstellen, verwenden Sie cv :: findContours mit entsprechenden Flags Außen- und Innenkonturen zu finden. – Micka

Antwort

3

Contour-Extraktion ist die einfachste Sache, dies zu tun:

int main(int argc, char* argv[]) 
{ 
    cv::Mat input = cv::imread("C:/StackOverflow/Input/ContourExtraction.png"); 

    cv::Mat mask; 
    // create a perfect mask: Easy if you know the 2 colors present in your image: 
    cv::inRange(input, cv::Scalar(100, 0, 0), cv::Scalar(255, 255, 255), mask); 
    cv::imshow("mask", mask); 

    std::vector<std::vector<cv::Point> > contours; // contour points 
    std::vector<cv::Vec4i> hierarchy; // this will give you the information whether it is an internal or external conotour. 

    // contour extraction: This will alter the input image, so if you need it later use mask.clone() instead 
    findContours(mask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cv::Point(0, 0)); // use different CV_CHAIN_APPROX_ if you dont need ALL the points but only the ones that dont lie on a common line 

    // output images: 
    cv::Mat contoursExternal = input.clone(); 
    cv::Mat contoursInternal = input.clone(); 
    cv::Mat contoursAll = cv::Mat::zeros(input.size(), CV_8UC1); 

    // draw contours 
    for (unsigned int i = 0; i < contours.size(); ++i) 
    { 
     cv::drawContours(contoursAll, contours, i, cv::Scalar::all(255), 1); 
     if (hierarchy[i][3] != -1) cv::drawContours(contoursInternal, contours, i, cv::Scalar::all(255), 1); 
     else cv::drawContours(contoursExternal, contours, i, cv::Scalar::all(255), 1); 
    } 

    cv::imshow("internal", contoursInternal); 
    cv::imshow("external", contoursExternal); 
    cv::imshow("all", contoursAll); 


    cv::imshow("input", input); 
    cv::waitKey(0); 
    return 0; 
} 

geben diese Ergebnisse:

Außenkonturen:

enter image description here

Innenkonturen:

enter image description here

Ergebnismaske:

enter image description here

+1

Ich nehme an, dass die "OpenCV-Demo" eine Gaußsche Unschärfe oder etwas vor Canny anwendet. Deshalb sind die Kanten "glatt" – Miki

+1

Nach wenigen Tests auf verschiedenen Bildern liefert dieser Algorithmus sehr gute Ergebnisse. – Toyo

1

Eines, das ein bisschen mehr Zerklüftung zu den Kanten gibt, ist das Roberts-Kreuz-Algorithmus. Obwohl es in Ihrem Beispiel sehr anfällig für Lärm ist, glaube ich nicht, dass es ein Deal Breaker sein wird.

Es gibt eine schöne Zusammenfassung, wie es funktioniert, das es viel besser als ich selbst erklärt Here. Im Wesentlichen nehmen Sie eine 2x2-Region, führen eine x- und y-Faltung durch und approximieren die Gradientengröße, da Quadratwurzeln für Slowpoke sind.

Verwandte Themen