提取并连接 Numpy 数组的第 3 维

背景


从一个计算机爱好者的视频中,我有了玩最低有效位隐写术的想法。现在,我正在尝试使用 Numpy 以图像的位格式提取和连接所有 RGB 值。最终,我只需要数组的第 7 位和第 8 位。


设置


我用Pillow以下方式加载图像并提取位:


from PIL import Image

import numpy as np


img = Image.open('test.png')

arr = np.array(img)

bits = np.unpackbits(arr, axis=2)

问题


bits对于 1600x1200 像素的图像,该阵列现在具有例如 (1600, 1200, 24) 的形状。我现在需要的是


为每个像素提取 24 位

将所有 24 位块连接成一个一维数组。

仅提取第 7、8、15、16、23 和 24 位,因此仅提取每个颜色分量的最后 2 位。

到目前为止的方法


我试图分裂沿着第二轴的3D阵列分为3组。然后我可以遍历 1200 个列表,每个列表包含 3 个列表并提取最后 2 位,如下所示:


sp = np.split(bits, 3, axis=2)

for i in range(0, 1200):

    for j in range(0, 3):

        print(sp[j][0][i][-2:])


虽然我的上述方法有效,但我觉得必须有一个更高效的解决方案,只使用Numpy Magic®. 你知道更好的方法吗?


明月笑刀无情
浏览 270回答 1
1回答

慕勒3428872

这是一个XY 问题。您不需要将像素转换为二进制或使用显式方法提取任何特定位,因为这样您就必须再次将其全部拼接起来。你可以直接用按位运算做你想做的事,因为“二进制”和十进制是同一个数字的两种表示。ANDs 和SHIFTs 的组合将允许您将整数的任何部分归零,或隔离特定范围的位例如,>> (107 >> 3) & 75因为Decimal: 107      >> 3 = 13       & 7        = 5Binary : 01101011 >> 3 = 00001101 & 00000111 = 00000101           |-|                |-|          we want         these 3现在,假设您的信息是世界“你好”。您可以像这样方便地将每个字节分成四部分。secret = b'hello'bits = []for byte in secret:    for i in range(6, -1, -2):        bits.append((byte >> i) & 3)bits = np.array(bits)由于每个bits元素包含两位,因此值的范围可以在 0 到 3 之间。如果您考虑二进制中的字母 'h',即 '01|10|10|00',您可以看到它的前几个值是bits如何1、2、2、0 等为了利用 numpy 中的矢量化操作,我们应该展平我们的图像数组,我假设它的形状为 (height, width, 3)。np.random.seed(0)img = np.random.randint(0, 255, (1600, 1200, 3)).astype(np.uint8)shape = img.shape# this specific type of flattening puts the pixels in your desired order, i.e.,# pixel (0, 0) red-green-blue, pixel (0, 1) red-green-blue, etcflat_img = img.reshape(-1).copy()现在嵌入很简单length = len(bits)flat_img[:length] = (flat_img[:length] & 252) + bitsstego_img = flat_img.reshape(shape)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python