如何使用 PIL 和 numpy 按行随机播放 .jpg 图像的像素

How to shuffle a .jpg image's pixels by rows using PIL and numpy

我想按行对 .jpg 图像中的像素重新排序。使用我在互联网上找到的各种答案,我写道:

from PIL import Image
import numpy as np

a = Image.open('donkey.jpg')
b = a.getdata()
b = np.reshape(b, (a.height, a.width, 3))

dic = []
for i in range(1, a.height):
    element = np.reshape(b[:i], (i * a.width, 3))
    dic.append(element)

dic 产生这样的东西:

[array([[205, 225, 232],
        [201, 222, 227],
        [203, 224, 227],
        ...,
        [204, 222, 224],
        [210, 226, 225],
        [230, 222, 186]]),
 array([[205, 225, 232],
        [201, 222, 227],
        [203, 224, 227],
        ...,
        [188, 183, 154],
        [180, 175, 146],
        [181, 175, 143]]),

        ...,

 array([[205, 225, 232],
        [201, 222, 227],
        [203, 224, 227],
        ...,
        [249, 251, 240],
        [249, 251, 240],
        [249, 249, 241]])]

我想我成功地按行打乱了图像的像素。但是,我无法将其转换回图像。

我试过了:

Image.fromarray(dic.astype)

哪个,没用。这是错误消息:

AttributeError: 'list' object has no attribute 'astype'

请帮我把打乱的图片转回图片!

您可以使用下面的代码实现您想要的效果。新手理解起来有点复杂,掌握了窍门就会大有作为。

重新格式化的原因;

  • 完全消除逐行操作:显着降低效率。使用 np.random.permutation 是一种更快更有效的方法。

  • 将图像拆分为通道:在进行整形时避免通道之间的数据传输。

  • 使用 dstack 来保持通道的顺序并且在整形时不会弄乱数据

  • 添加了 channel_count 以能够处理 png 或灰度照片,使代码片段更加简单。

import numpy as np
from PIL import Image

img = Image.open("donkey.jpg")

# getting the number of channels
channel_count = len(img.getbands())

img_arr = np.reshape(img, (img.height, img.width, channel_count))

# splitting up channels
channels = [img_arr[:,:,x] for x in range(channel_count)]

# setting up a shuffling order for rows
random_perm = np.random.permutation(img.height)

# reordering the rows with respect to the permutation
shuffled_img_arr = np.dstack([x[random_perm, :] for x in channels]).astype(np.uint8)

# creating the Image from the shuffled array
shuffled_img = Image.fromarray(shuffled_img_arr)

# saving the shuffled file
shuffled_img.save("shuffled_donkey.jpg")

此代码会将您提供的图像保存为完全随机排列的行。