实验完成形式:
用MATLAB函数实现LSB信息隐藏和提取
实验选择载体:
512×512灰度图像
实验效果和分析:
1.完成基本的LSB信息隐藏及提取
2.能随机选择嵌入位进行信息隐藏及提取(考虑安全性因素)
3.能够计算PSNR,分析信息隐藏图像质量
4.完成对秘密信息的图像载体进行攻击,采用的攻击方法: jpeg压缩,resize缩放
5.计算每种攻击方法提取的秘密信息误码率
gray=imread('lena_gray.bmp');
gray_8=bitget(gray,8);
gray_6=bitget(gray,6);
gray_7=bitget(gray,7);
woman=imread('woman_rgb.bmp');
woman_to_binary=im2bw(woman);
gray_set=bitset(gray,1,woman_to_binary);
gray_set_8=bitset(gray,8,woman_to_binary);
gray_get_8=bitget(gray_set_8,8);
gray_get_1=bitget(gray_set,1);
subplot(221),imshow(gray),title('原始图像');
subplot(222),imshow(logical(gray_8)),title('原始图像的第8层');
subplot(223),imshow(gray_set_8),title('在第8层隐藏信息后');
subplot(224),imshow(logical(gray_get_8)),title('获取隐藏的图像');
figure,%新打开一个窗口
subplot(221),imshow(gray),title('原始图像');
subplot(222),imshow(woman_to_binary),title('要隐藏的图像');
subplot(223),imshow(gray_set),title('在第1层隐藏信息后');
subplot(224),imshow(logical(gray_get_1)),title('获取隐藏的图像');
2.完成随机选择嵌入位进行LSB信息隐藏及提取算法。
随机选择嵌入位,嵌入水印信息,input为载体图像,file为要嵌入的文本文件,output为嵌入水印后的图像,key为随机数种子。
%2.随机选择嵌入位
function [ste_cover,len_total]=rand_lsb_hide(input,file,output,key)
%读入图像矩阵
cover=imread(input);
ste_cover=cover;
ste_cover=double(ste_cover);
%将文本文件转换为二进制
f_id=fopen(file,'r');
[msg,len_total]=fread(f_id,'ubit1');
%判断嵌入的信息量是否过大
[m,n]=size(ste_cover);
if len_total>m*n
error('嵌入信息量过大,请重新选择图像');
end
%p作为消息嵌入位计数器
p=1;
%调用随机间隔函数选取像素点
[row,col]=randinterval(ste_cover,len_total,key);
%在LSB隐藏信息
for i=1:len_total
ste_cover(row(i),col(i))=ste_cover(row(i),col(i))-mod(ste_cover(row(i),col(i)),2)+msg(p,1);
if p==len_total
break;
end
p=p+1;
end
ste_cover=uint8(ste_cover);
imwrite(ste_cover,output);
%显示实验结果
subplot(1,2,1);imshow(cover);title('原始图像');
subplot(1,2,2);imshow(output);title('隐藏信息的图像');
实现效果:
读取嵌入的水印信息,output为嵌入水印后的图像,goalfile为提取出的水印文件,key与嵌入水印时的值相同:
function result = rand_lsb_get(output,len_total,goalfile,key)
ste_cover=imread(output);
ste_cover=double(ste_cover);
%判断嵌入信息量是否过大
[m,n]=size(ste_cover);
if len_total>m*n
error('嵌入信息量过大,请重新选择图像');
end
frr=fopen(goalfile,'a');
%p作为消息嵌入位计数器,将消息序列写回文本文件
p=1;
%调用随机间隔函数选取像素点
[row,col]=randinterval(ste_cover,len_total,key);
for i=1 :len_total
if bitand(ste_cover(row(i),col(i)),1)==1
fwrite(frr,1,'ubit1');
result(p,1)=1;
else
fwrite(frr,0,'ubit1');
result(p,1)=0;
end
if p ==len_total
break;
end
p=p+1;
end
fclose(frr);
随机数生成算法:
%书上50页
function [row,col]=randinterval(matrix,count,key)
%计算间隔的位数
[m,n]=size(matrix);
interval1=floor(m*n/count)+1;
interval2=interval1-2;
if interval2==0
error('载体太小,不能将私密信息隐藏进去');
end
%生成随机序列
rand('seed',key);
a=rand(1,count);
%初始化
row=zeros([1 count]);
col=zeros([1 count]);
%计算row,col
r=1;
c=1;
row(1,1)=r;
col(1,1)=c;
for i=2:count
if a(i)>=0.5
c=c+interval1;
else
c=c+interval2;
end
if c>n
r=r+1;
if r>m
error('载体太小,不能私密信息隐藏进去');
end
c=mod(c,n);
if c==0
c=1;
end
end
row(1,i)=r;
col(1,i)=c;
end
3.计算误码率的算法——分别对含有秘密信息的图像载体进行攻击,攻击方式为jpeg压缩,resize缩放,根据不同的压缩比例,缩放比例的分别计算误码率并显示如下:
这部分代码是参考别人的博客编写的:https://blog.csdn.net/cheeseandcake/article/details/52997903?locationNum=11&fps=1
function ber_resize=calcute_resize_ber(input,messagefile,len_total,key)
for resize =0.5:1:10
%读取已经隐藏信息的图像。
fp=imread(input);
%使用 imresize 函数对图像进行缩放,设定缩放比例。
output=imresize(fp,resize,'bicubic'); %利用双三次插值方法将 Ifp放大 size 倍
intchanged=double(output);
%p作为消息嵌入位计数器,将消息序列写回文本文件
p=1;
%调用随机间隔函数选取像素点
[row,col]=randinterval(intchanged,len_total,key);
for i=1 :len_total
if bitand(intchanged(row(i),col(i)),1)==1
result(p,1)=1;
else
result(p,1)=0;
end
if p ==len_total
break;
end
p=p+1;
end
%读取原文件,即隐藏的信息,以二进制读取。并取得消息长度
message=fopen(messagefile,'r');
%按位以二进制形式读取文本内容与长度
[msg,len_total]=fread(message,'ubit1');
%比较取得的信息和原信息的每一位,记录不相等位数的个数。
bit_error=find(result~=msg); %寻找不相等的位置
bit_error_count=size(bit_error,1); %统计不相等的个数
%用不相等个数除以总长度即可得到误码率ber
ber_resize(resize+0.5)=bit_error_count/len_total;
end
% plot参数说明:
% 参数1是横坐标自变量,参数2是纵坐标自变量,参数3是指用说明形式描点,参数4和5代表把散点链接起来
resize=0.5:1:10;
plot(resize,ber_resize,'*',resize,ber_resize);
title('基于图片缩放质量的误码率图表');
function ber_jpeg=calcute_jpeg_ber(input,output,messagefile,len_total,key)
for compressibility=10:10:100
%Compressiblity是图像的质量因子,可设置在0-100范围内
%compressibility=90;
%读取已经隐藏信息的图像。
fp=imread(input);
%使用 imwrite 函数对图像进行压缩,设定压缩比例。
imwrite(fp,output,'quality',compressibility);
intchanged=imread(output);
intchanged=double(intchanged);
%p作为消息嵌入位计数器,将消息序列写回文本文件
p=1;
%调用随机间隔函数选取像素点
[row,col]=randinterval(intchanged,len_total,key);
for i=1 :len_total
if bitand(intchanged(row(i),col(i)),1)==1
result(p,1)=1;
else
result(p,1)=0;
end
if p ==len_total
break;
end
p=p+1;
end
%读取原文件,即隐藏的信息,以二进制读取。并取得消息长度
message=fopen(messagefile,'r');
%按位以二进制形式读取文本内容与长度
[msg,len_total]=fread(message,'ubit1');
%比较取得的信息和原信息的每一位,记录不相等位数的个数。
bit_error=find(result~=msg); %寻找不相等的位置
bit_error_count=size(bit_error,1); %统计不相等的个数
%用不相等个数除以总长度即可得到误码率ber
ber_jpeg(compressibility/10)=bit_error_count/len_total;
end
% plot参数说明:
% 参数1是横坐标自变量,参数2是纵坐标自变量,参数3是指用说明形式描点,参数4和5代表把散点链接起来
compressibility=10:10:100;
plot(compressibility,ber_jpeg,'*',compressibility,ber_jpeg);
title('基于图片压缩质量因子的误码率图表');
4.计算水印相关系数PSNR——PSNR值越大,图像质量越好:
function PSNR=calcute_psnr(input,inputchange)
img=imread(input);
[h,w]=size(img);
%imgn=imresize(img,[floor(h/2) floor(w/2)]);
%imgn=imresize(imgn,[h w]);
imgn=imread(inputchange);
img=double(img);
imgn=double(imgn);
%编码一个像素用多少二进制位
B=8;
%图像有多少灰度级
MAX=2^B-1;
MES=sum(sum((img-imgn).^2))/(h*w); %均方差
PSNR=20*log10(MAX/sqrt(MES)); %峰值信噪比