blind_watermark 是一个基于 DWT-DCT-SVD 算法的图片盲水印 Python 库。其核心特点是提取水印时无需原始图片,且嵌入的水印对人类视觉不可见,能抵抗旋转、裁剪、噪声等多种攻击。本教程将引导你完成从安装到实际使用的全过程。


一、准备工作

1.1 环境要求

  • Python 版本:3.6 及以上
  • 操作系统:Windows / macOS / Linux

1.2 安装方式

方式一:通过 pip 安装(推荐)

1
pip install blind-watermark

方式二:安装最新开发版(从源码安装)

1
2
3
git clone git@github.com:guofei9987/blind_watermark.git
cd blind_watermark
pip install .

二、命令行快速上手(Bash 用法)

如果你希望快速体验,可以直接在终端使用命令行工具。

嵌入水印

1
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png

提取水印

1
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png

三、Python 项目集成(核心用法)

3.1 嵌入文本水印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from blind_watermark import WaterMark

# 1. 初始化,设置密码
bwm = WaterMark(password_img=1, password_wm=1)

# 2. 读取原始图片
bwm.read_img('path/to/your/ori_img.jpg')

# 3. 读取水印文本(支持中文)
wm_text = '@guofei9987 开源万岁!'
bwm.read_wm(wm_text, mode='str')

# 4. 嵌入水印并保存
bwm.embed('output/embedded.png')

# 5. 记录水印长度,用于后续提取
len_wm = len(bwm.wm_bit)
print(f'请记录水印长度: {len_wm}')

3.2 提取文本水印(无需原图)

1
2
3
4
5
6
7
8
9
from blind_watermark import WaterMark

# 1. 使用相同的密码初始化
bwm = WaterMark(password_img=1, password_wm=1)

# 2. 从已嵌入水印的图片中提取
# 注意:wm_shape 必须与嵌入时的长度一致
wm_extract = bwm.extract('output/embedded.png', wm_shape=len_wm, mode='str')
print(f'提取的水印: {wm_extract}')

输出示例

1
@guofei9987 开源万岁!

3.3 嵌入图片水印

除了文本,你也可以将一张图片作为水印嵌入到另一张图片中。

嵌入流程

1
2
3
4
5
6
from blind_watermark import WaterMark

bwm = WaterMark(password_wm=1, password_img=1)
bwm.read_img('path/to/background.jpg') # 背景图
bwm.read_wm('path/to/watermark_logo.png') # 水印图(建议尺寸小于背景图)
bwm.embed('output/embedded_with_logo.png')

提取流程

1
2
3
4
5
6
7
bwm = WaterMark(password_wm=1, password_img=1)
# 提取时需指定水印图片的形状,并保存提取结果
bwm.extract(
filename='output/embedded_with_logo.png',
wm_shape=(128, 128), # 必须与嵌入时水印图的尺寸一致
out_wm_name='output/extracted_logo.png'
)

3.4 嵌入比特数组

如果需要嵌入自定义二进制数据,可以使用 mode='bit'

1
2
3
4
5
6
7
8
# 嵌入
wm_bits = [True, False, True, True, True, False]
bwm.read_wm(wm_bits, mode='bit')
bwm.embed('output/embedded_bit.png')

# 提取(注意:提取结果是一个浮点数数组,需要设定阈值如0.5来判定)
wm_extract = bwm.extract('output/embedded_bit.png', wm_shape=6, mode='bit')
print([1 if x > 0.5 else 0 for x in wm_extract])

四、高级功能与优化

4.1 提高并发处理速度

在处理大量图片或高分辨率图片时,可以启用多进程加速。

1
2
3
4
5
from blind_watermark import WaterMark

# processes=None 表示使用所有CPU核心,也可指定具体数字
bwm = WaterMark(password_img=1, password_wm=1, processes=4)
# ... 后续操作不变

4.2 鲁棒性测试

该算法对多种图像处理攻击具有较好的抵抗能力。根据项目文档和同类技术原理,以下攻击后仍能有效提取水印:

攻击方式 提取结果示例
旋转 45 度 可完整提取
随机裁剪 可完整提取
添加椒盐噪声 可完整提取
亮度降低 10% 可完整提取
调整尺寸(Resize) 可完整提取

五、常见问题与参数说明

Q1: 提取时提示 wm_shape 错误怎么办?

  • 原因wm_shape 是提取水印时的必需参数,必须与嵌入时 len(bwm.wm_bit) 的值完全一致。
  • 解决:在嵌入水印后立即打印并记录 len_wm,提取时传入该值。

Q2: 如何选择密码?

  • password_imgpassword_wm 是用于增强安全性的密钥,提取时必须使用相同的密码组合。

Q3: 提取的文本水印为什么是乱码?

  • 检查提取时使用的 mode'str')和 wm_shape 是否正确,并确认密码与嵌入时一致。

六、最小化部署清单

用途 命令/代码 说明
安装 pip install blind-watermark 基础依赖
嵌入文本水印 使用 WaterMark 需准备原图和水印文本
嵌入图片水印 使用 WaterMark 需准备背景图和水印图
提取水印 调用 extract() 方法 必须记住 wm_shape
提升性能 设置 processes 参数 充分利用多核CPU
官方文档 https://BlindWatermark.github.io/blind_watermark/ 获取最新更新和高级用法

总结

通过以上步骤,你已经掌握了 blind_watermark 的完整部署与使用方法。该工具的核心优势在于提取时不依赖原始图像,使其非常适用于版权追踪、内容认证等场景。

下一步建议:尝试将其集成到你的图片处理流程中,或结合 prometheus 等监控工具,对批量嵌入任务进行性能监控。

如果你在部署中遇到其他问题,可以随时查阅其官方文档或在GitHub仓库中提交Issue。