Getting Canny to provide good results

asked 2016-12-12 10:37:39 -0500

Soltius gravatar image

Hello everyone, I am working on edge detection. I have been developing under ImageJ for a while and converted most of my code to OpenCV in the past few weeks. Most of this process happened painlessly, however I cannot get the Canny filter to work in OpenCV as it did in ImageJ.

Here is an example of image I work with (left), results with ImageJ (middle) and results with OpenCV (right). Hysteresis thresholds were set about the same.

image description

I have been searching for why such differences in results occur. I found that for ImageJ, the Canny algorithm uses a convolution mask which combines a gaussian function and a sobel kernel, thus computing gradients on a smoothed image.

OpenCV's Canny only uses a Sobel Kernel I believe, but since the Gaussian and Sobel are linear, I should get the same results by gaussing the original image beforehand and then applying Canny. But it is not the case.

One main difference is that ImageJ's kernel size for its convolution mask is 16 (and not modifiable), while OpenCv's one is 3,5 or 7 (results are shown for kernel 7), and this parameter seems to have a big impact on results.

Do you think it is the reason why I have so different results ? If so, how can I get around it ?


PS : Things I tried : playing with hysteresis thresholds, morphological operations post Canny, but I would like as good results as ImageJ

edit retag flag offensive close merge delete



In master branch you can split Canny into gradient calculation and edge detection (link).

Perhabs you can make a custom filter kernel for larger Sobel masks. You can find a tutorial here.

matman gravatar imagematman ( 2016-12-12 12:31:16 -0500 )edit

I think that with image given (left) we can have only rigth part of canny results. Using canny I have got this results

LBerger gravatar imageLBerger ( 2016-12-12 14:10:46 -0500 )edit

Thank you both for your input. LBerger, glad to know that I'm not completely misusing Canny. matman, I was not aware of the existence of this overload, I want to give it a try. However, I can't figure out how to call it from my code, as Canny() calls the "normal" Canny function (this is probably a newbie problem, sorry...)

Soltius gravatar imageSoltius ( 2016-12-13 03:11:47 -0500 )edit

you have got an example here

LBerger gravatar imageLBerger ( 2016-12-13 03:15:35 -0500 )edit

Thanks for the fast answer ! But in your example, what part of the code specifies to the program to use the "second" Canny ? This may be my inexperience in C++ talking... I'm using Python, and by the way your Python equivalent example uses the "normal" Canny (maybe it is not possible in Python ?)

Soltius gravatar imageSoltius ( 2016-12-13 03:28:42 -0500 )edit

About python I don't know. x and y gradient image are computed and canny

LBerger gravatar imageLBerger ( 2016-12-13 03:37:32 -0500 )edit

Ok, thanks for everything !

Soltius gravatar imageSoltius ( 2016-12-13 03:47:32 -0500 )edit