Convert a image (png and jpg) to a multi-dimensional list and backwards in python

后端 未结 1 1752
被撕碎了的回忆
被撕碎了的回忆 2021-01-20 00:11

I use PIL in order to convert imagse to monochrome and afterwards to a list of lists, but I am not sure how to do so with rgb images.

Can someone give me a direction

1条回答
  •  一整个雨季
    2021-01-20 00:26

    Let's start with a known sample image. Here's a small 3x2 one to actually work with and a larger one just so you can see it:

    Small:

    Large:

    You can open an image and make it into an efficient, fast numpy multi-dimensional array like this:

    #!/usr/local/bin/python3
    import numpy as np
    from PIL import Image
    
    # Open image from disk
    im = Image.open('image.png')
    na = np.array(im)
    

    That will look like this:

    array([[[255,   0,   0],                      # Red
            [  0, 255,   0],                      # Green
            [  0,   0, 255]],                     # Blue
    
           [[  0,   0,   0],                      # Black
            [255, 255, 255],                      # White
            [126, 126, 126]]], dtype=uint8)       # Mid-grey
    

    And convert it back to a PIL Image and save like this (just append this code to the code above):

    # Convert array back to Image
    resultim = Image.fromarray(na)
    resultim.save('result.png')
    

    Some notes:

    Note 1

    If you expect and want an RGB888 image, and you are opening a PNG image, you may get a palettised image which doesn't have RGB values for each pixel, but instead has an index into a palette for each pixel and everything will go wrong!

    By way of example, here is the same image as above but when the generating application saved it as a palettised image:

    array([[0, 1, 2],
           [3, 4, 5]], dtype=uint8)
    

    And here what is returned from im.getpalette():

    [255,
     0,
     0,
     0,
     255,
     0,
     0,
     0,
     255,
     0,
     0,
     0,
     255,
     255,
     255,
     126,
     126,
     126,
     ...
     ...
    

    So, the moral of the story is... if you are expecting an RGB888 image, use:

    Image.open('image.png').convert('RGB')
    

    Note 2

    Likewise, if you open a PNG file that contains transparency, it will have 4 channels, the last being alpha/transparency, and you should call convert('RGB') if you wish to discard the alpha channel.

    Note 3

    You can abbreviate the loading and saving into single lines if you don't want the intermediate image:

    # Load and make array in one go
    na = np.array(Image.open('image.png').convert('RGB'))
    
    # Convert back to PIL Image and save in one go
    Image.fromarray(na).save('result.png')
    

    Keywords: Image, image processing, numpy, array, ndarray, PIL, Pillow, Python, Python3, palette, PNG, JPG

    0 讨论(0)
提交回复
热议问题