提取时必须提供 wm_shape(水印形状/长度),否则无法还原;嵌入与提取需使用相同的 password_img 和 password_wm;比特模式提取结果是浮点数组,需自行设阈值(如 0.5)判定
blind_watermark
guofei9987MIT更新放缓给图片嵌入肉眼不可见的盲水印,提取时不需要原图,适合版权追踪和泄露溯源。
Blind&Invisible Watermark ,图片盲水印,提取水印无须原图!
0.2.1发布于 2022-01-11 12:32 UTC14,845star +4 / 7 天1,448fork同步于 2026-11-10 17:26 UTC
pip install blind-watermark 硬件要求按 README 说明
README 未说明,仅标注支持 Windows、Linux、macOS,未提及 GPU 或显存要求
支持 Apple Silicon
基于 DWT-DCT-SVD 的图片盲水印工具,提取水印无需原图
给图片嵌入肉眼不可见的盲水印,提取时不需要原图,适合版权追踪和泄露溯源。
核心能力
- 用 DWT-DCT-SVD 变换把水印嵌入图片频域
- 提取水印时无需原图,只需密码与水印形状
- 支持字符串、图片、比特数组三种水印载体
- 可抵抗旋转、裁剪、遮挡、缩放、椒盐噪声等攻击
- 支持多进程并发处理,processes 参数可调
容易踩的坑
内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README
- 0.2.1version 0.2.1最新正式版2022-01-11 · 2022-01-11 12:32 UTC
- highly enhanced the performance against attacks
- 0.0.5Version 0.0.52020-08-17 · 2020-08-17 15:13 UTC
查看更新说明
pypi: correct the long_description.
- 0.0.2Version 0.0.22020-08-17 · 2020-08-17 13:39 UTC
查看更新说明
Add English Documents.
- 0.0.1Version 0.0.12020-08-13 · 2020-08-13 16:01 UTC
查看更新说明
first lines
用户点评
登录用户的真实使用记录,可按版本和硬件筛选共 0 条
还没有人点评。第一个说出真实体验的人最有价值。
blind-watermark
Blind watermark based on DWT-DCT-SVD.
- Documentation: https://BlindWatermark.github.io/blind_watermark/#/en/
- 文档: https://BlindWatermark.github.io/blind_watermark/#/zh/
- 中文 readme README_cn.md
- Source code: https://github.com/guofei9987/blind_watermark
install
pip install blind-watermark
For the current developer version:
git clone [email protected]:guofei9987/blind_watermark.git
cd blind_watermark
pip install .
How to use
Use in bash
# embed watermark into image:
blind_watermark --embed --pwd 1234 examples/pic/ori_img.jpeg "watermark text" examples/output/embedded.png
# extract watermark from image:
blind_watermark --extract --pwd 1234 --wm_shape 111 examples/output/embedded.png
Use in Python
Original Image + Watermark = Watermarked Image
+ '@guofei9987 开源万岁!' = 
See the codes
Embed watermark:
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_img('pic/ori_img.jpg')
wm = '@guofei9987 开源万岁!'
bwm1.read_wm(wm, mode='str')
bwm1.embed('output/embedded.png')
len_wm = len(bwm1.wm_bit)
print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))
Extract watermark:
bwm1 = WaterMark(password_img=1, password_wm=1)
wm_extract = bwm1.extract('output/embedded.png', wm_shape=len_wm, mode='str')
print(wm_extract)
Output:
@guofei9987 开源万岁!
attacks on Watermarked Image
| attack method | image after attack | extracted watermark |
|---|---|---|
| Rotate 45 Degrees | ![]() | '@guofei9987 开源万岁!' |
| Random crop | ![]() | '@guofei9987 开源万岁!' |
| Masks | ![]() | '@guofei9987 开源万岁!' |
| Vertical cut | ![]() | '@guofei9987 开源万岁!' |
| Horizontal cut | ![]() | '@guofei9987 开源万岁!' |
| Resize | ![]() | '@guofei9987 开源万岁!' |
| Pepper Noise | ![]() | '@guofei9987 开源万岁!' |
| Brightness 10% Down | ![]() | '@guofei9987 开源万岁!' |
embed images
embed watermark:
from blind_watermark import WaterMark
bwm1 = WaterMark(password_wm=1, password_img=1)
# read original image
bwm1.read_img('pic/ori_img.jpg')
# read watermark
bwm1.read_wm('pic/watermark.png')
# embed
bwm1.embed('output/embedded.png')
Extract watermark:
bwm1 = WaterMark(password_wm=1, password_img=1)
# notice that wm_shape is necessary
bwm1.extract(filename='output/embedded.png', wm_shape=(128, 128), out_wm_name='output/extracted.png', )
| attack method | image after attack | extracted watermark |
|---|---|---|
| Rotate 45 Degrees | ![]() | ![]() |
| Random crop | ![]() | ![]() |
| Mask | ![]() | ![]() |
embed array of bits
See it here
As demo, we embed 6 bytes data:
wm = [True, False, True, True, True, False]
Embed:
from blind_watermark import WaterMark
bwm1 = WaterMark(password_img=1, password_wm=1)
bwm1.read_ori_img('pic/ori_img.jpg')
bwm1.read_wm([True, False, True, True, True, False], mode='bit')
bwm1.embed('output/embedded.png')
Extract:
bwm1 = WaterMark(password_img=1, password_wm=1, wm_shape=6)
wm_extract = bwm1.extract('output/打上水印的图.png', mode='bit')
print(wm_extract)
Notice that wm_shape (shape of watermark) is necessary
The output wm_extract is an array of float. set a threshold such as 0.5.
Concurrency
WaterMark(..., processes=None)
processesnumber of processes, can be integer. DefaultNone, which means using all processes.
Related Project
- text_blind_watermark (Embed message into text): https://github.com/guofei9987/text_blind_watermark
- HideInfo(hide as image, hide as sounds, hide as text):https://github.com/guofei9987/HideInfo









