numpy 在Python(PIL)中对布尔掩码内图像像素进行置乱(随机排列)

ih99xse1  于 2022-11-29  发布在  Python
关注(0)|答案(1)|浏览(191)

我想置乱,也就是说,随机置换由布尔掩码界定的区域的像素,在本例中,仅置换面部的区域(省略背景)。
在整个图像上进行随机排列的代码是有效的,但是当我将其应用于掩码数组时,它也会改变颜色...如何仅在非颜色轴旁边执行洗牌?

from PIL import Image
import requests
from io import BytesIO
import numpy as np 

response = requests.get("https://www.4dface.io/wp-content/uploads/2018/10/4DFM_sample2.jpg")
img = Image.open(BytesIO(response.content))
    
img.show()

def _shuffle_2D(x):
    return _shuffled(_shuffled(x.swapaxes(0, 1)).swapaxes(0, 1))

def _shuffled(x):
    """Return a shuffled array. Because python does it in-place."""
    np.random.shuffle(x)
    return x

array = np.array(img)
PIL.Image.fromarray(_shuffle_2D(array))

下面,同样的方法也适用于掩码数组:如你所见,它也改变了颜色

# Get mask
mask = np.array(img.convert("L")) != 255
array[mask] = _shuffle_2D(array[mask])
PIL.Image.fromarray(array)

欢迎任何指针!

bmvo0sr5

bmvo0sr51#

我还没有研究过是否有任何洗牌的方法,允许轴被设置或从洗牌排除,但一个快速的方法可能是将每个RGB888像素转换成一个单一的uint32之前洗牌,然后分裂回RGB888之后。因为3字节将被打包在一起,成为一个单一的实体,他们不会得到分离,从他们的小朋友。
使用np.dot()可以非常快速地完成此操作,如下所示:

# Make a single 24-bit number for each pixel, instead of 3x 8-bit numbers
u32 = np.dot(RGBarray.astype(np.uint32),[1,256,65536])

所以我的具体建议是:

#!/usr/bin/env python3

from PIL import Image
import requests
from io import BytesIO
import numpy as np 

def _shuffled(x):
    """Return a shuffled array. Because python does it in-place."""
    np.random.shuffle(x)
    return x

response = requests.get("https://www.4dface.io/wp-content/uploads/2018/10/4DFM_sample2.jpg")
img = Image.open(BytesIO(response.content))
array = np.array(img)

# Get mask of non-white pixels
mask = np.array(img.convert("L")) != 255

# Combine RGB888 pixels into a single 24-bit entity
u32 = np.dot(array.astype(np.uint32),[1,256,65536])
u32[mask] = _shuffled(u32[mask])

# Now split 24-bit entities back into RGB888
r = u32 & 0xff
g = (u32 >> 8  ) & 0xff
b = (u32 >> 16 ) & 0xff
array = np.dstack((r,g,b)).astype(np.uint8)
res = Image.fromarray(array)
res.save('result.png')

相关问题