% 读入载体图像文件 file_name='1.bmp'; f=imread(file_name); subplot(221); imshow(f) title('原图'); f=double(f); % 读入载体文件的大小 Mc=size(f,1); %高度 Nc=size(f,2); %宽度 % 读入数字水印图像文件 file_name='2.bmp'; m=imread(file_name); subplot(222); imshow(m) title('原水印'); m=double(m); Mm=size(m,1); %水印图像的高度 Nm=size(m,2); %水印图像的宽度 %将水印图像转换为二值图像 m1=double(m); m=fix(m1./12); m=uint8(m); %一层haar小波变换 [A1,H1,V1,D1] = dwt2(f,'haar'); [r1,c1]=size(A1); r2=r1/2; c2=c1/2; % 嵌入水印 for i= 1:r1 for j= 1:c1 w(i,j)=m(mod(i,Mm)+1,mod(j,Nm)+1); end end for i=1:r2 for j=1:c2 if w(i,j)==1 if H1(i,(2*j-1))<H1(i,2*j) temp=H1(i,(2*j-1)); H1(i,(2*j-1))=H1(i,2*j); H1(i,2*j)=temp; end if H1(i,(2*j-1))==H1(i,2*j) H1(i,(2*j))=H1(i,(2*j))-0.0001; end end if w(i,j)==0 if H1(i,(2*j-1))>H1(i,2*j) temp=H1(i,2*j-1); H1(i,(2*j-1))=H1(i,2*j); H1(i,2*j)=temp; end if H1(i,(2*j-1))==H1(i,2*j) H1(i,(2*j))=H1(i,(2*j))+0.0001; end end end end % 实现小波的反变换 f=idwt2(A1,H1,V1,D1,'haar',[Mc,Nc]); subplot(223) imshow(uint8(f)); title('嵌入水印后的图'); % 读取该图像的高度和宽度 Mw=size(f,1); %高度 Nw=size(f,2); %宽度 %一层harr小波变换 [A1,H1,V1,D1] = dwt2(f,'haar'); [r1,c1] = size(A1); r2=r1/2; c2=c1/2; %提取水印 for i=1:r2 for j=1:c2 if H1(i,2*j-1)>=H1(i,2*j) k(i,j)=1; else k(i,j)=0; end end end subplot(224) imshow(k); title('提取的水印')
效果:
原理:嵌入算法
首先将256×256分辨率的256级载体灰度图像进行一层小波变换,如下:
[A1,H1,V1,D1] = dwt2(f,‘haar’)得到A1,H1,V1,D1这样四个128×128大小的矩阵。其中f是256×256大小的矩阵,保存着分辨率为256×256、灰度级别为256的载体灰度图像,A1、H1、V1、D1分别是lena图像的低频逼近子图、水平方向细节子图、垂直方向细节子图、对角线方向的高频细节子图。接着,读入水印图像,将水印图像转换为二值图像,要求水印图像的大小为载体图像的八分之一。将水印图像的信息存入一个二维数组中。
最后,嵌入水印。如果将水印嵌入低频系数A1中,水印的鲁棒性好,但水印的隐蔽性差;如果将水印嵌入高频系数D1中,水印的隐蔽性好,但水印的鲁棒性差。同时考虑到水印的鲁棒性和隐蔽性,将这两种方案折中一下,本算法将水印嵌入到小波变换的水平方向细节的中频系数H1中。H1是一个二维数组,将H1的数据分为像素对,比较每对像素值的大小,前者大于后者表示1,前者小于后者表示0,若二者相等,则将其中一个的值做微小调整,使得每一像素对的大小关系和水印二值图像的每一位相对应。对不能对应的像素对,将像素对前后的位置互换。
水印提取算法
首先读入带有水印的载体图像,将该图像进行一层小波分解:
[A1,H1,V1,D1]=dwt2(f,‘haar’)
其中f是256×256大小的矩阵,保存着分辨率为256×256、灰度级别为256的嵌入了水印图像的载体灰度图像。
接着,从H1中提取水印,提取水印是嵌入水印的逆过程,将H1分为像素对,比较每对像素值的大小,如果前者大于后者,提取1,如果前者小于后者,提取0。