前言
好不容易拍到一张满意的照片,回去又花时间修图、调色,发布出去没几天,却在别人的内容里看到了同一张图。角落里的署名已经被裁掉,图片也重新压缩过,单看现在这张成品,几乎找不到原作者留下的痕迹。
给图片铺上醒目的水印当然可以,但画面也会受到影响;只在角落放一个,又经不住简单的裁剪。那么,有没有一种水印,平时看不见,需要时却能从图片里重新读出来?GitHub 上有一个叫做 blind-watermark 的开源项目,做的正是这件事:把文字悄悄藏进图片里,肉眼基本看不出变化。
不过,原项目主要通过 Python 代码操作,对不熟悉命令行的用户来说并不方便。watermark-webui 在它的基础上增加了浏览器操作界面,并加入水印嵌入、提取和历史记录等功能,既可以直接运行在电脑上,也可以通过 Docker 部署到 NAS。图片、处理结果和操作记录都会保存在自己的设备中。
接下来就用一张图片实际测试一下,看看隐藏水印怎样添加和提取,处理前后的画面有什么区别,以及相关参数应该如何保存。
1 项目介绍
项目地址:https://github.com/JunWan666/watermark-webui
上游项目:https://github.com/guofei9987/blind_watermark
watermark-webui 是基于开源项目 blind-watermark 开发的可视化盲水印工具。它不会像普通水印一样,直接在图片表面叠加文字或 Logo,而是将指定内容隐藏在图片数据中。处理前后对比时,肉眼通常很难察觉画面发生了变化。
需要验证图片时,只要提供对应的水印长度和密码,就可以尝试将隐藏内容重新提取出来。水印文字可以是作者名称、联系方式、作品编号,也可以是一段用于识别图片来源的专属标记。
1.1 隐藏水印是怎样写进图片的
blind-watermark 使用了小波变换、离散余弦变换和奇异值分解等方式,将水印内容转换成二进制数据,再分散写入图片的不同区域。
可以简单理解为:普通水印是把名字直接写在图片上,而盲水印是把名字拆开,藏进图片内部。正常查看图片时看不到这些内容,只有使用正确的参数进行提取,才能将其重新组合出来。
嵌入水印时会生成一个重要参数 wm_shape,它表示水印转换成二进制数据后的长度,并不是图片的宽度或高度。后续提取时,wm_shape、图片密码和水印密码都需要与嵌入时保持一致,否则可能无法识别,或者提取出乱码。
1.2 watermark-webui介绍
blind-watermark 本身更像一个提供给开发者使用的 Python 工具,官方示例主要通过代码完成图片读取、水印嵌入和提取。watermark-webui 保留了原来的核心算法,同时将常用操作放进浏览器界面,不需要手动编写 Python 代码。
目前主要包含以下功能:
| 功能 | 说明 |
|---|---|
| 水印嵌入 | 上传图片并输入水印文字,生成带有隐藏水印的新图片 |
| 普通提取 | 通过 wm_shape 和密码,从图片中读取水印文字 |
| 恢复提取 | 借助完整水印参考图,对部分经过裁剪、缩放的图片进行恢复后提取 |
| 历史记录 | 保存每次嵌入和提取记录,方便重新查看图片及相关参数 |
| 本地存储 | 上传图片、生成结果和操作记录均保存在自己的设备中 |
| Docker 部署 | 可以部署在电脑或 NAS 上,通过浏览器完成操作 |
在实际使用时,只需要上传一张图片,填写准备隐藏的文字和密码,就可以生成新的水印图片。系统还会记录对应的 wm_shape,以后需要验证时,可以直接从历史记录中找到相关参数,不必每次单独保存。
相比直接使用命令行,这种方式操作更加直观,也方便统一管理生成过的图片。下面先将 watermark-webui 部署起来,再使用同一张图片分别测试水印嵌入、普通提取以及不同处理后的识别效果。
2 使用 Docker 部署 watermark-webui
watermark-webui 可以直接运行在电脑上,不过这类工具并不是只用一次就结束,后续还需要保存原图、水印图片、提取参数和历史记录,因此更适合部署在长期运行的 NAS 上。
项目提供的 Docker 镜像同时支持 amd64 和 arm64 架构,可以运行在飞牛 NAS、群晖 NAS、绿联 NAS 以及安装了 Docker 的电脑上。下面以飞牛 NAS 为例进行部署。
首先在飞牛 NAS 桌面打开 Docker,确认 Docker 服务已经正常启动:
接着,来到镜像仓库,搜索如下镜像名称:
tannic666/watermark-webui
镜像标签选择默认的【latest】即可,接着回到本地镜像页面,等待镜像下载完成,点击右侧的按钮进行创建容器,然后选择开机自动开启勾选上,点击下一步:
点击创建容器,然后回到容器页面,鼠标上移到刚才创建的容器右边链接按钮上,点击8655端口:
点击后,浏览器会跳转到该容器项目watermark的对应页面,如下图:

