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