Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 how to convert images to a multi-dimensional list and backwards an python?

like image 264
J.George Avatar asked Mar 05 '23 12:03

J.George


1 Answers

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:

enter image description here

Large:

enter image description here

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

like image 63
Mark Setchell Avatar answered Mar 16 '23 22:03

Mark Setchell