使用 Python 解码隐写术图像(维基百科上的示例图像)
Using Python to Decode Steganography Images (example images at Wikipedia)
在 Wikipedia's Steganography Article 处有一个带有隐藏图像数据的示例图像。
维基百科注释:
Image of a tree with a steganographically hidden image. The hidden image is revealed by removing all but the two least significant bits of each color component and a subsequent normalization. The hidden image is shown (here).
问题: 我对 "subsequent normalisation" 感到困惑;假设工作 Python 2.x 基于 PIL 模块的代码,规范化因素如何影响检索?
后续归一化是每个颜色分量linear interpolation。
比如说,像素 1,1 的红色分量是 234。
234的二进制表示是
In [1]: bin(234)
Out[1]: '0b11101010'
我们可以通过一些按位运算删除除两个最低有效位之外的所有内容:
In [2]: bin(234 & 0b11)
Out[2]: '0b10'
8 位图像的范围是 8 位或 256 种可能的阴影。但是我们的颜色值的范围只是 2 位或 4 种可能的色调。
归一化部分正在做 linear interpolation 拉伸 2 位值以填充 8 位 space:
In [3]: (234 & 0b11) * (256/4)
Out[2]: 128
在每个颜色分量上都这样做,猫就会出现。
规范化是将一个值范围更改为另一个值范围的过程。
由于二进制值为 00、01、10 和 11,因此范围为 [0,3]。之所以要将其标准化为 [0,255] 是为了覆盖整个像素强度范围。如果您只是从数组中保存一张图像,其值在 [0,3] 范围内,它会显示为黑色,因为所有这些值都非常接近 0 而远离 255。
image normalization 上的维基百科页面为您提供了通用公式。它还显示了将范围 [50,180](将此范围称为 A)转换为 [0,255](范围 B)的示例。
首先,我们移动 A,使其从零开始。实际上,您减去最低值 (50),使 [50,180] 变为 [0,130](称之为 C)。 C 的最大距离为 130-0 = 130,B 的最大距离为 255-0 = 255。因此您需要将 C 的所有值乘以 255/130。由于 C 中的最低值为 0,因此 C * 255/130。但是,如果 B 不是从 0 开始,您只需添加必要的偏移量即可。
为了防止单词混淆,下面是将 [2,5] 转换为 [-4,4] 的可视化。
在您的情况下,标准化是从 [0,3] 到 [0,255]。由于两个范围都从 0 开始,您不需要任何偏移量,只需乘以 255/3 即可。此结果将 {0,1,2,3} 转换为 {0,85,170,255}。
请注意,255/3 是一个整数。但是,如果您正在规范化,比如 [0,7],最准确的转换将需要浮点比例因子 255/7。无论您将其保留为浮点数还是将其四舍五入为整数,都超出了此答案的范围。
实现此目的的最简单代码是
import Image
import numpy as np
# The array will be of type `np.uint8`. For integer computations that exceed
# this range, use `np.asarray(Image.open(...), dtype=int)`.
stego = np.asarray(Image.open('Steganography_original.png'))
extracted = stego & 0b00000011
extracted *= (255 / 3)
# Compare result with the one from wikipedia
wiki_extracted = np.asarray(Image.open('Steganography_recovered.png').convert('RGB'))
if np.all(wiki_extracted == extracted):
print 'All pixels match'
在 Wikipedia's Steganography Article 处有一个带有隐藏图像数据的示例图像。
维基百科注释:
Image of a tree with a steganographically hidden image. The hidden image is revealed by removing all but the two least significant bits of each color component and a subsequent normalization. The hidden image is shown (here).
问题: 我对 "subsequent normalisation" 感到困惑;假设工作 Python 2.x 基于 PIL 模块的代码,规范化因素如何影响检索?
后续归一化是每个颜色分量linear interpolation。
比如说,像素 1,1 的红色分量是 234。
234的二进制表示是
In [1]: bin(234)
Out[1]: '0b11101010'
我们可以通过一些按位运算删除除两个最低有效位之外的所有内容:
In [2]: bin(234 & 0b11)
Out[2]: '0b10'
8 位图像的范围是 8 位或 256 种可能的阴影。但是我们的颜色值的范围只是 2 位或 4 种可能的色调。
归一化部分正在做 linear interpolation 拉伸 2 位值以填充 8 位 space:
In [3]: (234 & 0b11) * (256/4)
Out[2]: 128
在每个颜色分量上都这样做,猫就会出现。
规范化是将一个值范围更改为另一个值范围的过程。
由于二进制值为 00、01、10 和 11,因此范围为 [0,3]。之所以要将其标准化为 [0,255] 是为了覆盖整个像素强度范围。如果您只是从数组中保存一张图像,其值在 [0,3] 范围内,它会显示为黑色,因为所有这些值都非常接近 0 而远离 255。
image normalization 上的维基百科页面为您提供了通用公式。它还显示了将范围 [50,180](将此范围称为 A)转换为 [0,255](范围 B)的示例。
首先,我们移动 A,使其从零开始。实际上,您减去最低值 (50),使 [50,180] 变为 [0,130](称之为 C)。 C 的最大距离为 130-0 = 130,B 的最大距离为 255-0 = 255。因此您需要将 C 的所有值乘以 255/130。由于 C 中的最低值为 0,因此 C * 255/130。但是,如果 B 不是从 0 开始,您只需添加必要的偏移量即可。
为了防止单词混淆,下面是将 [2,5] 转换为 [-4,4] 的可视化。
在您的情况下,标准化是从 [0,3] 到 [0,255]。由于两个范围都从 0 开始,您不需要任何偏移量,只需乘以 255/3 即可。此结果将 {0,1,2,3} 转换为 {0,85,170,255}。
请注意,255/3 是一个整数。但是,如果您正在规范化,比如 [0,7],最准确的转换将需要浮点比例因子 255/7。无论您将其保留为浮点数还是将其四舍五入为整数,都超出了此答案的范围。
实现此目的的最简单代码是
import Image
import numpy as np
# The array will be of type `np.uint8`. For integer computations that exceed
# this range, use `np.asarray(Image.open(...), dtype=int)`.
stego = np.asarray(Image.open('Steganography_original.png'))
extracted = stego & 0b00000011
extracted *= (255 / 3)
# Compare result with the one from wikipedia
wiki_extracted = np.asarray(Image.open('Steganography_recovered.png').convert('RGB'))
if np.all(wiki_extracted == extracted):
print 'All pixels match'