上学期帮同校本科的同学做了毕业设计的实验部分,用MATLAB实现DCT水印算法,并且包含了攻击测试。先讲一个大体概念,然后放出具体代码。

一、DCT

DCT(离散余弦变换),这里只以二维DCT为例。
信号经过DCT后,从空间域变换到频域。是一种正交变换的方法。是图像处理中应用即为广泛的傅氏变换中一种特殊的情况(被展开函数是实偶函数,再离散化,即为离散余弦变换)。
同傅氏变换一样,有正反两种变换。
正DCT:从空间域变为频域。反DCT:从频域变为空间域。具体公式如下。

正DCT:

基于dct域的数字水印算法 python实现 基于dct图像水印技术_频域


其中:

基于dct域的数字水印算法 python实现 基于dct图像水印技术_毕业设计_02

反DCT

基于dct域的数字水印算法 python实现 基于dct图像水印技术_毕业设计_03


f(x,y)是空间采样值,简单说,就是点(x,y)的像素值。F(u,v)是频域采样值。

二、水印算法

水印,就好像给图片盖章,注明所有权。

基于dct域的数字水印算法 python实现 基于dct图像水印技术_算法_04

具体的概念不多讲,若是想深入了解,可以自行百度。

%图片加水印,提取出水印
%林多
%%%%%%%%%%%%%
M=256; %原图像长度
N=32; %水印图像长度
K=8; %8x8的分块
I=zeros(M,M);%创建一个MxM矩阵,元素全是0
J=zeros(N,N);
BLOCK = zeros(K,K);
%显示原图像
subplot(5,2,1);%显示多幅图像,在第一个位置显示
I=imread('23.bmp');%将23.bmp读入I中
imshow(I);%显示图像
title('原始公开图像');%标题
%显示水印图像
subplot(5,2,2);
J=imread('21.bmp');
imshow(J);
title('水印图像');
%水印嵌入算法
for p=1:N %从1到32循环
 for q=1:N %从1到32循环
  x=(p-1)*K+1; y=(q-1)*K+1;
  BLOCK=I(x:x+K-1,y:y+K-1);%取相应元素保存到BLOCK中
  BLOCK=dct2(BLOCK);%二维离散余弦变换
  if J(p,q)==0 %如果元素为0
    a=-1;
  else
    a=1;
  end
  BLOCK=BLOCK*(1+a*0.03);  BLOCK=idct2(BLOCK);%反二维离散余弦变换
  I(x:x+K-1,y:y+K-1)=BLOCK;
 end
end
%显示嵌入水印后的图像
subplot(5,2,3);
imshow(I);
title('嵌入水印后的图像');
imwrite(I,'watermarked.bmp','bmp');%保存成watermarked.bmp
I=imread('23.bmp');%未加水印的原图像
P=imread('watermarked.bmp');%水印图像
%提取水印算法
for p=1:N
for q=1:N
x=(p-1)*K+1;
y=(q-1)*K+1;
BLOCK1=I(x:x+K-1,y:y+K-1);%赋给BLOCK1元素
BLOCK2=P(x:x+K-1,y:y+K-1);%赋给BLOCK2元素
BLOCK1=idct2(BLOCK1);%对其本身进行反二维离散余弦变换
BLOCK2=idct2(BLOCK2);%对其本身进行反二维离散余弦变换
a=BLOCK2(1,1)/BLOCK1(1,1)-1;
if a<0
W(p,q)=0;
else
W(p,q)=1;
end
end
end
%显示提取的水印
subplot(5,2,4);
imshow(W);
title('从含水印图像中提取的水印');

%----------攻击测试-----------------------%

%----------中值攻击----------%
P1=imread('watermarked.bmp');
P1=double(P1(:,:,1));%取1通道
P1=medfilt2(P1);%中值滤波
subplot(5,2,5);
imshow(P1,[]);
title('中值滤波攻击');
I1=imread('23.bmp');%未加水印的原图像
%提取水印算法
for p=1:N
for q=1:N
x=(p-1)*K+1;
y=(q-1)*K+1;
BLOCK1=I1(x:x+K-1,y:y+K-1);%赋给BLOCK1元素
BLOCK2=P1(x:x+K-1,y:y+K-1);%赋给BLOCK2元素
BLOCK1=idct2(BLOCK1);%对其本身进行反二维离散余弦变换
BLOCK2=idct2(BLOCK2);%对其本身进行反二维离散余弦变换
a=BLOCK2(1,1)/BLOCK1(1,1)-1;
if a<0
W1(p,q)=0;
else
W1(p,q)=1;
end
end
end
subplot(5,2,6);
imshow(W1);
title('从含中值滤波图像中提取的水印');

%----------变小攻击----------%
P2=imread('watermarked.bmp');
P2=imresize(P2,0.5);%变为0.5倍,从256x256到128x128
subplot(5,2,7);
imshow(P2,[]);%显示变小后图像
title('变小攻击,变为128x128像素');
I2=imread('23.bmp');%未加水印的原图像
I2=imresize(I2,0.5);%原图像一样变小
%提取水印算法
for p=1:32
for q=1:32
x=(p-1)*4+1;
y=(q-1)*4+1;
BLOCK1=I2(x:x+4-1,y:y+4-1);%赋给BLOCK1元素
BLOCK2=P2(x:x+4-1,y:y+4-1);%赋给BLOCK2元素
BLOCK1=idct2(BLOCK1);%对其本身进行反二维离散余弦变换
BLOCK2=idct2(BLOCK2);%对其本身进行反二维离散余弦变换
a=BLOCK2(1,1)/BLOCK1(1,1)-1;
if a<0
W2(p,q)=0;
else
W2(p,q)=1;
end
end
end
subplot(5,2,8);
imshow(W2);
title('从128x128图像中提取水印');

%-------旋转攻击-------%
P3=imread('watermarked.bmp');
P3=imrotate(P3,90);%逆时针旋转90度;
subplot(5,2,9);
imshow(P3,[]);
title('旋转攻击');
I3=imread('23.bmp');%未加水印的原图像
I3=imrotate(I3,90); %原图像逆时针旋转90度;
%提取水印算法
for p=1:N
for q=1:N
x=(p-1)*K+1;
y=(q-1)*K+1;
BLOCK1=I3(x:x+K-1,y:y+K-1);%赋给BLOCK1元素
BLOCK2=P3(x:x+K-1,y:y+K-1);%赋给BLOCK2元素
BLOCK1=idct2(BLOCK1);%对其本身进行反二维离散余弦变换
BLOCK2=idct2(BLOCK2);%对其本身进行反二维离散余弦变换
a=BLOCK2(1,1)/BLOCK1(1,1)-1;
if a<0
W3(p,q)=0;
else
W3(p,q)=1;
end
end
end
subplot(5,2,10);
imshow(W3);
title('从含旋转图像中提取的水印');

基于dct域的数字水印算法 python实现 基于dct图像水印技术_算法_05


原图与加水印(右侧,仔细看)后的对比。

基于dct域的数字水印算法 python实现 基于dct图像水印技术_毕业设计_06