一、實驗内容
實驗完成形式:
用MATLAB函數實作LSB資訊隐藏和提取
實驗選擇載體:
512×512灰階圖像
實驗效果和分析:
1.完成基本的LSB資訊隐藏及提取
2.能随機選擇嵌入位進行資訊隐藏及提取(考慮安全性因素)
3.能夠計算PSNR,分析資訊隐藏圖像品質
4.完成對秘密資訊的圖像載體進行攻擊,采用的攻擊方法: jpeg壓縮,resize縮放
5.計算每種攻擊方法提取的秘密資訊誤碼率
二、實驗涉及到的相關算法
1.基本LSB資訊隐藏及提取算法——圖像的第一層是LSB層,替換後對原圖像的影響較小,第8層為MSB層對原圖像影響較大。
1)讀入圖像載體:gray=imread('lena_gray.bmp');
2)讀入要隐藏的圖像,并轉換為二進制:woman=imread('woman_rgb.bmp'); woman_to_binary=im2bw(woman);
3)在圖像載體的第一層隐藏圖像:gray_set=bitset(gray,1,woman_to_binary);
4)提取隐藏的圖像:gray_get_1=bitget(gray_set,1);
算法實作源代碼:
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資訊隐藏及提取算法。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwFdW12Y0R2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jM1cDNyUzMwETNwcDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
随機選擇嵌入位,嵌入水印資訊,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)); %峰值信噪比