到这里,watermark-webui 就已经部署完成。相比直接运行 Python 代码,Docker 版本不需要单独安装算法依赖;图片、提取参数和历史记录也可以集中保存在 NAS 中,后面在局域网内的其他电脑或手机上打开浏览器就能使用。
3 给图片添加并提取隐藏水印
项目部署完成后,接下来实际体验一下水印的嵌入和提取。这里准备一张测试图片,在不影响正常观看的情况下写入一段文字水印,再看看处理前后的图片有什么区别。后面的压缩和裁剪测试也会继续使用这张图片。
3.1 给图片嵌入水印
进入 watermark-webui 首页,打开“水印嵌入”页面,然后上传一张需要添加水印的图片。
这次测试使用的是一张 PNG 图片,分辨率为 1254 × 1254,文件大小为 2.09 MB。为了方便演示,水印文字、图片密码和水印密码均保留页面默认填写的内容:
| 参数 | 本次使用 | 作用 |
|---|---|---|
| 水印文字 | © 苏苏 2026 |
实际隐藏在图片中的文字 |
| 图片密码 | 1234 |
控制图片数据的排列方式 |
| 水印密码 | 1234 |
控制水印数据的编码方式 |
两组密码不一定要设置成相同的值,但后续提取时必须与嵌入时完全一致。正式处理自己的作品时,可以将水印文字换成作者名称、年份或作品编号,两组密码也建议换成自己设置的数字。
填写完成后,点击“嵌入水印”按钮:
稍等片刻,页面会生成一张带有隐藏水印的新图片,同时显示对应的 wm_shape值。wm_shape 并不是图片的宽度或高度,而是水印文字转换成二进制数据后的长度。后面提取水印时,除了两组密码,还需要填写这个数值。
可以看到,本次生成的水印长度为:
wm_shape = 112
点击【下载 PNG】按钮可将处理后的图片保存到本地。旁边还提供了【复制 wm_shape】钮,可以直接复制数值,避免手动输入出错。
3.2 对比添加水印前后的图片
将原图和生成后的水印图放在一起观察,正常尺寸下很难看出两者之间的区别。图片中的人物、颜色和背景细节没有出现明显的文字或 Logo,水印也不会像普通可见水印一样遮挡画面:
将图片放大后,部分绿色虚化区域可以看到一些非常轻微的纹理变化,但正常浏览时并不明显,也不会像普通可见水印一样遮挡画面。
本次处理前后的文件信息如下:
| 图片 | 格式 | 分辨率 | 文件大小 |
|---|---|---|---|
| 原始图片 | PNG | 1254 x 1254 | 2.09MB |
| 水印图片 | PNG | 1254 x 1254 | 2.40MB |
图片分辨率没有发生变化,文件大小由 2.09 MB 增加到了 2.40 MB,增加约 0.31 MB。本次原图本身就是 PNG,因此体积变化不算明显;如果上传的是经过压缩的 JPG,由于生成结果会保存为 PNG,文件体积可能增加得更多。
确认画面正常后,后续发布到网站或内容平台时,应使用下载得到的水印图,而不是最初上传的原图。
3.3 提取隐藏水印
提取页面需要填写水印长度、图片密码和水印密码。这里继续使用嵌入时生成和填写的参数:
| 参数 | 填写内容 |
|---|---|
| 水印长度 | 112 |
| 图片密码 | 1234 |
| 水印密码 | 1234 |
填写完成后,点击【开始提取】按钮,稍等片刻,右侧的【识别文字】区域便会显示提取结果:
这里最容易填错的是水印长度。本次应该填写的是
112,也就是wm_shape值。图片密码和水印密码也必须沿用嵌入时的数值,只要其中一项填写错误,就可能出现乱码或者无法得到正确的水印文字。
可以看到,提取出的文字与嵌入时填写的内容完全一致,说明隐藏水印已经成功写入图片。
3.4 查看和管理处理记录
每次完成水印嵌入或提取后,watermark-webui 都会自动生成一条处理记录。点击左侧的【记录】页,就能看到刚才完成的两次操作:

嵌入和提取记录会分开标注,并显示原始文件名、水印文字、处理时间、wm_shape、图片尺寸和文件大小。右侧还可以直接下载原图、生成的水印图或者提取出的水印内容。
如果后面保存的图片比较多,可以通过顶部的搜索框查找文件名、备注、水印文字或 wm_shape,也可以按照【嵌入水印】和 【提取水印】筛选记录。
如点击嵌入水印记录右侧的【详情】,可以继续查看这次操作使用的完整参数:
详情页面中会显示原图、水印内容、wm_shape、图片密码、水印密码以及处理前后的文件信息,还可以为这条记录补充备注。例如,可以写明图片发布的平台、文章名称或作品编号,后面查找时会方便很多。
提取水印的记录详情与嵌入记录略有不同。左侧显示本次上传的待提取图片,右侧则保存从图片中识别出来的水印内容,同时还会记录提取时使用的 wm_shape、图片密码和水印密码:

