0

Following this answer on SO, I build this python script to shuffle the pixels of each image inside a folder:

from PIL import Image
import numpy as np
import os

directory = "/my/path/images"
    
for file in os.listdir(directory):
    filename = os.fsdecode(file)
    if filename.endswith(".jpeg") or filename.endswith(".jpg"):
        orig = Image.open(os.path.join(directory, filename))
        orig_px = orig.getdata()
        orig_px = np.reshape(orig_px, (orig.height * orig.width, 3))
        np.random.shuffle(orig_px)
        orig_px = np.reshape(orig_px, (orig.height, orig.width, 3))
        res = Image.fromarray(orig_px.astype('uint8'))
        res.save(rf'images-scrambled/scr-{filename}')

        continue
    else:
        continue

Above code is working great for some images, for others it's failing with this traceback message:

Traceback (most recent call last):
  File "/Users/user1/image_scrambler/03-image_scrambler-v2.py", line 19, in <module>
    orig_px = np.reshape(orig_px, (orig.height * orig.width, 3))
  File "<__array_function__ internals>", line 5, in reshape
  File "/XYZ/site-packages/numpy/core/fromnumeric.py", line 298, in reshape
    return _wrapfunc(a, 'reshape', newshape, order=order)
  File "/XYZ/site-packages/numpy/core/fromnumeric.py", line 54, in _wrapfunc
    return _wrapit(obj, method, *args, **kwds)
  File "/XYZ/site-packages/numpy/core/fromnumeric.py", line 43, in _wrapit
    result = getattr(asarray(obj), method)(*args, **kwds)
ValueError: cannot reshape array of size 800000 into shape (200000,3)

I don't know why this happens. All images are of JPG format and have a resolution of 500x400 pixels. I am using Python version 3.10. What's causing the issue?

martineau
  • 119,623
  • 25
  • 170
  • 301
Madamadam
  • 842
  • 2
  • 12
  • 24
  • 1
    Double-check one of the files that's failing. I'll bet it's not 500x400. – Mark Ransom Nov 18 '21 at 18:46
  • Double-checked: the file is 500x400. Resolution is not the reason, it's the 4 channels of RGBA as @aberry suggested. – Madamadam Nov 18 '21 at 19:24
  • JPEG doesn't support RGBA or I would have suggested that myself. But it appears they can be CMYK, which is such an oddball format that I've never come across it. What is the source of your files? – Mark Ransom Nov 18 '21 at 19:31
  • The source is the scientific image set OASIS https://osf.io/6pnd7/ — a collection of free images. One image that doesn't wor was the image Monkey 3 (#502) of the set. – Madamadam Nov 18 '21 at 21:03

1 Answers1

0

Check the image mode using orig.mode when you do Image.open, you might be getting 4 channels RGBA and not 3 channels as RGB. So to fix it, you have to use 4 when you reshape at :-

orig_px = np.reshape(orig_px, (orig.height * orig.width, 4))

and

orig_px = np.reshape(orig_px, (orig.height, orig.width, 4))
aberry
  • 447
  • 3
  • 10
  • Yes, you are right, the mode is RGBA. I altered both lines as suggested, but without success. The error message is: KeyError: 'RGBA' OSError: cannot write mode RGBA as JPEG – Madamadam Nov 18 '21 at 19:19
  • 1
    Glad to see that your reshape error is resolved. I see that you are saving in JPEF , for that you need to convert to `RGB` for JPEG. Check thread at https://stackoverflow.com/questions/43258461/convert-png-to-jpeg-using-pillow/43258974#43258974 – aberry Nov 18 '21 at 19:30
  • 1
    @Madamadam Another thing you can do is that you can also convert your channel to `RGB` before reading Image. That will keep channel count 3 consistent a all places. – aberry Nov 18 '21 at 19:31
  • Thanks @aberry! Converting the images works and is a good solution. It may a good idea to add this advice to your answer, so I can up-vote it. – Madamadam Nov 18 '21 at 21:31