信息隐藏-图像盲水印实现

article/2025/11/7 13:37:17

相关知识

目前水印大抵可分为两种,可见和不可见,可见水印大多用来标记或声明版权,或防盗用冒用,但在影院、绘画等场景下,可见性水印会极大影响用户体验,所以产生了盲水印的概念。
盲水印即看不见的水印,多使用信息隐藏技术实现,基于空域或频域隐藏秘密信息,在不影响用户的感官体验下嵌入信息,且只有通过特殊的提取器才可提取。这种技术目前应用十分广泛,相当多的公司都采用这种方法来给外泄的秘密资料找到泄密者。但信息隐藏到底是一门年轻的学科,关于盲水印现成的实现方法还不是太多。
(也看到有说法是盲水印是不依赖原图即可提取水印的方法,也有一定道理,但是该如何可见和不可见水印的是否有区别叫法呢?)

工具

虽然不多,但还是让我找着了。
目前大部分盲水印嵌入算法都是基于频域的(因为其鲁棒性高),但大部分现成工具都不能克服频域转化算法的局限性,需要载体图像像素位2的幂次、载体图像要是方的、载体与水印的大小需相关等等,这无疑是不符合实际的,诶,有这么一个软件就克服了这些局限性。
下载链接附上:
水印制作软件-WaterMakev10.61 绿色版-腾牛下载 (qqtn.com)
该软件解压即可使用,还不依赖其他dll,一个exe打天下,且经过测试其鲁棒性较强,足以应对我认为最强的剪切攻击,使用界面简单易用。
使用界面
该工具的缺点在链接中也提到了,图像大小为2的n次方,如果大小不符的话会自动拉伸,这到也能接受,后面自行再缩放即可。关键的是对大图像的支持不足,目前测试2560×1660的图像还可,但是6000×4000这种级别的图像会直接报错,OutOfMemory,可能图像太大申请的内存不足以存放。
总之该工具在我们日常使用玩玩还是不错的,用起来很方便,但是当图片增大,商用领域就有些捉襟见肘。

现成库

blind-watermark

据说该库由阿里安全人员开发,同样可以克服频域算法的局限性,使用也较简单,相关介绍如下:
Python 实现数字图片盲水印(隐水印) - 知乎 (zhihu.com)
可使用pip install blind-watermark直接安装,国内环境也无需切换源,比较友好。可针对图像嵌入文本和水印,比较强的是水印恢复不依赖于原图,代码没看明白具体咋实现的也不懂。
不过都说该库鲁棒性极强,可从容应对几乎所有攻击,包括剪切旋转拉伸,但可能是我打开方式不对,污损情况下提取效果不错,但一些破坏图像结构的攻击直接就崩了,或提取出乱码或者雪花,或产生红色报错。
使用代码示例如下:

from blind_watermark import WaterMark
def encode(img,str):#嵌入文字信息startime = time.time()bwm1 = WaterMark(password_img=1, password_wm=1)bwm1.read_img(img)bwm1.read_wm(str, mode='str')bwm1.embed('embedded.png')len_wm = len(bwm1.wm_bit)print('Put down the length of wm_bit {len_wm}'.format(len_wm=len_wm))encodetime = time.time()print("encode time ", encodetime - startime)return len_wm
def decode(img,len):#解密文字信息startime=time.time()bwm1 = WaterMark(password_img=1, password_wm=1)wm_extract = bwm1.extract(img, wm_shape=len, mode='str')endtime = time.time()costtime = endtime - startimeprint("time cost:", costtime)print(wm_extract)
def encodeimg(carrier,watermark,output):#嵌入图像水印bwm1 = WaterMark(password_wm=1, password_img=1)# 读取原图bwm1.read_img(carrier)# 读取水印bwm1.read_wm(watermark)# 打上盲水印bwm1.embed(output)
def decodeimg(img,output):#提取图像水印bwm1 = WaterMark(password_wm=1, password_img=1)# 注意需要设定水印的长宽wm_shapebwm1.extract(filename=img, wm_shape=(150,167),out_wm_name=output)
#然后在主函数中调用就可以了

