Python实现基于傅里叶变换的鲁棒盲水印算法

本文介绍如何使用Python和OpenCV库实现一种基于傅里叶变换的鲁棒盲水印算法。该算法将水印信息嵌入到图像的频域中,具有较好的鲁棒性。

1. 算法原理

该算法的核心思想是利用傅里叶变换将图像从空间域转换到频域,然后将水印信息嵌入到图像的低频或中频系数中。最后,通过逆傅里叶变换将图像转换回空间域,得到嵌入水印的图像。

2. 代码实现

以下Python代码实现了该算法的编码和解码过程:

import cv2
import numpy as np
import random

def encode_image(image_path, watermark_path, output_path, alpha=0.1, seed=0, oldseed=False):
    '''
    将水印嵌入到图像中。

    参数:
    image_path:原图路径
    watermark_path:水印图路径
    output_path:嵌入水印后的图像保存路径
    alpha:水印嵌入强度
    seed:随机种子
    oldseed:是否使用旧版随机种子
    '''
    img = cv2.imread(image_path)
    wm = cv2.imread(watermark_path)

    h, w = img.shape[0], img.shape[1]
    hwm = np.zeros((int(h * 0.5), w, img.shape[2]))
    assert hwm.shape[0] > wm.shape[0]
    assert hwm.shape[1] > wm.shape[1]
    hwm2 = np.copy(hwm)
    for i in range(wm.shape[0]):
        for j in range(wm.shape[1]):
            hwm2[i][j] = wm[i][j]

    if oldseed: 
        random.seed(seed,version=1)
    else:
        random.seed(seed)
    m, n = list(range(hwm.shape[0])), list(range(hwm.shape[1]))
    if oldseed:
        random.shuffle(m,random=random.random)
        random.shuffle(n,random=random.random)
    else:
        random.shuffle(m)
        random.shuffle(n)

    for i in range(hwm.shape[0]):
        for j in range(hwm.shape[1]):
            hwm[i][j] = hwm2[m[i]][n[j]]

    rwm = np.zeros(img.shape)
    for i in range(hwm.shape[0]):
        for j in range(hwm.shape[1]):
            rwm[i][j] = hwm[i][j]
            rwm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = hwm[i][j]

    f1 = np.fft.fft2(img)
    f2 = f1 + alpha * rwm
    _img = np.fft.ifft2(f2)
    img_wm = np.real(_img)

    cv2.imwrite(output_path, img_wm, [int(cv2.IMWRITE_JPEG_QUALITY), 100])

def decode_image(original_image_path, watermarked_image_path, alpha=0.1):
    '''
    从嵌入水印的图像中提取水印信息。

    参数:
    original_image_path:原图路径
    watermarked_image_path:嵌入水印后的图像路径
    alpha:水印嵌入强度

    返回值:
    提取出的水印图像
    '''
    img = cv2.imread(original_image_path)
    img_wm = cv2.imread(watermarked_image_path)

    f1 = np.fft.fft2(img)
    f2 = np.fft.fft2(img_wm)
    rwm = (f2 - f1) / alpha
    rwm = np.real(rwm)

    hwm = np.zeros(rwm.shape)
    for i in range(int(rwm.shape[0] * 0.5)):
        for j in range(rwm.shape[1]):
            hwm[i][j] = np.uint8(rwm[i][j])
            hwm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = hwm[i][j]

    wm = np.zeros(hwm.shape)
    m, n = list(range(hwm.shape[0])), list(range(hwm.shape[1]))
    random.shuffle(m)
    random.shuffle(n)
    for i in range(hwm.shape[0]):
        for j in range(hwm.shape[1]):
            wm[m[i]][n[j]] = hwm[i][j]

    return wm

# 示例用法
# 嵌入水印
encode_image('P.jpg', 'wm.jpg', 'SP.jpg', alpha=0.05)
# 提取水印
wm_extracted = decode_image('P.jpg', 'SP.jpg', alpha=0.05)
cv2.imwrite('extracted_wm.jpg', wm_extracted)

3. 鲁棒性分析

该算法将水印信息嵌入到图像的频域中,具有一定的鲁棒性,可以抵抗一些常见的图像攻击,例如JPEG压缩、噪声添加、滤波等。

4. 提高鲁棒性的方法

为了进一步提高算法的鲁棒性,可以考虑以下方法:

  • 选择合适的嵌入强度:嵌入强度越大,水印越难以去除,但图像质量也会下降。
  • 将水印信息嵌入到多个频带中:可以将水印信息分散嵌入到图像的不同频带中,提高水印的鲁棒性。
  • 使用更 robust 的水印信息:可以考虑使用具有良好抗攻击能力的水印信息,例如二值图像或特定图案。

5. 总结

本文介绍了一种基于Python的鲁棒盲水印算法。该算法使用傅里叶变换将水印信息嵌入到图像的频域中,具有较好的鲁棒性。通过调整算法参数和使用更 robust 的水印信息,可以进一步提高算法的鲁棒性。

Python实现基于傅里叶变换的鲁棒盲水印算法

原文地址: https://www.cveoy.top/t/topic/fTgs 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录