织梦CMS - 轻松建站从此开始!

罗索

阿里巴巴公司根据截图查到泄露信息的具体员工

jackyhwei 发布于 2021-01-29 09:59 点击:次 
作者:fuqiang liu 链接:https://www.zhihu.com/question/50735753/answer/122593277 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 本文通过一个的实验,简要介绍 频
TAG: 水印  

本文通过一个的实验,简要介绍频域手段添加数字盲水印的方法,并进一步验证其抗攻击性。在上述实验的基础上,总结躲避数字盲水印的方法。(多图预警

本文分为五个部分,第一部分综述;第二部分频域数字盲水印制作原理介绍;第三部分盲水印攻击性实验;第四部分总结;第五部分附录(源代码)。

一、综述
本文提供的一种实现“阿里通过肉眼无法识别的标识码追踪员工”的技术手段。通过看其他答主的分析,阿里可能还没用到频域加水印的技术。

相对于空域方法,频域加盲水印的方法隐匿性更强,抵抗攻击能力更强。这类算法解水印困难,你不知道水印加在那个频段,而且受到攻击往往会破坏图像原本内容。本文简要科普通过频域手段添加数字盲水印。对于web,可以添加一个背景图片,来追踪截图者。

所谓盲水印,是指人感知不到的水印,包括看不到听不见(没错,数字盲水印也能够用于音频)。其主要应用于音像作品、数字图书等,目的是,在不破坏原始作品的情况下,实现版权的防护与追踪。

添加数字盲水印的方法简单可分为空域方法和频域方法,这两种方法添加了冗余信息,但在编码和压缩情况不变的情况下,不会使原始图像大小产生变化(原来是10MB添加盲水印之后还是10MB)。

空域是指空间域,我们日常所见的图像就是空域。空域添加数字水印的方法是在空间域直接对图像操作(之所以说的这么绕,是因为不仅仅原图是空域,原图的差分等等也是空域),比如将水印直接叠加在图像上。

我们常说一个音有多高,这个音高是指频率;同样,图像灰度变化强烈的情况,也可以视为图像的频率。频域添加数字水印的方法,是指通过某种变换手段(傅里叶变换,离散余弦变换,小波变换等)将图像变换到频域(小波域),在频域对图像添加水印,再通过逆变换,将图像转换为空间域。相对于空域手段,频域手段隐匿性更强,抗攻击性更高

所谓对水印的攻击,是指破坏水印,包括涂抹,剪切,放缩,旋转,压缩,加噪,滤波等。数字盲水印不仅仅要敏捷性高(不被人抓到),也要防御性强(抗打)。就像Dota的敏捷英雄往往是脆皮,数字盲水印的隐匿性和鲁棒性是互斥的。(鲁棒性是抗攻击性的学术名字)

二、频域制作数字盲水印的方法
信号是有频率的,一个信号可以看做是无数个不同阶的正弦信号的的叠加。
[公式]
上式为傅里叶变换公式,[公式]是指时域信号(对于信号我们说时域,因为是与时间有关的,而图像我们往往说空域,与空间有关),[公式]是指频率。想要对傅里叶变换有深入了解的同学,建议看一下《信号与系统》或者《数字信号处理》的教材,里面系统介绍了傅里叶变换、快速傅里叶变换、拉普拉斯变换、z变换等。

简而言之,我们有方法将时域信号转换成为频域,同样,我们也能将二维信号(图像)转换为频域。在上文中提到,图像的频率是指图像灰度变换的强烈情况。关于此方面更系统的知识,参见冈萨雷斯的《图像处理》。

下面以傅里叶变换为例,介绍通过频域给图像添加数字盲水印的方法。注意,因为图像是离散信号,我们实际用的是离散傅里叶变换,在本文采用的都是二维快速傅里叶变换,快速傅里叶变换与离散时间傅里叶变换等价,通过蝶型归并的手段,速度更快。下文中傅里叶变换均为二维快速傅里叶变换。

上图为叠加数字盲水印的基本流程。编码的目的有二,一是对水印加密,二控制水印能量的分布。以下是叠加数字盲水印的实验。

这是原图像,尺寸300*240 (不要问我为什么不用Lena,那是我前女友),

 


之后进行傅里叶变换,下图变换后的频域图像,

这是我想加的水印,尺寸200*100,

这是我编码后的水印,编码方式采用随机序列编码,通过编码,水印分布到随机分布到各个频率,并且对水印进行了加密,

将上图与原图的频谱叠加,可见图像的频谱已经发生了巨大的变化,

之后,将叠加水印的频谱进行傅里叶逆变换,得到叠加数字水印后的图像,

肉眼几乎看不出叠加水印后的图像与原图的差异,这样,数字盲水印已经叠加到图像中去。
实际上,我们是把水印以噪声的形式添加到原图像中。
下图是在空域上的加水印图与原图的残差(调整了对比度,不然残差调小看不见),

可以看出,实际上上述方法是通过频域添加冗余信息(像噪声一样)。这些噪声遍布全图,在空域上并不容易破坏。
最终,均方误差(MSE)为0.0244
信噪比(PSNR)为64.2dB

 

那么,为什么频谱发生了巨大的变化,而在空域却变化如此小呢?这是因为我们避开了图像的主要频率。下图是原图频谱竖过来的样子,其能量主要集中在低频。

水印提取是水印叠加的逆过程,

经提取后,我们得到如下水印,问:为什么水印要对称呢?嘿嘿,大家想想看。

三、攻击性实验
本部分进行攻击性实验,来验证通过频域手段叠加数字盲水印的鲁棒性。
1.进行涂抹攻击,这是攻击后的图片:

再进行水印提取:

2.进行剪切攻击,就是网上经常用的截图截取一部分的情况:

进行循环补全:

提取水印:

3.伸缩攻击(这个实验明码做的,水印能量较高,隐匿性不强):

提取水印(水印加的不好,混频挺严重的):

4.旋转攻击(明码):

提取水印:

5.JPEG压缩后(这个实验我好像是拿明码做的,能量主要加在了高频):

提取结果:

6.PS 4像素马赛克/均值滤波等,攻击后图像(这是我女朋友吗?丑死了):

提取水印后图像:

7.截屏,
截屏后我手动抠出要测试的图像区域,并且抽样或者插值到原图尺寸:

测试结果:

8. 亮度调节(明码):

水印提取:

9.色相调节(明码):

水印提取:

10.饱和度调节(明码):

水印:

11.对比度(明码):

水印:

12.评论区用waifu2x去噪后图片:


解水印:

13.美图秀秀,我对我女票一键美颜,美白,磨皮,加腮红,加唇彩(有一种很羞耻的感觉,捂脸):

提取水印:

14.对于背景纯色的图其实也是无所谓的
能量系数为10时加水印图片:觉得太显噪就把能量系数调低,不过水印的隐秘性和鲁棒性是互斥的

最终提取出的水印:

15.我用将RGB>600的像素设置成为(0,255,0)来模拟PS魔术手,

提取水印为:

16.屏摄,好吧,这个实验我做哭了
屏摄图:

实验结果:

我把水印能量系数调整到2000都没有用。
屏摄之后与原图信噪比为4dB左右,我用多抽样滤波的方式试过,滤不掉屏摄引入的噪声。屏摄不仅引入了椒盐噪声,乘性噪声,还有有规律的雪花纹理(摩尔纹)。

四、总结
基于频域的盲水印方法隐藏性强,鲁棒性高,能够抵御大部分攻击。但是,对于盲水印算法,鲁棒性和隐匿性是互斥的。

本文方法针对屏摄不行,我多次实验没有成功,哪位大神可以做一下或者讨论讨论。还有二值化不行,这是我想当然的,觉得肯定不行所以没做实验。其他的我试了试,用给出的方法调整一下能量系数都可以。

我想大家最关心的是什么最安全,不会被追踪。
不涉及图像的都安全,比如拿笔记下来。
涉及图像的屏摄最安全
截屏十分不安全。

=====彩蛋====

我在上图明码写入了信息。为了抵抗jpg压缩,我水印能量较高,并且因为没有编码,能量分布不均。图中规律性纹路,就是你懂的。嘿嘿,你懂的,解开看看吧。

 

在答案中给出了上图隐写的内容,(雾)。

 

  1.  
  2. %%傅里叶变换加水印源代码 
  3. %% 运行环境Matlab2010a  
  4. clc;clear;close all; 
  5. alpha = 1
  6.  
  7. %% read data 
  8. im = double(imread('gl1.jpg'))/255; 
  9. mark = double(imread('watermark.jpg'))/255; 
  10. figure, imshow(im),title('original image'); 
  11. figure, imshow(mark),title('watermark'); 
  12.  
  13. %% encode mark 
  14. imsize = size(im); 
  15. %random 
  16. TH=zeros(imsize(1)*0.5,imsize(2),imsize(3)); 
  17. THTH1 = TH; 
  18. TH1(1:size(mark,1),1:size(mark,2),:) = mark; 
  19. M=randperm(0.5*imsize(1)); 
  20. N=randperm(imsize(2)); 
  21. save('encode.mat','M','N'); 
  22. for i=1:imsize(1)*0.5 
  23.     for j=1:imsize(2) 
  24.         TH(i,j,:)=TH1(M(i),N(j),:); 
  25.     end 
  26. end 
  27. % symmetric 
  28. mark_ = zeros(imsize(1),imsize(2),imsize(3)); 
  29. mark_(1:imsize(1)*0.5,1:imsize(2),:)=TH; 
  30. for i=1:imsize(1)*0.5 
  31.     for j=1:imsize(2) 
  32.         mark_(imsize(1)+1-i,imsize(2)+1-j,:)=TH(i,j,:); 
  33.     end 
  34. end 
  35. figure,imshow(mark_),title('encoded watermark'); 
  36. %imwrite(mark_,'encoded watermark.jpg'); 
  37.  
  38. %% add watermark 
  39. FA=fft2(im); 
  40. figure,imshow(FA);title('spectrum of original image'); 
  41. FB=FA+alpha*double(mark_); 
  42. figure,imshow(FB); title('spectrum of watermarked image'); 
  43. FAO=ifft2(FB); 
  44. figure,imshow(FAO); title('watermarked image'); 
  45. %imwrite(uint8(FAO),'watermarked image.jpg'); 
  46. RI = FAO-double(im); 
  47. figure,imshow(uint8(RI)); title('residual'); 
  48. %imwrite(uint8(RI),'residual.jpg'); 
  49. xl = 1:imsize(2); 
  50. yl = 1:imsize(1); 
  51. [xx,yy] = meshgrid(xl,yl); 
  52. figure, plot3(xx,yy,FA(:,:,1).^2+FA(:,:,2).^2+FA(:,:,3).^2)
  53. ,title('spectrum of original image'); 
  54. figure, plot3(xx,yy,FB(:,:,1).^2+FB(:,:,2).^2+FB(:,:,3).^2)
  55. ,title('spectrum of watermarked image'); 
  56. figure, plot3(xx,yy,FB(:,:,1).^2+FB(:,:,2).^2+FB(:,:,3).^2-FA(:,:,1).^2+FA(:,:,2).^2+FA(:,:,3).^2)
  57. ,title('spectrum of watermark'); 
  58.  
  59. %% extract watermark 
  60. FA2=fft2(FAO); 
  61. G=(FA2-FA)/alpha; 
  62. GGG=G; 
  63. for i=1:imsize(1)*0.5 
  64.     for j=1:imsize(2) 
  65.         GG(M(i),N(j),:)=G(i,j,:); 
  66.     end 
  67. end 
  68. for i=1:imsize(1)*0.5 
  69.     for j=1:imsize(2) 
  70.         GG(imsize(1)+1-i,imsize(2)+1-j,:)=GG(i,j,:); 
  71.     end 
  72. end 
  73. figure,imshow(GG);title('extracted watermark'); 
  74. %imwrite(uint8(GG),'extracted watermark.jpg'); 
  75.  
  76. %% MSE and PSNR 
  77. C=double(im); 
  78. RC=double(FAO); 
  79. MSE=0PSNR=0
  80. for i=1:imsize(1) 
  81.     for j=1:imsize(2) 
  82.         MSEMSE=MSE+(C(i,j)-RC(i,j)).^2; 
  83.     end 
  84. end 
  85. MSEMSE=MSE/360.^2; 
  86. PSNR=20*log10(255/sqrt(MSE)); 
  87. MSE 
  88. PSNR 
  89.  
  90. %% attack test 
  91. %% attack by smearing 
  92. %A = double(imread('gl1.jpg')); 
  93. %B = double(imread('attacked image.jpg')); 
  94. attack = 1-double(imread('attack.jpg'))/255; 
  95. figure,imshow(attack); 
  96. FAOFAO_ = FAO; 
  97. for i=1:imsize(1) 
  98.     for j=1:imsize(2) 
  99.         if attack(i,j,1)+attack(i,j,2)+attack(i,j,3)>0.5 
  100.             FAO_(i,j,:) = attack(i,j,:); 
  101.         end 
  102.     end 
  103. end 
  104. figure,imshow(FAO_); 
  105. %extract watermark 
  106. FA2=fft2(FAO_); 
  107. G=(FA2-FA)*2; 
  108. GGG=G; 
  109. for i=1:imsize(1)*0.5 
  110.     for j=1:imsize(2) 
  111.         GG(M(i),N(j),:)=G(i,j,:); 
  112.     end 
  113. end 
  114. for i=1:imsize(1)*0.5 
  115.     for j=1:imsize(2) 
  116.         GG(imsize(1)+1-i,imsize(2)+1-j,:)=GG(i,j,:); 
  117.     end 
  118. end 
  119. figure,imshow(GG);title('extracted watermark'); 
  120.  
  121. %% attack by cutting 
  122. s2 = 0.8; 
  123. FAOFAO_ = FAO; 
  124. FAO_(:,s2*imsize(2)+1:imsize(2),:) = FAO_(:,1:int32((1-s2)*imsize(2)),:); 
  125. figure,imshow(FAO_); 
  126. %extract watermark 
  127. FA2=fft2(FAO_); 
  128. G=(FA2-FA)*2; 
  129. GGG=G; 
  130. for i=1:imsize(1)*0.5 
  131.     for j=1:imsize(2) 
  132.         GG(M(i),N(j),:)=G(i,j,:); 
  133.     end 
  134. end 
  135. for i=1:imsize(1)*0.5 
  136.     for j=1:imsize(2) 
  137.         GG(imsize(1)+1-i,imsize(2)+1-j,:)=GG(i,j,:); 
  138.     end 
  139. end 
  140. figure,imshow(GG);title('extracted watermark'); 
  141.  
  142.  
  143. %%小波变换加水印,解水印大家按照加的思路逆过来就好 
  144. clc;clear;close all; 
  145. %% read data 
  146. im = double(imread('gl1.jpg'))/255; 
  147. mark = double(imread('watermark.jpg'))/255; 
  148. figure, imshow(im),title('original image'); 
  149. figure, imshow(mark),title('watermark'); 
  150. %% RGB division 
  151. im=double(im);  
  152. mark=double(mark);  
  153. imimr=im(:,:,1);  
  154. markmarkr=mark(:,:,1);  
  155. imimg=im(:,:,2);  
  156. markmarkg=mark(:,:,2);  
  157. imimb=im(:,:,3);  
  158. markmarkb=mark(:,:,3);  
  159. %% parameter 
  160. r=0.04;  
  161. g = 0.04;  
  162. b = 0.04; 
  163. %% wavelet tranform and add watermark 
  164. % for red 
  165. [Cwr,Swr]=wavedec2(markr,1,'haar');  
  166. [Cr,Sr]=wavedec2(imr,2,'haar');  
  167. % add watermark 
  168. Cr(1:size(Cwr,2)/16)=...  
  169. Cr(1:size(Cwr,2)/16)+r*Cwr(1:size(Cwr,2)/16);  
  170. k=0;  
  171. while k<=size(Cr,2)/size(Cwr,2)-1  
  172. Cr(1+size(Cr,2)/4+k*size(Cwr,2)/4:size(Cr,2)/4+...  
  173. (k+1)*size(Cwr,2)/4)=Cr(1+size(Cr,2)/4+...  
  174. k*size(Cwr,2)/4:size(Cr,2)/4+(k+1)*size(Cwr,2)/4)+...  
  175. r*Cwr(1+size(Cwr,2)/4:size(Cwr,2)/2);  
  176. Cr(1+size(Cr,2)/2+k*size(Cwr,2)/4:size(Cr,2)/2+...  
  177. (k+1)*size(Cwr,2)/4)=Cr(1+size(Cr,2)/2+...  
  178. k*size(Cwr,2)/4:size(Cr,2)/2+(k+1)*size(Cwr,2)/4)+...  
  179. r*Cwr(1+size(Cwr,2)/2:3*size(Cwr,2)/4);  
  180. Cr(1+3*size(Cwr,2)/4+k*size(Cwr,2)/4:3*size(Cwr,2)/4+...  
  181. (k+1)*size(Cwr,2)/4)=Cr(1+3*size(Cr,2)/4+...  
  182. k*size(Cwr,2)/4:3*size(Cr,2)/4+(k+1)*size(Cwr,2)/4)+...  
  183. r*Cwr(1+3*size(Cwr,2)/4:size(Cwr,2));  
  184. kk=k+1;  
  185. end;  
  186. Cr(1:size(Cwr,2)/4)=Cr(1:size(Cwr,2)/4)+r*Cwr(1:size(Cwr,2)/4);  
  187.  
  188. % for green 
  189. [Cwg,Swg]=WAVEDEC2(markg,1,'haar');  
  190. [Cg,Sg]=WAVEDEC2(img,2,'haar');  
  191. Cg(1:size(Cwg,2)/16)=...  
  192. Cg(1:size(Cwg,2)/16)+g*Cwg(1:size(Cwg,2)/16);  
  193. k=0;  
  194. while k<=size(Cg,2)/size(Cwg,2)-1  
  195. Cg(1+size(Cg,2)/4+k*size(Cwg,2)/4:size(Cg,2)/4+...  
  196. (k+1)*size(Cwg,2)/4)=Cg(1+size(Cg,2)/4+...  
  197. k*size(Cwg,2)/4:size(Cg,2)/4+(k+1)*size(Cwg,2)/4)+...  
  198. g*Cwg(1+size(Cwg,2)/4:size(Cwg,2)/2);  
  199. Cg(1+size(Cg,2)/2+k*size(Cwg,2)/4:size(Cg,2)/2+...  
  200. (k+1)*size(Cwg,2)/4)=Cg(1+size(Cg,2)/2+...  
  201. k*size(Cwg,2)/4:size(Cg,2)/2+(k+1)*size(Cwg,2)/4)+...  
  202. g*Cwg(1+size(Cwg,2)/2:3*size(Cwg,2)/4);  
  203. Cg(1+3*size(Cg,2)/4+k*size(Cwg,2)/4:3*size(Cg,2)/4+...  
  204. (k+1)*size(Cwg,2)/4)=Cg(1+3*size(Cg,2)/4+...  
  205. k*size(Cwg,2)/4:3*size(Cg,2)/4+(k+1)*size(Cwg,2)/4)+...  
  206. g*Cwg(1+3*size(Cwg,2)/4:size(Cwg,2));  
  207. kk=k+1;  
  208. end;  
  209. Cg(1:size(Cwg,2)/4)=Cg(1:size(Cwg,2)/4)+g*Cwg(1:size(Cwg,2)/4);  
  210.  
  211. % for blue 
  212. [Cwb,Swb]=WAVEDEC2(markb,1,'haar');  
  213. [Cb,Sb]=WAVEDEC2(imb,2,'haar');  
  214. Cb(1:size(Cwb,2)/16)+b*Cwb(1:size(Cwb,2)/16);  
  215. k=0;  
  216. while k<=size(Cb,2)/size(Cwb,2)-1  
  217. Cb(1+size(Cb,2)/4+k*size(Cwb,2)/4:size(Cb,2)/4+...  
  218. (k+1)*size(Cwb,2)/4)=Cb(1+size(Cb,2)/4+...  
  219. k*size(Cwb,2)/4:size(Cb,2)/4+(k+1)*size(Cwb,2)/4)+...  
  220. g*Cwb(1+size(Cwb,2)/4:size(Cwb,2)/2);  
  221. Cb(1+size(Cb,2)/2+k*size(Cwb,2)/4:size(Cb,2)/2+...  
  222. (k+1)*size(Cwb,2)/4)=Cb(1+size(Cb,2)/2+...  
  223. k*size(Cwb,2)/4:size(Cb,2)/2+(k+1)*size(Cwb,2)/4)+...  
  224. b*Cwb(1+size(Cwb,2)/2:3*size(Cwb,2)/4);  
  225. Cb(1+3*size(Cb,2)/4+k*size(Cwb,2)/4:3*size(Cb,2)/4+...  
  226. (k+1)*size(Cwb,2)/4)=Cb(1+3*size(Cb,2)/4+...  
  227. k*size(Cwb,2)/4:3*size(Cb,2)/4+(k+1)*size(Cwb,2)/4)+...  
  228. b*Cwb(1+3*size(Cwb,2)/4:size(Cwb,2));  
  229. kk=k+1;  
  230. end;  
  231. Cb(1:size(Cwb,2)/4)=Cb(1:size(Cwb,2)/4)+b*Cwb(1:size(Cwb,2)/4);  
  232. %% image reconstruction 
  233. imr=WAVEREC2(Cr,Sr,'haar');  
  234. img=WAVEREC2(Cg,Sg,'haar');  
  235. imb=WAVEREC2(Cb,Sb,'haar');  
  236. imsize=size(imr);  
  237. FAO=zeros(imsize(1),imsize(2),3);  
  238. for i=1:imsize(1);  
  239. for j=1:imsize(2);  
  240. FAO(i,j,1)=imr(i,j);  
  241. FAO(i,j,2)=img(i,j);  
  242. FAO(i,j,3)=imb(i,j);  
  243. end  
  244. end  
  245. figure, imshow(FAO); title('watermarked image'); 

 

(fuqiang liu)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/202101/17799.html]
本文出处:知乎 作者:fuqiang liu 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容