Code Monkey home page Code Monkey logo

blindwatermark's Introduction

盲水印

介绍

你还在为别人盗用你的图片却不承认而烦恼吗? 你还在为自己创作的图片被坏东西(视觉xx)拿去找别人索赔,版权还莫名其妙到了坏东西手里而烦恼吗?

为了解决这个问题,我创建了这个项目,并用python实现了它

什么是盲水印? 盲水印算法可以把你的水印嵌入到图片里面,而得到的图片在视觉上和原图几乎没有差别,但是可以通过算法和自己的密钥解出你的水印

盲水印相比普通水印有什么优势呢? 盲水印首先不会对影响你的图片观感,而且不像普通水印一样被裁剪,覆盖而失去作用。我的这个盲水印算法可以有效抵抗模糊,图片覆盖,椒盐噪声,亮度变化,裁剪带来的影响,甚至连截图也能提取出水印(要先用ps去除掉截图中和目标图片无关的部分, 并缩放会原本的大小)

todo list

  • 添加支援恰饭途径
  • 支持多级离散小波变换
  • 支持自动补以去除图片长宽需要是偶数的限制
  • 打包并上传pypi , 占时还不考虑,等较完善了再打包上传
  • 添加命令行模式
  • 添加更多的嵌入方式(0/n)
    • 尝试QIM用于嵌入,失败,理论与实际有差距
  • 用pyqt编写GUI界面
  • 实现将受到形变攻击,如平移,旋转,缩放,透视等形变的图片恢复成接近原图,是从受到形变攻击的图片中提取水印的必要前置步骤
    • from BlindWatermark import recovery

大更新

  • 解决了嵌入水印的时候在黑色区域内出现白点的问题

  • 支持多级小波变换和设定分块大小

    设小波变换级数为d默认1,分块大小为(m,m)默认(4,4),图片大小为x * y ,水印的长宽乘积为wm_size
    需满足
    

条件

  • 实现抵抗形变攻击

现在的问题

如果你不想因为当前本程序的不足之处而使得你对本程序有偏见, 请跳过这一部分

  • 这或许是所有开源盲水印的问题, 由于算法的公开, 我们必须使用采用密钥(这儿指随机种子和除数)的方式防止发布到网上的图片被别人依据我们的算法和密钥反向破解. 但是为了展示图片中有我们的图片, 我们不得不在公开的环境下提取水印, 以证实我们的确是从这张图片中提取出了水印. 但是这会导致我们的密钥暴露, 使得这张图片内的盲水印被之后的坏东西去除掉, 这似乎使得这个盲水印只生效一次
    • 设想的可能的解决办法: 寻找一个有公信力的平台, 水印版权的争夺者们, 把自己的密钥上传给平台, 由平台进行解水印的操作, 但是短期内这样的平台很难建立起来
    • 想来P站或许会有可能成为这样的平台, 如果我能做出较好地视频添加盲水印的办法, 也许B站等视频网站也会有所行动吧. 如果我的算法够牛逼的话, 毕竟梦想还是要有的
  • 闭源? 这根本是行不通的, 因为对于闭源程序你不知道它具体干了什么, 你会相信这个所谓的解出的水印是真的从那张图片中得到的吗? 我甚至能写出程序,不管读的图片是什么, 都输出加了随机噪声的我的水印,那是不是天底下的所以图片都是我的呢?
  • 当然我的视野是不够广阔的, 忽略了什么关键的点,或者说错了什么东西, 希望大家能够指出, 并帮助我改善我的程序, thank you my friends

适用情况

  • 适用人群: 希望保护自己创作的图片的创作者

  • 图片要求: 无

  • 水印要求:

    • 只能嵌入二值化的信息, 会自动取水印的B通道并二值化嵌入,水印最好是黑白的图片
    • 要求水印的长×宽 <= 图片的长/2/4 × 图片的宽/2/4 , 程序会自动验证
  • 程序依赖:

    • python3
    • numpy
    • opencv
    • PyWavelets

如何使用

B站视频链接

恰饭警告 请关注我的B站账号,三连, 和star

使用git pull https://github.com/fire-keeper/BlindWatermark.git或者直接下载压缩包把项目拉到本地, 然后在项目目录下

命令行版

#嵌入
python bwm.py -k 4399 2333 32 -em -r pic/lena_grey.png -wm pic/wm.png -o out.png -s
#提取
python bwm.py -k 4399 2333 32 -ex -r out.png -wm pic/wm.png -ws 64 64 -o out_wm.png -s

