目录
在这里先引入像素直方图的概念:
像素直方图就是根据一幅图像的像素值【0-255】和像素数量画出的x-y图。
一、实验的相关理论介绍
1、实验算法流程
算法的基本流程如图1所示。其中嵌入的算法的基本流程为:读入灰度图像,然后找到图像的像素分布直方图的峰值点和零点,将直方图向Z方向平移一个像素空出峰值附近的那个直方图块,最后将信息嵌入空出来的这个位置即可实现信息的嵌入。提取的算法基本流程为:读入含隐藏信息的图像、峰值点的像素值P和文本信息长度,按照嵌入的规则逆向提取信息,最后将直方图向P方向平移实现无损恢复。
由于本文的篇幅已经比较长了,所以算法原理部分可以参考另一位博主的文章,下面是文章链接:
为了节约阅读时间,这里给出了实验算法简化的步骤(非原创)
2、实验步骤及原理
2.1 平移直方图
在一幅像素分布不是很均匀的灰度图载体图像上,由于灰度分布不均匀造成图像的直方图会有一个比较高的峰。扫描整幅图像找到图像直方图的中的最大值P和最小值Z,然后将像素值介于P+1和Z(包括Z)的像素直方图向Z方向移动,这样就能实现直方图的平移并为即将嵌入的信息空出位置[1]。
式中h表示图像像素灰度值,h'表示平移后的像素值,move是像素移动的位置和大小,这里大小恒等于1。直方图移动方向即move的正负需要根据P和Z的大小来决定。
在进行直方图平移时需要注意像素边界问题,所谓的像素边界是指灰度图中像素的下界0和上界255。这里用P<Z的情况举例,在进行直方图平移时,我们需要将P+1 Z之间的像素加1,从而实现这段区间的直方图向Z方向平移一个位置。但是,如果像素加1后超过了255那就会出现边界问题;同理,若像素减1小于0也会有像素边界问题。在此算法中只涉及1个单位的平移,所以边界问题几乎不会对图像的成像造成什么影响,但是在直方图高度差距很小的图像或平移单位比较大的情况下就会造成平移后的直方图出现假峰值的情况。
如图2和图3所示,在经过不同的单位平移后直方图在边界处的位置会随着平移单位的增加而增加。这是因为读入的灰度图在matlab中的数据保存类型为uint8类型,这种类型的数据代表的是像素的值。灰度像素值的区间为[0,255],经过对像素值的加减操作从而实现直方图的平移在理论上是行得通的,但是当操作后的像素值不在这个区间时,uinit8这种数据类型的作用就会被发挥,会将超过255的像素变为255,小于0的像素变为0。这样一来,由于左边(右边)平移过来直方图积累,就会在255(0)的位置出现直方图的假峰值(如图3红框内所示)。但是在本次实验的算法中由于只移动一个位置,所以不会出现这种情况。
2.2 嵌入信息
按照和移动直方图时相同的顺序扫描图像,当像素值为P时,将读入的文本转化为二进制流后根据规定嵌入直方图平移后空白的部分[2]。写入规则如下式,b表示待嵌入的秘密信息,P表示峰值点像素灰度值,h'表示嵌入秘密信息的像素值。如果待嵌入信息位b=1,像素值P变成P+move;如果待嵌入信息位是0,像素值P保持不变[3]。
2.3 信息提取
在提取的过程中,需要按照嵌入流程中使用的顺序扫描标记图像。提取信息之前需要传入原始图像的直方图峰值点对应的像素值P和写入文本信息的长度。若像素值为P或P+1,则提取嵌入信息,恢复像素值,具体操作流程见下面两式:
2.4 图像无损恢复
由于在嵌入秘密信息的时候没有破坏原有的数据结构而造成发数据丢失,所以直方图平移后再再向反方向平移即可实现图像的无损恢复。基本流程为:提取信息后,将之前向Z方向平移的像素区间整体向P方向平移一个单位,图像就实现了无损恢复。具体计算过程如下:
2.5 文本信息的处理
在matlab中读入的文本信息是double类型的数据,所以在进行文本信息嵌入之前需要将double类型的数据转换为二进制数据流,再将数据的每一位按规则嵌入即可。在matlab中转二进制有集成的函数,但是转换后的结果是n×8的char类型数组,为了方便后续操作我对这个数组进行重构,将n×8的char类型数组重构为n×1的char类型数组,再将重构后的数组转为double类型的数组,这样在隐藏信息时可以减小文本信息索引的难度。
2.6 计算相关系数
为了判断提取完信息的图像经过复原后是否与原图一致,所以我计算了原图(载体图像)和复原后图像的相关系数R。计算公式如下:
式中A代表原图(载体图像),代表图像A的像素均值,B代表复原后的图像,代表图像B的像素均值,m和n分别代表图像的长和宽。
二、实验代码及注释
为了提升代码的可读性以及程序的可调试性,我将程序分为了五个节。
%% 直方图平移信息隐藏
close all
clear,clc
%读入信息
IMG=imread("cameraman.tif");
% IMG=imread("lena_gray_512.tif");
% IMG=imread("lena_gray_256.tif");
I=IMG;
fid=fopen('info.txt','r');
[txt,txt_len]=fread(fid);
figure(1)
imshow(IMG)
title('宿主图像')
[counts,binLocations] = imhist(IMG); %计算灰度图像 I 的直方图。
% imhist函数在 counts 中返回直方图计数,在 binLocations 中返回 bin 位置。
figure(2)
bar(binLocations,counts)%直方图
title('原图的直方图')
P=find(counts==max(counts))-1;
Z=find(counts==min(counts))-1;
capacity=counts(P+1);%信息容量
%txt转换为二进制流
txtb=dec2bin(txt);%转二进制
txtb=reshape(txtb',[],1);%二维变一维
txtb=str2num(txtb);
if(txt_len*8>capacity)
display('隐藏信息过多,请更换载体图像!');
display(['信息长度:',num2str(txt_len*8)]);
display(['载体容量:',num2str(capacity)]);
return
end
%%
%平移直方图
move=1;
if(P>Z(1))%判断P和Z的大小
move=-1;
end
[m,n]=size(IMG);
for i=1:m
for j=1:n
if((IMG(i,j)>P)&&(IMG(i,j)<=Z(1)))
IMG(i,j)=IMG(i,j)+move;
end
end
end
figure(3)
[ct,bin]=imhist(IMG);
bar(bin,ct)
title('平移后的直方图')
%%
%隐藏
txt_len=length(txtb);
len=1;
for i=1:m
for j=1:n
if(len<=txt_len)
if((IMG(i,j)==P)&&(txtb(len)==1))%txt=1----P-->P+move
IMG(i,j)=IMG(i,j)+move;
len=len+1;
elseif((IMG(i,j)==P)&&(txtb(len)==0))
len=len+1;
end
end
end
end
imwrite(IMG,'cameraman1.tif')%写出
%%
%提取
Img=imread("cameraman1.tif");
len=1;
for i=1:m
for j=1:n
if(len<=txt_len)
if(Img(i,j)==P)
txtbs(len)=0;
len=len+1;
elseif(Img(i,j)==P+move)
txtbs(len)=1;
Img(i,j)=P;
len=len+1;
end
end
end
end
txtb=reshape(txtbs,8,txt_len/8);%一维变二维
txtb=txtb';
txt_out=num2str(txtb);%转为二进制字符串
txt_out=bin2dec(txt_out);%转为0-255
fid=fopen('info_out.txt','w+','n','UTF-8');%打开文件,因为是中文所以采用UTF-8编码
[r,j]=size(txt_out);
%写入
for i=1:r
fwrite(fid,txt_out(i));
end
fclose(fid);
%%
%恢复原图
for i=1:m
for j=1:n
if((Img(i,j)>P)&&(Img(i,j)<=Z(1)))
Img(i,j)=Img(i,j)-move;
end
end
end
figure(4)
imshow(Img)
title('复原结果')
imwrite(Img,'re_cameraman.tif')
%比较图像
R=corr2(I,Img);
%%
三、实验结果及分析
3.1 源文件准备
使用的源文件如图4所示,载体图像是512×512的灰度图像,隐藏的文本信息大小为554字节,换算为二进制后信息大小为4432位。
3.2 寻找直方图的峰值点和零点
通过对图4中读入载体图像的直方图分析,找到直方图的峰值点P=13,对应的像素数量为6212;直方图的零点Z=254,对应的像素数量为10。
3.3 平移直方图
由图5中的直方图中可以得到P<Z,所以位于[P+1,Z]即[14,254]之间直方图要向Z方向(向右)移动一个位置,对应的算法为[14,254]之间的像素值加1。得到移动后的直方图如下:
由平移后的直方图可以看出,平移的区域符合预期,评议后的直方图在P+1的位置(如图6中红框内所示)有空缺,所以说明平移直方图的结果正确。
3.4 嵌入信息
通过在图6直方图中空缺的位置嵌入文本信息后生成含有秘密信息的图像如图7所示。可以发现嵌入秘密信息后的图像与原图(宿主图像)几乎没有任何区别,结果符合预期,嵌入算法成功。
3.5 嵌入结果分析
我对嵌入的文本信息(转换为二进制流后的文本信息)数据进行了0-1分布的统计,统计结果如下图:
从结果中可以看出0的数量为2032,1的数量为2400,1的数量大于0的数量。
从图9中可以看出在P值以前的两条曲线是完全重合的,说明这部分的像素没有更改,在P和P+1的位置由于含有秘密信息,所以链条曲线的重合度较低,其中绿色的曲线在P+1的位置隐藏的信息是1,所以这部分对应的纵坐标数值是2400,和原来的P+1数值会有一个差值。在P+1后面的部分由于平移时像素值都加了1,所以绿色的曲线会比红色曲线超前一个位置。
3.6 复原
通过复原算法对提取秘密信息后的图像复原得到的结果如图10所示,可以看到两幅图像没有任何区别,通过计算两幅图像的相关系数发现相关系数R=1,这也说明两幅图像没有区别。
通过图11所示的曲线对复原后的图像和原始图像进行像素曲线对比发现原图和复原后的像素曲线完全重合,这也说明复原结果正确。
3.7 信息提取
嵌入的文本信息和提取到的文本信息如图12所示,其中左边的文本信息时嵌入的文本信息,右边的文本信息时提取到的文本信息。通过比对发现两个文档中的文本信息没有任何差别,所以提取信息的结果准确,程序正确。
3.8 更换测试载体
通过更换不同大小的载体图像进行测试发现:不同大小,图像内容一致的载体图像有趋势相似的直方图,但是图像大小大的图像有更大的信息容量(如图13和图14所示)。
3.9 最大数据嵌入量测试
在题目的思考题中有:更换载体图像,分析最大嵌入数据量的变化与载体图像的关系。为了对此进行分析,我用不同的图像对最大数据嵌入量进行了测试。
图15中我对8幅图像的最大数据嵌入量进行了测试,其中图3时大小为256×256的灰度图,其它的7幅灰度图大小均为512×512,测试结果如下:
通过图16中的测试结果可以得到结论:直方图平移算法允许嵌入的水印量依赖于图像自身的灰度分布,一副灰度值分布较为集中的图像可以嵌入较多水印,而灰度值分布较平均的图像可嵌入的水印量就非常有限。
四、参考文献
[2] 刘芳,汪玉凯. 一种基于差值直方图平移的多层可逆水印算法[J].计算机应用与软件. 2014(1):303-307
[3] 崔炳德,辛晨,裴祥喜.基于直方图平移的安全可逆信息隐藏算法[J].科学技术与工 程,2019,19(22):215-222.
[5] Lin Chiachen,Tai Weiliang,Chang Chinchen. Multilevel reversible dwata hidwing based on histogram modwification of dwifference images[J]Pattern R ecognition,2008( 41) : 3582 3591