Armin Armin - 18 days ago 8
Python Question

How to convert a grayscale image into a list of pixel values?

I am trying to create a python program which takes a grayscale, 24*24 pixel image file (I haven't decided on the type, so suggestions are welcome) and converts it to a list of pixel values from 0 (white) to 255 (black).

I plan on using this array for creating a MNIST-like bytefile of the picture, that can be recognized by Tensor-Flow handwriting recognition algorithms.

I have found the Pillow library to be the most useful in this task, by iterating over each pixel and appending its value to an array
from PIL import Image

img = Image.open('eggs.png').convert('1')
rawData = img.load()
data = []
for y in range(24):
for x in range(24):
data.append(rawData[x,y])


Yet this solution has two problems (1) The pixel values are not stored as integers, but pixel objects which cannot be further mathematically manipulated and are therefore useless. (2) Even Pillow docs state that:


Accessing individual pixels is fairly slow. If you are looping over all of >the pixels in an image, there is likely a faster way using other parts of >the Pillow API.

Answer

You can convert the image data into a Python list (or list-of-lists) like this:

from PIL import Image

img = Image.open('eggs.png').convert('L')  # convert image to 8-bit grayscale
WIDTH, HEIGHT = img.size

data = list(img.getdata()) # convert image data to a list of integers
# convert that to 2D list (list of lists of integers)
data = [data[offset:offset+WIDTH] for offset in range(0, WIDTH*HEIGHT, WIDTH)]

for y in range(HEIGHT):
    row = (data[y][x] for x in range(WIDTH))
    print(' '.join('{:3}'.format(value) for value in row))

Here's an enlarged version of a 24x24 RGB eggs.png image I used for testing:

enlarged version of eggs.png

And here's the output from running the script on it:

  0   0  55 110  19   0   0   0  40 171 239 109   0   0   0   0   0   0   0   0   0   0   0   0
  0  18 238 255 248 134  21  76 248 255 255 162   0   0   0   0   0   0   0   0   0   0   0   0
  0  87 255 255 255 255 255 255 254 253 255  87   0   0   0   0   0   0   0   0   0   0   0   0
  0  75 255 255 249 253 255 254 253 255 255 132  50  41   0   0   0   0  79 143  27   0   0   0
  0  39 255 255 255 245 200 186 187 192 222 255 255 255  51   0  43 202 255 255  75   0   0   0
  0  67 255 255 239 162 154 174 179 172 155 197 227 236 164 166 255 255 255 255  39   0   0   0
  0 146 255 255 173 159 206 196 194 200 184 155 241 253 255 255 240 217 250 255  44   0   0   0
 54 255 255 242 167 193 192 193 192 205 172 150 247 255 248 186 163 166 163 255 178   0   0   0
167 255 250 255 189 157 196 207 199 167 141 186 219 248 185 156 195 204 171 165 255 207  92  33
193 255 251 255 245 179 153 138 144 190 241 255 227 175 169 202 193 192 193 168 239 255 255 174
154 255 247 207 214 233 198 190 235 255 255 255 219 160 178 197 193 197 177 168 252 255 236  30
 54 255 225 207 245 255 255 254 210 181 177 231 220 146 190 198 196 199 145 203 255 255  73   0
  0  66 215 255 252 255 245 165 154 187 179 156 230 154 125 192 184 151 192 253 255 235  12   0
  0   0  82 255 255 253 179 169 205 192 205 156 197 253 174 159 163 220 254 253 255 255  75   0
  0   0  39 255 255 224 161 198 192 192 204 154 192 255 255 214 197 255 251 249 254 255 193   0
  0   0 104 255 255 206 159 203 192 197 190 152 235 255 240 195 241 255 251 255 255 251 118   0
  0  74 255 255 255 227 142 189 202 186 145 206 255 255 206 222 255 251 255 190  36   0   0   0
 95 255 255 249 251 254 200 153 167 171 215 254 252 255 183 234 255 255 170   0   0   0   0   0
103 255 252 253 255 255 255 233 221 245 255 250 250 255 193 164 254 150   0   0   0   0   0   0
  0 206 255 255 172 175 255 255 255 253 249 249 253 255 255  62   0   0   0   0   0   0   0   0
  0  26 144  70   0   0 106 255 255 250 250 255 255 240 172  18   0   0   0   0   0   0   0   0
  0   0   0   0   0   0   8 230 255 250 255 239  77   0   0   0   0   0   0   0   0   0   0   0
  0   0   0   0   0   0   0 198 255 255 242  37   0   0   0   0   0   0   0   0   0   0   0   0
  0   0   0   0   0   0   0  67 231 204  36   0   0   0   0   0   0   0   0   0   0   0   0   0

Access to the pixel data should now be faster than using the object img.load() returns (and the values will be integers in the range of 0..255).