Python: 使用openCV保存(cv2.imwrite)和读取(cv2.imread)过程中的隐写问题
Python: Problems of steganography in process of saving(cv2.imwrite) and reading(cv2.imread) using openCV
我有一个隐写代码,可以将图像隐藏在另一个图像中。
我通过这段代码在我的图片中加入了水印。
原理很简单
我使用了 source_image
和 watermark_images
来插入水印。
这将随机分发 watermark_images
。
首先,使用随机种子散布水印图像的 x 和 y。
然后,使用快速傅里叶变换将source_image
转换为频率区域。
最后,将watermark_layer
与source_image
的频域结合起来。
这个编码过程非常有效。但是在解码的过程中出现了问题
解码代码是将随机种子分散的像素按照同样的原理收集在一处。
这是解码的结果:
这个问题,如果我尝试编码图像保存(cv2.imwrite)和调用(cv2.imread),解码不起作用。
如果我按原样使用编码对象,就没有问题。保存和调用过程中像素是否损坏?
这是我的完整代码:
import cv2 as cv
import numpy as np
import random
import time
class Watermark:
def __init__(self):
self.watermark_image = cv.imread('../Watermark/google_logo.png')
self.result_image_path = '../Watermark/result.jpg'
self.random_seed = 2021
self.alpha = 5
def encoding(self, image_path):
# Code Start
start_time = time.time()
# Read Image
source_image = cv.imread(image_path)
source_height, source_width, _ = source_image.shape
watermark_height, watermark_width, _ = self.watermark_image.shape
print('source height : ', source_height, ', source_width : ', source_width)
print('watermark height : ', watermark_height, ', watermark width : ', watermark_width)
# Convert image to frequency area with Fast Fourier Transform (image -> frequency)
source_frequency = np.fft.fft2(source_image)
# Get random seed
y_random_indices, x_random_indices = list(range(source_height)), list(range(source_width))
random.seed(self.random_seed)
random.shuffle(x_random_indices)
random.shuffle(y_random_indices)
print('y random seed : ', y_random_indices)
print('x random seed : ', x_random_indices)
# Injection watermark
watermark_layer = np.zeros(source_image.shape, dtype=np.uint8)
for y in range(watermark_height):
for x in range(watermark_width):
watermark_layer[y_random_indices[y], x_random_indices[x]] = self.watermark_image[y, x]
# Encoding frequency area + watermark layer
result_frequency = source_frequency + self.alpha * watermark_layer
# Apply Inverse Fast Fourier Transform (frequency -> image)
result_image = np.fft.ifft2(result_frequency)
result_image = np.real(result_image)
result_image = result_image.astype(np.uint8)
# Show elapsed time
end_time = time.time()
print('Encoding elapsed time : ', end_time - start_time, '\n')
# Visualization
cv.imshow('source_image', source_image)
cv.imshow('watermark', self.watermark_image)
cv.imshow('watermark_layer', watermark_layer)
cv.imshow('result_image', result_image)
# Save and Close
cv.imwrite(self.result_image_path, result_image)
cv.waitKey(0)
cv.destroyAllWindows()
return result_image
def decoding(self, source_image_path, encoded_image):
# Code Start
start_time = time.time()
# Read Image
source_image = cv.imread(source_image_path)
source_height, source_width, _ = source_image.shape
print('original_height : ', source_height)
print('original_width : ', source_width)
encoded_height, encoded_width, _ = encoded_image.shape
# Convert image to frequency area with Fast Fourier Transform (image -> frequency)
source_frequency = np.fft.fft2(source_image)
encoded_frequency = np.fft.fft2(encoded_image)
# Convert frequency area to image (frequency -> image)
watermark_layer = (source_frequency - encoded_frequency) / self.alpha
watermark_layer = np.real(watermark_layer).astype(np.uint8)
# Get random seed
y_random_indices, x_random_indices = [list(range(encoded_height)), list(range(encoded_width))]
random.seed(self.random_seed)
random.shuffle(x_random_indices)
random.shuffle(y_random_indices)
print('y random seed : ', y_random_indices)
print('x random seed : ', x_random_indices)
# Restore watermark
result_image = np.zeros(watermark_layer.shape, dtype=np.uint8)
for y in range(encoded_height):
for x in range(encoded_width):
result_image[y, x] = watermark_layer[y_random_indices[y], x_random_indices[x]]
# Show elapsed time
end_time = time.time()
print('Encoding elapsed time : ', end_time - start_time, '\n')
# Visualization
cv.imshow('original image', source_image)
cv.imshow('target image', encoded_image)
cv.imshow('watermark layer', watermark_layer)
cv.imshow('result image', result_image)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__ == '__main__':
source_path = '../Watermark/jennie.jpg'
# good work
protected_image = Watermark().encoding(source_path)
Watermark().decoding(source_path, protected_image)
# doesn't work
result_path = '../Watermark/result.jpg'
result_image = cv.imread(result_path)
Watermark().decoding(source_path, result_image)
请多多指教
Carlos Melus 说得有道理。
您的代码不适合处理 jpg 图像。
如果你使用png格式,效果会很好。
我有一个隐写代码,可以将图像隐藏在另一个图像中。
我通过这段代码在我的图片中加入了水印。
原理很简单
我使用了 source_image
和 watermark_images
来插入水印。
这将随机分发 watermark_images
。
首先,使用随机种子散布水印图像的 x 和 y。
然后,使用快速傅里叶变换将source_image
转换为频率区域。
最后,将watermark_layer
与source_image
的频域结合起来。
这个编码过程非常有效。但是在解码的过程中出现了问题
解码代码是将随机种子分散的像素按照同样的原理收集在一处。
这是解码的结果:
这个问题,如果我尝试编码图像保存(cv2.imwrite)和调用(cv2.imread),解码不起作用。
如果我按原样使用编码对象,就没有问题。保存和调用过程中像素是否损坏?
这是我的完整代码:
import cv2 as cv
import numpy as np
import random
import time
class Watermark:
def __init__(self):
self.watermark_image = cv.imread('../Watermark/google_logo.png')
self.result_image_path = '../Watermark/result.jpg'
self.random_seed = 2021
self.alpha = 5
def encoding(self, image_path):
# Code Start
start_time = time.time()
# Read Image
source_image = cv.imread(image_path)
source_height, source_width, _ = source_image.shape
watermark_height, watermark_width, _ = self.watermark_image.shape
print('source height : ', source_height, ', source_width : ', source_width)
print('watermark height : ', watermark_height, ', watermark width : ', watermark_width)
# Convert image to frequency area with Fast Fourier Transform (image -> frequency)
source_frequency = np.fft.fft2(source_image)
# Get random seed
y_random_indices, x_random_indices = list(range(source_height)), list(range(source_width))
random.seed(self.random_seed)
random.shuffle(x_random_indices)
random.shuffle(y_random_indices)
print('y random seed : ', y_random_indices)
print('x random seed : ', x_random_indices)
# Injection watermark
watermark_layer = np.zeros(source_image.shape, dtype=np.uint8)
for y in range(watermark_height):
for x in range(watermark_width):
watermark_layer[y_random_indices[y], x_random_indices[x]] = self.watermark_image[y, x]
# Encoding frequency area + watermark layer
result_frequency = source_frequency + self.alpha * watermark_layer
# Apply Inverse Fast Fourier Transform (frequency -> image)
result_image = np.fft.ifft2(result_frequency)
result_image = np.real(result_image)
result_image = result_image.astype(np.uint8)
# Show elapsed time
end_time = time.time()
print('Encoding elapsed time : ', end_time - start_time, '\n')
# Visualization
cv.imshow('source_image', source_image)
cv.imshow('watermark', self.watermark_image)
cv.imshow('watermark_layer', watermark_layer)
cv.imshow('result_image', result_image)
# Save and Close
cv.imwrite(self.result_image_path, result_image)
cv.waitKey(0)
cv.destroyAllWindows()
return result_image
def decoding(self, source_image_path, encoded_image):
# Code Start
start_time = time.time()
# Read Image
source_image = cv.imread(source_image_path)
source_height, source_width, _ = source_image.shape
print('original_height : ', source_height)
print('original_width : ', source_width)
encoded_height, encoded_width, _ = encoded_image.shape
# Convert image to frequency area with Fast Fourier Transform (image -> frequency)
source_frequency = np.fft.fft2(source_image)
encoded_frequency = np.fft.fft2(encoded_image)
# Convert frequency area to image (frequency -> image)
watermark_layer = (source_frequency - encoded_frequency) / self.alpha
watermark_layer = np.real(watermark_layer).astype(np.uint8)
# Get random seed
y_random_indices, x_random_indices = [list(range(encoded_height)), list(range(encoded_width))]
random.seed(self.random_seed)
random.shuffle(x_random_indices)
random.shuffle(y_random_indices)
print('y random seed : ', y_random_indices)
print('x random seed : ', x_random_indices)
# Restore watermark
result_image = np.zeros(watermark_layer.shape, dtype=np.uint8)
for y in range(encoded_height):
for x in range(encoded_width):
result_image[y, x] = watermark_layer[y_random_indices[y], x_random_indices[x]]
# Show elapsed time
end_time = time.time()
print('Encoding elapsed time : ', end_time - start_time, '\n')
# Visualization
cv.imshow('original image', source_image)
cv.imshow('target image', encoded_image)
cv.imshow('watermark layer', watermark_layer)
cv.imshow('result image', result_image)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__ == '__main__':
source_path = '../Watermark/jennie.jpg'
# good work
protected_image = Watermark().encoding(source_path)
Watermark().decoding(source_path, protected_image)
# doesn't work
result_path = '../Watermark/result.jpg'
result_image = cv.imread(result_path)
Watermark().decoding(source_path, result_image)
请多多指教
Carlos Melus 说得有道理。
您的代码不适合处理 jpg 图像。
如果你使用png格式,效果会很好。