GameMale
登陆 / 注册 搜索

USERCENTER

SEARCHSITE

搜索

查看: 861|回复: 26
收起左侧

[实用工具] 【异界方块】Blind Watermark 图片盲水印,提取水印无须原图!

[复制链接] |关注本帖

果体76虚空之海的鲸『伊黎丝的赞美词』『不败之花』失窃『冰雕马拉橇』Amicus巴比伦辞典

     楼主| 相见忧 发表于 3 天前 | 显示全部楼层 |阅读模式 <

    利用 blind-watermark 为图片批量添加与提取盲水印(Python 教程)

    本教程基于 GitHub 开源项目 blind-watermark,支持单张及批量图片的盲水印嵌入与提取,水印内容为字符串或图片,本篇教程只讲字符串。盲水印的特点是人眼不可见、鲁棒性强,即使图片经过裁剪、压缩等处理,仍有可能成功提取。
    项目地址:blind-watermark


    1.环境准备
    编译器:任意支持 Python 的环境(如 PyCharm、VS Code)
    Python 版本:3.6 及以上
    依赖安装:在终端中执行以下命令
    1. pip install blind-watermark
    复制代码
    项目结构:新建一个空文件夹,在其中创建以下目录
    1. mkdir pic      # 存放原始图片
    2. mkdir output   # 存放加水印后的图片
    复制代码
    最终的项目结构示例:
    your_project/

    ├── pic/               # 原始图片
    ├── output/            # 水印图片
    ├── embed.py           # 单张嵌入脚本
    ├── extract.py         # 单张提取脚本
    ├── batch_embed.py     # 批量嵌入脚本
    ├── batch_extract.py   # 批量提取脚本
    └── ...


    2. 单张图片:添加与提取水印
    2.1 创建脚本文件
    新建 embed.py 和 extract.py 两个文件。
    2.2 嵌入水印代码(embed.py)
    1. from blind_watermark import WaterMark
    2. import os

    3. # 确保输出文件夹存在
    4. os.makedirs('output', exist_ok=True)

    5. # 创建水印对象
    6. bwm = WaterMark(password_img=1, password_wm=1)

    7. # 读取原始图片(你需要先放一张图片到 pic 文件夹)
    8. bwm.read_img('pic/0001.jpg')

    9. # 水印内容
    10. wm = '这只是一个测试!'
    11. bwm.read_wm(wm, mode='str')

    12. # 嵌入水印
    13. bwm.embed('output/embedded.png')

    14. # 获取水印长度(提取时需要)
    15. len_wm = len(bwm.wm_bit)
    16. print(f'水印嵌入成功!')
    17. print(f'水印长度: {len_wm}')
    18. print(f'输出文件: output/embedded.png')

    19. # 保存水印长度供后续使用
    20. with open('watermark_length.txt', 'w') as f:
    21. f.write(str(len_wm))
    复制代码
    2.3 提取水印代码(extract.py)
    1. from blind_watermark import WaterMark

    2. # 读取之前保存的水印长度
    3. try:
    4. with open('watermark_length.txt', 'r') as f:
    5. len_wm = int(f.read())
    6. except FileNotFoundError:
    7. print("找不到 watermark_length.txt,请先运行 embed.py")
    8. exit(1)

    9. # 创建水印对象(使用相同密码)
    10. bwm = WaterMark(password_img=1, password_wm=1)

    11. # 提取水印
    12. wm_extract = bwm.extract('output/embedded.png', wm_shape=len_wm, mode='str')
    13. print(f'提取出的水印: {wm_extract}')
    复制代码
    运行效果示例:




    3. 多张图片:添加与提取水印
    3.1 创建脚本文件
    新建 batch_embed.py 和 batch_extract.py
    3.2 批量嵌入代码(batch_embed.py)
    1. from blind_watermark import WaterMark
    2. import glob
    3. import os

    4. # 配置
    5. PASSWORD_IMG = 1
    6. PASSWORD_WM = 1
    7. WATERMARK_TEXT = '这只是一个测试!'
    8. INPUT_FOLDER = 'pic/'
    9. OUTPUT_FOLDER = 'output/'

    10. # 确保输出文件夹存在
    11. os.makedirs(OUTPUT_FOLDER, exist_ok=True)

    12. # 支持的图片格式
    13. image_files = []
    14. for ext in ['*.jpg', '*.jpeg', '*.png', '*.bmp']:
    15. image_files.extend(glob.glob(f'{INPUT_FOLDER}{ext}'))

    16. print(f"找到 {len(image_files)} 张图片")

    17. # 记录所有水印信息
    18. all_info = {}

    19. for i, img_path in enumerate(image_files, 1):
    20. basename = os.path.basename(img_path)
    21. name, ext = os.path.splitext(basename)
    22. output_path = f'{OUTPUT_FOLDER}{name}{ext}'

    23. # 嵌入水印
    24. bwm = WaterMark(password_img=PASSWORD_IMG, password_wm=PASSWORD_WM)
    25. bwm.read_img(img_path)
    26. bwm.read_wm(WATERMARK_TEXT, mode='str')
    27. bwm.embed(output_path)

    28. len_wm = len(bwm.wm_bit)
    29. all_info[output_path] = len_wm

    30. print(f"[{i}/{len(image_files)}]  {basename} -> {output_path} (长度: {len_wm})")

    31. # 保存所有水印信息
    32. with open(f'{OUTPUT_FOLDER}watermark_info.txt', 'w', encoding='utf-8') as f:
    33. for output_path, length in all_info.items():
    34. f.write(f"{output_path}: {length}\n")

    35. print(f"\n 批量处理完成!共处理 {len(image_files)} 张图片")
    复制代码
    3.3 批量提取代码(batch_extract.py)
    1. from blind_watermark import WaterMark
    2. from blind_watermark import bw_notes
    3. import warnings
    4. import glob
    5. import os

    6. # 关闭欢迎信息和警告
    7. bw_notes.close()
    8. warnings.filterwarnings('ignore')

    9. # 配置
    10. PASSWORD_IMG = 1
    11. PASSWORD_WM = 1
    12. INPUT_FOLDER = 'output/' # 带水印的图片所在文件夹
    13. OUTPUT_INFO_FILE = 'output/watermark_info.txt' # 之前保存的水印信息文件

    14. # 读取水印信息(文件名 -> 水印长度)
    15. watermark_lengths = {}
    16. with open(OUTPUT_INFO_FILE, 'r', encoding='utf-8') as f:
    17. for line in f:
    18. if ': ' in line:
    19. file_path, length = line.strip().split(': ')
    20. # 只取文件名(不含路径)
    21. filename = os.path.basename(file_path)
    22. watermark_lengths[filename] = int(length)

    23. print(f"读取到 {len(watermark_lengths)} 条水印信息")
    24. print(f"水印信息文件列表: {list(watermark_lengths.keys())}")

    25. # 获取所有带水印的图片
    26. watermarked_images = []
    27. for ext in ['*.jpg', '*.jpeg', '*.png', '*.bmp']:
    28. watermarked_images.extend(glob.glob(f'{INPUT_FOLDER}{ext}'))

    29. print(f"找到 {len(watermarked_images)} 张带水印的图片")
    30. print(f"图片文件列表: {[os.path.basename(f) for f in watermarked_images]}")
    31. print("=" * 60)

    32. # 批量提取水印
    33. success_count = 0
    34. for img_path in watermarked_images:
    35. basename = os.path.basename(img_path)

    36. # 检查是否有对应的水印长度信息
    37. if basename not in watermark_lengths:
    38. print(f" {basename} - 找不到水印长度信息,跳过")
    39. continue

    40. len_wm = watermark_lengths[basename]

    41. # 提取水印
    42. bwm = WaterMark(password_img=PASSWORD_IMG, password_wm=PASSWORD_WM)
    43. try:
    44. wm_extract = bwm.extract(img_path, wm_shape=len_wm, mode='str')
    45. print(f" {basename} -> 提取水印: {wm_extract}")
    46. success_count += 1
    47. except Exception as e:
    48. print(f" {basename} - 提取失败: {e}")

    49. print(f"\n 批量提取完成!成功提取 {success_count}/{len(watermarked_images)} 张图片的水印")
    复制代码
    运行效果示例:



    若图片内容为空白(图中第二张)(如纯色或无效图像数据),水印将无法被正确识别或提取。

    4. 注意事项
    密码一致:嵌入和提取时使用的 password_img 和 password_wm 必须相同,否则无法正确提取。
    水印长度:提取时需要知道水印的二进制长度,脚本中已通过文件保存,请勿删除。
    水印内容:支持字符串、二进制等多种模式,本教程以字符串为例。

    来自群组: 小浣熊饲养中心

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x

    评分

    参与人数 1血液 +4 追随 +1 收起 理由
    ditto + 4 + 1

    查看全部评分

    回复

    使用道具 举报

    【新手友好】昆進牧羊人GM論壇初心者勛章炼金之心失效的魔仙棒小凤凰

      RaphaelJC 发表于 3 天前 | 显示全部楼层 <
      回复

      使用道具 举报

        商人弗霖 发表于 3 天前 | 显示全部楼层 <
        商人弗霖打开异界的百宝袋,袋口微光一闪,一枚【紫色方块】轻巧地蹦了出来。
        回复

        使用道具 举报

        炉石与家法师I· 学识之章盈满心相元石『召唤好运的角笛』鎏彩万幢男巫之歌女巫之路虚空之海的鲸業火死鬥实现梦想

          娱乐法师火布偶 发表于 3 天前 | 显示全部楼层 <
          回复

          使用道具 举报

          猫咪点唱机夜魔护符霉运小精灵[红]暗蚀魔典吃饱金币的Doge四季如旧堕落飞升!荣光的残像♬狂舞终乐章♬丹雀衔五穗,人间始丰登

            小蓝龙泷泽 发表于 3 天前 | 显示全部楼层 <
            回复

            使用道具 举报

            喜欢金币的Doge夜魔藤敖蜃星丹妮莉丝·坦格利安史莱姆牧场结晶火鹰幼崽猩红魔鹫紫粹露饮

              Adam123456 发表于 3 天前 | 显示全部楼层 <
              回复

              使用道具 举报

              人到中年裸体克里斯『落樱缤纷』【新春限定】果体 隆『原味焦糖』内森·德雷克『伊黎丝的赞美词』隐秘的讯息纯真护剑㊕凯登‧阿兰科

                Se7en 发表于 3 天前 | 显示全部楼层 <
                回复

                使用道具 举报

                【夏日限定】夏日的泰凯斯裸体克里斯霉运小精灵[红]圣甲虫秘典克里斯‧雷德菲尔德亚瑟‧摩根【新春限定】果体 隆瓮中能言蛙永远的克叔凯登‧阿兰科

                  ditto 发表于 3 天前 | 显示全部楼层 <
                  回复

                  使用道具 举报

                  灵光补脑剂茉香啤酒炼金之心念念往日士官盔漂洋小船我有一个暗恋对象驯化黑龙幼崽

                    aaawwwww 发表于 3 天前 | 显示全部楼层 <
                    回复

                    使用道具 举报

                    亚当‧简森塞拉斯堕落狂鳄安德森‧戴维斯索尔·奥丁森安德鲁·库珀传奇跨过这道墙官复原职Beauty and the Beast

                      KamiuBlued 发表于 3 天前 | 显示全部楼层 <
                      回复

                      使用道具 举报

                      暗蚀魔典喜欢金币的Doge萨赫的蛋糕『领甜甜圈』史莱姆蛋杰森‧斯坦森威尔卡斯发条八音盒

                        azrael3 发表于 3 天前 | 显示全部楼层 <
                        回复

                        使用道具 举报

                        岛田半藏永远的克叔杰西·麦克雷莱因哈特·威尔海姆果体76亚索杰森‧斯坦森迪恩‧温彻斯特

                          天恩 发表于 3 天前 | 显示全部楼层 <
                          回复

                          使用道具 举报

                          莱因哈特·威尔海姆森林羊男石鬼面驯化黑龙幼崽SCP-s-1889-第七页『开心果奶酥』冒险用绷带敖蜃星

                            accel734 发表于 3 天前 | 显示全部楼层 <
                            回复

                            使用道具 举报

                            飞升之力!淬炼裸体克里斯闪耀的魔仙棒史莱姆蛋『草莓乳酪』琉璃玉坠都市:天际线2

                              drhung 发表于 3 天前 | 显示全部楼层 <
                              回复

                              使用道具 举报

                              没有梦想的咸鱼飘飘出动!收到情书人到中年超人传说中的黑龙高桥剑痴龙头的宝玉

                                Cassini 发表于 3 天前 | 显示全部楼层 <
                                回复

                                使用道具 举报

                                内森·德雷克残忍捕猎诺克提斯·路西斯·伽拉姆巴哈姆特至尊巴哈姆特传奇虚空之海的鲸業火死鬥远行保加利亚妖王

                                  mintea 发表于 3 天前 | 显示全部楼层 <
                                  回复

                                  使用道具 举报

                                  禽兽扒手野兽之子香草樱桃塔眼镜蛇图腾山猫图腾猎鹰图腾不屈之枪·阿特瑞斯

                                    hs90419a 发表于 3 天前 | 显示全部楼层 <
                                    回复

                                    使用道具 举报

                                    灵光补脑剂我的天使霉运小精灵[红]终归一人至尊巴哈姆特You Can Pet Blaidd炽焰咆哮虎官复原职实现梦想卡利亚权杖

                                      黑夜下的灯光 发表于 前天 00:22 | 显示全部楼层 <
                                      回复

                                      使用道具 举报

                                      裸体克里斯男用贞操带都市:天际线2最终幻想XIV万众瞩目玄甲金盾内森·德雷克吃饱金币的Doge

                                        scious 发表于 前天 00:54 | 显示全部楼层 <
                                        批量的话就会很方便了,但感觉有点点复杂欸,不过应该能抑制那些盗卖资源的人
                                        回复

                                        使用道具 举报

                                          凯诺斯 发表于 前天 01:31 手机端 | 显示全部楼层 <
                                          盲水印感觉很强大惹,给本子打这种水印不仅不影响观看还能一定程度上防倒卖啥的
                                          回复

                                          使用道具 举报

                                          您需要登录后才可以回帖 登录 | 立即注册

                                          本版积分规则

                                          关闭

                                          站长公告上一条 /1 下一条

                                          文字版|手机版|小黑屋|GameMale

                                          GMT+8, 2026-6-13 17:24 , Processed in 0.211473 second(s), 145 queries , Redis On.

                                          Copyright © 2013-2026 GameMale

                                          All Rights Reserved.

                                          快速回复 返回列表