在Wikipedia's Steganography Article,有一个隐藏图像数据的示例图像。
维基百科说明:
带有隐藏隐藏图像的Image of a tree。通过除去每个颜色分量的两个最低有效位以及随后的归一化来揭示隐藏图像。隐藏的图片显示为(here)。
问题:我对"随后的规范化感到困惑&#34 ;;假设基于PIL模块运行Python 2.x代码,归一化因素如何影响检索?
答案 0 :(得分:3)
随后的标准化是每个颜色分量的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位空间:
In [3]: (234 & 0b11) * (256/4)
Out[2]: 128
这是在每个颜色组件上完成的,猫会出现。
答案 1 :(得分:2)
标准化是将值范围更改为另一个值范围的过程。
由于二进制值为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'