¿Diferencias entre OpenCV Canny y MatLab Canny?

8

¿Alguien sabe por qué MatLab Canny (MLC) es tan diferente en comparación con OpenCV Canny (OCC)? ML-C ofrece bordes precisos y más conectados que el OCC, pero ¿cómo es eso posible? La razón por la que pregunto es que necesito implementar mi prototipo de código ML en C ++ y quería usar OpenCV. Exportar código de ML no es realmente posible por lo que he intentado.

Saludos cordiales,

mchlfchr
fuente
3
¿Verificó los umbrales y otras configuraciones de parámetros? Si no los proporciona, se eligen automáticamente y la estrategia puede variar.
Andrey Rubshtein
Hola Andrey, sé que se proporcionan automáticamente si no los configura. Verifiqué los umbrales y los varié, pero los resultados no son de la misma calidad que los resultados de ML con cualquier combinación.
mchlfchr
Hasta donde sé, OpenCV está usando Sobel para los gradientes. ¿Quizás ML está usando una aproximación de Gauss para los gradientes, porque modela las propiedades de los bordes de una mejor manera? saludos,
mchlfchr
Puede escribir edit edgeMatlab y ver el caso relevante. Todo es de código abierto, no hay incorporados hasta donde yo sé.
Andrey Rubshtein
Sí, lo sé, pero para algunas rutinas (como el cálculo de gradiente) no puedes profundizar. Y la rutina de Canny es muy larga, así que pensé que alguien aquí ya había hecho esa experiencia. ;) Entonces me equivoqué, porque nadie me dio una respuesta al respecto.
mchlfchr

Respuestas:

11

Como se sugirió anteriormente, el detector de bordes Matlab Canny calcula el gradiente utilizando una "derivada de un filtro gaussiano" (como se indica en la documentación). En otras palabras, Matlab hace un desenfoque gaussiano de la imagen y luego encuentra el gradiente de esa imagen suavizada ... todo utilizando un único filtro elegante. [Si desea conocer los detalles, simplemente escriba edit edgecomo sugirió Andrey, y luego desplácese hacia abajo hasta la smoothGradient()función.]

La operación de desenfoque reduce significativamente la cantidad de ruido presente en la imagen, elimina muchos bordes espurios y deja atrás lo bueno.

Desafortunadamente, la función OpenCV Canny no le permite cambiar el núcleo del filtro que usa a través de los parámetros de la función. Sin embargo. Puede generar los mismos resultados desenfocando primero la imagen de entrada y luego pasando esta imagen borrosa a la función Canny.

Esto limpia significativamente el mapa de borde resultante. Para desenfocar la imagen de entrada, yo personalmente uso la GaussianBlur()función de OpenCV con sigmaX=2. Esto imita la sigma predeterminada en Matlab. El mejor tamaño de kernel borroso puede variar de un caso a otro, pero en Matlab se calcula utilizando filterLength = 8*ceil(sigma);, por lo que para un sigma de 2 eso significaría un tamaño de kernel de(16,16)

Dado que los filtros Gaussian Blur y Sobel son lineales, pasar una imagen de entrada borrosa a la Canny()función OpenCV es matemáticamente equivalente a lo que hace Matlab debido al principio de superposición, como se demuestra en este pseudocódigo (nota: *es el operador de convolución):

// The Matlab method: the sobel and blur operations are combined into
// a single filter, and that filter is then convolved with the image
matlabFancyFilter = (sobel * blur);
gradient = matlabFancyFilter * image;

// Equivalent method: image is first convolved with the blur filter, and
// then convolved with the sobel filter.
gradient = sobel * (blur * image); // image is filtered twice

Aquí hay un tutorial de OpenCV Canny que muestra cómo hacer esto usando C ++. Soy un tipo de pitón, así que esto es lo que hago:

smoothedInput = cv2.GaussianBlur(image, (7,7), 2);
edges = cv2.Canny(smoothedInput, 25, 50);
Brandon Jackson
fuente