实验四二值图像信息隐藏
一、实验目的
了解二值图像的特点,掌握基于二值图像的信息隐藏原理,读懂两种基于二值图像的信息隐藏方法,并自己设计另一种二值信息隐藏的方法。
二,实验环境
(1)Windows XP操作系统;
(2)MATLAB 7.2版本软件;
(3)二值图像文件。
三、实验原理
二值图像又称为单色图像或黑白图像,一般用1或0表示黑色或白色像素点,利用二值图像信息隐藏的方法主要是根据图像中黑白像素数量的比较来隐藏信息。
方法一:把一个二值图像分成一系列矩形图像区域B,某个图像区域B中黑色像素的个数大于一半,则表示嵌入0;如果白色像素的个数大于一半,则表示嵌入1。
但是当需要嵌入的比特与所选区域的黑白像素的比例不一致时,为了达到希望的像素关系,则需要修改一些像素的颜色。
方法二:采用游程编码方法在二值图像中隐藏信息。
秘密信息嵌入时修改二值图像的游程长度,如果秘密信息位是0,则修改该游程长度为偶数;如果为1,则修改游程长度为奇数;如果秘密信息的取值与游程长度的奇偶性相匹配,则不改变游程长度。
方法三:将二值图像分块,使用一个与图像块大小相同的密钥二值图像块,与每一个图像块按像素进行“与”运算,“与”运算的结果可以确定是否在该块中嵌入数据,或嵌入怎样的数据。
四,实验步骤
下面以方法三为原理,进行实验。
1.嵌入秘密信息
主要思想:首先将载体图像分块,块数为秘密信息的二进制码个数,分块大小为载体图像的长和宽分别除以块数;设定一个与图像块大小相同的密钥二值图
像块,具体为一个8×8的数组,其中前4行全为1,后4行全为0;将载体图像块与密钥二值图像块进行“与”运算。
经过运算后,参与统计的像素变为前4行。
接下来统计“有效”像素黑白的个数,某个图像区域B中黑色像素的个数大于“有效”像素一半,则表示嵌入0;如果白色像素的个数大于“有效”像素一半,则表示嵌入1。
但是当需要嵌入的比特与所选区域的黑白像素的比例不一致时,为了达到希望的像素关系,则需要修改一些像素的颜色。
Matlab代码如下:
msgfid=fopen('hidden.txt','r');%打开秘密文件
[msg,count]=fread(msgfid);
fclose(msgfid);
msg = str2bit(msg);
msg = msg';
count=count*8;
io=imread('hunter.bmp');%读入载体图像
watermarklen=count;%嵌入水印信息长度,也就是载体图像分块的数量值
[row col]=size(io);
l1=floor(row/watermarklen);%载体图像分块后的长度
l2=floor(col/watermarklen);%载体图像分块后的宽度
pixelcount=l1*l2;%每个分块总像素的数量值
miyue=[ones(6,8);zeros(2,8)];%密钥二值图像块
percent=24;
iw=io;
in=io;%存放与运算后的图像信息
%将原图像块与密钥块进行与运算
m=1;
while m<=watermarklen
i=1;
j=1;
in(i:(i+l1-1),j:(j+l2-1))=io(i:(i+l1-1),j:(j+l2-1)) & miyue;
i=i+8;
j=j+8;
m=m+1;
end
inblack(1,watermarklen)=0;%某一个分块中黑色像素的个数
inwhite(1,watermarklen)=0;%某一个分块中白色像素的个数
n=1;
while n<=watermarklen
for i=l1*(n-1)+1:(l1*n-2) %只计算有效前4行的黑白个数
for j=l2*(n-1)+1:l2*n
if in(i,j)==0
inblack(1,n)=inblack(1,n)+1;%计算每个分块中的黑色像素的个数
else
inwhite(1,n)=inwhite(1,n)+1;%计算每个分块中的白色像素的个数
end
end
end
n=n+1;
end
n=1;
while n<=watermarklen
if msg(n,1)==1 %需要嵌入1
if inblack(1,n)>=percent;
%嵌入1的时候,黑色像素比白色像素多,需要修改一些像素的颜色
modcount(1,n)=inblack(1,n)-percent+1;
k=1;
for i=l1*(n-1)+1:(l1*n-2)
for j=l2*(n-1)+1:l2*n
if (iw(i,j)==0&&k<=modcount(1,n))
iw(i,j)=1;k=k+1;
end
end
end
end
else
if inwhite(1,n)>=percent;
%嵌入0的时候,白色像素比黑色像素多,需要修改一些像素的颜色
modcount(1,n)=inwhite(1,n)-percent+1;
k=1;
for i=l1*(n-1)+1:(l1*n-2)
for j=l2*(n-1)+1:l2*n
if (iw(i,j)==1&&k<=modcount(1,n))
iw(i,j)=0;k=k+1;
end
end
end
end
end
n=n+1;
end
n=1;
iwblack(1,watermarklen)=0;%某一个分块中黑色像素的个数
iwwhite(1,watermarklen)=0;%某一个分块中白色像素的个数
while n<=watermarklen
for i=l1*(n-1)+1:l1*n
for j=l2*(n-1)+1:l2*n
if iw(i,j)==0
iwblack(1,n)=iwblack(1,n)+1;%计算每个分块中的黑色像素的个数
else
iwwhite(1,n)=iwwhite(1,n)+1;%计算每个分块中的白色像素的个数
end
end
end
n=n+1;
end
figure;
imshow('hunter.bmp');
imwrite(iw,'huntermarked.bmp');
figure;
imshow('huntermarked.bmp');得到的结果如下图所示:
这是隐藏前后载体图像变化的比较,可以明显的看出图像经过存储秘密信息的处理后图像发生了很大的变化,即出现了一条间断斜线,这是因为在存储秘密信息时,如果图像块中0/1的比例与密文不一致,则需要改动载体图像的像素(常常不止改变一个像素点),所以对载体图像的影响还是比较明显的。
但是这种使用密钥二值图像块的方法比将整个图像块作为对象的方法效果
稍微好一些,因为在分析和修改0/1个数时数量减少了,对载体图像的影响也稍微减轻了一些。
下面是使用密钥二值图像块和不使用密钥二值图像块的目标载体的比较:
2.提取秘密信息
wi=imread('huntermarked.bmp');%读入载体图像
[row col]=size(wi);
watermarklen=80;%嵌入的水印信息的长度
l1=floor(row/watermarklen);%载体图像分块后的长度
l2=floor(col/watermarklen);%载体图像分块后的宽度
pixelblack(1,watermarklen)=0;%某一个分块中黑色像素的个数
pixelwhite(1,watermarklen)=0;%某一个分块中白色像素的个数
n=1;
while n<=watermarklen
for i=l1*(n-1)+1:l1*n
for j=l2*(n-1)+1:l2*n
if wi(i,j)==0
pixelblack(1,n)=pixelblack(1,n)+1;
%计算每个分块中的黑色像素的个数
else
pixelwhite(1,n)=pixelwhite(1,n)+1;
%计算每个分块中的白色像素的个数
end
end
end
n=n+1;
end
n=1;
while n<=watermarklen
if pixelwhite(1,n)>pixelblack(1,n)
%如果白色像素块多于黑色像素块,秘密信息为1 message(n,1)=1
else
message(n,1)=0
%如果黑色像素块多于白色像素块,秘密信息为0 end
n=n+1;
end
%将提取的秘密信息转换成字符串
out=bit2str(message);
fid=fopen('message.txt', 'wt');
fwrite(fid, out)
fclose(fid);
转换为字符串的结果:
五,实验总结
采用游程编码方式隐藏的信息量较大,而且隐写后的载体图像和原始载体图像从视觉上看差别不大,是一种较好的二值图像信息隐藏方法。