Issues with scaling images for canny edge detection

Robin Wilson r.t.wilson.bak at googlemail.com
Wed Jun 26 07:08:12 EDT 2013


Hi Josh,

Thanks for the responses - I think I've managed to sort out what is going 
on a bit more clearly now.

In terms of the data types issue, the original image is a float array, with 
both positive and negative values. I didn't realise that img_as_float 
wouldn't take a floating point array as input - I thought if it got given a 
float it would just do the rescaling as appropriate. Given that the 
original image is a float, all of the derived arrays are floats too - 
including the result of the division operation.

Anyway, I think your final comment about the canny parameters possibly 
being far off is the real problem. I've now managed to get a sensible 
result with both the scaled image, and the original image (which is 
interesting, as the documentation specifically states that the input image 
should be normalised to be in the range 0.0-1.0). I managed to do this by 
using radically different canny parameters to the ones I was using before:

# For the scaled image
edges = canny(normhot, sigma=2.0, low_threshold=0.0000000000000001, 
high_threshold=0.01)

# For the original image
edges = canny(hot, sigma=2.0, low_threshold=10, high_threshold=150)

(for comparison, the parameters I was using earlier - which worked fine in 
IDL - were 0.3 and 0.9)

I've worked out why those parameters worked in IDL but didn't give useful 
results when using skimage: the IDL documentation (
http://www.exelisvis.com/docs/CANNY.html) describes the parameters as:

High: The high value used to calculate the high threshold during edge 
detection, given as a factor of the histogram of the magnitude array.
Low: The low value used to calculate the low threshold during edge 
detection, given as a factor of the HIGH<http://www.exelisvis.com/docs/CANNY.html#C_854643309_1362362>
 value. 

Thus, the IDL code expects parameters in the range 0-1, which are then used 
to find a percentile of the histogram of magnitude values, whereas the 
skimage code does thresholding on the raw magnitude values, and that is why 
the same parameters were giving such different results in IDL and skimage. 
I'm now engaged in looking into the IDL code to see exactly how their 
thresholding works, as my naive modification of the skimage canny code to 
try and replicate the IDL results doesn't give me quite the same answers.

I think I've managed to solve most of my problems, but I have one question: 
the canny routine seems to work fine for my original image, without 
rescaling it from 0-1. Is there a reason that it should only work for 
images between 0-1, or am I safe to use my original images?

Cheers,

Robin

On Wednesday, 26 June 2013 04:59:09 UTC+1, Josh Warner wrote:
>
> Argh, correction: if normhot = abs_hot / np.max(abs_hot) were conducting 
> truncating division the result wouldn't be a boolean array but an integer 
> array, with all values 0 except the previous maximum value(s), which would 
> be 1. Functionally boolean, but the dtype would be integer.
>
>
> On Tuesday, June 25, 2013 10:55:31 PM UTC-5, Josh Warner wrote:
>>
>> I can‘t duplicate this, but I may know what's going on.
>>
>> img_as_float converts non-float datatypes into floating-point images on 
>> the range [0, 1]. The traceback you note shows that a floating point array 
>> was passed to img_as_float, but the image had values outside [0, 1]. Try 
>> checking hot.dtype before running img_as_float; if it's an (unsigned) 
>> integer, everything should work fine. 
>>
>> From the operation you listed, abs_hot = hot + abs(np.min(hot)), it 
>> seems like hot should still be an integer, but that traceback code path 
>> is only active for inputs where arr.dtype.kind == 'f' so abs_hot got 
>> converted to float at some point. Check abs_hot.dtype right prior to 
>> running img_as_float; is it an integer or a float?
>>
>> My intuition for a blank canny result is that your division operation abs_hot 
>> / np.max(abs_hot) may have been between two integer types, resulting in 
>> a boolean array which would have almost no edges. Try assigning normhot 
>> = abs_hot / np.max(abs_hot) and checking the dtype; if it's boolean, 
>> cast one or both to float before the division and re-run. The other 
>> possibility is the canny parameters are pretty far off.
>>
>> I‘m not sure what’s going on with the raw result, but check the above and 
>> get back with us! Hopefully that helps to get things moving.
>>
>> Josh
>>
>> On Tuesday, June 25, 2013 10:37:20 AM UTC-5, Robin Wilson wrote:
>>
>> Hi,
>>>
>>> *Summary: *I'm fairly new to skimage, and I'm trying to replicate some 
>>> work I've done in IDL using the Canny edge detector. I've imported the same 
>>> image into skimage and tried running the Canny function with the same 
>>> parameters, but I either get a blank image, or very different results to 
>>> IDL which don't change regardless of the parameters I use. I suspect my 
>>> problems may be related to how I am scaling my image to make it between 0 
>>> and 1, as the documentation for the skimage Canny function requires.
>>>
>>> *More details:*
>>> The input image I used in both IDL and skimage is available at 
>>> https://www.dropbox.com/s/xaiq9kitrf1b4cf/HOT_sub.tif.
>>>
>>> In IDL I called the CANNY function (documentation available at 
>>> http://www.exelisvis.com/docs/CANNY.html) as follows:
>>>
>>> result = CANNY(image, HIGH=0.95, LOW=0.3, SIGMA=2)
>>>
>>> and got the following image:
>>>
>>>
>>>
>>> <https://lh3.googleusercontent.com/-xwuyuH_mxEA/Ucm2Y2m2EyI/AAAAAAAAEnw/46OmI8iuf0Q/s1600/IDL_Output.png>
>>> I loaded the image into skimage as follows:
>>>
>>> hot = skimage.io.imread("HOT_sub.tif")
>>>
>>> And removed all negative values by adding the absolute value of the 
>>> minimum:
>>>
>>> abs_hot = hot + abs(np.min(hot))
>>>
>>> From what I'd read in the documentation, the function img_as_float would 
>>> then scale this between 0 and 1 in a sensible way, but it gave an error:
>>>
>>> C:\Python27\lib\site-packages\skimage\util\dtype.pyc in convert(image, 
>>> dtype)
>>>      73     if kind_in == 'f':
>>>      74         if np.min(image) < 0 or np.max(image) > 1:
>>> ---> 75             raise ValueError("Images of type float must be 
>>> between 0 and 1")
>>>      76         if kind == 'f':
>>>      77             # floating point -> floating point
>>>
>>> ValueError: Images of type float must be between 0 and 1
>>>
>>> So I did it myself by simply dividing by the maximum value:
>>>
>>> im_hot = img_as_float(abs_hot/np.max(abs_hot)
>>>
>>> However, running the Canny edge detector on this image produces an 
>>> entirely blank edge image:
>>>
>>> edges = canny(im_hot, sigma=2, low_threshold=0.3, high_threshold=0.90)
>>> np.sum(edges) # Gives 0 showing there are no edges found
>>>
>>> Regardless how I play with the parameters, I can't seem to get it to 
>>> give me any edges.
>>>
>>> Interestingly, if I ignore the instructions to make sure that my input 
>>> image is between 0 and 1, and just use the raw image:
>>>
>>> edges = canny(hot, sigma=2, low_threshold=0.3, high_threshold=0.90)
>>>
>>> I get a more sensible result (well, at least it isn't blank!):
>>>
>>>
>>> <https://lh5.googleusercontent.com/-Ta33pkF-pIY/Ucm4abti3lI/AAAAAAAAEoA/iyX6FSKSPF4/s1600/skimage.png>
>>> But this is very different to the result given by IDL - and furthermore, 
>>> adjusting the parameters doesn't seem to change the output at all.
>>>
>>> What am I doing wrong here? I suspect it is something to do with the 
>>> image scaling, but I'm not sure - it could be a conceptual problem with my 
>>> image processing knowledge, or I could be using skimage improperly. Does 
>>> anyone have any ideas or suggestions as to where to go from here? If I 
>>> manage to solve this I will, of course, write up the solution on my blog so 
>>> that others can benefit too.
>>>
>>> Best regards,
>>>
>>> Robin
>>> University of Southampton, UK
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scikit-image/attachments/20130626/1949b310/attachment.html>


More information about the scikit-image mailing list