Como sugerido acima, o detector de borda Matlab Canny calcula o gradiente usando uma "derivada de um filtro Gaussiano" (conforme declarado na documentação). Em outras palavras, o Matlab faz um desfoque gaussiano da imagem e encontra o gradiente dessa imagem suavizada ... tudo usando um único filtro sofisticado. [Se você quiser conhecer os detalhes, basta digitar edit edge
como Andrey sugeriu e, em seguida, role para baixo até a smoothGradient()
função.]
A operação de desfoque reduz significativamente a quantidade de ruído presente na imagem, eliminando muitas bordas falsas e deixando para trás as coisas boas.
Infelizmente, a função OpenCV Canny não permite alterar o kernel de filtro usado pelos parâmetros de função. Contudo. Você pode gerar os mesmos resultados primeiro desfocando a imagem de entrada e passando essa imagem desfocada para a função Canny.
Isso limpa significativamente o mapa de arestas resultante. Para desfocar a imagem de entrada, eu pessoalmente uso a GaussianBlur()
função do OpenCV com sigmaX=2
. Isso imita o sigma padrão no Matlab. O melhor tamanho de kernel de desfoque pode variar de caso para caso, mas no Matlab é calculado usando filterLength = 8*ceil(sigma);
, portanto, para um sigma de 2, isso significaria um tamanho de kernel de(16,16)
Como os filtros Gaussian Blur e Sobel são lineares, passar uma imagem de entrada borrada para a Canny()
função OpenCV é matematicamente equivalente ao que o Matlab faz por causa do princípio de superposição, conforme demonstrado neste pseudocódigo (nota: *
é o operador de convolução):
// 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
Há um tutorial do OpenCV Canny aqui que demonstra como fazer isso usando C ++. Eu sou um cara python, então aqui está o que eu faço:
smoothedInput = cv2.GaussianBlur(image, (7,7), 2);
edges = cv2.Canny(smoothedInput, 25, 50);