以下代码实现了将水印嵌入到原始图像中,并将结果保存为新的图像。然后,通过解密过程,从加密图像中提取出水印信息。

if cmd == 'encode':
    print ('image<'+fn1+'> + watermark<'+fn2+'> -> image(encoded)<'+fn3+'>' % (fn1, fn2, fn3))
    img = cv2.imread(fn1)  # 读取原始图像
    wm = cv2.imread(fn2)  # 读取水印图像

    # 将图像显示在子图中
    if debug:
        plt.subplot(231), plt.imshow(bgr_to_rgb(img)), plt.title('image')
        plt.xticks([]), plt.yticks([])
        plt.subplot(234), plt.imshow(bgr_to_rgb(wm)), plt.title('watermark')
        plt.xticks([]), plt.yticks([])

    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)  # 获取傅里叶逆变换后的实部

    assert cv2.imwrite(fn3, img_wm, [int(cv2.IMWRITE_JPEG_QUALITY), 100])  # 将加密后的图像保存为文件

    # 计算保存前后的误差
    img_wm2 = cv2.imread(fn3)
    sum = 0
    for i in range(img_wm.shape[0]):
        for j in range(img_wm.shape[1]):
            for k in range(img_wm.shape[2]):
                sum += np.power(img_wm[i][j][k] - img_wm2[i][j][k], 2)
    miss = np.sqrt(sum) / (img_wm.shape[0] * img_wm.shape[1] * img_wm.shape[2]) * 100
    print ('Miss %s%% in save' % miss)

    f2 = np.fft.fft2(img_wm)  # 对加密后的图像进行傅里叶变换
    rwm = (f2 - f1) / alpha  # 计算解密后的水印图像
    rwm = np.real(rwm)

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

这段代码实现了将水印嵌入到原始图像中,并将结果保存为新的图像。然后,通过解密过程,从加密图像中提取出水印信息。

要使用这段代码,需要传入以下参数:

  • fn1:原始图像的文件名
  • fn2:水印图像的文件名
  • fn3:生成的加密图像的文件名
  • alpha:水印的加密强度
  • seed:随机数种子
  • oldseed:是否使用旧的随机数种子
  • debug:是否显示调试信息

encode命令下运行该代码将生成加密图像,并将其保存为文件。然后,可以使用以下代码从加密图像中提取出水印信息:

f1 = np.fft.fft2(img_wm)  # 对加密图像进行傅里叶变换
    rwm = (f2 - f1) / alpha  # 计算解密后的水印图像
    rwm = np.real(rwm)

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

这段代码将从加密图像中提取出水印信息,并将其保存在wm变量中。

该代码实现了一种简单的盲水印算法,它利用傅里叶变换将水印信息嵌入到图像中。该算法具有较高的鲁棒性,能够抵抗一些常见的攻击,例如噪声、压缩、裁剪等。

代码解释:

  • 读取原始图像和水印图像
  • 创建一个与原始图像大小相同的空图像,并将其大小缩减为一半
  • 将水印图像复制到空图像中
  • 对空图像进行随机像素置换操作
  • 将置换后的水印图像扩展到与原始图像相同的大小,并在水平和垂直方向上进行镜像操作
  • 对原始图像进行傅里叶变换
  • 将傅里叶变换后的图像与加密后的水印图像相加
  • 对相加后的图像进行傅里叶逆变换
  • 获取傅里叶逆变换后的实部,并将其保存为加密图像
  • 从加密图像中提取出水印信息
  • 对提取出的水印信息进行反向置换操作,恢复原始的水印图像

注意:

  • 该代码需要使用 OpenCV 和 NumPy 库
  • alpha参数控制水印的加密强度,值越大,水印嵌入越明显
  • seed参数用于控制随机数生成器
  • oldseed参数用于指定是否使用旧的随机数种子
  • debug参数用于控制是否显示调试信息
Python 盲水印算法:将水印嵌入图像并解析提取

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

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