文章目錄
一、在BMP圖像中隱藏數據
1、在圖像文件尾部添加任意長度的數據,僅需修改文件頭中文件長度的值即可。
2、如果將秘密數據放在文件頭與圖像數據之間,則至少需要修改文件頭中文件長度、數據起始偏移地址這兩個域的值。
3、修改文件頭和信息頭中保留字段隱藏信息。
4、在圖像像素區利用圖像寬度字節必須是4的倍數額特點,在補足位處隱藏數據。
實驗一:在BMP圖像數據后隱藏數據
待隱藏的密碼信息文件名稱為:hidden.txt(里面有6個a),pic1.bmp 為載體圖像,將載體和秘密信息放置在同一目錄下,在Windows的CMD中執行命令:
Copy pic1.bmp /b + hidden.txt /a pic11.bmp
執行該命令后,生成一個新的pic11.bmp文件,使用圖像瀏覽工具瀏覽該文件會發現它與原始載體圖像幾乎完全相同。
信息隱藏在pic11.bmp文件的尾部。
從BMP圖像的結構中可知,圖像的3、4、5、6四個字節表示整個BMP圖像的長度(大小)。使用該方式隱藏信息時,未修改圖像文件的文件長度字節,通過比較文件的實際長度和文件中保存的文件長度,就可發現該圖像是否隱藏秘密信息。
clc;
clear;
fid=fopen('pic11.bmp','r');
[a,length]=fread(fid,inf,'uint8');
status=fseek(fid,2,'bof');
fileb=fread(fid,4,'uint8');
filelength=fileb(1)*1+fileb(2)*256+fileb(3)*256^2+fileb(4)*256^3;
diff=length-filelength;
fclose(fid);
clc;
clear;
fid=fopen('pic11.bmp','r');
% 以只讀方式打開pic11.bmp圖像文件,該文件必須存在,fid用於存儲文件句柄值
[a,length]=fread(fid,inf,'uint8');
% 創造存放讀取數據的矩陣,length中返回所讀取的數據元素個數
% inf讀出fid指向的打開文件的全部數據
% fclose(fid);
% 關閉fid所表示的文件,文件在進行完讀、寫等操作后,應及時關閉以免數據丟失
% fid=fopen('pic11.bmp','r');
status=fseek(fid,2,'bof');
% fseek函數用於定位文件位置指針,fid為文件句柄,
% offset(第2個參數)表示位置指針相對移動的字節數,“2”指的是跳過前兩個文件標識字節
% origin(第3個參數)表示位置指針移動的參照,'bof',表示文件頭;'cof',表示當前位置 ;'eof',表示文件尾
fileb=fread(fid,4,'uint8');
% 讀取4個元素(就是文件大小),精度為uint8
filelength=fileb(1)*1+fileb(2)*256+fileb(3)*256^2+fileb(4)*256^3;
% 把這4個字節轉換成大小
diff=length-filelength;
% 有差值,可發現該圖像隱藏秘密信息
fclose(fid);
實驗二:在文件頭與圖像數據之間隱藏信息
clear;
clc;
fid=fopen('pic1.bmp','r');
[a,length]=fread(fid,inf,'uint8');
fclose(fid);
msgfid=fopen('hidden.txt','r');
[msg,count]=fread(msgfid,inf,'uint8');
fclose(msgfid);
wa=a;
wa(3)=wa(3)+count;
% 圖像頭(從3開始)+ 隱藏文件內容的字節
wa(11)=wa(11)+count;
% 000A-000D:從文件開始到圖像數據之間的偏移量
% 偏移量 + 隱藏文件內容的字節
j=1;
for i=55:55+count-1
wa(i)=msg(j,1); % msg(行,列)
j=j+1;
end
% 文件頭有54個字節(從0開始算),從55個字節開始藏
for i=55:length
wa(i+count)=a(i);
end
% 把原來的圖像信息往后面移動要隱藏的信息長度
new=fopen('newpic11.bmp','wb'); % wb:只寫打開或新建一個二進制文件
fwrite(new,wa);
% 數組wa的元素按 列順序 以 8 位無符號整數的形式寫入二進制文件new
figure;
imshow('newpic11.bmp');
36(16)=54,3C(16)=60,61(16)=97=a(ASCII)
二、圖像LSB隱寫
最低有效位( least significant bit,LSB)指的是一個二進制數字中的第0位(即最低位)。
實驗一:在圖像中嵌入相同分辨率的二值圖像
將BMP圖像pic2.bmp轉換為二值圖像,並將其嵌入相同分辨率的RGB圖像pic1.bmp的任一層(R層、G層或B層灰度圖像)的最低位平面。
clear;
clc;
I=imread('pic1.bmp');
J=I;
JR=J(:,:,1);
L=imread('pic2.bmp');
BW=im2bw(L);
set1=bitset(JR,1,BW);
% 將JR轉換成二進制,並將其右邊第一個位置(即最低位)換成BW的值
J(:,:,1)=set1;
get1=bitget(J(:,:,1),1);
% 輸出J(:,:,1)最低位的數值
figure;
subplot(2,2,1);imshow(I);title('原圖');
subplot(2,2,2);imshow(BW);title('待嵌入原圖的二值圖');
subplot(2,2,3);imshow(J);title('嵌后圖像');
subplot(2,2,4);imshow(get1,[]);title('取出嵌入的圖像'); % 加[]讓圖像自適應顯示
實驗二:在圖像中嵌入不同分辨率的二值圖像
將lena.jpg圖像嵌入到不同分辨率RGB圖像pic1.bmp任一層(R層、G層或B層灰度圖像)的最低位平面並提取。
clear;
clc;
I=imread('pic1.bmp');
L=imread('lena.jpg');
BW=im2bw(L);
J=double(I);
[m,n]=size(BW);
[l,w]=size(I);
if or(m>l,n>w/3)
error('嵌入信息量過大,請重新選擇圖像');
end
for i=1:m
for j=1:n
J(i,j,1)=J(i,j,1)-mod(J(i,j,1),2)+BW(i,j);
% 把J的紅色圖層最低位清空換成二值圖像BW相應的行列值
end
end
M=bitget(J(:,:,1),1);
J=uint8(J);
imwrite(J,'embedded.bmp'); % embed vt.嵌入
figure;
subplot(221);imshow(I);
subplot(222);imshow(BW);
subplot(223);imshow('embedded.bmp');
subplot(224);imshow(M);
三、直接4bit替換法
圖像的低4bit,通常可以做隱藏信息的空間,也就是載體的冗余空間。
直接4bit替換法,就是直接用秘密圖像像素值的高4bit去替換載體圖像像素值的低4bit。
目的:把rice.png(256×256)藏到baboon.bmp(512×512)
不同分辨率直接4位替換法:
clear;
clc;
I=imread('baboon.bmp');
msg=imread('rice.png');
[row,col]=size(msg);
IR=I(:,:,1);
[m,n]=size(IR);
if or(row>m,col>n)
error('嵌入信息量過大,請重新選擇圖像');
end
for i=1:row
for j=1:col
IR(i,j)=bitand(IR(i,j),240); % 240轉二進制為11110000
end
end
% 置載體圖像R層的低4bit為0
figure;imshow(IR);
figure;imshow(msg);
takemsg4=bitand(msg,240);
% 置秘密圖像的低4bit為0
figure;imshow(takemsg4);
shiftmsg4=bitshift(takemsg4,-4);
% 將秘密圖像的高4bit右移4位
figure;imshow(shiftmsg4,[]);
for i=1:row
for j=1:col
IR(i,j)=bitor(IR(i,j),shiftmsg4(i,j));
end
end
% 圖像隱藏
I(:,:,1)=IR;
% 寫回並保存
figure;imshow(I);
imwrite(I,'bit4hide.bmp');
不同分辨率直接4位替換法提取:
clear;
clc;
I=imread('bit4hide.bmp');
[row,col]=size(I)
A=I(:,:,1);
for i=1:row/2 % 這里除以2是為了完整顯示rice.png,下圖展示的是不除2的
for j=1:col/3/2
M(i,j)=bitand(A(i,j),15); % 1111
end
end
M=bitshift(M,4);
imshow(M);
四、灰度圖8位分別藏於RGB層
將灰度圖rice.png的8位像素數據分別藏於載體圖像baboon.bmp的R、G、B層像素值的低幾位:
clear;
clc;
I=imread('baboon.bmp');
J=imread('rice.png');
[row,col]=size(J);
for h=1:3
for i=1:row
for j=1:col
I(i,j,h)=bitand(I(i,j,h),248); % 1111 1000
end
end
end
figure;
subplot(221);imshow(I);
subplot(222);imshow(I(:,:,1));
subplot(223);imshow(I(:,:,2));
subplot(224);imshow(I(:,:,3));
Y=bin2dec('11100000'); % 224
y1=bitshift(Y,-3);
y2=bitshift(Y,-6);
for h=1:3
M=bitand(J(1:row,1:col),bitshift(Y,-3*(h-1)));
shiftM=bitshift(M,h*3-8);
I(1:row,1:col,h)=bitor(I(1:row,1:col,h),shiftM);
end
figure;imshow(I);
imwrite(I,'fullhide.bmp');
將上題中隱藏的灰度圖提取出來並保存:
clear;
clc;
I=imread('fullhide.bmp');
for h=1:3
for i=1:256
for j=1:256
I(i,j,h)=bitand(I(i,j,h),7); % 0111
end
end
end
figure;
subplot(221);imshow(I,[]);
subplot(222);imshow(I(:,:,1));
subplot(223);imshow(I(:,:,2));
subplot(224);imshow(I(:,:,3));
K=uint8(zeros(256,256));
for h=1:3
M=bitshift(I(1:256,1:256,h),8-h*3); % 向左移動8-h*3位,5、2、-1
K=bitor(K,M);
end
imwrite(K,'riceget.bmp');
figure;imshow('riceget.bmp');
五、圖片中隱藏文本信息
目的:實現文本信息在載體圖像中的偽隨機位置的信息隱藏並提取文本信息。
1、編寫偽隨機序列發生函數randinterval.m
function [row,col]=randinterval(map,count,key)
[m,n]=size(map);
interval1=floor(m*n/count)+1; % 向下取整,即取不大於m*n/count的最大整數
interval2=floor(m*n/count)-1;
if interval2==0
error('載體太小,請重新選擇載體圖像');
end
rand('seed',key); % 生成隨機序
a=rand(1,count);
row=zeros(1,count); % 初始化
col=zeros(1,count);
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
2、編寫程序binhide.m,完成功能:將文本信息hidden.txt嵌入pic1.bmp圖像中的某一層的偽隨機位置
clear;
clc;
I=imread('pic1.bmp');
IR=I(:,:,1);
cover=double(IR);
fid=fopen('hidden.txt','r');
[msg,len_total]=fread(fid,inf,'ubit1');
[m,n]=size(cover);
if len_total>m*n
error('嵌入信息量過大,請重新選擇圖像');
end
[row,col]=randinterval(cover,len_total,2021);
p=1;
for i=1:len_total
cover(row(i),col(i))=cover(row(i),col(i))-mod(cover(row(i),col(i)),2)+msg(p,1);
if p==len_total
break;
end
p=p+1;
end
cover=uint8(cover);
I(:,:,1)=cover;
imwrite(I,'randhide.bmp');
M=cover-IR;
figure;imshow(M,[]);
figure;imshow('randhide.bmp');
fclose(fid);
3、編寫程序binget.m,將上題中隱藏的文本信息提取出來,並保存在binget.txt中
clear;
clc;
I=imread('randhide.bmp');
IR=double(I(:,:,1));
count=11520;
[row_1,col_1]=randinterval(IR,count,2021);
fid=fopen('binget.txt','a');
for i=1:count
fwrite(fid,mod(IR(row_1(i),col_1(i)),2),'ubit1');
end
fclose(fid);