相比来说该库的鲁棒性确实不错,jpg的压缩也可以轻松应对,不足的是对图像质量的破坏偏大。不论图像大小,都可能对图像造成一定破坏,虽不至于影响整体感官,但也能看出图像差别,透明度要求较高的话不建议使用。

BlindWaterMark

项目地址
盲水印
使用控制台执行,具体操作方法文档都有,比较简单,优点是透明性高,且支持大图处理,加了水印的图像肉眼几乎无法识别。但面对jpg格式的压缩时有些力不从心,水印直接变成雪花,毕竟鲁棒性和透明性不能兼得。算法据说可以抗PS等这种在已有结构上的修改的攻击,没有PS还没法测试,如果是真的话还是相当适合商用的,可以达到防篡改的效果。

自行编写 - 基于离散余弦变换的盲水印

自行编写的好处是可以根据需求调整,在鲁棒性和透明性之间做出最适合自己的决定,但是相对比较繁琐,而且一些异常处理很难像已有系统那么周密,以学习为目的的话还是相当适合的。
主流隐藏方法,且兼顾效率与隐蔽性的算法是基于离散余弦变换的信息隐藏算法(DCT),该算法涉及比较复杂的数学知识,只能简要说下其原理:离散余弦变换是将图像由空间域转化到频率域上,将图像计算为二维余弦波,从效果来说是将图像计算为一个DCT系数矩阵,该矩阵代表图像的频率分布,频率低的为图像中相对重要的主体信息,高频则是图像的一些细节,但该矩阵中的像素与图像像素不存在一一对应关系。 然后将秘密信息根据自己的算法隐藏到DCT系数中即可,隐藏位置多选择中频区域,是在透明性和鲁棒性之间做了折中的选择。
本文设计的算法是利用dct系数的相对变化存储10信息(可用该10信息代表黑白,即可嵌入图片)。
引用一张觉得很不错关于域的分解图
在这里插入图片描述

具体思路

