【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)

作为信息隐藏方面的研究者,预测误差扩展法是必须要掌握的一门技术。今天本人就详细介绍一下预测误差扩展直方图的信息隐藏技术。

1.原理简介

以灰度图像为例,在计算机里存储的数据是一个个0-255的数字。并且图像里相邻的像素是相关性极高的。因此我们可以用某种预测方法,用周围的像素来预测这个像素,从而产生预测值与预测误差。利用这个预测误差,我们就可以做到信息隐藏。

【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第1张图片

(1)嵌入步骤

  • 将原始图像扫描为一个序列 ( x 1 , x 2 , x 3 , . . . , x N x_1,x_2,x_3,...,x_N x1,x2,x3,...,xN
  • 用指定的预测器预测 x i x_i xi 的值,记作 ( x 1 ^ , x 2 ^ , x 3 ^ , . . . , x N ^ \hat{x_1},\hat{x_2},\hat{x_3},...,\hat{x_N} x1^,x2^,x3^,...,xN^
  • 计算预测误差 e i e_i ei = x i x_i xi - x i ^ \hat{x_i} xi^
  • 得到一个预测误差序列 ( e 1 , e 2 , e 3 , . . . , e N e_1,e_2,e_3,...,e_N e1,e2,e3,...,eN
  • 由预测误差生成预测误差直方图,横坐标为误差值,纵坐标为误差值的数量
  • 根据下图公式将预测误差值进行扩展,得到扩展后的预测误差序列( e 1 ′ , e 2 ′ , e 3 ′ , . . . , e N ′ e_1',e_2',e_3',...,e_N' e1,e2,e3,...,eN)。此处b是秘密信息,是二进制的0或1。
    【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第2张图片
  • 根据扩展后的预测误差,修改载体图像的像素,得到含密图像。 公式为 : x i ′ x_i' xi = x i ^ \hat{x_i} xi^ + e i ′ e_i' ei

根据上面的步骤,我们就可以得到一张含密图像了。可以从 e i ′ e_i' ei的公式里看出,这个过程是可逆的。

(2) 提取步骤

  • 将含密图像扫描为一个序列 ( x 1 ′ , x 2 ′ , x 3 ′ , . . . , x N ′ x_1',x_2',x_3',...,x_N' x1,x2,x3,...,xN
  • 用相同的预测器预测 x i x_i xi 的值,记作 x i ^ \hat{x_i} xi^,得到预测序列 ( x 1 ^ , x 2 ^ , x 3 ^ , . . . , x N ^ \hat{x_1},\hat{x_2},\hat{x_3},...,\hat{x_N} x1^,x2^,x3^,...,xN^
  • 计算扩展后的预测误差 e i ′ e_i' ei = x i ′ x_i' xi - x i ^ \hat{x_i} xi^, 注意,此时的预测误差是扩展后的预测误差。
  • 得到一个扩展后的预测误差序列 ( e 1 ′ , e 2 ′ , e 3 ′ , . . . , e N ′ e_1',e_2',e_3',...,e_N' e1,e2,e3,...,eN
  • 由预测误差生成预测误差直方图,横坐标为误差值,纵坐标为误差值的数量
  • 根据下图公式将预测误差值进行还原,得到原始的预测误差序列( e 1 , e 2 , e 3 , . . . , e N e_1,e_2,e_3,...,e_N e1,e2,e3,...,eN)。此处 ⌊ \lfloor ⌋ \rfloor 代表向下取整。例如: ⌊ \lfloor 4.5 ⌋ \rfloor 取4。
    【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第3张图片
  • 根据 e i ′ e_i' ei / 2 的结果,整数则提取 b=0,非整数则提取 b=1

在这一步如果 e i ′ e_i' ei / 2 不能整除的话,说明嵌入的秘密信息为1,否则为0。这个方法其实就是模二取余法。例如 某个 e i e_i ei 为4,秘密信息 b = 1,那么 e i ′ e_i' ei = 2 ∗ e i + 1 2*e_i + 1 2ei+1 = 9。在提取的过程中 e i ′ e_i' ei / 2 = 4.5,说明嵌入的信息为1,才会得到不为0的结果。

(3)恢复图像。

  • 由步骤(2),我们得到一个预测序列 ( x 1 ^ , x 2 ^ , x 3 ^ , . . . , x N ^ \hat{x_1},\hat{x_2},\hat{x_3},...,\hat{x_N} x1^,x2^,x3^,...,xN^)和 原始预测误差序列 ( e 1 , e 2 , e 3 , . . . , e N e_1,e_2,e_3,...,e_N e1,e2,e3,...,eN)。
  • 由公式 x i x_i xi = x i ^ \hat{x_i} xi^ + e i e_i ei 得到原始载体图像序列 ( x 1 , x 2 , x 3 , . . . , x N x_1,x_2,x_3,...,x_N x1,x2,x3,...,xN),然后恢复图像即可。
    其实这一步,就是步骤(1)中公式 e i e_i ei = x i x_i xi - x i ^ \hat{x_i} xi^ 的逆向计算结果。

2. 算法效果展示:

直方图 (嵌入前,嵌入后):

【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第4张图片
【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第5张图片

原始图像与含密图像展示 :

【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第6张图片
【最全的】预测误差直方图可逆信息隐藏算法原理及代码(matlab实现)_第7张图片

3.代码实现。

clear all;clc;
img = imread("1.bmp");
img = double(img);
img_hiding = img;
index = 1;

% 这里为了方便计算,我直接把数组长度设置为嵌入容量了
predict_value = zeros(1,62500);
predict_error = zeros(1,62500);

% 生成一个随机01序列,作为此次信息隐藏的秘密信息
secret_msg = zeros(1,62500);
for i=1:62500
    secret_msg(1,i) = round(rand(1));
end

% ------------------------------  嵌入步骤  -------------------------
% 假设我们的预测方法是 : 以   当前像素的 左右两个像素的均值  来作为预测值
for i=2:2:500
    for j=2:2:500
        % 计算左右两个像素的均值,作为预测值
        predict_value(1,index) = round((img(i,j-1) + img(i,j+1))/2);
        %  得到预测误差
        predict_error(1,index) = img(i,j) - predict_value(1,index);
        index = index + 1;
    end
end

histogram(predict_error); % 生成直方图

% 将秘密信息嵌入误差直方图,构成扩展预测误差直方图
predict_expand = predict_error;  
% 选择阈值  T = 5
T = 5;
for i=1:62500
    if predict_error(1,i) >= -1 * T && predict_error(1,i) < T
        predict_expand(1,i) = 2 * predict_error(1,i) + secret_msg(1,i);
    elseif predict_error(1,i) >= T
        predict_expand(1,i) = predict_error(1,i) + T;
    else
        predict_expand(1,i) = predict_error(1,i) - T;
    end
end

histogram(predict_expand); % 生成直方图

index = 1;
% 将嵌入秘密信息后的预测误差直方图转移回载体图像(原始图像)
for i=2:2:500
    for j=2:2:500
        img_hiding(i,j) = predict_value(1,index) + predict_expand(1,index);
        index = index + 1;
    end
end
imshow(uint8(img_hiding));
imwrite(uint8(img_hiding),'2.bmp');  % 将信息隐藏后的图片保存


% ----------------------------可以从这里分为两份代码。一份嵌入一份提取-------------------------

img_hiding2 = imread("2.bmp");
img_hiding2 = double(img_hiding2);
img2 = img_hiding2;
index = 1;
extract_msg = zeros(1,62500);
predict_value2 = zeros(1,62500);
predict_expand2 = zeros(1,62500);
predict_error2 = zeros(1,62500);
T = 5;

% 先进行同样的预测,得到预测序列
for i=2:2:500
    for j=2:2:500
        % 计算左右两个像素的均值,作为预测值
        predict_value2(1,index) = round((img_hiding2(i,j-1) + img_hiding2(i,j+1))/2);
        %  得到预测误差
        predict_expand2(1,index) = img_hiding2(i,j) - predict_value2(1,index);
        index = index + 1;
    end
end
% 恢复预测误差 并  提取秘密信息
for i=1:62500
    if predict_expand2(1,i) >= -2*T && predict_expand2(1,i) < 2*T
        predict_error2(1,i) = floor(predict_expand2(1,i) / 2);
        extract_msg(1,i) = abs( predict_error2(1,i) - floor(predict_expand2(1,i) / 2) );
    elseif predict_expand2(1,i) >= 2*T
        predict_error2(1,i) = predict_expand2(1,i) - T;
    else
        predict_error2(1,i) = predict_expand2(1,i) + T;
    end
end
% 恢复图像:
index = 1;
for i=2:2:500
    for j=2:2:500
        img2(i,j) = img2(i,j) +  predict_error2(1,index);
        index = index + 1;
    end
end


% -------------------------------检验是否算法有误-----------------------------------
img = double(imread('1.bmp'));

if img ~= img2
    disp("实验结果有误");
else
    disp("原始图像完全恢复");
end

if secret_msg ~= extract_msg
    disp("秘密信息提取有误");
else
    disp("秘密信息完全一致");
end



更多内容请关注我

JPEG 相关
直方图平移

你可能感兴趣的:(信号处理,信号处理,matlab,信息安全)