脆弱水印嵌入算法及 MATLAB 代码实现

本代码实现了一种基于小波变换的脆弱水印嵌入算法,能够将水印信息嵌入到图像中,并通过提取水印信息来检测图像是否被篡改。

算法原理:

  1. 对图像进行一层小波分解,得到四个子带:LL, LH, HL, HH。
  2. 根据 LH 和 HL 子带的能量大小,选择其中一个子带作为嵌入水印的区域。
  3. 在选择的子带中,将水印信息嵌入到 2x2 的图像块中。
  4. 将嵌入水印后的子带与其他子带进行合并,得到嵌入水印后的图像。

代码实现:

% 脆弱水印嵌入算法
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

使用方法:

  1. 将上述代码保存为 wm_embed.m 文件。
  2. 在 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

注意事项:

  • 水印信息应该是一个二进制数组。
  • 嵌入水印后,图像可能会发生轻微的变化,但不会影响图像的视觉效果。
  • 算法的鲁棒性取决于图像的质量和水印的长度。
  • 如果图像被篡改,提取的水印信息将与原水印信息不一致。

扩展:

  • 可以尝试使用其他小波函数或分解层数。
  • 可以尝试使用更复杂的嵌入方案。
  • 可以尝试使用其他类型的数字水印。

其他信息:

  • 本代码仅供参考,如有任何问题,请自行解决。
  • 欢迎大家在评论区交流。
脆弱水印嵌入算法及 MATLAB 代码实现

原文地址: https://www.cveoy.top/t/topic/jpPS 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录