1.嵌入区域选择:首选中频,中频对角区域填满后向高频偏移,故容量最大为载体像素个数的一半。
2.嵌入算法:此步需要传入参数嵌入强度coefficient,根据标记字符串0或1增大或缩小自身的coefficient倍,这种相对变化能让自身统计特征的变化降到最小,且避免了因变化绝对值而产生对图像的破坏。
3.提取算法:用嵌入了秘密信息的DCT系数矩阵与原图像系数矩阵作差,会得到有正有负的新矩阵,因为先前规定了0减小1增大,故可根据目前的新矩阵恢复出先前的01序列,进而可以恢复字符甚至图像。
基于DCT的隐写算法python实现代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt#图片展示
import base64 #图片转string
import time
def dct_encode(img1,img,coefficient):  #返回处理好的dctstarttime=time.time()height, width = img.shapeprint("Number of the carrirer can contain:",height*width/2)str=watermarkTostring(img1)if len(str)>height*width/2:#如果信息数量过多返回错误 只能存储在后二分之一print("Too many information to hide!")img1=img.astype('float')img_dct = cv2.dct(img1)h=0w=width-1                #行数向下递增 列数向右递增last_h=1                 #保存上一次跳转的列数print("Embeding...")print("隐藏",len(str),"位")black=0white=0for i in range(0,len(str)):#所有水印字符嵌入  范围前闭后开if h==height:h=last_hlast_h=last_h+1w=width-1if str[i]=="0":#白色变小#print("白色颜色记录位置",h,w)if img_dct[h][w]<0:img_dct[h][w]=img_dct[h][w]*(1+coefficient)else:img_dct[h][w]=img_dct[h][w]*(1-coefficient)h=h+1w=w-1white=white+1else: #黑色变大if img_dct[h][w]<0:img_dct[h][w]=img_dct[h][w]*(1-coefficient)else:img_dct[h][w]=img_dct[h][w]*(1+coefficient)#print("黑色颜色记录位置", h, w)h=h+1w=w-1black=black+1print("stop caculuation location ", h, w)print("number of white is ",white)print("number of black is ",black)print("Embeding complete.")   #嵌入完成encode_img=cv2.idct(img_dct)cv2.imwrite('D:/carrywatermark.png',encode_img)endtime=time.time()costtime=endtime-starttimeprint("encode cost",costtime)show("carrier",img)show("encode",encode_img)return  encode_imgdef dct_decode(watermark,img,orginal_img):  #现在图像减原图像 负数为白色 正数为黑色starttime=time.time()height,width=watermark.shapestr_len=height*widthprint("需解析",str_len,"位")print("组成高为",height,"宽为",width,"的图像")carrier_height, carrier_width = img.shapecarrier_h=0carrier_w=carrier_width-1last_carrierh=1height2,width2=orginal_img.shape'''if height1<height2:  #以最小的计算height=height1else:height=height2if width1<width2:width=width1else:width=width2'''black=0white=0img1 = img.astype('float')img1_dct = cv2.dct(img1)img2=orginal_img.astype('float')img2_dct=cv2.dct(img2)watermark_list=[[]for i in range(0,height)]    #生成空二维数组h=0w=width-1last_h=1list_height=0for i in range(0,str_len):#所有水印字符嵌入  范围前闭后开if carrier_h==carrier_height:#到底了carrier_h=last_carrierhcarrier_w=carrier_width-1last_carrierh=last_carrierh+1flag=img1_dct[carrier_h][carrier_w]-img2_dct[carrier_h][carrier_w]carrier_w=carrier_w-1carrier_h=carrier_h+1if flag>0:#黑色black=black+1if len(watermark_list[list_height])==width:list_height=list_height+1watermark_list[list_height].append(0)h=h+1w=w-1else: #白色white=white+1if len(watermark_list[list_height]) == width:list_height = list_height + 1watermark_list[list_height].append(255)h=h+1w=w-1print("stop caculuation location ", carrier_h, carrier_w)print(len(watermark_list[0]))print("number of white is ", white)print("number of black is ", black)watermark=np.array(watermark_list)              #list 类型转为numpy.ndarray#print(watermark)print("Extract complete!")   #提取完成cv2.imwrite('D:/getwatermark.png', watermark)endtime=time.time()costtime=endtime-starttimeprint("decode cost",costtime)show("get_watermark",watermark)return watermark

代码写了这么长还是有相当的不足,
1.受限于DCT算法本身计算方法,输入的载体图像必须是方的。
2.只测试了黑白图像。
3.鲁棒性一般,可以应对一些修改攻击,但剪切旋转等格式变化未有考虑。
优点是时间效率和透明性还可,因为只修改了嵌入密文长度的dct系数,1024×1024的图像只需要0.3秒即可完成,不论从人眼还是计算机角度来看,透明性也都是比较优异的。

评价标准

盲水印能嵌入后其主要评价指标就是透明度,这需要从两个角度来评价。
1.视觉感官,需要人主观判断,由于人注意的重点不同,所以可能会有不同的细节被忽略,最好让多个人分别评价打分,取他们的平均值来判断。
2.计算机分析,人看不到的细节往往会被计算机捕获,这时我们需要引入一个评价标准–峰值信噪比PSNR,具体计算方法网上随便一查全都是,PSNR高于40dB说明图像质量极好(即非常接近原始图像),在30-40dB通常表示图像质量是好的(即失真可以察觉但可以接受),在20-30dB说明图像质量差;PSNR低于20dB时说明图像不可接受。

总结

盲水印是实现溯源和防盗版的一个渠道,但是其局限性也比较多。
首先是效率问题,一张1080的图片使用频域算法嵌入水印可能需要两秒左右,而商用的海报可能需要几分钟时间,如果觉得这还好的话想一下盲水印用于视频的防伪,目前视频帧率大多为60,一秒钟的盲水印嵌入可能就需要两分钟,十分钟呢?两个小时的电影呢?这样的时间效率能接受吗?且目前大的视频平台都会对用户上传的视频进行压缩,这种压缩可能是很强力的,大部分嵌入水印可能都无法存活。
其次是易被攻击,虽然嵌入的水印其他人很难破解和修改,但是让图像中的水印消失还是比较好达到的。把图片打印出来再扫描、拍摄展示图像的屏幕、甚至利用qq微信社交软件进行发送再接受等,都可能导致水印的失效,所以只从可用性的角度来说防盗用是很难的。但是这一切是建立在对图像质量要求不高的前提下,不论是扫描还是拍摄,得到的图像终究不是原图,当对图像质量有一定要求必须使用原图时,我们的水印就会再次出现。