到这里,图片嵌入、隐藏水印提取和记录管理都已经可以正常使用了。
4 远程访问
目前访问的还是 NAS 局域网地址。离开家里或公司网络后,手机或电脑就打不开这个服务了,遇到疑似被转载的图片时,也就没法随时查看记录或提取水印分辨。
要解决这个问题,通常有三种选择:
- 申请公网 IP + 端口映射:需要向运营商申请公网 IP,再配置路由器端口转发和 DDNS,流程繁琐,且很多地区根本申请不到。
- 自建 frp 内网穿透:需要自己购买一台有公网 IP 的云服务器,部署服务端和客户端,维护成本高,月租至少几十元起。
- 使用现成的内网穿透服务(如 cpolar):无需公网 IP,无需云服务器,也不用配置路由器。在 NAS 上安装客户端,执行一条命令即可创建隧道,获得公网访问地址。
三者对比下来,cpolar 最适合当前的场景——省去了所有网络层的折腾,免费版足够临时查看(域名每 24 小时变化),如果觉得频繁换域名麻烦,基础版每年 99 元,平均每月不到 9 块钱,就能保留自定义二级子域名,带宽也更高。安装配置完成后,出门在外打开那个地址,就能像在家里一样访问 NAS 上的服务了。
4.1 安装cpolar
在系统设置中打开ssh功能,然后使用ssh命令,连接进入飞牛NAS的终端:
ssh 飞牛用户名@你的Nas系统IP地址
进入终端中后输入如下命令,一键安装cpolar:
sudo curl https://get.cpolar.sh | sh
安装完成后,执行下方命令查看cpolar服务状态:(如图所示即为正常启动)
sudo systemctl status cpolar
接着,在浏览器中输入飞牛NAS的IP地址+9200端口访问 web ui管理界面,如:
http://192.168.50.212:9200/
如果还没有账号,可以点击页面上的免费注册,进行注册账号。输入注册好的账号登录即可进入后台页面:
4.2 穿透watermark-webui
点击左侧菜单栏的【隧道管理】的【创建隧道】,进入创建隧道页面,隧道名称可以自定义,本地地址填写watermark的访问端口,然后点击创建:
接着,来到状态下的在线隧道列表,可以看到同一隧道2条不同协议的公网地址:
复制其中的公网地址,在浏览器中进行访问,以https为例:
可以看到,浏览器地址栏中已经不再是 NAS 的局域网地址,而是 cpolar 生成的公网域名。此时,即使手机或电脑没有连接家中的网络,也可以通过该地址打开 watermark-webui,登录后查看历史记录,或者上传图片提取隐藏水印。至此,watermark-webui 的远程访问就配置完成了。
免费版提供的是随机公网地址,适合偶尔在外临时使用,不过地址会定期变化。如果只是临时查看,免费版基本够用;如果希望长期使用固定地址,可以再按需选择支持固定二级子域名的套餐即可。固定二级子域名的教程可以参考:
https://www.cpolar.com/blog/secondary-subdomain-name
需要注意的是,创建隧道后,watermark-webui 的登录入口已经可以从公网访问。建议设置独立的高强度登录密码,不要随意公开访问地址;平时没有远程访问需求时,也可以暂时关闭隧道。
总结
watermark-webui 将 blind-watermark 原本需要通过 Python 完成的操作放进了浏览器中。水印嵌入、提取和历史记录管理都可以在同一界面完成,部署到 NAS 后,家中的电脑和手机也能共同使用。对于经常发布原创照片、插画或设计素材的用户来说,它提供了一种不遮挡画面的来源标记方式。
- 嵌入后的水印肉眼通常难以察觉,不会像普通文字水印一样遮挡画面;
- 后续提取需要保存对应的
wm_shape、图片密码和水印密码,缺少或填错任一项都可能无法识别; - 图片经过压缩、缩放、裁剪或截图后能否继续提取,与处理强度、图片内容和提取方式有关,并不能保证每次都成功。
因此,盲水印更适合作为图片来源识别和版权追溯的辅助线索,而不是唯一证据。原始图片、编辑工程、拍摄信息和首次发布时间等材料仍然需要妥善保存。将工具部署在 NAS 并做好数据持久化后,日常添加水印和后续核验都会方便不少;远程访问则根据自己的实际需求开启即可。
感谢您阅读本篇文章,有任何问题欢迎留言交流。cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站
























