Code covered by the BSD License  

Highlights from
Binary Image Watermarking/Data Hiding: Data, Algorithms, and Distortion Measure

Binary Image Watermarking/Data Hiding: Data, Algorithms, and Distortion Measure

by

 

26 Apr 2012 (Updated )

A package on binary image watermarking/data hiding, including data, algorithms & distortion measure.

fhidingSecure(testimg)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function fhidingSecure(testimg)
%testimg='french-4';
MaskSize=7;%5;
skwid=3;
blksize=8; 
%IF THIS IS NOT SATISFIED, THEN IN EMBEDDING, REVERSE SHIFTING SHOULD BE MORE COMPLICATED.

%testimg='ccitt4';%'french-4';
save SecureResults\paras blksize testimg MaskSize skwid
clear all
load SecureResults\paras
WeiTable=WeiCal(MaskSize);
ImIn = imread(['test_images\',testimg,'.tif']);

[inRows, inCols]=size(ImIn);
RowsNum=double(floor(inRows/blksize));
ColsNum=double(floor(inCols/blksize));
Rows=blksize*RowsNum;
Cols=blksize*ColsNum;
Im0=zeros(Rows,Cols);%ignore rest if blocks don't fit well. Testing purpose only. Zero-padding in practice.
Im0=ImIn(1:Rows,1:Cols);

clear ImIn 

Im0=double(Im0);

%shift key generation
sblksize=blksize;%2^skwid;
sklen_row=ceil(Rows/sblksize);
sklen_col=ceil(Cols/sblksize);
sklen=skwid*(sklen_row+sklen_col);
skey=rand(sklen,1);
skey=double(im2bw(skey));
save SecureResults\skey skey

%2-D Shifting%%%%%%%%%%%%%%%%%%%
blkrows = 1:sblksize;
blkcols = blkrows;
srIm0=Im0;
%row shift first, shift to left side
for i=1:sklen_row
    this_rskey=skey(((i-1)*skwid+1):(i*skwid));
    this_rswid=num2str(this_rskey(1));
    for j=2:skwid
        this_rswid=[this_rswid,num2str(this_rskey(j))];
    end
    this_rswid=bin2dec(this_rswid);
    srIm0(((i-1)*sblksize+1):(i*sblksize),1:(Cols-this_rswid))=Im0(((i-1)*sblksize+1):(i*sblksize),(this_rswid+1):Cols);
    srIm0(((i-1)*sblksize+1):(i*sblksize),(Cols-this_rswid+1):Cols)=Im0(((i-1)*sblksize+1):(i*sblksize),1:this_rswid);
end
%Shift upwards.
s2Im0=srIm0;
for i=1:sklen_col
    this_cskey=skey(((sklen_row+i-1)*skwid+1):((sklen_row+i)*skwid));
    this_cswid=num2str(this_cskey(1));
    for j=2:skwid
        this_cswid=[this_cswid,num2str(this_cskey(j))];
    end
    this_cswid=bin2dec(this_cswid);
    s2Im0(1:(Rows-this_cswid),((i-1)*sblksize+1):(i*sblksize))=srIm0((this_cswid+1):Rows,((i-1)*sblksize+1):(i*sblksize));
    s2Im0((Rows-this_cswid+1):Rows,((i-1)*sblksize+1):(i*sblksize))=srIm0(1:this_cswid,((i-1)*sblksize+1):(i*sblksize));
end
%s2Im0 is the 2D shifted version in which the odd-even feature is used to embed
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%Watermark geneartion
nubn_blksize=mark_length(s2Im0,blksize,RowsNum,ColsNum,1);
disp(['There are ', num2str(nubn_blksize),' non-uniform ', num2str(blksize), 'x', num2str(blksize),' blocks out of ',num2str(RowsNum*ColsNum)]);
data2hide=rand(nubn_blksize,1);
data2hide=im2bw(data2hide);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Im_1=Im0;
blkrows = 1:blksize;
blkcols = blkrows;
k=0;
MaxMinDRDM=0;
for i=0:(RowsNum-1)
    for j=0:(ColsNum-1)
        blk0=s2Im0(i*blksize+blkrows, j*blksize+blkcols);
        if max(max(blk0))~=min(min(blk0))          
            sum_blk=sum(sum(blk0));
            k=k+1;
            if mod(sum_blk,2)~=data2hide(k)
                blk_scores=ones(blksize);
                blk_isIm0=zeros(blksize);
                blk_jsIm0=zeros(blksize);
                for blki=blkrows
                    for blkj=blkcols
                        %Do Inverse shifting in effect!
                        this_sj=floor((j*blksize+blkj-1)/sblksize);
                        this_cskey=skey(((sklen_row+this_sj)*skwid+1):((sklen_row+this_sj+1)*skwid));
                        this_cswid=num2str(this_cskey(1));
                        for blkk=2:skwid
                            this_cswid=[this_cswid,num2str(this_cskey(blkk))];
                        end
                        this_cswid=bin2dec(this_cswid);                        
                        srIm0i=blki+i*blksize;
                        if srIm0i<Rows-this_cswid+1
                            blkiIm0=srIm0i+this_cswid;
                        else
                            blkiIm0=srIm0i+this_cswid-Rows;
                        end

                        this_si=floor((blkiIm0-1)/sblksize);
                        this_rskey=skey((this_si*skwid+1):((this_si+1)*skwid));
                        this_rswid=num2str(this_rskey(1));
                        for blkk=2:skwid
                            this_rswid=[this_rswid,num2str(this_rskey(blkk))];
                        end
                        this_rswid=bin2dec(this_rswid);
                        s0Im0j=blkj+j*blksize;
                        if s0Im0j<Cols-this_rswid+1
                            blkjIm0=s0Im0j+this_rswid;
                        else
                            blkjIm0=s0Im0j+this_rswid-Cols;
                        end                        
                        
                        blk_scores(blki,blkj)=CalPxlDRDM(Im0,Rows,Cols,blkiIm0,blkjIm0,MaskSize,WeiTable,blksize);
                        blk_isIm0(blki,blkj)=blkiIm0;
                        blk_jsIm0(blki,blkj)=blkjIm0;
                    end
                end
                                  
                [MinRow,i1]=min(blk_scores);
                [RowMin,i2]=min(MinRow);
                row_No=i1(i2);
                col_No=i2;    
                if RowMin>MaxMinDRDM
                    MaxMinDRDM=RowMin;
                end
                blk0(row_No,col_No)=~blk0(row_No,col_No);
                %Problem: Confusion caused if after flipping, it becomes a uniform (all BLACK/WHITE) BLOCK
                if max(max(blk0))==min(min(blk0))
                    k=k-1;
                end               
                Im_1(blk_isIm0(row_No,col_No), blk_jsIm0(row_No,col_No))=~Im_1(blk_isIm0(row_No,col_No), blk_jsIm0(row_No,col_No));
            end
        end
    end
end
truecapacity=k;
disp(['Amount of data hidden successfully is ',num2str(truecapacity),' bits']);
datahidden=data2hide(1:k);
save SecureResults\datahidden datahidden
imwrite(Im_1, ['SecureResults\',testimg,'-wm-m',num2str(MaskSize),'.tif']);
diffimg=xor(Im_1,Im0);
imwrite(diffimg,['SecureResults\',testimg,'-dif-m',num2str(MaskSize),'.tif']);
changednum=sum(sum(diffimg));
disp(['The number of changed pixels are ',num2str(changednum)]);
baseimg=0.8+Im0*0.2;
[diffm,diffn]=find(diffimg==1);
for i=1:changednum
    baseimg(diffm(i),diffn(i))=0;
end
imwrite(mat2gray(baseimg),['SecureResults\',testimg,'-supdif-m',num2str(MaskSize),'.tif']);

psnr_value=psnr(Im_1,double(Im0));
disp(['PNSR is ',num2str(psnr_value)]);
DRDM_value=CalDRDM(['test_images\',testimg,'.tif'],['SecureResults\',testimg,'-wm-m',num2str(MaskSize),'.tif'],5,nubn_blksize);
disp(['DRDM is ',num2str(DRDM_value)]);

fid=fopen(['SecureResults\',testimg,'-hiding_LOG-m',num2str(MaskSize),'.tex'],'w');
fprintf(fid,'Document Image Name: %s',testimg);
fprintf(fid,'\nImage is of size %d x %d, weight matrix size is %d',Rows, Cols,MaskSize);
fprintf(fid,'\nThere are %d non-uniform  %d by %d, blocks out of %d blocks.',nubn_blksize,blksize,blksize,RowsNum*ColsNum);
fprintf(fid,'\nAmount of data hidden successfully is %d bits',truecapacity);
fprintf(fid,'\nThe number of changed pixels are %d pixels',changednum);
fprintf(fid,'\nThe worst case flipping (largest min DRDM) is %f',MaxMinDRDM);
fprintf(fid,'\nPNSR is %fdB',psnr_value);
fprintf(fid,'\nDRDM is %f with m = %d',DRDM_value,MaskSize);
fclose(fid);

extract_secure

Contact us