参数介绍

"--key",'-k' 依次输入2个随机种子和除数(正数),除数可以是一个或者两个,之间用空格隔开.如(4399,2333,32)
'-em','--embed' 后不带参数,表征本次操作是嵌入水印
'-ex','--extract' 后不带参数,表征本次操作是提取水印
               以上两者要求必须有且只有一个
"--read",'-r'   "要嵌入或提取水印的图片的路径"
"--read_wm",'-wm'  要嵌入的水印的路径
"--wm_shape",'-ws' 要解出水印的形状
"--out_put",'-o'   图片的输出路径
"--show_ncc",'-s'  展示输出图片和原图的NC值(相似度)

'-bs','--block_shape' 设定分块大小,因为限定长宽相同,所以只需要传一个整数就行了,对于大图可以使用更大的数,如8,更大的形状使得对原图影响更小,而且运算时间减少,但对鲁棒性没有提高,注意太大会使得水印信息超过图片的承载能力
'-d','--dwt_deep',设定小波变换的次数,次数增加会提高鲁棒性,但会减少图片承载水印的能力,通常取1,2,3

在调节参数的时候主要调节除数,即--key的第3(第4)个参数, 在图片没有失真的前提下使得值最大

运行以下python命令

# python代码
#导入模块
from BlindWatermark import watermark
#嵌入

bwm1 = watermark(4399,2333,36,20)
#4399和2333是两个随机种子,36和20是用于嵌入算法的除数,理论上第一个除数要大于第二个,除数越大鲁棒性越强,但是除数越大,输出图片的失真越大,需要权衡后决定
#这两个随机种子最好对不同图片有不同的取值, 防止种子暴露而使得所有图片失去保护
#第二个除数可以不加,增加对水印鲁棒性没有明显的提升,但是会一定情况想影响输出图片的质量
bwm1.read_ori_img("pic/lena_grey.png")
#读取原图
bwm1.read_wm("pic/wm.png")
#读取水印
bwm1.embed('out.png')
#在原图中嵌入水印并输出到'out.png'
# 用NCC数值化判断输出图片与原图的相似度
from BlindWatermark import test_ncc
   
test_ncc('pic/lena_grey.png','out.png')
#判断这两种图片的相似度, 输出为0~1,数值越接近1表示二者越相似
#提取

bwm1 = watermark(4399,2333,36,20,wm_shape=(64,64))
#用之前嵌入水印的参数,实例化对象,注意需要设定水印的长宽
bwm1.extract("out.png","out_wm.png")   
#注意需要在输出的水印的同级目录下创建 Y_U_V/ 文件夹, 否则单通道提取出来的水印不会被保存

支援恰饭

Alipaysetu

效果展示

要嵌入水印的原图lena_grey.png和水印图片wm.png

lena watermark

嵌入后的图片

嵌入水印后的图片

提取出的图片

提取出的图片

各种攻击以及提取出的水印

攻击方式 攻击后的图片 提取出的水印
模糊 blur_lena.png blur_wm.png
用图像覆盖 cover_lena.png
用线条覆盖 randline_lena.png
亮度调高10% brighter10_lena.png
亮度调低10% darker10_lena.png
添加椒盐噪声 saltnoise_lena.png
裁剪5%并填充
裁剪10%
裁剪30%

针对jpeg压缩, 经检验单独对Y通道解水印效果最好,以下解出的水印均来自Y通道

压缩因子 压缩后的图片 提取出的水印
90
85
80
70
60
50
40

水印防破解

如果有不良商家要破坏我们的水印再加上他的水印时, 如果他知道了我们的加密方式(不知道我们的随机种子和除数)时, 破解影响应该是最大的, 针对这种情况作出演示

现在网络上有两种图片A,B. A是我们嵌入水印后发表出去的, B是破解者在A上用相同的添加盲水印方式添加了自己的水印生成的. 然而我们使用我们的参数(随机种子和除数)可以从A,B中提取出我们的水印, 但是用破解者的参数进行提取时,不能从A中提取出破解者的水印,,只能从B中提取出破解者的水印

这便能说明这张图的创作者究竟是谁, 我认为这对保护创作者的权益是至关重要的一步

破解者的水印

介绍 图片 提取出的水印
我们嵌入水印的图片A
破解者在上面这种我们已经嵌入水印的图中再次嵌入水印的图片B
用我们的参数提取破解者的图片B
用破解者的参数提取我们的图片A

blindwatermark's People

Contributors

