阿里巴巴公司通过截图,根据肉眼无法识别的标识码追踪到泄露信息的具体员工……

阿里月饼事件中的新闻中提到“泄露内部信息丢了工作,因为截图上「看不见的水印」”。那么该技术(简称“阿里水印”)的原理是什么?又能否利用Python实现呢。

1. 原理

传统的水印,是将水印直接叠加在图像上。但由于水印可见,那么通过PS等方式去除水印就很容易做到。

而阿里水印的关键,在于水印的隐藏。实际上,是把水印添加到了频域中。

频域添加数字水印的方法,是指通过某种变换手段(傅里叶变换,离散余弦变换,小波变换等)将图像变换到频域(小波域),在频域对图像添加水印,再通过逆变换,将图像转换为空间域。相对于空域手段,频域手段隐匿性更强,抗攻击性更高。

上图为叠加数字盲水印的基本流程。编码的目的有二:

一是对水印加密

二控制水印能量的分布

2. 鲁棒性: 对抗水印攻击

所谓对水印的攻击,是指破坏水印,包括涂抹,剪切,放缩,旋转,压缩,加噪,滤波等。数字盲水印不仅仅要敏捷性高(不被人抓到),也要防御性强(抗打)。

注意:数字盲水印的隐匿性和鲁棒性是互斥的。

3. Python实现

3.1. 原始图像读取

这里以Doc为例:

# %%

im = mvlib.io.imread("test/doc.png")

uu.imshow(im)

# %%

im_gray = mvlib.color.rgb2gray(im)

uu.imshow(im_gray)

3.2. 傅立叶变换

im_fft = np.fft.fft2(im_gray)

变换后,你会得到一个复数的array。

如果想审视,请调用以下代码:

# %% 显示频域图像

fshift = np.fft.fftshift(im_fft) # 平移频谱到图像中央

# 将频谱转换成db

magnitude_spectrum = 20 * np.log(np.abs(fshift))

uu.imshow(magnitude_spectrum) # 频谱

3.3. 准备文字信息的内容

# %% 创建文字图片

im_msg = np.zeros(im_gray.shape)

# %%

from PIL import ImageFont

font = ImageFont.truetype(

"/usr/share/fonts/truetype/freefont/FreeMono.ttf",

400)

im_txt = mvlib.draw.pil_drawing(im_msg, "text", (100,100),

color="white", text="ABC", font=font)

uu.imshow(im_txt)

# %% 颜色取反

im_txt = (False == im_txt) * 255

uu.imshow(im_txt)

所谓编码,其实简单点,就是按照随机数组,打散文字信息。那么,按照这个随机数组进行逆操作,就能恢复图像的原始状态(解码)。

seq_column = list(range(im_txt.shape[0]))

seq_raw = list(range(im_txt.shape[1]))

import random

random.shuffle(seq_column)

random.shuffle(seq_raw)

im_random = im_txt.copy()

im_tmp = im_txt.copy()

for idx, i in enumerate(seq_column):

im_tmp[idx, ...] = im_txt[i, ...]

for idx, i in enumerate(seq_raw):

im_random[..., idx] = im_tmp[..., i]

uu.imshow(im_random)

第一阶段,被打散的raws:

第二阶段,打散的columns:

实际上,这个问题整复杂了,直接使用 random.seed() 添加种子,即可获取到固定的随机列表,而无需把随机序列存储起来。

不过,目前这个版本看起来更容易理解,就暂时不做修改了。

3.4. 在频域合并图像

合并后,使用逆傅立叶函数,恢复时域图像

im_txt_fft = np.fft.fft2(im_random)

im_merge = im_fft + im_txt_fft * 0.1

im_ifft = np.fft.ifft2(im_merge).real

uu.imshow(im_ifft)

图像看起来会多了一些噪点,如果控制的好,可以做到肉眼无差别。这里为了体现噪点,放大了系数,效果如下图:

3.5. 解码

接下来就是解码的过程,提取info信息。

通过傅立叶变换到频域,然后过滤掉原图的fft频域值,即获得了文字图像的频域图。这个图再恢复到时域,及打乱了状态的那个“散点图”。

按照之前random的编码规则逆向运行,即可恢复原文字图像。

im_fft2 = np.fft.fft2(im_ifft)

im_txt_random = (im_fft2 - im_fft) * 10

im_random2 = np.fft.ifft2(im_fft2).real

# %% 编码的恢复

im_recover = im_random2.copy()

for idx, i in enumerate(seq_raw):

im_tmp[..., i] = im_random2[..., idx]

for idx, i in enumerate(seq_column):

im_recover[i, ...] = im_tmp[idx, ...]

uu.imshow(im_recover)

4. 后续思考

其实,添加的文字没必要这么大。或者更准确的说,没必要这么粗。点可以是那种有点镂空的虚点。

不过,个人一直无法理解,转换到频域叠加图像后在反变换,与直接在时域相加,有什么区别?或者说,有一个关键点,我还没有实现:高频嵌入或低频嵌入的选择。

