En openCV, las altas y bajas de los umbrales para el operador de canny son obligatorios:

cvCanny(input,output,thresh1,thresh2)

En Matlab, hay una opción para calcular esos automáticamente:

edge(input,'canny')

He mirado en Matlab del código de borde, y esto no es realmente sencillo para calcular esos automáticamente.

Son conscientes de que cualquier aplicación del operador de canny, junto con el umbral automático de cálculo de opencv?

gracias

  • Puedes publicar el código de Matlab que hace esto?
InformationsquelleAutor hoffer | 2010-11-27

7 Comentarios

  1. 46

    Me topé con esta respuesta, mientras que yo estaba buscando una manera de calcular automáticamente Astuto de los valores de umbral.

    Espero que esto ayuda a cualquier persona que viene en busca de un buen método para la determinación automática de los valores de umbral para el algoritmo de Canny…


    Si su imagen se compone de distintos primer plano y de fondo, a continuación, el borde de un objeto en primer plano se puede utilizar extraído por el siguiente:

    1. Calcular Otsu del umbral de uso:

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

      No necesitamos la _img. Nos interesa sólo la otsu_thresh_val pero lamentablemente, actualmente no hay ningún método en OpenCV que permite calcular sólo el valor de umbral.

    2. Utilizar el Otsu del valor de umbral superior umbral y la mitad de la misma como el umbral más bajo para el algoritmo de Canny.

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

    Más información relacionada con este se puede encontrar en este papel: El Estudio sobre la Aplicación de Un Método de Otsu en Operador de Canny. Una explicación de Otsu la aplicación puede encontrarse aquí.

    • ¿qué es el cv de por aquí ? @VP.
    • OpenCV @TapanHP
    • Tengo.. gracias @Dennis
  2. 4

    Echa un vistazo a este enlace: http://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/

    Que implementar una solución similar utilizando estadísticas básicas para determinar el bajo y el alto umbral para la detección de bordes Canny.

    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
    
  3. 3

    He mirado a través del código fuente de Matlab Canny, detección de bordes y me las arreglé para escribir en Java con 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;
    }
    

    La ruta de acceso es el lugar para celebrar la salida de imágenes. Y la imagen de entrada debe ser una imagen de escala de grises con U8 tipo de datos.
    El principio básico es para descartar nonEdgeRate(60%) de píxeles como no-borde de un pixel por el brillo. Un histograma se utiliza para ordenar el brillo y el umbral superior se fijará de modo que hay un 60% de los píxeles debajo de ella. El bajo umbral se establece multiplicando el umbral superior por el thresholdRate(0.6).

    Tenga en cuenta que la doble nonEdgeRate = 0,6 y doble thresholdRate = 0.6 es sintonizada por mí mismo, en mi caso de uso específico. Th valores originales son de 0.7 y 0.4 por separado en matlab.

  4. 1

    Tengo otro enfoque para el mismo problema. Esta solución también implica la selección de los umbrales óptimos para la detección de bordes.

    • Primer lugar, calcular la mediana de la imagen en escala de grises.
    • Elegir dos valores (inferior y superior de los umbrales) con base en la mediana de la
      valor de la imagen en escala de grises.

    El siguiente pseudo-código se muestra cómo se hace:

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

    Solucionar estos umbrales como parámetros en la detección de bordes canny función.

    Ilustración: Si observa una curva Gaussiana en las estadísticas, los valores entre 0.33 desde ambos lados de la curva son considerados en la distribución. Cualquier valor fuera de estos puntos que se supone que los valores atípicos. Dado que las imágenes son considerados datos, este concepto se asume aquí.

    • Ha visto usted este, o es su teoría?
    • Nunca me encontré con que! Gracias por mencionarlo !!
  5. 0

    Como Luca Del Tongo ha sugerido, usted puede calcular los umbrales de gris de la imagen, por ejemplo, en Java usando 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);
    
    • No te falta algo de matemáticas aquí? La media es generalmente más grande que el de la desviación. Así que supongo que debe ser algo parecido a threshold1 = mu - stddev y threshold2 = mu + stddev
    • Para un objeto blanco en un brillante en la tabla I se obtiene 180 y 67 de la media y la desviación. Canny, no detecta los bordes con esos valores. 14 y 30 años de trabajo bien para esa imagen.

Dejar respuesta

Please enter your comment!
Please enter your name here