作为信息隐藏方面的研究者,预测误差扩展法是必须要掌握的一门技术。今天本人就详细介绍一下预测误差扩展直方图的信息隐藏技术。
以灰度图像为例,在计算机里存储的数据是一个个0-255的数字。并且图像里相邻的像素是相关性极高的。因此我们可以用某种预测方法,用周围的像素来预测这个像素,从而产生预测值与预测误差。利用这个预测误差,我们就可以做到信息隐藏。
根据上面的步骤,我们就可以得到一张含密图像了。可以从 e i ′ e_i' ei′的公式里看出,这个过程是可逆的。
在这一步如果 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 2∗ei+1 = 9。在提取的过程中 e i ′ e_i' ei′ / 2 = 4.5,说明嵌入的信息为1,才会得到不为0的结果。
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 相关
直方图平移