5. 项目应用

推荐一个封装较为完善的实现:github链接

5.1. PDF或图像添加水印

5.2. Web页面添加水印

对于web,可以添加一个背景图片,来追踪截图者。

python读取水印_阿里水印的Python实现相关推荐

  1. python编程基础_月隐学python第2课

    python编程基础_月隐学python第2课 学习目标 掌握变量的输入和输出 掌握数据类型的基本概念 掌握算数运算 1.变量的输入和输出 1.1 变量输入 使用input输入 input用于输入数据 ...

  2. 查看Python的版本_查看当前安装Python的版本

    一.查看Python的版本_查看当前安装Python的版本 具体方法: 首先按[win+r]组合键打开运行: 然后输入cmd,点击[确定]: 最后执行[python --version]命令即可. 特 ...

  3. Python读取xlsx表格并转换成Python列表

    Python读取xlsx表格并转换成Python列表 参考链接https://www.cnblogs.com/ilovepython/p/11068841.html import xlrd from ...

  4. python给视频加水印_视频水印_Python SDK_服务端SDK_视频点播 - 阿里云

    初始化客户端 使用前请先初始化客户端,请参见 添加水印 调用AddWatermark接口,完成添加水印功能. 接口参数和返回字段请参见 说明水印文件OSS上传详细参数请参见from aliyunsdk ...

  5. python神经网络多元函数_阿里达摩院推荐的最新400集python教程,据说懂中文就能上手...

    小编的内心是强大的,网友虐我千百遍,我待网友如初恋,因为今天又给大家带来了干货,Python入门教程完整版,完整版啊!完整版! 为了吸取教训,小编一定要分享一下攻略,"怎样获得小编分享的教程 ...

  6. python读取二进制文件_如何用python读取二进制文件?

    我发现用Python读取二进制文件特别困难.你能帮我一把吗?我需要读取这个文件,在Fortran 90中,该文件很容易被int*4 n_particles, n_groups real*4 group ...

  7. python读取文件_一日一技:使用Python读取Excel文件

    安装xlrd模块: pip install xlrd 使用xlrd模块,可以从电子表格中检索信息. 例如,可以在Python中完成读取,写入或修改数据的操作. 另外,用户可能必须浏览各种工作表并根据某 ...

  8. 用python读取图像_如何用python获取图像

    方法一:利用PIL中的Image函数,这个函数读取出来不是array格式 这时候需要用 np.asarray(im) 或者 np.array()函数:区别:np.array() 是深拷贝,np.asa ...

  9. python 读取文本文件_如何在Python中读取大文本文件

    python 读取文本文件 Python File object provides various ways to read a text file. The popular way is to us ...

最新文章

  1. 如何让ThinkPHP支持模糊搜索
  2. [caffe解读] caffe从数学公式到代码实现5-caffe中的卷积
  3. java中能构成循环的语句_《编程导论(Java)#183;3.2.4 循环语句》
  4. LeetCode 823. 带因子的二叉树(动态规划)
  5. 避免大规模故障的微服务架构设计之道
  6. 收藏 | Python必备技能之 25个Matplotlib常用代码!
  7. 【干货】2021短视频营销攻略:短视频内容策略下的5i沟通法则.pdf(附下载链接)...
  8. 线性代数【八】二次型
  9. 机器学习与神经网络绪论
  10. 阿里褚霸专访-揭秘技术男开挂升级的职业路径(回帖有奖)
  11. ACM-ICPC 2018 北京赛区网络预赛 B Tomb Raider(二进制枚举暴力)
  12. 《REAL-TIME INDOOR SCENE RECONSTRUCTION WITH RGBD AND INERTIA INPUT 》 原文翻译与解读
  13. Microsoft Visual Studio - 代码格式化设置项
  14. 迪文串口屏幕DMG10600T101_01WTR实现图片切换并和串口通讯
  15. 车载计算机模块,【荐】DIY车载电脑续:开模自制电路板(含DAC和7850)V2.0测试成功...
  16. Android Studio下Svn忽略文件配置的几种方法
  17. 为什么接入了高防还是会被ddos打死
  18. java.lang.IllegalStateException错误
  19. 小s探秘之HTTP和HTTPS
  20. CANIOT车联网远程网关给EPEC控制器远程升级解决特种车升级难点

热门文章

  1. 【Java】网络编程——多线程下载文件
  2. Python爬虫入门教程【18】: 36氪(36kr)数据抓取 scrapy
  3. Jenkins安装与系统配置
  4. 那些让我效率倍增的 Mac 软件
  5. 运营商分配给专线的多个固定公网IP怎么用
  6. 玩客云1608第二个短接点
  7. DHT算法的一知半解
  8. 视频转音频mp3软件哪个好?这些转换软件就很好用
  9. MYSQL - 算一算1000万条数据大概占了多大磁盘空间
  10. 网站性能优化时Cookie常用的优化方式