Archive

Posts Tagged ‘data hiding’

Similarity threshold computation for Cox watermarking

May 18, 2010 18 comments

If you dive into watermarking field, you will have to deal for sure with Cox embedding technique.

Cox’s embedding works in the transform domain (e.g. DCT or DWT) while LSB works in the spatial domain. The idea behind this technique is the following:

1) take an image and a watermark (let’s say the watermark is 512*512 binary)

2) compute the DCT (DWT) of the image, and compute all it’s coefficients

3) sort the coefficients preserving their position

4) we know that most of energy is (approximately) inside the first 1000 coefficients so we could easily embed the watermark inside the first 1024 coefficients by exploiting on each of these coefficients one of the following embedding:

  • V'(i) = V'(i) * (1 + alpha*W(i))
  • V'(i) = V(i)+ alpha*W(i)
  • V'(i) = V(i) * e ^ (alpha*W(i))

where V(i) is the original value of the coefficient, V'(i) is the value of the coefficient after the embedding, W(i) is the watermark and alpha is a strength embedding factor.

5) Reorder the coefficients on the their original positions and perform an antitrasform

Since the code is pretty easy I will not post it here, but if you have troubles please just write me and I will make it available.

Ok, at this point we have a watermarked image…but what about the detection???

Well, you can’t recover the original watermark as you did for LSB watermarking, but you can assert whether your mark is inside the cover image or not. The procedure is the following:

1) take the watermarkded image

2) compute again the DCT (DWT) of the image, and compute all it’s coefficients

3) sort again the coefficients preserving their position

4) try to compute an approximate mark (Wap(i)) by inverting the formula you used in embedding

5) Check if the similarity between the original mark and Wap(i) is above a certain threshold, if so your watermark is present

To compute the threshold you have to run an experimental study; basically you must compute the similarity between many fake watermarks (e.g. 999) and the original watermark, than the similarity between your watermark and itself.

Similarity fuction is defined as: SIM(W,Wi) = (W * Wi) / sqrt(Wi * Wi)

When you have all the similarities, you may notice that you have many peaks you can see as noise, and a peak where you computed the similarity with itself. To set the threshold you just need to take the second peak and add it its 15%, so that you will rarely have false positive matching.

Here is the code to compute the similarity:

function [threshold,sim_detection] = threshold_computation
    watermarks=zeros(1000,1024);
    %% generate 999 random fake (1,1024) watermarks
    for i=1:999
        watermarks(i,:)=round(rand(1,1024));
    end
    %% load from a mat file the original (512,512) watermark
    %% (variable name is watermark as well)
    load('test.mat');
    wm=watermark;
    %% reshape original watermark to (1,1024)
    [r c]=size(wm);
    w=reshape(wm,1,r*c);
    w=round(rand(1,1024));
    w=double(w);

    %% add reshaped watermark as the 1000 element of watermarks set
    watermarks(1000,:)=w;

    %% for each watermark compute similarity detection and save result in a vector
    sim_detection=zeros(1000);
    for i=1:1000
        sim_detection(i)=w*watermarks(i,:)'/sqrt(watermarks(i,:)*watermarks(i,:)');
    end
    %% sort values according to magnitude
    [values,index]=sort(sim_detection,'descend');
    threshold=values(1);
    %% compute threshold
    threshold=values(2)+((values(2)*10)/100);
end

Let’s execute the code:

>> [real_threshold,threshold_vec] = threshold_computation;
>> plot(threshold_vec,'DisplayName','threshold_vec','YDataSource','threshold_vec');

Here is the result of the plot operation, in the abscissa we have the watermarks, while in the in ordinate we have the similarity computed for the given watermark (notice that in abscissa 1000 there is a peak of similarity due to the fact that for the computation we are using the real watermark).

That’s all foks! Stay tuned!

LSB watermarking using MATLAB

March 22, 2010 155 comments

Lately at university, I have been following the “Data Hiding” course. Basically the lecture are focused on digital watermarking (on images and audio files), and cryptography.