http://chatgpt.dhexx.cn/article/LnVXMFho.shtml

相关文章

Python给图片添加盲水印

文章目录 简介安装初试遇到的坑参考文献 简介 盲水印就是图片有水印但人眼看不出来&#xff0c;需要通过程序才能提取水印&#xff0c;相当于隐形“盖章”&#xff0c;可以用在数据泄露溯源、版权保护等场景。 该库出自阿里巴巴安全团队&#xff0c;强大之处&#xff1a; 解…

Opencv实现盲水印技术(三)——傅里叶变换算法及盲水印实现

前言 之前的文章中&#xff0c;介绍了如何构建Java工程和Java Web工程&#xff0c;本文将简单介绍对傅里叶变换的理解&#xff0c;以及使用opencv实现盲水印。关于傅里叶变换&#xff0c;有篇博文介绍的很详细&#xff0c;链接地址为&#xff1a;看了此文你还不了解傅里叶变换&…

双图+盲水印

1.双图 打开压缩包&#xff0c;发现有两张图片 first1和second.png&#xff0c;使用Stegsolve打开first1.png进行一次异或处理 然后分析选择结合second.png得到 用stegslove对二维码进行运算得到三张二维码 扫描结果是DES 6XaMMbM7 和一长串字符&#xff0c;很显然是des加密&a…

Python 数字图片盲水印

blind-watermark 基于傅里叶变换的数字盲水印 文档&#xff1a; https://BlindWatermark.github.io/blind_watermark/#/zh/Source code: https://github.com/guofei9987/blind_watermark install pip install blind-watermarkFor the current developer version: git clon…

watermark前端js盲水印添加方法

1,引入js <script src"/Public/js/watermark-dom/watermark.js" language"JavaScript"></script> 2,实例化对象 <script language"JavaScript"> //参数详情请参考watermark.js 文件里的说明 window.onload function(){wate…

给你的web页面添加盲水印,附带检盲水印方案

应用场景 在一些敏感系统有的时候我们为了防止别人截图或追溯图片源头是谁发的。我们需要在页面上埋下我们的隐形水印。 开始做 埋水印 github上有很多水印的js插件&#xff0c;download下来一个改一改&#xff0c;源码见最后附录。 改动内容&#xff1a;增加了判断dom被人…

有意思的数字盲水印的简单的实现。

早期大约是10年前从一本数字图像处理上看到过数字水印的概念&#xff0c;觉得确实一种很有意思的东西&#xff0c;那个时候主要就是基于LSB的图像信息的隐藏&#xff0c;这种在空域里的方法有较大的缺陷&#xff0c;鲁棒性是比较差的。随便一个后期的都会造成水印的丢失&#x…

python脚本实现盲水印提取和添加

python脚本实现盲水印提取和添加 首先github上找个BlindWaterMark-master文件下载一下&#xff0c;打开后是我这个样子 在python里面添加两个库&#xff0c;python.exe目录上方输入cmd pip install opencv-python python.exe -m pip install matplotlib新手这里装库的时候&am…

文字隐写术-盲水印研究笔记

gitee 开源代码(java) shuiyin: blind watermark 盲水印技术实现 java 实现版权保护 - Gitee.comhttps://gitee.com/chejiangyi/shuiyin/tree/master 需求概述 研究盲水印对于版权保护的效果和能力 研究尝试概述 水印实现: 大部分的python或者java算法都基于频域的盲水印效果…

web系统添加盲水印

