DCT暗水印 Python实现
时间: 2025-01-01 20:12:19 浏览: 11
### Python 实现基于DCT的数字水印嵌入与提取
在图像处理领域,离散余弦变换 (Discrete Cosine Transform, DCT)[^1] 是一种常用的技术手段,在此基础之上可以实现数字水印技术。下面提供一段简单的Python代码来展示如何利用DCT进行基本的数字水印嵌入和提取。
#### 数字水印嵌入过程
对于给定的一幅灰度图作为载体图片以及另一张较小尺寸的二值化图像作为待嵌入的水印图案,通过修改载体图片经过DCT转换后的低频系数部分完成水印信息隐藏:
```python
import numpy as np
from scipy.fftpack import dct, idct
import cv2
def embed_watermark(image_path, watermark_path, alpha=0.1):
image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE).astype(float)
watermark = cv2.imread(watermark_path, cv2.IMREAD_GRAYSCALE)
# Resize the watermark to fit into a block of the cover image
h, w = image.shape[:2]
wm_h, wm_w = watermark.shape[:2]
blocks_vertical = int(h / wm_h)
blocks_horizontal = int(w / wm_w)
resized_watermark = cv2.resize(watermark, (blocks_horizontal * wm_w,
blocks_vertical * wm_h))
# Apply DCT on each 8x8 block and add scaled watermark
watermarked_image = np.zeros_like(image)
for i in range(blocks_vertical):
for j in range(blocks_horizontal):
y_start = i * wm_h
x_start = j * wm_w
block = image[y_start:y_start + wm_h, x_start:x_start + wm_w].copy()
transformed_block = dct(dct(block.T, norm='ortho').T, norm='ortho')
transformed_wm = dct(dct(resized_watermark[i*wm_h:(i+1)*wm_h,j*wm_w:(j+1)*wm_w], norm='ortho'), norm='ortho')
modified_dct_coeffs = transformed_block + alpha * transformed_wm
inverse_transformed_block = idct(idct(modified_dct_coeffs.T, norm='ortho').T, norm='ortho')
watermarked_image[y_start:y_start + wm_h, x_start:x_start + wm_w] = inverse_transformed_block.real
return watermarked_image.astype(np.uint8), resized_watermark
```
这段代码实现了将一幅指定大小的黑白水印图形按照一定比例缩放并嵌入到原始图像中的功能[^2]。
#### 提取已嵌入的数字水印
为了验证之前所嵌入的信息确实存在于目标文件内,则可以通过逆向操作尝试恢复出原版水印内容:
```python
def extract_watermark(embedded_image, original_image, watermark_shape=(64, 64)):
embedded_image_flt = embedded_image.astype(float)
orig_image_flt = original_image.astype(float)
extracted_watermark = np.zeros(shape=watermark_shape)
h, w = embedded_image_flt.shape[:2]
wm_h, wm_w = watermark_shape
blocks_vertical = int(h / wm_h)
blocks_horizontal = int(w / wm_w)
for i in range(blocks_vertical):
for j in range(blocks_horizontal):
y_start = i * wm_h
x_start = j * wm_w
emb_block = embedded_image_flt[y_start:y_start + wm_h, x_start:x_start + wm_w]
org_block = orig_image_flt[y_start:y_start + wm_h, x_start:x_start + wm_w]
trans_emb_blk = dct(dct(emb_block.T, norm='ortho').T, norm='ortho')
trans_org_blk = dct(dct(org_block.T, norm='ortho').T, norm='ortho')
diff = abs(trans_emb_blk - trans_org_blk)
avg_diff = np.mean(diff.flatten())
if avg_diff > 0:
extracted_watermark[i:i+wm_h//8, j:j+wm_w//8] += diff[::8, ::8]/avg_diff
normalized_extracted_watermark = ((extracted_watermark-np.min(extracted_watermark))/
(np.max(extracted_watermark)-np.min(extracted_watermark))*255.).astype('uint8')
_, binary_extracted_watermark = cv2.threshold(normalized_extracted_watermark, thresh=127, maxval=255, type=cv2.THRESH_BINARY)
return binary_extracted_watermark
```
上述函数接收两个参数——一个是含有潜在隐秘数据的目标位图;另一个则是未经任何改动过的参照样本用于对比分析差异之处从而定位可能存在的标记位置[^3]。
阅读全文