3

I have this code:

from PIL import Image
import numpy as np
img = Image.open('img.jpg')
Image.fromarray(np.array([[np.mean(i, axis=1).astype(int).tolist()]*len(i) for i in np.array(img).tolist()]).astype('uint8')).show()

And I am trying to modify the pixels of the image in PIL, however when I run it it gives an error as follows:

KeyError: ((1, 1, 1280), '|u1')

Not just that, it also outputs a second error as follows:

TypeError: Cannot handle this data type

Is there a way to overcome this?

P.S. I searched and the most related question to mine was:

Convert numpy.array object to PIL image object

However I don't get it nor know how to implement it.

U13-Forward
  • 69,221
  • 14
  • 89
  • 114

2 Answers2

3

For reading specific pixel via any image library such as PIL or OpenCV first channel of image is Height second channel is Width and last one is number of channels and here is 3. When you convert image to gray scale, third channel will be 1.

But this error happen when you want to convert a numpy array to PIL image using Image.fromarray but it shows the following error:

KeyError: ((1, 1, 3062), '|u1')

Here you could see another solution: Convert numpy.array object to PIL image object

the shape of your data. Pillow's fromarray function can only do a MxNx3 array (RGB image), or an MxN array (grayscale). To make the grayscale image work, you have to turn you MxNx1 array into a MxN array. You can do this by using the np.reshape() function. This will flatten out the data and then put it into a different array shape.

img = img.reshape(M, N) #let M and N be the dimensions of your image

(add this before the img = Image.fromarray(img))

BarzanHayati
  • 637
  • 2
  • 9
  • 22
  • Height first or width first? – U13-Forward Aug 23 '19 at 08:36
  • So if 1920x1020 `M` will be `1020` and `N` will be `1920`? – U13-Forward Aug 23 '19 at 08:39
  • In PIL height is the first and width is the second. I wrote answer based on https://github.com/facebookresearch/visdom/issues/48#issuecomment-289331878 and height, width = np.array(im).shape and https://stackoverflow.com/posts/34704661/revisions and https://stackoverflow.com/questions/6444548/how-do-i-get-the-picture-size-with-pil/6444612 – BarzanHayati Aug 23 '19 at 08:43
  • @U10-Forward Absolutely when you write 1920*1020, 1920 is width and 1020 is height. But what dimension PIL give us when you call it? So function return (1020,1920) so 1020 is height and 1920 is width – BarzanHayati Aug 23 '19 at 08:46
  • Lemme try will give you feedback soon – U13-Forward Aug 23 '19 at 08:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/198356/discussion-between-u10-forward-and-barzanhayati). – U13-Forward Aug 23 '19 at 08:51
0

I am not certain what you are trying to do but if you want the mean:

from PIL import Image
import numpy as np
img = Image.open('img.jpg')

# Make Numpy array
imgN = np.array(img)

mean = np.mean(imgN,axis=2)

# Revert back to PIL Image from Numpy array
result = Image.fromarray(mean)

Alternatively, if you want a greyscale which is an alternative to the mean

from PIL import Image
import numpy as np
img = Image.open('img.jpg').convert('L')
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432