# Differences between OpenCV Canny and MatLab Canny?

does anyone know why the MatLab Canny (MLC) is so different compared to the OpenCV Canny (OCC)? ML-C delivers precise and more connected edges than the OCC, but how is that possible? The reason why I ask is, that I need to implement my protoype of ML code into C++ and I wanted to use OpenCV. Exporting code of ML isn't really possible as far as I have tried.

Kind regards,

-
Did you check the thresholds and other parameters settings? If you don't supply them, they are chosen automatically, and the strategy can vary. –  Andrey Oct 18 '12 at 22:46
Hey Andrey, I know that they are provided automatically if you don't set them. I checked the thresholds and varied them, but results aren't of the same quality as the ML results with any combination. –  mchlfchr Oct 19 '12 at 6:09
As far as I know that OpenCV is using Sobel for the gradients. Maybe ML is using an approximation of Gauss for the gradients, because it models the properties of edges in a better way? regards, –  mchlfchr Oct 22 '12 at 16:35
You can type edit edge in Matlab, and see the relevant case. It is all open-source - no built-ins as far as I know. –  Andrey Oct 22 '12 at 16:55
Yes, I know, but for some routines (like the gradient calculus) you can't go deeper. And the routine of the Canny is very long, so I thought someone here already has made that experience. ;) So I was wrong, because nobody gave me an answer on that. –  mchlfchr Oct 23 '12 at 7:49

As suggested above, the Matlab Canny edge detector calculates the gradient using a "derivative of a Gaussian filter" (as stated in the documentation). In other words, Matlab does a Gaussian blur of the image and then finds the gradient of that smoothed image... all using a single fancy filter. [If you want to know the details, just type in edit edge as Andrey suggested, and then scroll down to the smoothGradient() function.]

The blurring operation significantly reduces the amount of noise present in the image, eliminating many spurious edges and leaving behind the good stuff.

Unfortunately, the OpenCV Canny function doesn't let you change the filter kernel it uses via the function parameters. However. You can generate the same results by first blurring the input image, and then passing this blurred image into the Canny function.

This significantly cleans up the resulting edge map. To blur the input image, I personally use OpenCV's GaussianBlur() function with sigmaX=2. This mimics the default sigma in Matlab. The best blurring kernel size can vary from case to case, but in Matlab it is calculated using filterLength = 8*ceil(sigma);, so for a sigma of 2 that would mean a kernel size of (16,16)

Since both the Gaussian Blur and Sobel filters are linear, passing a blurred input image to the OpenCV Canny() function is mathematically equivalent to what Matlab does because of the principle of superposition, as demonstrated in this pseudocode (note: * is the convolution operator):

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


There is an OpenCV Canny tutorial here that demonstrates how to do this using C++. I'm a python guy, so here is what I do:

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

-