matlabsteganographylsb

PSNR of image in matlab


I am confused with the Peak signal-to-noise ratio (PSNR) between original image and encrypted image. As i know, the higher PSNR value means the better image quality. I tried to test and calculate the PSNR value. I used LSB technique on the text steganography.

  1. I tried embed 100 character into an image. It results with 69.9696 dB.
  2. I tried embed 5 character into an image. It results with 68 dB.

Now, what I think in my mind is:

Anyone can tell me or correct me with my mistake?

------Attached Coding------

Str = 'after this, I tried calculate the PSNR value with original image and stego image. 100 character which is read from file is embedded into image, higher PSNR value. 5 character, less PSNR value.';%many character
%Str = 'a';   %one character 

Str=uint8(Str);    %converting to 8 bit numbers for proper calculation
fprintf('%d ', Str);
fprintf('\n');
stringLength = length(Str);


x=imread('lena.bmp');   %reading the image file
x=uint8(x);                %conversion to 8 bit
[x_row,x_col]=size(x);


numPixelsInImage = numel(x);
bitsPerLetter = 7;  % For ASCII, this is 7.
numPixelsNeededForString = stringLength * bitsPerLetter;

binaryAsciiString = dec2bin(Str)'
whos binaryAsciiString
binaryAsciiString = binaryAsciiString(:)'

 stegoImage = x;
 stegoImage(1:numPixelsInImage) = bitset(stegoImage(1:numPixelsInImage), 1, 0);
 oneIndexes = find(binaryAsciiString == '1'); 
 stegoImage(oneIndexes) = bitset(stegoImage(oneIndexes), 1, 1);



 imwrite(uint8(stegoImage),'stego123.bmp') 

fprintf('\nPSNR: %9.7f dB\n\n', psnr(x,stegoImage));

After this, I tried calculate the PSNR value with original image and stego image. 100 character which is read from file is embedded into image, higher PSNR value. 5 character, less PSNR value.

That's why I get confused.

---HERE is my PSNR code---

function [PSNR,mse]=psnr(X,Y)
% function [PSNR,mse]=psnr(X,Y)
% Peak signal to noise ratio of the difference between images and the
%mean square error
% If the second input Y is missing then the PSNR and MSE of X itself
% becomes the output (as if Y=0).
if nargin<2, D=X;
else
if any(size(X)~=size(Y)), error('The input size is not equal to each other!'); end
D=X-Y;
end
mse=sum(D(:).*D(:))/prod(size(X));
PSNR=10*log10(255^2/mse);

I just call the function of PSNR and print the PSNR value of original image and stego image.

lena original bmp

The many character I embed, I get 51.1687256 dB. The one character I embed, I get 51.1578686 dB.

Can tell me why?


Solution

  • There is an error in your pnsr function. Both inputs are uint8, which restricts all values in the 0-255 range. This can be a problem for D=X-Y.

    >> uint8(0) - uint8(1)
    0
    >> double(0) - double(1)
    -1
    

    Changing to D = double(X) - double(Y) will give you the correct values for the long and 1-letter strings, 51.1576 dB and 51.1578 dB respectively.

    However, your algorithm is suboptimal. You set the LSB of every pixel to 0 before embedding your bits. You effectively modify up to 262144 pixels while your message is much shorter. This brings down the PSNR by a lot and explains why the value is so similar for messages of both 7 and 1536 bits long. Instead, you should modify only the minimum number of pixels required for embedding your message by using numPixelsNeededForString. Or more compactly,

    cover = imread('lena512.png');
    Str = 'after this, I tried calculate the PSNR value with original image and stego image. 100 character which is read from file is embedded into image, higher PSNR value. 5 character, less PSNR value.';
    %Str = Str(1:1);
    
    bits = dec2bin(Str, 7)';
    bits = bits(:);
    
    stego = cover;
    stego(1:numel(bits)) = bitset(stego(1:numel(bits)), 1, str2num(bits)');
    
    psnr(cover, stego)
    

    Doing so will give you a PSNR of 73.9530 dB for the long string and 95.3265 dB for the 1-letter string.