dependabot[bot] avatar fire-keeper avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blindwatermark's Issues

[Bug] 在多个输入图片嵌入水印时闪退

1.导入图片 多文件 (测试文件数量4)
2.导入水印 单文件
3.嵌入时 会按导入图片数量 多次弹出 【参数错误请参考关于中的公式修改参数,使其满足公式】
并 在后台提示 【水印的大小超过图片的容量】
4.在关闭警告时 闪退

个人接触过密码学和认证相关,提出一点不成熟的建议

密钥和签名个人认为可以使用RSA这一非对称加密形式,只要私钥保存在太太手里就能有效防止反向破解,可以使用openssl实现

甚至可以使用Let's Encrypt或自签名GPG证书生成密钥和签名,保证密钥的公信力

算法方面也可以尝试对图片进行FFT之类的操作做水印

bwm运行错误

GUI版闪退,使用图片:https://mysteriouspreserve.com/assets/images/sources/origin.jpg
水印:https://mysteriouspreserve.com/assets/images/sources/mark.png

python2.7: File "bwm.py", line 6
SyntaxError: Non-ASCII character '\xe5' in file bwm.py on line 6, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Python 3.7:ModuleNotFoundError: No module named BlindWatermark

已知:如果工作目录存在中文字符,则GUI版bwm检测参数是否符合公式时会崩溃。

水印经过微信传输信息必丢失

平台:Iphone11 Pro Max

原图:RGB都是220的纯背景图
image

水印图: 用PS生成四个字符的水印图,水印图是二值化的
image

合成图: 添加到RGB的背景图生成水印图。
image

过程:把水印图以图片的形式放到app里显示,然后苹果系统方式截图,截取出来的图片只要经过微信传输一定会识别不出来,尤其是1080p以上的分辨率的机型

问题:是否是水印对JPG攻击的抵抗性特别弱?
而且我发现有时把mod1调到了对水印的鲁棒性并没有多大的改善,并非越大越好,跟描述不太一致。

Scaling robustness

When an input image is scale towards a different dimension (even remaining aspect ratio) the software is unable to extract the watermark. But when the image is scaled back to its original dimension (even being blurry) the watermark can be recovered. Would there be a way to be scale invariant? For example by using features such as SIFT/SURF/ORB as landmarks for embedding?

抗攻击性太弱

抗攻击性太弱,截图后水印几乎无法提取,除非百分百截取;画笔涂抹后也几乎无法提取水印,不知后续还有没有优化版本
6
0

增加 jpg 输出质量的参数 & 一些问题

感谢作者,感觉还挺好用的。
代码还没细看,先跑了点测试。然后有些问题请教一下。

加了个jpg压缩的参数

cv2.imwrite(output_filename, img_data, [int(cv2.IMWRITE_JPEG_QUALITY), 90])

png也有对应的IMWRITE_PNG_COMPRESSION,但那个有损得比较厉害,不太用到。
jpg的还是挺常用的。

做了一些测试

同水印大小不同源图大小

  • plot_src256_wm32_block4_jpg60-100_mod16-32
    plot_src256_wm32_block4_jpg60-100_mod16-32
  • plot_src512_wm32_block4_jpg60-100_mod16-32
    plot_src512_wm32_block4_jpg60-100_mod16-32
  • plot_src1024_wm32_block4_jpg60-100_mod16-32
    plot_src1024_wm32_block4_jpg60-100_mod16-32

显然大图包含信息更多,还原更精准。(横坐标为jpg品质,纵坐标为mod)

水印刚好是图源1/8

  • plot_src256_wm32_block4_jpg60-100_mod16-32
    plot_src256_wm32_block4_jpg60-100_mod16-32
  • plot_src512_wm64_block4_jpg60-100_mod16-32
    plot_src512_wm64_block4_jpg60-100_mod16-32
  • plot_src1024_wm128_block4_jpg60-100_mod16-32
    plot_src1024_wm128_block4_jpg60-100_mod16-32

大图有好一些,但优势不明显。(个人理解是承载信息的范围和信息本身在同比增加,压缩之后干扰程度也就差不多)
接合上一条,也许水印可以有一个上限,比如128的bitmap,足够承载较多的内容。

block的影响

同样源图用到最大水印 block4->1

  • plot_src256_wm32_block4_jpg60-100_mod16-32
    plot_src256_wm32_block4_jpg60-100_mod16-32
  • plot_src256_wm128_block1_jpg60-100_mod16-32
    plot_src256_wm128_block1_jpg60-100_mod16-32

