分享一下最近看到的一个关于图片嵌入隐藏的算法:
“大容量的信息隐藏算法",这是一种基于空间域的自适应多平面位的信息隐藏算法。该算法计算复杂度低、信息隐藏量大。且有实验表明在不影响图像视觉效果的前提下,其信息隐藏量比LSB算法大,并具有更高的安全性。该算法的主要思想是对每个像素点进行判断,根据HVS的特性,在最高非0有效位后的指定位(y)开始嵌入隐藏信息,嵌入到另一个指定位(z)为止。
下面直接贴上MATLAB代码和实验结果:
(1) main_ImgEmbed.m
clc; clear all; close all; warning off all; yr=4;//论文中实验得到 yg=5; yb=3; Img=imread('lena.jpg'); figure;imshow(Img,[]);title('原图'); Img=double(Img); ImgR=Img(:,:,1); ImgG=Img(:,:,2); ImgB=Img(:,:,3); Imgmark=imread('ImgEmbed.jpg'); Imgmark=double(Imgmark); figure;imshow(Imgmark,[]);title('ImgEmbed'); [markm,markn]=size(Imgmark); Imgmarkline = Imgmark(:); %二维数组转成一列 Imgmarklinebin=zeros(markm*markn*8,1); %转化为二进制 for ii=1:markm*markn [Imgmarklinebin(8*ii-7),Imgmarklinebin(8*ii-6),Imgmarklinebin(8*ii-5),Imgmarklinebin(8*ii-4),Imgmarklinebin(8*ii-3),... Imgmarklinebin(8*ii-2),Imgmarklinebin(8*ii-1),Imgmarklinebin(8*ii)]=Find8bits(Imgmarkline(ii)); end %% %嵌入 %对于红色通道 embedNumsed=0;%已嵌入个数 [M,N,Z]=size(Img); y=zeros(8,1); flag=0; %辅助跳出的标志 ImgRline=ImgR(:); %转换为一列 ImgRlineNew=ImgRline; %嵌入后 for ii=1:M*N if flag==1; %跳出外层循环 break; end [y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)]=Find8bits(ImgRline(ii)); posNzreo=FindNotZero(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)); embedNums=posNzreo-yr; %能嵌入的个数 if embedNums>0 %符合嵌入条件 for jj=1:embedNums embedNumsed=embedNumsed+1; %已嵌入个数 if embedNumsed>markm*markn*8 %嵌入完成 flag=1; %设置标识,使外层循环也跳出 break; end y(jj)=Imgmarklinebin(embedNumsed);%嵌入 end end ImgRlineNew(ii)=bin2dec_trans(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1));%嵌入后的 end ImgR2=reshape(ImgRlineNew,[M,N]); %对于G通道 ImgGline=ImgG(:); %转换为一列 ImgGlineNew=ImgGline; %嵌入后 for ii=1:M*N if flag==1; %跳出外层循环 break; end [y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)]=Find8bits(ImgGline(ii)); posNzreo=FindNotZero(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)); embedNums=posNzreo-yg; %能嵌入的个数 if embedNums>0 %符合嵌入条件 for jj=1:embedNums embedNumsed=embedNumsed+1; %已嵌入个数 if embedNumsed>markm*markn*8 %嵌入完成 flag=1; %设置标识,使外层循环也跳出 break; end y(jj)=Imgmarklinebin(embedNumsed);%嵌入 end end ImgGlineNew(ii)=bin2dec_trans(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1));%嵌入后的 end ImgG2=reshape(ImgGlineNew,[M,N]); %对于B通道 ImgBline=ImgB(:); %转换为一列 ImgBlineNew=ImgBline; %嵌入后 for ii=1:M*N if flag==1; %跳出外层循环 break; end [y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)]=Find8bits(ImgBline(ii)); posNzreo=FindNotZero(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)); embedNums=posNzreo-yb; %能嵌入的个数 if embedNums>0 %符合嵌入条件 for jj=1:embedNums embedNumsed=embedNumsed+1; %已嵌入个数 if embedNumsed>markm*markn*8 %嵌入完成 flag=1; %设置标识,使外层循环也跳出 break; end y(jj)=Imgmarklinebin(embedNumsed);%嵌入 end end ImgBlineNew(ii)=bin2dec_trans(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1));%嵌入后的 end ImgB2=reshape(ImgBlineNew,[M,N]); ImgNew=zeros(M,N,Z); ImgNew(:,:,1)=ImgR2; ImgNew(:,:,2)=ImgG2; ImgNew(:,:,3)=ImgB2; figure;imshow(uint8(ImgNew),[]);title('嵌入后的RGB图'); % imwrite(uint8(ImgNew),'介质图片_嵌入图像后.jpg'); %保存图片 %% %提取嵌入图像 flag=0; Imgmark_extractlinebin=zeros(markm*markn*8,1); extractNumsed=0;%已提取个数 % R通道 ImgRline2=ImgR2(:); %转换为一列 for ii=1:M*N if flag==1; %跳出外层循环 break; end [y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)]=Find8bits(ImgRline2(ii)); posNzreo=FindNotZero(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)); embedNums=posNzreo-yr; %已嵌入的个数 if embedNums>0 %符合嵌入条件 for jj=1:embedNums extractNumsed=extractNumsed+1; %已提取个数 if extractNumsed>markm*markn*8 %提取完成 flag=1; %设置标识,使外层循环也跳出 break; end Imgmark_extractlinebin(extractNumsed)=y(jj);%提取 end end end % G通道 ImgGline2=ImgG2(:); %转换为一列 for ii=1:M*N if flag==1; %跳出外层循环 break; end [y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)]=Find8bits(ImgGline2(ii)); posNzreo=FindNotZero(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)); embedNums=posNzreo-yg; %已嵌入的个数 if embedNums>0 %符合嵌入条件 for jj=1:embedNums extractNumsed=extractNumsed+1; %已提取个数 if extractNumsed>markm*markn*8 %提取完成 flag=1; %设置标识,使外层循环也跳出 break; end Imgmark_extractlinebin(extractNumsed)=y(jj);%提取 end end end % G通道 ImgBline2=ImgB2(:); %转换为一列 for ii=1:M*N if flag==1; %跳出外层循环 break; end [y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)]=Find8bits(ImgBline2(ii)); posNzreo=FindNotZero(y(8),y(7),y(6),y(5),y(4),y(3),y(2),y(1)); embedNums=posNzreo-yb; %已嵌入的个数 if embedNums>0 %符合嵌入条件 for jj=1:embedNums extractNumsed=extractNumsed+1; %已提取个数 if extractNumsed>markm*markn*8 %提取完成 flag=1; %设置标识,使外层循环也跳出 break; end Imgmark_extractlinebin(extractNumsed)=y(jj);%提取 end end end %二进制转十进制 Imgmarklinedec=zeros(markm*markn,1); %转化为十进制 for ii=1:markm*markn Imgmarklinedec(ii)=bin2dec_trans(Imgmark_extractlinebin(8*ii-7),Imgmark_extractlinebin(8*ii-6),Imgmark_extractlinebin(8*ii-5),Imgmark_extractlinebin(8*ii-4),... Imgmark_extractlinebin(8*ii-3),Imgmark_extractlinebin(8*ii-2),Imgmark_extractlinebin(8*ii-1),Imgmark_extractlinebin(8*ii)); end Imgmarkextract=reshape(Imgmarklinedec,[markm,markn]); figure;imshow(Imgmarkextract,[]);title('提取的嵌入图片'); % imwrite(uint8(Imgmarkextract),'待嵌入图片_gray_提取结果.jpg'); %保存图片 %检查提取的水印和原水印的区别 difmarked=Imgmarkextract-Imgmark; %做差 %发现差为0,即说明完全一致,提取正确
(2)Find8bits.m
function [y7,y6,y5,y4,y3,y2,y1,y0]=Find8bits(Data) y0=mod(Data,2); y7=fix(Data/128);Data=Data-y7*128; y6=fix(Data/64); Data=Data-y6*64; y5=fix(Data/32); Data=Data-y5*32; y4=fix(Data/16); Data=Data-y4*16; y3=fix(Data/8); Data=Data-y3*8; y2=fix(Data/4); Data=Data-y2*4; y1=fix(Data/2); Data=Data-y1*2; end
(3)bin2dec_trans.m
%二进制转十进制 function Data=bin2dec_trans(y7,y6,y5,y4,y3,y2,y1,y0) Data=y7*128+y6*64+y5*32+y4*16+y3*8+y2*4+y1*2+y0; end
(4)FindNotZero.m
%找出第一个不为零的数位 从最高位(第八位)开始 function posNzreo=FindNotZero(y7,y6,y5,y4,y3,y2,y1,y0) if y7~=0 posNzreo=8; elseif y6~=0 posNzreo=7; elseif y5~=0 posNzreo=6; elseif y4~=0 posNzreo=5; elseif y3~=0 posNzreo=4; elseif y2~=0 posNzreo=3; elseif y1~=0 posNzreo=2; else posNzreo=1; end end
实验结果如下:
(1)原图
(2)要嵌入隐藏的图片
(3)嵌入隐藏图片后的介质图像
(4)提取的嵌入图片
整个工程代码下载请到:http://download.csdn.net/download/tianma5/9508467
才疏学浅,多多指教。