【发布时间】:2017-08-15 16:10:07
【问题描述】:
编辑 24.03.2017:我决定拒绝 JPEG 和 YCBCR。我正在使用bmp图像和RGB,但是问题仍然存在。
我正在尝试实现Zhao-Koch的隐写算法,但是提取的消息与执行的不对应,我似乎无法掌握,是什么原因造成的。
代码如下:
实施:
from PIL import Image
from sklearn.feature_extraction import image
import numpy as np
from scipy.fftpack import dct
from scipy.fftpack import idct
pic = Image.open('lama.bmp') # container, 400x400 bmp picture
pic_size = pic.size #picture size
(r, g, b) = pic.split() #splitting the colour channels
u1 = 4 # coordinates for the DCT coefficients to change. [u1][v1] and [u2][v2]
v1 = 5
u2 = 5
v2 = 4
P = 25 # Threshold value to compare the difference of the coefficients with
cvz = [1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1] # test message
i = 0 #
acb = np.asarray(b, dtype='int64') # colour channel as array. int64 because absolute difference may go out of the [0,255] boundaries.
patches = image.extract_patches_2d(acb, (8, 8)) # dividing array to 8x8 blocks
for patch in patches: # Applying
dct(patch, overwrite_x = True)
while (i < len(cvz)): # going through message bits
patch = patches[i] # take block
K1 = patch[u1][v1] # first coefficient
K2 = patch[u2][v2] # second coefficient
K = abs(K1) - abs(K2) # difference of absolute values
cur_bit = cvz[i] # take one bit of the message
if (cur_bit == 1) & (K >= -P): # Implementation works the following way: if message bit is 0 than K must be more than P. If it's 1, K must be less than -P. If the requirements are not met, the coefficients change.
i = i +1
while (K >= -P): # changing coefficient
K1 = K1 - 1
print(K1)
K2 = K2 + 1
print(K2)
K = abs(K1) - abs(K2)
patch[u1][v1] = K1 # applying new values
patch[u2][v2] = K2 # applying new values
elif (cur_bit == 0) & (K <= P): # changing coefficient
i = i + 1
while (K <= P):
K1 = K1 + 1
print(K1)
K2 = K2 - 1
print(K2)
K = abs(K1) - abs(K2)
patch[u1][v1] = K1 # applying new values
patch[u2][v2] = K2 # applying new values
else: # requirements are met and there is no need to change coefficients
i = i + 1
for patch in patches: # applying IDCT to blocks
idct(patch, overwrite_x = True)
acb2 = image.reconstruct_from_patches_2d(patches, (400,400)) # reconstructing colour channel
acb2 = acb2.astype(np.uint8) # converting
b_n = Image.fromarray(acb2, 'L') # converting colour channel array to image
changed_image = Image.merge('RGB', (r,g,b_n)) # merging channels to create new image
changed_image.save("stego.bmp") # saving image
提取:
from PIL import Image
from sklearn.feature_extraction import image
import numpy as np
from scipy.fftpack import dct
from scipy.fftpack import idct
pic = Image.open('stego.bmp')
(r, g, b) = pic.split()
u1 = 4
v1 = 5
u2 = 5
v2 = 4
length = 13
i = 0
cvz = []
acb = np.asarray(b, dtype='int64')
patches = image.extract_patches_2d(acb, (8, 8))
for patch in patches:
dct(patch,overwrite_x = True)
while (i < length): # extracting message. If absolute of coefficient 1 is more than absolute of coefficient 2 than message bit is 0. Otherwise it's 1
patch = patches[i]
print (patch[u1][v1])
print (patch[u2][v2])
K1 = abs(patch[u1][v1])
K2 = abs(patch[u2][v2])
if (K1 > K2):
cvz.append(0)
i = i + 1
else:
cvz.append(1)
i = i + 1
print(cvz)
但是提取出来的消息是错误的:
原文:
[1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1]
提取的消息:
[1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1]
我猜我在系数变化方面做错了。
有人可以帮帮我吗?
UPD:似乎没有保存更改的 DCT 系数,因为如果我尝试专门查找它们,我无法在更改的图片中找到它们。
【问题讨论】:
-
我不熟悉这种算法(或 sklearn 或 scipy),但我怀疑您在 JPEG 压缩过程中丢失了信息(特别是在 @987654321 @ 步)。如果将修改后的数据保存为 PNG 等无损格式会怎样?
-
是的,我试过了。尝试使用纯 RGB(更改为 B 而不是 Cb)。结果是:[1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0] 还尝试另存为 PNG : [1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1]
-
检查您是否没有因为 Numpy 溢出/精度丢失而丢失数据,就像 here 发生的那样。
-
阅读this。如果您尝试进行 JPEG 隐写术,那么您做错了。如果您确实打算获取 IDCT 然后保存图像,则不能使用 JPEG,因为您会导致编码的另一层量化。
-
如果您要回答自己的问题,请不要在问题中进行编辑。相反,将其回滚到问题所在并添加单独的答案。如果您在切换到 BMP 后仍有问题,请明确这一点。
标签: python numpy python-imaging-library scikit-image steganography