Search code examples
pythonnumpypython-imaging-libraryimagefilter

Casting images to different class PIL


I'm working with PIL and trying to use the median filter on an image in order to de-noise it. But when I try, the result is a black image. What I think is the cause of the problem is the fact that the image is of class 'PIL.Image.Image'.

Let me explain what I am doing/the issue in more depth. I had to perform some image manipulations using numpy. In order to do that I first had to cast the PIL image to a numpyArray. I did this with the following code:

img = np.array(image)

After performing the needed transformations I cast the image back to PIL with the following code:

def numpy_to_pil(image):
    minv = np.amin(image)
    maxv = np.amax(image)
    img = Image.fromarray((255 * (image - minv) / (maxv - minv)).astype(np.uint8))
    return img

When I try to filter 'img' with a median filter, as previously stated, the result is a black image. This is how I use the filter function of PIL:

img.filter(ImageFilter.MedianFilter(3))

I tried comparing the results with an image (let's call it 'cat' (literally image of a cat)) that wasn't put through the casting process that 'img' was put through. I tried printing out the types to see what differed. This is the result:

cat =  <class 'PIL.PngImagePlugin.PngImageFile'>
img =  <class 'PIL.Image.Image'>

Seeing this I wonder if the problem is that 'img' is of type 'PIL.Image.Image' instead of 'PIL.PngImagePlugin.PngImageFile'. Did I do something wrong whilte casting form numpyArray to PIL? Or is it something else.

Any help is greatly appreciated! (I tried being as specific as possible)

P.S: The type of noise is salt&pepper P.P.S: I tried using img.convert('PIL.PngImagePlugin.PngImageFile') but it outputs the following error:

conversion from RGB to PIL.PngImagePlugin.PngImageFile not supported


Solution

  • There is a lot going on in this step: (255 * (image - minv) / (maxv - minv)).astype(np.uint8).

    The image is of datatype uint8 so when you multiply by 255 first, you are exceeding the maximum value of an 8-bit integer. You can either change the datatype to int64 or break the steps out and the datatype will be cast for you earlier.

    If you break those steps out and multiply by 255 last, it no longer gives a black screen because of overflowing the 8-bit integer:

    minv = np.amin(image)
    maxv = np.amax(image)
    image = image - minv
    image = image / (maxv - minv)
    image = image * 255
    img = Image.fromarray(image.astype(np.uint8))