Greg
Greg

Reputation: 47094

Trouble with Canny Edge Detector - Returning black image

I'm trying to run the canny edge detector on this image:

enter image description here

With this code:

def edges(img):
    from skimage import feature
    img = Image.open(img)
    img.convert('L')
    array = np.array(img)    
    out = feature.canny(array, sigma=1, )
    return Image.fromarray(out,'L')

edges('Q_3.jpg').save('Q_3_edges.jpg')

But I'm just getting a black image back. Any ideas what I could be doing wrong? I tried sigma of 1 and of 3.

enter image description here

Upvotes: 4

Views: 6422

Answers (5)

yasin amini
yasin amini

Reputation: 23

The problem happens when the image is saved. You can save image with other library like matplotlib:

import numpy as np
import matplotlib.pyplot as plt
from skimage import feature
from skimage import io 

def edges(img):
    img = io.imread(img)
    array = np.array(img)    
    out = feature.canny(array, sigma=1, )
    return out

plt.imsave("canny.jpg", edges("input.jpg"), cmap="Greys")

Upvotes: 1

user13282626
user13282626

Reputation: 51

I have the same situation and this helps for me. Before use the Canny filter, just convert your elements of image array to float32 type:

array = np.array(img)
array = array.astype('float32')    
out = feature.canny(array, sigma=1, )

Upvotes: 5

Tony Power
Tony Power

Reputation: 1178

The problem happens when the image is loaded as float (i.e. in the range 0-1). The loader does that for some types of images. You can check the type of the loaded image by:

print(img.dtype)

If the output is something like float64 (i.e. not uint8), then your image is in the range 0-1.

Canny expects an image in the range 0-255. Therefore, the solution is as easy as:

from skimage import img_as_ubyte
img = io.imread("an_image.jpg")
img = img_as_ubyte(img)

Hope this helps,

Upvotes: 1

Greg
Greg

Reputation: 47094

So the issue was with the canny function returning and array of type boolean.

Oddly, setting the Image.fromarray mode to '1' didn't help. Instead this was the only way I could get it working; converting the output array to grayscale:

def edges(img):
    from skimage import feature
    img = Image.open(img)
    img.convert('L')
    array = np.array(img)
    out = np.uint8(feature.canny(array, sigma=1, ) * 255)
    return Image.fromarray(out,mode='L')

Upvotes: 1

Stefan van der Walt
Stefan van der Walt

Reputation: 7253

Your images need to be in the correct range for the relevant dtype, as discussed in the user manual here: http://scikit-image.org/docs/stable/user_guide/data_types.html

This should be automatically handled if you use the scikit-image image I/O functions:

from skimage import io
img = io.imread('Q_3.jpg')

Upvotes: 2

Related Questions