如何逆向还原随机打乱像素的图像,或求可逆还原的静态风格图像生成方案?
方案解答
现有代码无法直接逆向的原因
- 你使用的
np.random.shuffle是无状态的随机打乱操作,运行后不会保留像素的原始位置与新位置的对应关系,没有映射规则自然无法还原 - 输出时使用了JPG有损压缩格式,会修改打乱后的像素RGB值,就算保留了映射规则也无法匹配到原始像素实现无损还原
改进现有逻辑实现可逆操作
你可以通过保存打乱索引、使用无损格式存储的方式实现可逆,示例代码如下:
正向生成打乱图像代码
from PIL import Image import numpy as np import pickle # 读取原始图像 orig = Image.open('lena.jpg') w, h = orig.size orig_px = np.array(orig).reshape(h*w, 3) # 生成打乱索引并保存 shuffle_idx = np.random.permutation(h*w) with open('shuffle_map.pkl', 'wb') as f: pickle.dump((shuffle_idx, h, w), f) # 生成打乱后的图像 shuffled_px = orig_px[shuffle_idx] shuffled_img = shuffled_px.reshape(h, w, 3) res = Image.fromarray(shuffled_img.astype('uint8')) # 用无损PNG存储避免像素值损失 res.save('out.png')
逆向还原代码
from PIL import Image import numpy as np import pickle # 读取打乱后的图像和映射文件 shuffled_img = np.array(Image.open('out.png')) h, w = shuffled_img.shape[:2] with open('shuffle_map.pkl', 'rb') as f: shuffle_idx, orig_h, orig_w = pickle.load(f) # 反向映射还原像素 shuffled_px = shuffled_img.reshape(h*w, 3) orig_px = np.zeros_like(shuffled_px) orig_px[shuffle_idx] = shuffled_px # 生成原始图像 orig_img = orig_px.reshape(orig_h, orig_w, 3) res = Image.fromarray(orig_img.astype('uint8')) res.save('restored_lena.jpg')
替代实现思路
如果不想额外保存映射文件,可以用密码作为伪随机数种子生成打乱索引,只要记住密码即可还原,不需要携带额外的映射文件:
- 正向打乱时,用自定义密码的哈希值作为
np.random.seed的入参,再生成打乱索引 - 逆向还原时输入相同密码即可生成完全一致的打乱索引,完成还原
- 如果需要更自然的静态风格,可按8x8/16x16等尺寸分块打乱,而非逐像素打乱,视觉效果更统一,可逆逻辑和上述方案完全一致
内容的提问来源于stack exchange,提问作者Abbas Mohamadi
相关产品推荐
相关产品推荐

