Search code examples
python-3.xtkinterpython-imaging-libraryscikit-image

Image converted from a scikit array to PIL photoimage is being distorted


I'm trying to add an image that was processed by scikit-image and scipy to a tkinter gui. To add it to the canvas it needs to be either saved as a png, or converted to a PIL image. However, when I try to use ImageTk's Image.fromarray() it distorts the image a lot. I would prefer not to save it as a png, because it's just an intermediate step for generating data labels.

I tried checking the shapes of the arrays, and they're the same. I tried printing out the images, and the filled_objects is the correct image, while im is distorted. So it's not problem in the Tkinter gui. Also, if I don't use np.asarray() it produces the same output.

def generateCanny(imageName):
    #imagename should be a path to the image, created with os path join
    img = skimage.io.imread(imageName)
    print('orig {}'.format(img.shape))

    gray = np.sqrt((img*img).sum(-1))
    #converts the image to greyscale

    edges = skimage.feature.canny(gray, sigma=3)

    fill = scipy.ndimage.binary_fill_holes(edges)
    return fill

imageName = os.path.join(imagePath, imageStr)
filled_objects = generateCanny(imageName)
a = np.asarray(filled_objects)
im = PIL.Image.fromarray(a)

Here are the two images, im is on the left and filled_objects is on the right

scikit to PIL image conversion distortion

I would think that you could just convert it easily because filled_objects is just an array, but Image.fromarray() must be doing some processing.


Solution

  • The problem is that fromarray isn't interpreting the boolean array a correctly. If you convert a back to RGB with:

    # Extend the array into 3 dimensions, repeating the data:
    a = np.repeat(a[...,None],3,axis=2).astype(np.uint8)
    # Scale to 0-255:
    a = 255*a
    im = PIL.Image.fromarray(a)
    

    then im.show() will display the correct image.