这里都是256的原图,分别用了32的水印和128的水印,明显128的品质更好,但block少了。

同样源图/水印/仅改变block

  • plot_src512_wm32_block2_jpg60-100_mod16-32
    plot_src512_wm32_block2_jpg60-100_mod16-32
  • plot_src512_wm32_block3_jpg60-100_mod16-32
    plot_src512_wm32_block3_jpg60-100_mod16-32
  • plot_src512_wm32_block4_jpg60-100_mod16-32
    plot_src512_wm32_block4_jpg60-100_mod16-32
  • plot_src512_wm32_block8_jpg60-100_mod16-32
    plot_src512_wm32_block8_jpg60-100_mod16-32

我的理解是block越多,单个block就越小,能承载的信息越少,所以解码质量越低。
这里我源码还没细看,请问block在这里的作用是什么?从原图反解码的效果来看是越少品质越好,那block增加是能实现什么效果呢?防遮挡,多处采样比较吗?

其他一些问题

  • 从多次保存等情况下看,jpg还是按60的标准来处理比较保险,那样的话貌似mod就只能取24-32这个范围。
  • 请问block具体作用是什么?有没有所谓的上限,比如4就足够应付大部分场景了?

考虑自动根据源图生成参数

  • 另外逆向出来水印的质量,除了除数,还是和图片/水印大小,block分区,压缩品质,源图大小及保护价值(源图太小就牺牲block)等各种因素相关。
  • 我现在考虑能不能自动根据源图大小(锁定源图和jpg60这两个参数),自动判断所需的block/水印尺寸/除数,这三个参数,获得一个画质和保护的平衡。
  • 解码的时候考虑方式一是通过上述的自动参数来做,二是固定水印大小(比如128/64/32/16)试个4次,变相自动。

读完源码自答一下

block有一个比较隐蔽的问题是配合dwt,要凑到8px,因为jpg是按8px来压缩的,也就是block*(2^dwt_deep)刚好。
block过小,运算量几何级数增加,效率过慢。而且block过细,会导致画面有明显噪点感。
block过大,解高压缩的jpg水印会出问题。
jpg60时,block数量的宽高,达到水印2倍后解水印质量不错。比如画布1024,dwt1次,有效画布512,block4,可记载宽度128,如果用来记载32的水印,就达到了4:1,解水印效果就很好。

图片还原问题

为何裁剪后必须还原到原图大小才能提取水印呢,填补后图片的像素值已经变了呀

[关于密钥的猜想] 一次性加密水印的解决思路

众所周知,我们现在所了解到的的水印只能生效一次,是因为其密钥是对称的,只要有一个key即可加解密;正如大多数对称加密算法(如AES)的特性。
那么能否结合非对称加密的特性(比如ECC,RSA)等方式加密,对于每一个创作者生成一个私钥,然后发布一个给与大家验证的公钥,由于私钥加密的东西只有公钥可以解开,公钥加密的东西只有私钥能解开,就解决了上述的一次性加密问题。

具体原理我认为可以参考一下PGP;但请各位创作者务必保存好你的私钥。

文献出处?

不知这个方法是否有文献出处?没有的话完全可以发一篇文章了!并且如果是原创的话建议给这个方法取个名字,加个版本号,甚至申请个专利什么的

我多年前有实现这个功能的想法,但是没有相关的知识储备,被您做出来了真是太棒了!以后有机会我会常识把它移植到C++/C#进行高效处理!

Request: English Localization

I would like to request a written tutorial on how to use the software in English. And also an English localization of the software could be very nice.

这个算法对RGB偏移的抵抗性很差

RBG其中某一两个通道的值总体增加一点,再加上25-50%的jpg压缩,在肉眼较难分辨的情况下,可以对水印造成极大破坏。
如果想要提高抵抗性,就不能发未压缩过的原图,得先压成AV画质打上隐水印再发出去

图像隐写

是跟图像隐写相关的吗,之前看过一下图像隐写,加密这部分一直不行

更改图片尺寸的时候无法提取

修改了图片尺寸的时候,就无法提取了。。
Traceback (most recent call last):
File "bwm.py", line 57, in
bwm.extract(args.ori_img,args.output)
File "/Users/qianhuang/workspace/git_repos/BlindWatermark/BlindWatermark/BlindWatermark.py", line 314, in extract
cv2.imwrite(out_wm_name,extract_wm.reshape(64,64))
ValueError: cannot reshape array of size 1024 into shape (64,64)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.