Automatyczne obliczanie niskich i wysokich progów dla operacji Canny w opencv

W openCV progi niskie i wysokie dla operatora canny są obowiązkowe:

cvCanny(input,output,thresh1,thresh2)

W Matlab istnieje możliwość automatycznego obliczania tych wartości:

edge(input,'canny')

Przyjrzałem się kodowi Matlaba dla edge ' a i naprawdę nie jest to proste, aby obliczyć je automatycznie.

Czy wiesz o jakiejś implementacji operatora canny wraz z automatycznym obliczaniem progu dla opencv?

Dzięki

Author: hoffer, 2010-11-27

7 answers

Natknąłem się na tę odpowiedź, gdy szukałem sposobu, aby automatycznie obliczyć wartości progowe Canny ' ego.

Mam nadzieję, że pomoże to każdemu, kto szuka dobrej metody określania automatycznych wartości progowych dla algorytmu Canny ' ego...


Jeśli obraz składa się z oddzielnego pierwszego planu i tła, wtedy krawędź obiektu pierwszego planu może zostać wyodrębniona przez:

  1. Oblicz próg Otsu używając:

    double otsu_thresh_val = cv::threshold(
        orig_img, _img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU
    );
    

    Nie potrzebujemy _img. Interesuje nas tylko otsu_thresh_val, ale niestety obecnie w OpenCV nie istnieje metoda pozwalająca obliczyć tylko wartość progową.

  2. Użyj wartości progowej Otsu jako wyższego progu i połowy tego samego co próg dolny dla algorytmu Canny ' ego.

    double high_thresh_val  = otsu_thresh_val,
           lower_thresh_val = otsu_thresh_val * 0.5;
    cv::Canny( orig_img, cannyOP, lower_thresh_val, high_thresh_val );
    

Więcej informacji na ten temat można znaleźć w this paper: the Study on an Application of Otsu Method in Canny Operator . Wyjaśnienie Otsu implementację można znaleźć tutaj .

 42
Author: VP.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-21 02:48:34

Możesz użyć średniej wartości wejściowego obrazu w skali szarości i zdefiniować dolny i górny próg za pomocą odchylenia standardowego. Możesz mieć bardziej szczegółowe wyjaśnienie i Kod opencv tutaj: http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/

 16
Author: Luca Del Tongo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-11 01:35:54

Dostępny jest również kod, który może to zrobić automatycznie, umieszczając to w kompilacji OpenCV. Znalazłem go na liście dyskusyjnej OpenCV-users, więc żadnych gwarancji. :)

Dyskusja: http://opencv-users.1802565.n2.nabble.com/Automatic-thresholding-in-cvCanny-td5871024.html GitHub (kod): https://gist.github.com/756833

 7
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-13 13:24:23

Przejrzałem kod źródłowy programu Matlab Canny edge detection i udało mi się go napisać w Javie za pomocą OpenCV 3.

private static Mat getpartialedge(Mat image){
    double nonEdgeRate = 0.6;
    double thresholdRate = 0.6;
    double w = image.cols();
    double h = image.rows();
    int bins = 256;
    Mat sobel = new Mat();
    Mat sobelx = new Mat();
    Mat sobely = new Mat();
    Mat sobelxabs = new Mat();
    Mat sobelyabs = new Mat(); 
    Size gsz = new Size(5, 5);
    if(false) {
        Imgproc.Canny(image, sobel, 41, 71);
    }else {

        //Imgproc.GaussianBlur(graycopy,graycopy, gsz, 2);
        //Imgproc.dilate(image, image, kernel8);
        Imgproc.GaussianBlur(image, image, gsz, 2);


        int apertureSize = 3;
        Imgproc.Sobel(image, sobelx, CvType.CV_16S, 1, 0, apertureSize, 1, 0);
        Core.convertScaleAbs(sobelx, sobelxabs);
        Imgproc.Sobel(image, sobely, CvType.CV_16S, 0, 1, apertureSize, 1, 0);
        Core.convertScaleAbs(sobely, sobelyabs);
        Core.addWeighted(sobelxabs, 1, sobelyabs, 1, 0, sobel);
        sobel.convertTo(sobel, CvType.CV_8U);


        Mat equalized = new Mat();
        Imgproc.equalizeHist(sobel, equalized);
        Imgcodecs.imwrite(filePath + "aftersobel(eq).png", equalized);
        Imgcodecs.imwrite(filePath + "aftersobel.png", sobel);


        Mat hist = new Mat();
        List<Mat> matList = new ArrayList<Mat>();
        matList.add(sobel);
        Imgproc.calcHist(matList, new MatOfInt(0), new Mat(), hist, new MatOfInt(bins), new MatOfFloat(0f, 256f));
        float accu = 0;
        float t = (float) (nonEdgeRate * w * h);
        float bon = 0;
        float[] accutemp = new float[bins];
        for (int i = 0; i < bins; i++) {
            float tf[] = new float[1];
            hist.get(i, 0, tf);
            accu = accu + tf[0];
            accutemp[i] = accu;
            if (accu > t) {
                bon = (float) i;
                break;
            }
        }
        Imgproc.threshold(sobel, sobel, bon, 255, Imgproc.THRESH_BINARY);
        double ut = bon;
        double lt = thresholdRate * bon;


        Imgproc.Canny(image, sobel, lt, ut);
        //Imgproc.dilate(sobel, sobel, kernel2);
    }
    return sobel;
}

