吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3678|回复: 19
收起左侧

[Python 原创] 【Python】图像处理之看不见的水印

  [复制链接]
jjjzw 发表于 2022-8-30 18:44
本帖最后由 jjjzw 于 2022-8-30 20:23 编辑

一直对各大互联网大厂传说中揪出内鬼的能力感到好奇,机缘巧合下了解到其中一种数字水印的方法,在员工操作的设备上添加隐藏的水印,通过解密可以得到附加的信息,因此学习复现一下。

原理

现阶段常见的,使用最多的水印技术,就是用水印图片覆盖原有像素,虽然简洁明了,但容易被PS干掉,也不可逆地破坏了原图片的内容,因此隐藏数字水印的技术只能作用于频域中

为了获得图像的频域,需要使用二维的快速傅立叶变换(FFT2),将灰度图转化为频率的分布

一张频谱图如下所示:

原图频谱

其中,频谱图反映了图像中突变、边缘的变化等信息,对其进行细微修改不会显著地变化原图

因此,将一张水印直接添加到待加密的图片的频谱上,再进行傅立叶逆变换,恢复到空间域的图像,得到一张加密过的图像

解密时,将图像进行傅立叶变换,减去原图的频谱,得到隐藏在其中的信息

代码验证

待加密图 水印
52pojie.jpg watermark.jpg

代码:需要opencv-python + matplotlib

import cv2
import random
import numpy as np
import matplotlib.pyplot as plt

# 随机序列表
key1 = []
key2 = []

def read(name):
    img0 = cv2.imread(name)
    return cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)

# 读取图片和水印
raw_pic = read("52pojie.jpg")
watermark = read("watermark.jpg")
if raw_pic.shape[0] != watermark.shape[0] & raw_pic.shape[1] != watermark.shape[1]:
    print("水印尺寸错误")

# 水印随机序列编码
if key1 == key2 == []:
    key1 = random.sample(range(watermark.shape[0]), watermark.shape[0])
    key2 = random.sample(range(watermark.shape[1]), watermark.shape[1])
    with open("key.txt", "w") as f:
        f.write(str(key1) + "\n" + str(key2))
temp = np.zeros((watermark.shape[0], watermark.shape[1]))
for i in range(watermark.shape[0]):
    for j in range(watermark.shape[1]):
        temp[i][j] = watermark[key1[i]][key2[j]]
watermark_encoded = temp
cv2.imwrite("watermark_encoded.jpg", watermark_encoded)

# 添加水印
FR = np.fft.fft2(raw_pic)
FA = FR + watermark_encoded
fshift = np.fft.fftshift(FA)
s = np.log(np.abs(fshift))
fimg = np.abs(s)

# 从频域恢复图片
ifshift = np.fft.ifftshift(fshift)
back = np.fft.ifft2(ifshift)
back = np.abs(back)
cv2.imwrite("picture.jpg", back)

# 提取水印
F_encoded = np.fft.fft2(back)
F_watermark = (F_encoded - FR)
plt.savefig("watermark_extracted.jpg")

# 水印解码
FF = np.zeros((F_watermark.shape[0], F_watermark.shape[1]))
for i in range(F_watermark.shape[0]):
    for j in range(F_watermark.shape[1]):
        FF[key1[i]][key2[j]] = F_watermark[i][j]
cv2.imwrite("watermark_decoded.jpg", FF)

运行结果如下:

1. 原图频谱 2. 水印编码
3. 加密频谱 4. 加密图片
5. 提取水印 6. 水印解码

测试1:水印不编码

将水印直接加到原图的频域中,频域之差即水印,观察提取出来的水印

发现一正一反重叠了起来,和上面的图有差距,这是由于傅立叶变换的对称性,在本图中表现为出现了相反的两张水印

但水印的总能量是不变的,两张水印各占有一半的能量,因此水印的灰度相比原水印都发生了变化

因此,随机序列编码的优势在于,只恢复了想要的正确水印,将相反的水印散布在背景中,使得水印看起来清晰可见

该问题很好解决,只要做一张对称的水印即可

对称水印 水印提取
对称水印 对称解码

在对称水印的情况下,是否编码的结果没有任何差别(可以完全取出水印)

我只是简单把像素加到频域中,是否编码不影响矩阵作差的准确性,在一些使用滤波器的数字水印加密中,编码可以使得图片的频域与原图的频域相对分离,可以做到不需要原图也可以提取水印

测试2:鲁棒性测试

对图片造成一点破坏——添加一块噪声上去:原图 + 噪声系数 * 噪声像素

再次测试结果:

(这里应当有一张全白的图片.jpg)

信息完全丢失了

修改噪声系数小于0.1时能看到被破坏过的结果:

可以看出这种加密对像素攻击有一定的抵御能力(涂改的地方已经挺多了,一般图片不会这样损坏)

优缺点

  1. 优点:足够隐蔽(完全看不出来-见4. 加密图片),可以抵御一定程度的攻击
  2. 缺点:信息直接加在图片的频域上,在复频域中,但是在保存加密图片时只能储存0-255的像素值,过大的误差导致计算出来的加密图片和保存的图片频域差距较大,无法正常隐藏信息,暂时没有想到好方法解决该问题

总结

去年实验课的时候有个题目是在音频中隐藏信息,没做成功,后来发现图像领域有类似的鲁棒性水印,在生活中有一定用处,便学习了一下。各位看到水印的文字大概能想到它原来的用途(笑)可惜没能解决保存加密图片的问题,只能提前放出。待我再研究研究使用滤波器的数字水印技术,下次原创发布区见!


免费评分

参与人数 7吾爱币 +8 热心值 +7 收起 理由
角刀牛 + 1 + 1 谢谢@Thanks!
lu_ + 2 + 1 v50
zzhaoxue + 1 + 1 我很赞同!
18839137536 + 1 + 1 谢谢@Thanks!
burning + 1 谢谢@Thanks!
smartfind + 1 + 1 我很赞同!
fanvalen + 2 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| jjjzw 发表于 2022-8-30 22:47
三滑稽甲苯 发表于 2022-8-30 22:41
能抵抗截屏/拍屏攻击吗

可以抵抗截屏,对抗拍摄的能力稍差
vethenc 发表于 2022-8-30 19:00
Gif 发表于 2022-8-30 19:06
likaiaixuexi 发表于 2022-8-30 19:30
我也没咋看懂
Chenmozero 发表于 2022-8-30 19:35
用matlab做过,过了一年还是照着葫芦画瓢,楼主厉害
smartfind 发表于 2022-8-30 19:43
楼主厉害了,感谢分享
Piz.liu 发表于 2022-8-30 22:02
厉害厉害,虽然看不懂,
想知道如果对图做了修改,比如裁剪,或再添加一层水印,还能获取到信息么
xsw1000 发表于 2022-8-30 22:13
没看懂,厉害..感谢分享,
Airey 发表于 2022-8-30 22:35
快速傅里叶变换
三滑稽甲苯 发表于 2022-8-30 22:41
能抵抗截屏/拍屏攻击吗
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-10-6 00:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表