基于MATLAB的数字水印算法实现
一、课题介绍
数字水印(Digital Watermark)技术是指用信号处理的方法在数字化的多媒体数据中嵌入隐蔽的标记,这种标记通常是不可见的,只有通过专用的检测器或阅读器才能提取。数字水印是信息隐藏技术的一个重要研究方向。随着数字水印技术的发展,数字水印的应用领域也得到了扩展,数字水印的基本应用领域是版权保护、隐藏标识、认证和安全不可见通信。
当数字水印应用于版权保护时,潜在的应用市场在于电子商务、在线或离线地分发多媒体内容以及大规模的广播服务。数字水印用于隐藏标识时,可在医学、制图、数字成像、数字图像监控、多媒体索引和基于内容的检索等领域得到应用。数字水印的认证方面主要ID卡、信用卡、ATM卡等上面数字水印的安全不可见通信将在国防和情报部门得到广泛的应用。
本文主要是根据所学的数字图象处理知识,在MATLAB环境下,通过系统编程的方式,建立并实现基于DCT域的数字水印加密系统。该系统主要包含数字水印的嵌入与提取,仿真结果表明,数字水印算法具有有效性、可靠性、抗攻击性、鲁棒性和不可见性,能够为数字媒体信息在防伪、防篡改、认证、保障数据安全和完整性等方面提供有效的技术保障。
二、课题提纲
1 设计目的
2 设计要求
3 数字水印技术基本原理
3.1 数字水印基本框架
3.2 算法分类
3.2.1 DCT法
3.2.2 其他方法
3.3 实际需要考虑的问题
3.3.1 不可见性
3.3.2 鲁棒性
3.3.3 水印容量
3.3.4 安全性
4 基于DCT变换仿真
4.1 算法原理
4.1.1 准备工作
4.1.2 选取8*8变换块
4.1.3 边界自适应
4.1.4 DCT变换与嵌入
4.1.5 恢复空域8
4.2 嵌入算法扩展
4.2.1 RGB彩色图像三个矩阵的划分
4.2.2 八色彩色水印
4.3 水印的提取
4.4 仿真程序
5 结果分析4
结束语7
参考文献8
三、数字水印技术基本原理
3.1 数字水印基本框架
一个数字水印系统一般包括三个基本方面:水印的生成、水印的嵌入和水印的提取或检测。数字水印的嵌入和提取的一般过程基本框架如图3.1,图3.2所示。
水印生成算法(G)
数字水印(W)
原始载体数据(J)
水印嵌入算法(E)
私钥/公钥(K)
嵌入水印后的数据(IW)
图3.1 水印嵌入的一般过程基本框架
待检测数据(IW)
水印检测算法(D)
私钥/公钥(K)
估计水印(W)/相似度检测(Sim)
数字水印(W)/原始数据(I)
图3.2 水印检测的一般过程基本框架
3.2 算法分类
根据水印实现方法不同,数字水印可分为空(时)域数字水印和频域数字水印。
空域数字水印是直接在信号空间上叠加水印信号,而频域法加入数字水印的原理是首先将原始信号(语音一维信号、图像二维信号)变换到频域,常用的变换一般有DWT、DCT、DFT、WP和分形。然后,对加入了水印信息的信号进行频域反变换(IDWT、IDCT、DFT、WP),得到含有水印信息的信号。
频域法检测水印的原理是将原始信号与待检测信号同时进行变换域变换,比较两者的区别,进行嵌入水印的逆运算,得出水印信息。如果是可读的水印,那么就此结束,如果是不可读水印,如高斯噪声,就将得出的水印与已知水印作比较,由相关性判断,待检测信号含不含水印,故水印的检测有两个结束点。
频域法有以下优点:嵌入的水印信号能量可以分布到空域的所有像素上,有利于保证水印的不可见性;视觉系统(HVS)的某些特性(如频率的掩蔽特性)可以更方便地结合到水印编码过程中;频域法可与国际数据压缩标准兼容,从而实现在压缩域(compressed domain)内的水印编码。
3.2.1 DCT法
对原始信号做DCT的算法:Cox和Piva等人提出的DCT技术的经典之作。Cox利用随机数发生器产生标准正态序列作为水印信息对图像进行整体DCT变换后,选取除去DC系数之外部分较低频率系数叠加水印信息;Piva则修改整幅图像的中频部分。
对原始信号分块后,再作DCT的算法:Hsu和Wu把图像进行8*8分块,将一个二进制序列作为水印放入DCT的中频区;有些学者则计算整个图像的DCT,把一个实数序列嵌入DCT的中频系数上。选择中频区的好处是一方面尽量减少嵌入信息对图像主观视觉的影响;同时,尽量避免有损压缩对水印信息可能带来的损失。
还有一种DCT方法就是把水印信息嵌入到高频系数上,但是采用这种方法,抗压缩性非常差。
3.3 实际需要考虑的问题
在数字水印技术中,水印的数据量和鲁棒性构成了一对基本矛盾。从主观上讲,理想的水印算法应该既能隐藏大量数据,又可以抗各种信道噪声和信号变形。然而在实际中,这两个指标往往不能同时实现,不过这并不会影响数字水印技术的应用,因为实际应用一般只偏重其中的一个方面。如果是为了隐蔽通信,数据量显然是最重要的,由于通信方式极为隐蔽,遭遇敌方篡改攻击的可能性很小,因而对鲁棒性要求不高。但对保证数据安全来说,情况恰恰相反,各种保密的数据随时面临着被盗取和篡改的危险,所以鲁棒性是十分重要的,此时,隐藏数据量的要求居于次要地位。
3.3.1 不可见性
对于以模拟方式存储和分发的信息(如电视节目),或是以物理形式存储的信息(如报刊、杂志),用可见的标志就足以表明其所有权。但在数字方式下,标志信息极易被修改或擦除。因此应根据多媒体信息的类型和几何特性,利用用户提供的密钥将水印隐藏到一系列随机产生的位置中,使人无法察觉。图3.3左侧为原始图像,右侧为嵌入水印后的图像。
图3.3 原始图像与嵌入水印后的图像对比
3.3.2 鲁棒性
水印必须对一般的信号处理操作(如滤波、平滑、增强、有失真压缩等)、删除攻击、迷惑攻击等具有鲁棒性。除非对数字水印具有足够的先验知识,任何破坏和消除水印的企图都将严重破坏多媒体信息的质量。
3.3.3 水印容量
嵌入的水印信息必须足以表示多媒体内容的创建者或所有者的标志信息,或是购买者的序列号。这样在发生版权纠纷时,创建者或所有者的信息用于标示数据的版权所有者,而序列号用于标示违反协议而为盗版提供多媒体数据的用户。
数字水印在多媒体信息安全中的另一个重要应用就是内容的真实性鉴定(即认证)。当多媒体内容发生改变时,具有较强的敏感性的易损水印(Fragile watermarking)会随之发生一定程度的改变,从而可以鉴定原始数据是否被篡改。
3.3.4 安全性
水印的安全性要求未授权者不能发现数字作品中含有水印信息。或者算法安全性仅仅依赖于密钥而不依赖于算法的保密性。因此在没有密钥的情况下,未授权者即使知道含有水印信息和知道水印算法,也不能提取出水印信息或者破坏水印信息。另外算法还应该能够抵抗合谋攻击。
由于水印特性的要求对应用的依赖型很强,恰当的评价准则和具体的应用有关。
四、基于DCT变换的具体实现
4.1 算法原理
离散余弦变换(Diserete Cosine Transform)简称DCT变换。离散余弦变换是傅立叶变换的一种特殊情况,在傅立叶级数展开式中,如果被展开的函数是实偶函数,那么其傅立叶级数中只包含余弦项,再将其离散化可导出离散余弦变换,因此余弦变换与傅里叶变换一样有明确的物理意义,DCT变换避免了傅里叶变换中的复数运算,它是基于实数的正交变换。
DCT变换域数字水印算法的基本原理是将空域图像变成频域,然后将水印信息嵌入其直流项之中,最后将频域转换成空域以完成图片的水印的嵌入。其主要思想是:在DCT变换域上选择中、低频系数叠加水印信息,因为人眼的感觉主要集中在中、低频段,攻击者破坏水印时,不可避免地会引起图像质量的严重下降,而且一般的图像处理也不会改变这部分数据。再者,由于JPEG、MPEG等压缩算法的核心是在DCT变换域上进行量化,故通过巧妙的融合水印和量化过程,可以使水印抵御一定的有损压缩。此外,DCT变换域系数的统计分布有比较好的数学模型,可以从理论上估计水印的信息量。基于DCT变换的数字水印在逆变换时会散布在整个图像空间中,故水印不像空间域技术那样易受到裁剪、低通滤波等攻击的影响,具有鲁棒性高、隐蔽性好的特点。
4.1.1 DCT变换与嵌入
首先,要检测变换块是否含有边界,可以将边界图像与原图相对应位置的象素块提出,将块中所有象素的值(只含0,1)求和的方法检测它是否含有边界,不妨设置一个阈值等于3,即该块中含有三个或以上的边界点就认为该块含有较多的边界信息,通过边界自适应的原理应当将较大的强度值嵌入。
然后,需要将每一个8*8块进行DCT变换,并将变换后的直流分量与强度值和水印图像相应点象素的信息相乘。在这里需要指出的是为了保证提取算法的简单可以令水印图像象素的值减一个比较小的值。
这一步用MATLAB来实现可以用block_dct1=dct2(block_dct1)分别将8*8块进行二维DCT变换,block_dct1(1,1)=block_dct1(1,1)*(1+Alpha*(mark(m,n)-0.1))其中的mark表示水印图像的象素值,将它嵌入块的直流项中。
4.1.2 恢复空域
将嵌入后的块分别进行反DCT变换,并且按顺序存回I矩阵,这时的I就是嵌入水印后的图像。
4.2 嵌入算法扩展
上面的方法一般只能对一幅灰度图像嵌入一幅二值图像,在下面将进行彩色图像嵌入三幅二值图像或一幅8色彩色图像的方法。
4.2.1 RGB彩色图像三个矩阵的划分
由于所有的RGB彩色图像都是由红绿蓝三个颜色组成的,在存储中这三个图像也是分为3个矩阵存储的,那么我们就可以将每个矩阵视为一个灰度,并且每个灰度图像中都可以分别潜入一个水印图像。
1、彩色图像的边缘图像
由于edge函数中的I必须是灰度图像,所以要想用GRAY=rgb2gray(I)语句将彩色图像变成灰度图像,再将灰度图像GRAY取其边界图像。
2、彩色图像分层
在MATLAB中,将彩色RGB图像读入I后,不同于灰度图像,I矩阵是一个三维矩阵它可以表示为I(a,b,c)其中当c=1时,I(a,b,1)表示彩色图像中红色分量的矩阵,同样的,I(a,b,2)、I(a,b,3)分别表示彩色图像中绿色和蓝色分量的矩阵。在分层嵌入的时候,表示原图像矩阵就需要加入第三维分量c的值,否则MATLAB会默认c=1。
这里需要注意的是,在新图像的生成的时候,要将R、G、B三个矩阵全部存入输出的矩阵,否则会缺色。
4.2.2 八色彩色水印
类似于上面的原理,作为水印的彩色图像也分为R,G,B三层,每层可以作为一幅水印图像分别嵌入原图像的矩阵中。提取的时候只要将提取出的三个水印图像存入一个三维矩阵即使一幅彩色图像。
但是这里要注意的是所用的水印图像的R、G、B分量分别只有0、1两个值。所以如果使用的彩色图像不当将会影响嵌入效果,甚至无法提取。
4.3 水印的提取
这里的水印提取方法可以看作是嵌入的反变换,由于在频域的8*8块的直流量中乘上了与水印信息有关的系数,那么同样我们可以通过原图像与水印图像8*8块直流分量的值相除得到的商即是与水印图像相关的值,由于嵌入时水印图像值只含0、1,而且我们在这个值得后面又减了一个小的常数,因此将除得的商减去1记为cc,这样就可以在嵌入的水印值为0的时候cc<0,反之在嵌入的水印值为1的时候cc>0。这样就可以绘制出水印图像。
4.4 源码
blockno=size/block; %每行块的个数
LENGTH=size*size/64; %总块的个数1024
Alpha1=0.03; %非边界处的强度因子
Alpha2=0.1; %边界处的强度因子
T1=3; %域值为三个边界点
I=zeros(size,size); %原始图像
BW=zeros(size,size); %原始图像的边缘图
block_dct1=zeros(block,block);
mark=imread('D:\水印图','bmp'); %沈阳理工大学字样彩色水印图
mark1=logical(mark(:,:,1));
mark2=logical(mark(:,:,2));
mark3=logical(mark(:,:,3));
figure(1)
subplot(2,2,1);
imshow(mark);title('水印图像');
%显示原图
subplot(2,2,2);I=imread('D:\原始图','bmp'); %读入彩色图像
imshow(I);title('原始图像:I');
%显示prewitt为算子的边缘图
GRAY=rgb2gray(I); %变灰度要用三位数,即彩色图片
BW=edge(GRAY,'prewitt'); %取边界,用于边界自适应
subplot(2,2,3);imshow(BW);
title('原始图像的边缘');
%嵌入水印
for m=1:blockno; %到第(m,n)个块
for n=1:blockno;
x=(m-1)*block+1; %该块的起始像素
y=(n-1)*block+1;
block_dct1=I(x:x+block-1,y:y+block-1); %取该块所有像素
block_dct1=dct2(block_dct1); %变换
%第二维
block_dct2=I(x:x+block-1,y:y+block-1,2); %取该块所有像素
block_dct2=dct2(block_dct2); %变换
BW_8_8=BW(x:x+block-1,y:y+block-1); %取边缘的对应块像素
if m<=1|n<=1;%m或n小于等于1时,
T=0;
else
T=sum(BW_8_8); %列取和
T=sum(T); %对整个BW_8_8中的数字取和
%取和
end
if T>T1; %如果改为<则意味着高频区嵌入了低能量,低频区嵌入了高能量。所以在低频区嵌入的过高能量会是不该看出的水印显示出来
%因此这里表示着边缘自适应性
Alpha=Alpha2; %0.1
else
Alpha=Alpha1; %0.03
end
block_dct1(1,1)=block_dct1(1,1)*(1+Alpha*(mark1(m,n)-1)); %对直流进行嵌入
block_dct2(1,1)=block_dct2(1,1)*(1+Alpha*(mark2(m,n)-1)); %第二层
block_dct3(1,1)=block_dct3(1,1)*(1+Alpha*(mark3(m,n)-1)); %第三层
block_dct1=idct2(block_dct1); %变回空域
block_dct2=idct2(block_dct2); %第二层
block_dct3=idct2(block_dct3); %第三层
I(x:x+block-1,y:y+block-1)=block_dct1; %贴回原图像
I(x:x+block-1,y:y+block-1,2)=block_dct2; %第二层
I(x:x+block-1,y:y+block-1,3)=block_dct3; %第三层
end
end
%显示嵌入水印后的图像
subplot(2,2,4);imshow(I);title('嵌入水印后的图像');
imwrite(I,'D:\输出图.bmp','bmp');
figure(2);subplot(2,2,1);imshow(mark(:,:,1));title('原水印的第一层');
subplot(2,2,2);imshow(mark(:,:,2));title('原水印的第二层');
subplot(2,2,3);imshow(mark(:,:,3));title('原水印的第三层');
imwrite(I,'D:\压缩图.jpg','jpg','quality',90); %压缩
%通过原图片对比提取水印
I=imread('D:\原始图.bmp','bmp');
J=imread('D:\输出图.bmp','bmp');
K=zeros(32,32,3); %水印图片为32*32
for q=1:blockno;
for p=1:blockno;
x=(p-1)*block+1;
y=(q-1)*block+1;
BLOCK1=I(x:x+block-1,y:y+block-1); %取无水印图的块
BLOCK2=J(x:x+block-1,y:y+block-1); %取带水印图的块
BLOCK1=dct2(BLOCK1);
BLOCK2=dct2(BLOCK2);
a=BLOCK2(1,1)/BLOCK1(1,1)-1;
%第二层
BLOCK12=I(x:x+block-1,y:y+block-1,2);
BLOCK22=J(x:x+block-1,y:y+block-1,2);
BLOCK12=dct2(BLOCK12);
BLOCK22=dct2(BLOCK22);
b=BLOCK22(1,1)/BLOCK12(1,1)-1;
%第三层
BLOCK13=I(x:x+block-1,y:y+block-1,3);
BLOCK23=J(x:x+block-1,y:y+block-1,3);
BLOCK13=dct2(BLOCK13);
BLOCK23=dct2(BLOCK23);
c=BLOCK23(1,1)/BLOCK13(1,1)-1;
if a<0
W(p,q)=0; %恢复水印图像
else
W(p,q)=1;
end
if b<0
W2(p,q)=0;
else
W2(p,q)=1;
end
end
end
figure(3);
subplot(2,2,1);imshow(W);
title('从第一层提取的水印(红R)'); %0表示黑色
subplot(2,2,2);imshow(W2);
title('从第二层提取的水印(绿G)');
subplot(2,2,3);imshow(W3);
title('从第三层提取的水印(蓝B)');
K(:,:,1)=W;
K(:,:,2)=W2;
K(:,:,3)=W3;
subplot(2,2,4);imshow(K);title('合并的彩图');
%检测压缩后的水印图像
J=imread('D:\压缩图.jpg','jpg');
for q=1:blockno;
for p=1:blockno;
x=(p-1)*block+1;
y=(q-1)*block+1;
BLOCK1=I(x:x+block-1,y:y+block-1); %取无水印图的块
BLOCK2=J(x:x+block-1,y:y+block-1); %取带水印图的块
%第二层
BLOCK12=I(x:x+block-1,y:y+block-1,2);
BLOCK22=J(x:x+block-1,y:y+block-1,2);
BLOCK12=dct2(BLOCK12);
BLOCK22=dct2(BLOCK22);
b=BLOCK22(1,1)/BLOCK12(1,1)-1;
%第三层
BLOCK13=I(x:x+block-1,y:y+block-1,3);
BLOCK23=J(x:x+block-1,y:y+block-1,3);
BLOCK13=dct2(BLOCK13);
BLOCK23=dct2(BLOCK23);
c=BLOCK23(1,1)/BLOCK13(1,1)-1;
if a<0
W(p,q)=0;
else
W(p,q)=1;
end
if b<0
W2(p,q)=0;
else
W2(p,q)=1;
end
if c<0
W3(p,q)=0;
else
W3(p,q)=1;
end
end
end
K(:,:,1)=W;K(:,:,2)=W2;K(:,:,3)=W3;
figure(4);imshow(K);title('90压缩的提取');
五、运行结果仿真
图5.1 原始图像与嵌入水印后的图像对比
原始图像与嵌入水印后的图像仅有微小的差别,人眼基本分辨不出两图像的任何不同。这说明DCT域水印算法具有较好的不可见性,基本不影响视觉质量,同时也很好的达到了透明性的要求。
图5.2 通过与原图片对比提取的水印
图5.3 分层提取的水印图像
在分层提取水印图像时,出现了部分误差,部分图像像素点出现了消失,组成彩色水印还原水印图像时,已经不能还原出原本彩色图像。
图5.4 检测压缩后的水印图像结果
由以上结果可以看出,该方法在水印嵌入和提取中方法比较简单。这个方法对于压缩攻击的抗性很低,可以说是脆弱的,很明显在90质量的压缩下已经很难分辨水印内容。
实验结果在某方面验证了该算法的有效性、可靠性、抗攻击性、鲁棒性和不可见性,能够为数字媒体信息在防伪、防篡改、认证、保障数据安全和完整性等方面提供有效的技术保障。
文献
[1] 阮秋琦. 数字图像处理学[M]. 北京:电子工业出版社,2001.
[2] 龚声蓉,刘纯平,王强等. 数字图像处理与分析[M]. 北京:清华大学出版社,2006.
[3] 贾永红. 计算机图像处理与分析[M]. 武汉:武汉大学出版社,2001.
[4] 陈桂明. 应用MATLAB语言处理数字信号与图像处理[M]. 北京:科学出版社,2000.
[5] 夏德深,傅德胜. 计算机图像处理及应用[M]. 南京:东南大学出版社,2004.
[6] 姚敏. 计算机图像处理[M]. 北京:机械工业出版社,2006.
[7] 容观澳. 计算机图像处理[M]. 北京:清华大学出版社,2000.
[8] 吴健康. 数字图像分析[M]. 北京:邮电出版社,1989.