Ścieżka pliku jest miejscem przechowywania obrazów wyjściowych. A obraz wejściowy powinien być obrazem w skali szarości z typem danych U8. Podstawową zasadą jest wykluczenie piksela bez krawędzi (60%) jako piksela bez krawędzi przez jasność. Histogram jest używany do sortowania jasności, a górny próg zostanie ustawiony tak, że poniżej niego znajduje się 60% pikseli. Dolny próg ustala się przez pomnożenie górnego progu przez próg (0,6).

Zauważ, że double nonEdgeRate = 0.6 i double thresholdRate = 0.6 jest dostrojony przeze mnie w moim konkretnym przypadku użycia. Oryginalne wartości to 0,7 i 0,4 oddzielnie w matlab.

 3
Author: fangzhan shi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-26 14:10:35

Zobacz ten link: http://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/

Implementują podobne rozwiązanie za pomocą podstawowych statystyk w celu określenia niskiego i wysokiego progu wykrywalności krawędzi.

def auto_canny(image, sigma=0.33):
     # compute the median of the single channel pixel intensities
     v = np.median(image)

    # apply automatic Canny edge detection using the computed median
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edged = cv2.Canny(image, lower, upper)

    # return the edged image
    return edged
 2
Author: Ryan Marten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 16:34:52

Mam inne podejście do tego samego problemu. Rozwiązanie to obejmuje również dobór optymalnych progów wykrywania krawędzi.

  • najpierw Oblicz medianę obrazu w skali szarości.
  • Wybierz dwie wartości (dolny i górny próg) na podstawie mediany wartość obrazu w skali szarości.

Następujący pseudo-kod pokazuje, jak to zrobić:

v = np.median(gray_img)
sigma = 0.33

#---- apply optimal Canny edge detection using the computed median----
lower_thresh = int(max(0, (1.0 - sigma) * v))
upper_thresh = int(min(255, (1.0 + sigma) * v))

Napraw te progi jako parametry w wykrywaniu krawędzi canny funkcja.

Illustration: jeśli zaobserwujesz krzywą Gaussa w statystyce, wartości między 0,33 z obu stron krzywej są brane pod uwagę w rozkładzie. Każda wartość poza tymi punktami przyjmuje się za wartości odstające. Ponieważ obrazy są uważane za dane, koncepcja ta jest również przyjęta tutaj.

 1
Author: Jeru Luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-20 12:00:41

Jak zasugerował Luca Del Tongo, można obliczyć progi z szarego obrazu, np. w Javie za pomocą OpenCV...

MatOfDouble mu = new MatOfDouble();
MatOfDouble stddev = new MatOfDouble();
Core.meanStdDev(greyMat, mu, stddev);
threshold1 = mu.get(0, 0)[0];
threshold2 = stddev.get(0, 0)[0];
Imgproc.Canny(greyMat, outputMat, threshold1, threshold2);
 0
Author: Buddhisthead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-22 17:36:17