5 分钟跑通 blind_watermark 盲水印:3 条命令嵌入,提取不用原图
2026/9/12 16:49:20 网站建设 项目流程

5 分钟跑通 blind_watermark 盲水印:3 条命令嵌入,提取不用原图

【免费下载链接】blind_watermarkBlind&Invisible Watermark ,图片盲水印,提取水印无须原图!项目地址: https://gitcode.com/GitHub_Trending/bl/blind_watermark

上周一个做插画的朋友跟我吐槽:他发在网上的一张图,被某电商直接拿去当商品详情页,署名也被抹掉了。他想去理论,对方一句"一张图而已,你怎么证明是你拍的"就把他噎住了。这事让我意识到,证据其实可以就藏在图片本身里——如果当初就嵌入一条盲水印,现在直接提取出来就是证据。我由此开始找图片盲水印工具,试了几个之后,blind_watermark 这个开源项目用得最顺手,这里把它整理出来。

它凭什么值得挑一个用

不少水印方案有个要命的短板:提取水印时要拿原图去比对。可图片一旦流出去,你手里只有被裁剪、截图、压缩过的版本,根本找不回原图,"依赖原图"的方案基本等于白做。

blind_watermark 把这个关系反过来了:提取水印无须原图。只需要拿到手的这张图,加上嵌入时用的同一个口令,就能把藏进去的信息恢复出来。算法基于 DWT-DCT-SVD,在频域上动手脚,核心逻辑都在 bwm_core.py 里。这些数学细节你完全可以不管,调接口就行。

5 分钟跑通盲水印嵌入与提取

先装:

pip install blind-watermark

仓库自带示例图片,终端里两条命令就能走完嵌入和提取全流程(命令行入口是 cli_tools.py):

# 第一条:嵌入水印 blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png # 第二条:提取水印,不需要原图 blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png

有两个细节值得记下来。一是--pwd口令:嵌入和提取必须一致,对不上提出来就是一串乱码。二是--wm_shape:它告诉程序水印有多长,文本水印就是比特数,嵌入时程序会打印出来,或者用len(bwm.wm_bit)顺手取到。

用 Python 写也差不多,最小版本长这样:

from blind_watermark import WaterMark bwm = WaterMark(password_img=1, password_wm=1) bwm.read_img('examples/pic/ori_img.jpeg') bwm.read_wm('@yourname', mode='str') bwm.embed('output/embedded.png')
bwm1 = WaterMark(password_img=1, password_wm=1) wm = bwm1.extract('output/embedded.png', wm_shape=len(bwm.wm_bit), mode='str') print(wm) # @yourname

跑完把两张图放在一起对比——肉眼看不出差别,这才是盲水印该有的样子:

原图嵌入盲水印后

藏什么:按使用场景选模式

它支持三种嵌入方式,各管各的活,按自己的场景挑就行。

个人作品署名的,选文本模式

最常见的需求就是把名字、账号或者一句话留在图里。mode='str'直接传字符串,一条命令搞定:

blind_watermark --embed --pwd 1234 your.jpg "© YourName" out.jpg

短文案完全够用,提取也最省事,适合摄影师、博客作者这类给个人作品署名的场景。

要嵌 Logo 或二维码的,选图片模式

品牌方想埋的往往是一个小 Logo 或者二维码图片。这时水印就按整张图处理,read_wm直接给水印图路径,不用传 mode;提取时要额外告诉它水印的高宽,以及把结果存到哪:

bwm.read_wm('logo.png') bwm.embed('out.jpg') # 提取时 wm_shape 是 logo 的 (高, 宽) bwm1.extract('out.jpg', wm_shape=(64, 64), out_wm_name='extracted.png')

完整可跑的版本在 example_img.py。

藏流水号、数字指纹的,选二进制模式

开发者还有另一类玩法:给每张图绑定一个流水号、订单号或指纹位串,将来图片外泄了,能查出来是哪一批、哪个渠道出去的。mode='bit'就是一串 0/1:

bwm.read_wm([True, False, True, False] * 50, mode='bit') bwm.embed('out.jpg')

提取回来是一组浮点数,按 0.5 划阈值就能还原成 0/1。能编码成比特的东西都能塞进去,灵活性最高。

三种模式的完整示例都在 examples/ 目录下,每个模式一份脚本,照抄就能跑。

旋转、裁剪、遮挡之后还能捞回来吗

这才是盲水印好不好用的分水岭。图片在传播中免不了被缩放、被裁、被截图,水印如果一次处理就失效,那就只是装饰。项目示例里真的跑了一轮攻击测试,效果如下:

攻击攻击后的图从攻击后的图里提取的水印
旋转 45°
60 处随机遮挡
缩放到 400×300

三次的提取结果都和嵌入时完全一致。实践上还有两点经验:

  • 旋转、缩放这类攻击,提取前通常先做一次"反向操作"(转回来、拉回原分辨率),命中率更高,att.py 里有现成的工具函数。
  • 截图和裁剪是最麻烦的,图变小了、位置也跑了。recover.py 能推断出裁剪参数、把图先还原回原始尺寸再提取,完整流程见 example_str.py。

需要提醒一句:这些测试图都是先压成 JPG 再处理的,已经比较贴近真实传播环境。但别指望百战百胜——图被切成一小块、再经过多轮重度压缩,任何方案都会更吃力。

一页选型速查

你要干什么模式水印内容提取时要记住什么
署名、嵌联系方式str几个字到一句话文本的比特长度
嵌 Logo、二维码img一张小图图片高宽 + 输出文件名
流水号、指纹、自定义数据bit一串 0/1比特个数
要扛旋转、裁剪、遮挡上面任意同上相同口令;裁剪场景还要原图尺寸

想快速体验就从文本模式开始;要上线使用,建议先拿自己业务里真实的图片质量(压缩后的、缩略图尺寸的)跑一遍攻击示例,确认提取还稳不稳,再铺开。

就到这里

blind_watermark 体量小,个人装完敲几条命令就能用,开发场景接WaterMark这个类即可。细节可以翻 docs/ 里的文档,或者通读一遍 bwm_core.py,核心算法不长,读下来心里就有底了。

【免费下载链接】blind_watermarkBlind&Invisible Watermark ,图片盲水印,提取水印无须原图!项目地址: https://gitcode.com/GitHub_Trending/bl/blind_watermark

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询