脆弱水印嵌入算法及 MATLAB 代码实现
脆弱水印嵌入算法及 MATLAB 代码实现
本代码实现了一种基于小波变换的脆弱水印嵌入算法,能够将水印信息嵌入到图像中,并通过提取水印信息来检测图像是否被篡改。
算法原理:
- 对图像进行一层小波分解,得到四个子带:LL, LH, HL, HH。
- 根据 LH 和 HL 子带的能量大小,选择其中一个子带作为嵌入水印的区域。
- 在选择的子带中,将水印信息嵌入到 2x2 的图像块中。
- 将嵌入水印后的子带与其他子带进行合并,得到嵌入水印后的图像。
代码实现:
% 脆弱水印嵌入算法
function I_wm = wm_embed(I, wm)
% 输入:I 为待嵌入水印的图像,wm 为水印
% 输出:I_wm 为嵌入水印后的图像
%%
% 一层小波分解
[LL,LH,HL,HH] = dwt2(I,'haar');
%=======计算avr_LH======
[m,n] = size(LH); avr_LH = 0;
for i = 1:m
for j = 1:n
avr_LH = avr_LH + abs(LH(i,j));
end
end
avr_LH = avr_LH / (m*n);
%=======计算avr_HL======
[m0,n0] = size(HL); avr_HL = 0;
for i = 1:m0
for j = 1:n0
avr_HL = avr_HL + abs(HL(i,j));
end
end
avr_HL = avr_HL / (m0*n0);
% 判断嵌入的子带
if avr_LH <= avr_HL
num = 0; loca = LH;
else
num = 1; loca = HL;
end
%%
% 嵌入水印
if num == 0
I_wm = wm_embed_type1(I, loca, wm); % 写出嵌入子函数
else
I_wm = wm_embed_type0(I, loca, wm); % 写出嵌入子函数
end
%%
% 显示嵌入水印后的图像
figure,imshow(I_wm);
title('嵌入水印后的图像');
%%
% 提取水印
rw = wm_extr(I_wm);
%%
% 比较提取的水印和原水印
if isequal(rw,wm)
disp('水印正确提取!');
else
disp('水印提取错误!');
end
end
%%
% 子函数1:嵌入水印到 LH 子带
function I_wm = wm_embed_type1(I, loca, wm)
[mm,nn] = size(loca);
wm_len = length(wm);
index = 1;
% 取出 2x2 的块
for k = 1:2:mm-1
for kk = 1:2:nn-1
tem = loca(k:k+1,kk:kk+1);
a11 = tem(1,1);
a12 = tem(1,2);
a21 = tem(2,1);
a22 = tem(2,2);
%-------a11+a21 >= a12+a22则水印为0,否则为1-------
if wm(index) == 0
if a11 + a21 >= a12 + a22
loca(k:k+1,kk:kk+1) = [a11,a12;a21,a22];
else
loca(k:k+1,kk:kk+1) = [a12,a11;a22,a21];
end
else
if a11 + a21 >= a12 + a22
loca(k:k+1,kk:kk+1) = [a12,a11;a22,a21];
else
loca(k:k+1,kk:kk+1) = [a11,a12;a21,a22];
end
end
index = index + 1;
if index > wm_len
break;
end
end
if index > wm_len
break;
end
end
% 将修改后的 LH 子带和其他子带合并
I_wm = idwt2(LL,loca,HL,HH,'haar');
end
%%
% 子函数2:嵌入水印到 HL 子带
function I_wm = wm_embed_type0(I, loca, wm)
[mm,nn] = size(loca);
wm_len = length(wm);
index = 1;
% 取出 2x2 的块
for k = 1:2:mm-1
for kk = 1:2:nn-1
tem = loca(k:k+1,kk:kk+1);
a11 = tem(1,1);
a12 = tem(1,2);
a21 = tem(2,1);
a22 = tem(2,2);
%-------a11+a21 >= a12+a22则水印为0,否则为1-------
if wm(index) == 0
if a11 + a21 >= a12 + a22
loca(k:k+1,kk:kk+1) = [a11,a21;a12,a22];
else
loca(k:k+1,kk:kk+1) = [a21,a11;a22,a12];
end
else
if a11 + a21 >= a12 + a22
loca(k:k+1,kk:kk+1) = [a21,a11;a22,a12];
else
loca(k:k+1,kk:kk+1) = [a11,a21;a12,a22];
end
end
index = index + 1;
if index > wm_len
break;
end
end
if index > wm_len
break;
end
end
% 将修改后的 HL 子带和其他子带合并
I_wm = idwt2(LL,LH,loca,HH,'haar');
end
%%
% 子函数3:提取水印(通用)
function rw = wm_extr(J)
% 此函数为提取过程
% 输入:J 为水印嵌入的图像;
% 输出:rw 为提取的水印
%%
% 一层小波分解
[LL,LH,HL,HH] = dwt2(J,'haar');
%=======计算avr_LH======
[m,n] = size(LH); avr_LH = 0;
for i = 1:m
for j = 1:n
avr_LH = avr_LH + abs(LH(i,j));
end
end
avr_LH = avr_LH / (m*n);
%=======计算avr_HL======
[m0,n0] = size(HL); avr_HL = 0;
for i = 1:m0
for j = 1:n0
avr_HL = avr_HL + abs(HL(i,j));
end
end
avr_HL = avr_HL / (m0*n0);
% 判断嵌入的子带
if avr_LH <= avr_HL
num = 0; loca = LH;
else
num = 1; loca = HL;
end
%%
% 提取水印
if num == 0
rw = wm_extr_type1(loca); % 写出提取子函数
else
rw = wm_extr_type0(loca); % 写出提取子函数
end
end
%%
% 子函数4:提取水印(嵌入到 LH 子带)
function rw = wm_extr_type1(loca)
[mm,nn] = size(loca);
index = 1;
% 取出 2x2 的块
for k = 1:2:mm-1
for kk = 1:2:nn-1
tem = loca(k:k+1,kk:kk+1);
a11 = tem(1,1);
a12 = tem(1,2);
a21 = tem(2,1);
a22 = tem(2,2);
%-------a11+a21 >= a12+a22则水印为0,否则为1-------
if a11 + a21 >= a12 + a22
rw(index) = 0;
else
rw(index) = 1;
end
index = index + 1;
end
end
end
%%
% 子函数5:提取水印(嵌入到 HL 子带)
function rw = wm_extr_type0(loca)
[mm,nn] = size(loca);
index = 1;
% 取出 2x2 的块
for k = 1:2:mm-1
for kk = 1:2:nn-1
tem = loca(k:k+1,kk:kk+1);
a11 = tem(1,1);
a12 = tem(1,2);
a21 = tem(2,1);
a22 = tem(2,2);
%-------a11+a21 >= a12+a22则水印为0,否则为1-------
if a21 + a22 >= a11 + a12
rw(index) = 0;
else
rw(index) = 1;
end
index = index + 1;
end
end
end
使用方法:
- 将上述代码保存为
wm_embed.m文件。 - 在 MATLAB 中运行以下代码:
% 加载图像
I = imread('image.jpg');
% 生成水印
wm = randi([0,1],1,100); % 生成 100 位随机水印
% 嵌入水印
I_wm = wm_embed(I, wm);
% 提取水印
rw = wm_extr(I_wm);
% 比较提取的水印和原水印
if isequal(rw,wm)
disp('水印正确提取!');
else
disp('水印提取错误!');
end
注意事项:
- 水印信息应该是一个二进制数组。
- 嵌入水印后,图像可能会发生轻微的变化,但不会影响图像的视觉效果。
- 算法的鲁棒性取决于图像的质量和水印的长度。
- 如果图像被篡改,提取的水印信息将与原水印信息不一致。
扩展:
- 可以尝试使用其他小波函数或分解层数。
- 可以尝试使用更复杂的嵌入方案。
- 可以尝试使用其他类型的数字水印。
其他信息:
- 本代码仅供参考,如有任何问题,请自行解决。
- 欢迎大家在评论区交流。
原文地址: https://www.cveoy.top/t/topic/jpPS 著作权归作者所有。请勿转载和采集!