前言 为增加系统安全性&#xff0c;避免重要敏感信息通过截图方式泄露&#xff0c;对web页面增加盲水印标识&#xff0c;标注系统名称&#xff0c;登陆人&#xff0c;当前时间等信息&#xff0c;这里的盲水印指肉眼不可见的html水印 增加水印 引入watermark.js调用 watermar…

【OpenCV 例程 300篇】219. 添加数字水印(盲水印)

OpenCV 例程200篇 总目录 【youcans 的 OpenCV 例程 300篇】219. 添加数字水印&#xff08;盲水印&#xff09; 8.2 添加数字盲水印 数字水印&#xff0c;是指将特征信息嵌入音频、图像或是视频等数字信号中。 数字水印分为明水印和盲水印&#xff08;blind watermark&#…

照片里的盲水印

这个题是安恒月赛里面的一道misc类型的题&#xff0c;在CTF中misc所谓最考验你的脑洞和检验你的赛事水平&#xff08;赛棍&#xff1f;&#xff1f;&#xff1f;&#xff09; 但是这个方面还是要看一下&#xff0c;就当做开发脑力了。 题目&#xff1a;暴力可解 题目文件 下载…

[python] 基于blind-watermark库添加图片盲水印

blind-watermark是一个能够给图片添加/解析基于频域的数字盲水印的Python库。图像水印image watermark是指在图片里添加文本或图形&#xff0c;以标记图片的来源。但是图像水印会破坏原图。因此另外一种水印形式&#xff0c;即图像盲水印blind image watermark在实践中更多地用…

图片盲水印软件

bulid_watermark_gui Blind&Invisible Watermark &#xff08;图片盲水印&#xff0c;提取水印无须原图&#xff01;) 增加图形界面 项目地址&#xff1a;github开源 软件下载地址&#xff1a;无需环境软件下载 how to use pip install -r requirements.txt 运行main.py…

隐写术(盲水印):从入门到出门

0. 前言 我在做 Blind Watermark 这个库的时候&#xff0c;翻阅了大量材料&#xff0c;学到了关于隐写术、盲水印的很多知识&#xff0c;现在梳理了一遍&#xff0c;发出来。 本文结构&#xff1a; 简介&#xff1a;隐写术的应用场景、分类、特点隐写术&#xff1a;介绍几种…

图片隐写,盲水印,加密logo

1.定义 隐写术算是一种加密技术&#xff0c;权威的 wiki 说法是“ 隐写术是一门关于信息隐藏的技巧与科学&#xff0c;所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。” example&#xff1a; 钱图&#xff08;钱上面的水印&#xff0…

CTF盲水印详解

原创稿件征集 邮箱&#xff1a;eduantvsion.com QQ&#xff1a;3200599554 黑客极客技术、信息安全热点安全研究分析等安全相关的技术文章 稿件通过并发布还能收获 200-800元不等的稿酬 前言 在CTF杂项题型中&#xff0c;盲水印的出现频率是相当高的&#xff0c;但大多数人处于…

盲水印(Blind-WaterMark)

盲水印是一种肉眼不可见的水印方式&#xff0c;对图片资源使用图片盲水印或者文字水印&#xff0c;借此避免数字媒体未经授权的复制和拷贝&#xff0c;可通过对原图进行解码操作&#xff0c;得到水印图来证明版权归属。 这类盲水印是怎样实现的呢&#xff1f;原理并不复杂&…

Windows系统通过CMD连接MySql

1.按压WindowsR快捷键后输入"cmd" 2.点击"确定"按钮后打开命令行 3.通过输入"cd"MySql安装的bin目录&#xff0c;按压"Enter"后进入MySql安装的bin目录 4.输入"mysql -h localhost -u root -p"&#xff0c;此处-h后为对应ho…

cmd中无法连接MySQL

本人电脑是win10系统&#xff0c;安装的是MySQL5.7版本的&#xff0c;最近在登录MySQL的时候老师出现下面的错误&#xff0c;有的时候重启电脑耶也会出现这样的情况 1.先检查你的环境变量是否配置好了&#xff1b; &#xff08;如果没有配置好&#xff0c;请参考一下的步骤&am…