One of the first lab lessons was about LSB (least significant bit) replacement. The idea behind this watermarking technique is the following: if you see you image as a matrix NxM (where N and M are the dimension of the image) you can represent the value of the pixel in the position (i,j) as a binary number; this binary can be then divided in all of its bit, so that you will have a most significant bit (the one that contains quite a lot of information, and a least significant bit that contains few information).

If your image is for example in gray scale, you can make changes to the value of the LSB without any perceptible distortion for the human user therefore you can think of taking the LSB of an image (the cover image) and change its value in every pixel with the MSB of another image, that we would like to embed in a secret/non perceptible way in the cover image). For my code I used two bitmap image, unfortunately wordpress doesn’t allow me to publish bmp images, so I’m just going to put here the links for getting the images from the web: http://www.ece.rice.edu/~wakin/images/lena512.bmp http://www.eecs.qmul.ac.uk/~phao/CIP/Images/Baboon.bmp

Ok, now (as always) a lot of code about LSB watermarking and few words about it 😀 Briefly with the following code I will try to embed the MSB of the baboon image into the picture of Lena by exploiting the LSB embedding technique. We will try also to add an WGN (white gaussian noise) to the image then after these operations we will write to file the results. The code is heavily commented, so I think that further explanations are not needed.

%Project: 	Tutorial on Least Significant Bit Substitution
%               Watermark Embedding

clear all; 

% read in the cover object you want to use for embedding
file_name='lena.bmp';
cover_object=imread(file_name);

% read the message image you want to hide in the cover image
file_name='baboon.bmp';
message=imread(file_name);

% conversions needed to spread the image values on a 256 gray-scale
message=double(message);
message=round(message./256);
message=uint8(message);

% determine the size of cover image used for embedding
Mc=size(cover_object,1);	%Height
Nc=size(cover_object,2);	%Width

% determine the size of message object to embed
Mm=size(message,1);	        %Height
Nm=size(message,2);	        %Width

%y = uint8(wgn(Mm,Nm,1));

% title the message object out to cover object size to generate watermark
for ii = 1:Mc
    for jj = 1:Nc
        watermark(ii,jj)=message(mod(ii,Mm)+1,mod(jj,Nm)+1);
    end
end

% set the LSB of cover_object(ii,jj) to the value of the MSB of watermark(ii,jj)
watermarked_image=cover_object;
for ii = 1:Mc
    for jj = 1:Nc
        watermarked_image(ii,jj)=bitset(watermarked_image(ii,jj),1,watermark(ii,jj));
    end
end

% add noise to watermarked image
noisy = imnoise(watermarked_image,'gaussian');

% write to file the two images
imwrite(watermarked_image,'lsb_watermarked.bmp','bmp');
imwrite(noisy,'lsb_watermarked_noise.bmp','bmp');

% display watermarked image
figure(1)
imshow(watermarked_image,[])
title('Watermarked Image')

% display watermarked and noised image
figure(2)
imshow(noisy,[])
title('Watermarked and noised Image')

So if you execute this code you are going to have on screen and on disk two images, that I can’t dsiplay here because they are bmp files.

Now let’s see how to recover the watermark:

%Project: 	Tutorial on Least Significant Bit Substitution
%               Watermark Recover

clear all;

% read in watermarked image
file_name='lsb_watermarked.bmp';
watermarked_image=imread(file_name);

% determine size of watermarked image
Mw=size(watermarked_image,1);	%Height
Nw=size(watermarked_image,2);	%Width

% use lsb of watermarked image to recover watermark
for ii = 1:Mw
    for jj = 1:Nw
        watermark(ii,jj)=bitget(watermarked_image(ii,jj),1);
    end
end

% scale the recovered watermark
watermark=256*double(watermark);

% scale and display recovered watermark
figure(1)
imshow(watermark,[])
title('Recovered Watermark')

Try the code and let me know in case of troubles!