├── .gitignore
├── Paper.pdf
├── large.mp4
├── small.mp4
├── message.png
├── r_message.png
├── images
├── steganography.png
├── r_message_large.png
├── r_message_small.png
├── hamming_decoding.png
├── hamming_encoding.png
├── steganography_decoding.png
└── steganography_encoding.png
├── yuv2rgb.m
├── rgb2yuv.m
├── psnr.m
├── combine_frames.m
├── main.m
├── construct_frames.m
├── Design.md
├── frames_to_video.m
├── embed_message.m
├── Introduction.md
├── receiver_retrieve.m
├── README.md
├── unscramble.m
└── scramble.m
/.gitignore:
--------------------------------------------------------------------------------
1 | frames
2 | em_small.avi
3 | em_video.avi
4 | r_message.png
--------------------------------------------------------------------------------
/Paper.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/Paper.pdf
--------------------------------------------------------------------------------
/large.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/large.mp4
--------------------------------------------------------------------------------
/small.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/small.mp4
--------------------------------------------------------------------------------
/message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/message.png
--------------------------------------------------------------------------------
/r_message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/r_message.png
--------------------------------------------------------------------------------
/images/steganography.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/steganography.png
--------------------------------------------------------------------------------
/images/r_message_large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/r_message_large.png
--------------------------------------------------------------------------------
/images/r_message_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/r_message_small.png
--------------------------------------------------------------------------------
/images/hamming_decoding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/hamming_decoding.png
--------------------------------------------------------------------------------
/images/hamming_encoding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/hamming_encoding.png
--------------------------------------------------------------------------------
/images/steganography_decoding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/steganography_decoding.png
--------------------------------------------------------------------------------
/images/steganography_encoding.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CSE-Projects/Secure-Video-Steganography/HEAD/images/steganography_encoding.png
--------------------------------------------------------------------------------
/yuv2rgb.m:
--------------------------------------------------------------------------------
1 | %yuv2rgb Convert Y, U, V components of a frame to a RGB frame
2 | function [RGB] = yuv2rgb( Y, U, V )
3 | % Conversion formula YUV to RGB
4 | R = Y + 1.139834576 * V;
5 | G = Y -.3946460533 * U -.58060 * V;
6 | B = Y + 2.032111938 * U;
7 |
8 | % combine components
9 | RGB = cat(3,R,G,B);
10 | imshow(RGB);
11 | end
--------------------------------------------------------------------------------
/rgb2yuv.m:
--------------------------------------------------------------------------------
1 | %rgb2yuv Convert RBG frame to separate Y, U, V components
2 | function [Y, U, V] = rgb2yuv( RGB )
3 | % Get R, G, B components of the frame
4 | R = RGB(:,:,1);
5 | G = RGB(:,:,2);
6 | B = RGB(:,:,3);
7 | % Conversion formula RGB to YUV
8 | Y = 0.299 * R + 0.587 * G + 0.114 * B;
9 | U = (-0.14713 * R )- (0.28886 * G) + (0.436 * B);
10 | V = 0.615 * R - 0.51499 * G - 0.10001 * B;
11 | % imshow(Y);
12 | % imshow(U);
13 | % imshow(V);
14 | end
--------------------------------------------------------------------------------
/psnr.m:
--------------------------------------------------------------------------------
1 | %=== Get both messages ===%
2 | r_message = logical(imread('r_message.png'));
3 | message = imread('message.png');
4 |
5 | %=== Calculate squared error ===%
6 | squared_error = 0;
7 | for i = 1:140
8 | for j = 1:200
9 | % difference in pixel squared
10 | squared_error = squared_error + (message(i, j) - r_message(i, j))^2;
11 | end
12 | end
13 |
14 | % calculate mean squared error
15 | mean_squared_error = squared_error / (140*200);
16 |
17 | % Get PSNR value
18 | psnr_val = -10*(log10(mean_squared_error))
--------------------------------------------------------------------------------
/combine_frames.m:
--------------------------------------------------------------------------------
1 | %=== Set directory of frames ===%
2 | workingDir = 'frames';
3 | mkdir(workingDir,'embeddedFramesRGB');
4 |
5 | % Unscramble each of the frames Y, U, V
6 | unscramble(key, height, width, noOfFrames, workingDir, 'framesY', 'framesU', 'framesV');
7 |
8 | % read Y, U, V frames, convert and combine them into single RGB frame
9 | for i = 1:noOfFrames
10 | % Get Y component
11 | filename = [sprintf('%d',i) '.bmp'];
12 | fullname = fullfile(workingDir,'framesY',filename);
13 | Y = imread(fullname);
14 | % Get U component
15 | filename = [sprintf('%d',i) '.bmp'];
16 | fullname = fullfile(workingDir,'framesU',filename);
17 | U = imread(fullname);
18 | % Get V component
19 | filename = [sprintf('%d',i) '.bmp'];
20 | fullname = fullfile(workingDir,'framesV',filename);
21 | V = imread(fullname);
22 |
23 | % convert and combine Y, U, V components into RGB frame
24 | % YCbCr = cat(3, Y, U, V);
25 | % RGB = ycbcr2rgb(YCbCr);
26 | RGB = yuv2rgb(Y, U, V);
27 |
28 | % store the RGB frame
29 | filename = [sprintf('%d',i) '.bmp'];
30 | fullname = fullfile(workingDir, 'embeddedFramesRGB', filename);
31 | imwrite(RGB,fullname);
32 | end
--------------------------------------------------------------------------------
/main.m:
--------------------------------------------------------------------------------
1 | %=== Set directories to store video frames ===%
2 | workingDir = 'frames';
3 | %=== exist with two arguments is better than single argument as it searches for all categories (file, dir, var, func, buitlin etc) ===%
4 | %=== when a single argument is given. So, its better to provide specific category as second argument to search for... ===%
5 | if( exist(workingDir, 'dir') )
6 | rmdir(workingDir, 's');
7 | end
8 | mkdir(workingDir);
9 | mkdir(workingDir,'framesRGB');
10 | mkdir(workingDir,'framesY');
11 | mkdir(workingDir,'framesU');
12 | mkdir(workingDir,'framesV');
13 |
14 | %=== Get video reader obj for the video ===%
15 | video = VideoReader('small.mp4');
16 |
17 | %=== construct frames and get their dimentions from the video reader object ===%
18 | %=== store them in these directories ===%
19 | [height, width] = construct_frames(video, workingDir, 'framesRGB', 'framesY', 'framesU', 'framesV');
20 |
21 | %=== Get no of frames of the video ===%
22 | noOfFrames = floor(video.FrameRate*video.Duration) - 1;
23 | disp(noOfFrames);
24 |
25 | %=== Fix a key ===%
26 | key = 5;
27 |
28 | %=== scamble the video frames ===%
29 | scramble(key, height, width, noOfFrames, workingDir, 'framesY', 'framesU', 'framesV');
30 |
--------------------------------------------------------------------------------
/construct_frames.m:
--------------------------------------------------------------------------------
1 | % Construct frames from video and store in respective directories
2 | function [height, width] = construct_frames(video, workingDir, frameLocationRGB, frameLocationY, frameLocationU, frameLocationV)
3 |
4 | i = 1;
5 | %=== Convert each video frame into different formats and store them ===%
6 | while hasFrame(video)
7 | % read frame from the video %
8 | img = readFrame(video);
9 | height = size(img,1);
10 | width = size(img,2);
11 | % get YUV format from function defined in rgb2yuv.m %
12 | % each frame's Y, U, V component to be stored separately %
13 | [Y, U, V] = rgb2yuv(img);
14 |
15 | % maming for each frame %
16 | filename = [sprintf('%d',i) '.bmp'];
17 |
18 | %=== Store the frames in their respective directories ===%
19 | fullname = fullfile(workingDir,frameLocationRGB,filename);
20 | imwrite(img,fullname);
21 | fullname = fullfile(workingDir,frameLocationY,filename);
22 | imwrite(Y,fullname);
23 | fullname = fullfile(workingDir,frameLocationU,filename);
24 | imwrite(U,fullname);
25 | fullname = fullfile(workingDir,frameLocationV,filename);
26 | imwrite(V,fullname);
27 | i = i+1;
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/Design.md:
--------------------------------------------------------------------------------
1 | ## Design Details
2 |
3 | The folowing points will be implemented in MATLAB
4 |
5 | ### Sender's Side:
6 |
7 | * Convert the video stream into frames.
8 |
9 | * Separate each frame into Y, U and V components.
10 |
11 | * Change the position of all pixels in three components Y, U and V by a special key.
12 |
13 | * Convert the message which is to be sent to a one dimension array, and then change the position of the whole message by a key.
14 |
15 | * Encode each 4 bits of the message using Hamming (7, 4) encoder.
16 |
17 | * The result of the encoded data, which consists of 7 bits (4 bits of message + 3 bits of parity) is XORed with the
18 | 7 bits of random value using a key.
19 |
20 | * The pixels are then repositioned to the original locations and the video is rebuilt.
21 |
22 |
23 |
24 |
25 | ### Receivers's Side:
26 |
27 | * Convert the video stream into frames.
28 |
29 | * Separate each frame into Y, U and V components.
30 |
31 | * Change the position of all pixel values in the three Y, U, and V components by the special key that was used in the embedding process.
32 |
33 | * Obtain the encoded data from the YUV components and XOR with the random number using the same key that was used in the sender side.
34 |
35 | * Decode 4 bits of the message by the Hamming decoder.
36 |
37 | * Reposition the whole message again into the original order.
38 |
39 | * Convert the message array to two dimensions.
40 |
41 |
42 |
--------------------------------------------------------------------------------
/frames_to_video.m:
--------------------------------------------------------------------------------
1 | %=== Set directory of frames ===%
2 | workingDir = 'frames';
3 | mkdir(workingDir,'receiver_embeddedFramesRGB');
4 |
5 | %=== Get embedded RGB frames ===%
6 | imageNames = dir(fullfile(workingDir,'embeddedFramesRGB','*.bmp'));
7 | imageNames = {imageNames.name}';
8 | % for ii = 1:length(imageNames)
9 | % disp(imageNames{ii});
10 | % end
11 |
12 | % original video
13 | video1 = VideoReader('small.mp4');
14 |
15 | %=== Set output video writer object ===%
16 | outputVideo = VideoWriter('em_video.avi', 'Uncompressed AVI');
17 | % set lossless compression
18 | ouputVideo.LosslessCompression = true;
19 | % Set same frame rate as original video
20 | outputVideo.FrameRate = video1.FrameRate
21 | open(outputVideo);
22 |
23 | %=== Frames to Video ===%
24 | for ii = 1:length(imageNames)
25 | % read a RGB frame
26 | img = imread(fullfile(workingDir,'embeddedFramesRGB',[sprintf('%d',ii) '.bmp']));
27 | % put the frame in the video writer object
28 | writeVideo(outputVideo,img)
29 | end
30 | close(outputVideo);
31 |
32 |
33 | %=== Check if the frames after video formation ===%
34 | %=== are same as the frames before =====%
35 |
36 | video = VideoReader('em_video.avi');
37 | i = 1;
38 |
39 | count = 0;
40 | %=== Convert each video frame into different formats and store them ===%
41 | while hasFrame(video)
42 |
43 | % Read frame from the video %
44 | img = readFrame(video);
45 | %=== Store the frames in their respective directories ===%
46 | filename = [sprintf('%d',i) '.bmp'];
47 | fullname = fullfile(workingDir,'receiver_embeddedFramesRGB',filename);
48 | imwrite(img,fullname);
49 | img1 = imread(fullfile(workingDir,'receiver_embeddedFramesRGB',filename));
50 | img2 = imread(fullfile(workingDir,'embeddedFramesRGB',filename));
51 | if img1 == img2
52 | count = count + 1;
53 | end
54 | i = i+1;
55 | end
56 |
57 | disp(count);
58 |
59 |
--------------------------------------------------------------------------------
/embed_message.m:
--------------------------------------------------------------------------------
1 | filename = 'message.png';
2 |
3 | % Read message
4 | message = imread(filename);
5 | figure, imshow(message);
6 | message_transpose = message';
7 |
8 | % Converting the 2-D image into 1-D matrix
9 | one_d = message_transpose(:);
10 |
11 | count=1;
12 |
13 | % key = 5;
14 |
15 | % Cyclic shift for the message matrix using the key
16 | temp = one_d(1:key,1);
17 |
18 | for i = key+1:28000
19 | one_d (i-key,1) = one_d (i, 1);
20 | end
21 |
22 | for i = 28000-key+1:28000
23 | one_d (i,1) = temp (i-28000+key,1);
24 | end
25 |
26 | % Using G for calculating Hamming code
27 | G = [1 1 0 1 0 0 0; 0 1 1 0 1 0 0; 1 1 1 0 0 1 0; 1 0 1 0 0 0 1];
28 | % Using xor_key for xoring the bits of the message matrix
29 | xor_key = 8;
30 | % Using embed_key for determining the row where the message should be embedded
31 | embed_key = 3;
32 | % image_count keeps track of which image is being modified
33 | image_count = 1;
34 | % position keeps track of where the message pixels are to be embedded
35 | position = 1;
36 | workingDir = 'frames';
37 |
38 | fullnameV = '';
39 | fullnameU = '';
40 | fullnameY = '';
41 |
42 | frameV = zeros(height,width);
43 | frameU = zeros(height,width);
44 | frameY = zeros(height,width);
45 |
46 | for i = 1:4:28000
47 | if i+3>28000
48 | break;
49 | end
50 | temp = one_d(i:i+3,1);
51 | % Applying Hamming code
52 | temp = temp'*G;
53 | % Calculating the xor and taking mod 2
54 | for j = 1:7
55 | temp(1,j) = mod(temp(1,j),2);
56 | temp(1,j) = xor(temp(1,j),xor_key);
57 | end
58 |
59 | %temp(1,1)+temp(1,4)+temp(1,6)+temp(1,7)+temp(1,1)
60 |
61 | % Shifting the image_count for message embedding
62 | if position == 181
63 | position = 1;
64 | image_count = image_count + 1;
65 | end
66 | if position == 1
67 | filename = [sprintf('%d',image_count) '.bmp'];
68 | fullnameV = fullfile(workingDir,'framesV',filename);
69 | frameV = imread(fullnameV);
70 |
71 | filename = [sprintf('%d',image_count) '.bmp'];
72 | fullnameU = fullfile(workingDir,'framesU',filename);
73 | frameU = imread(fullnameU);
74 |
75 | filename = [sprintf('%d',image_count) '.bmp'];
76 | fullnameY = fullfile(workingDir,'framesY',filename);
77 | frameY = imread(fullnameY);
78 | end
79 |
80 | % Embedding the message
81 | frameY(embed_key,(position-1)*3+1) = temp(1,1);
82 | frameY(embed_key,(position-1)*3+2) = temp(1,2);
83 | frameY(embed_key,(position-1)*3+3) = temp(1,3);
84 |
85 | frameU(embed_key,(position-1)*2+1) = temp(1,4);
86 | frameU(embed_key,(position-1)*2+2) = temp(1,5);
87 |
88 | frameV(embed_key,(position-1)*2+1) = temp(1,6);
89 | frameV(embed_key,(position-1)*2+2) = temp(1,7);
90 |
91 | imwrite(frameU,fullnameU);
92 | imwrite(frameV,fullnameV);
93 | imwrite(frameY,fullnameY);
94 |
95 | % Shifting the position for message embedding
96 | position = position + 1;
97 | end
98 |
--------------------------------------------------------------------------------
/Introduction.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 | Due to connected nature of world because of the Internet many computer systems and other devices have become prone to attacks. Preventing unauthorized access, use, disclosure or destruction of data is gaining importance in the Digital world. Steganography and data hiding have become necessary for information security.
3 |
4 |
5 | ## Steganography
6 | Steganography is the art and science of writing covert messages such that the presence of the message is only known to the sender and the receipient. It involves concealing a file, message, image, or video within another file, message, image, or video. If cover is video file then it is called Video Steganography.
7 |
8 |
9 |
10 | There are two important factors that every successful steganography system should take into consideration, which are embedding efficiency and embedding payload.
11 |
12 | * First, the steganography scheme that has a high embedding efficiency means good quality of stego data and less amount of host (carrier) data are going to be changed.
13 |
14 | * Second, the high embedding payload means the capacity of secret
15 | information to be hidden inside host data is large.
16 |
17 | ### Some implementations fo video steganography
18 | * In 2012, Rongyue et al proposed an efficient BCH coding
19 | for steganography which is embedding the secret information
20 | inside a block of cover data by changing some coefficients.
21 | Authors have improved the computational time of the system
22 | and the complexity becomes low because of the system’s
23 | linearity.
24 |
25 | * In 2013, Liu et al proposed a robust data hiding scheme in
26 | H.264 compressed video stream, where they have prevented a
27 | drift of intra-frame distortion. To give the system more
28 | robustness, authors have encoded the message using BCH
29 | code before making the embedding process. The host data is
30 | the DCT coefficients of the luminance I-frame component.
31 | The obtained results have a high quality and robustness.
32 |
33 |
34 | ## (7, 4) Hamming Code
35 |
36 | The Hamming code is one of the most well-known block code methods that can do both error detection and correction on a block of data. In the Hamming code technique, the original information will be coded by adding some extra data
37 | with the minimum amount of redundancy, which is called the codeword, of length n bits. The added part consists of parity information of length (n-k) bits where k is the length of message that is expected to be coded.
38 |
39 | The Hamming codes are linear codes so they have two matrices: parity-check matrix H and generator matrix G, which they need for both encoding and decoding.
40 |
41 | On the encoding side, each message M, which consists of 4-bits, will be multiplied by the generator matrix and then have modulo of 2 applied; the result is the codeword X of 7-bits ready to be sent through a noisy channel.
42 |
43 |
44 |
45 | On the decoding side, for the purpose of checking the encoded message of 7-bits R (data + parity) will be received,
46 | then will be multiplied by the transpose of the parity-check matrix, and taking modulo of 2 again.
47 |
48 |
49 |
50 | The result is a syndrome vector Z (z1, z2, z3) of three bits, which has to be all zeroes (000) if it’s an error-free message. Otherwise, any change in the message during transmission will lead to flipping one or more bits of the message; then it needs an error correction process.
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/receiver_retrieve.m:
--------------------------------------------------------------------------------
1 | workingDir = 'frames';
2 |
3 | % Read video
4 | video = VideoReader('em_video.avi');
5 |
6 | % Constructing frames
7 | construct_frames(video, workingDir, 'receiver_embeddedFramesRGB', 'framesY', 'framesU', 'framesV');
8 |
9 | % Fix the same key
10 | key = 5;
11 |
12 | % Scrambling frames
13 | scramble(key, height, width, noOfFrames, workingDir, 'framesY', 'framesU', 'framesV');
14 | read_message = zeros(28000,1);
15 |
16 | % Initializing matrices for hamming correction
17 | r = zeros(1,7);
18 | ht = [1 0 0; 0 1 0; 0 0 1; 1 1 0; 0 1 1; 1 1 1; 1 0 1];
19 | count = 1;
20 | position = 1;
21 |
22 | % Used to keep image count
23 | image_count = 1;
24 |
25 | % Key to xor
26 | xor_key = 8;
27 |
28 | % intializations
29 | count_diff = 1;
30 |
31 | frameY = zeros(height,width);
32 | frameV = zeros(height,width);
33 | frameU = zeros(height,width);
34 |
35 |
36 | % Iterating over each pixel
37 | for i= 1:28000
38 | if count>=28001
39 | break
40 | end
41 |
42 | % Going to next image once we are done with the current one
43 | if position == 181
44 | position = 1;
45 | image_count = image_count + 1;
46 | end
47 |
48 | % Opening a new image
49 | if position == 1
50 | % Get Y component
51 | filename = [sprintf('%d',image_count) '.bmp'];
52 | fullnameY = fullfile(workingDir,'framesY',filename);
53 | frameY = imread(fullnameY);
54 | % Get V component
55 | filename = [sprintf('%d',image_count) '.bmp'];
56 | fullnameV = fullfile(workingDir,'framesV',filename);
57 | frameV = imread(fullnameV);
58 | % Get U component
59 | filename = [sprintf('%d',image_count) '.bmp'];
60 | fullnameU = fullfile(workingDir,'framesU',filename);
61 | frameU = imread(fullnameU);
62 | end
63 |
64 | % Assigning values to read matrix
65 | r(1,1)=xor(xor_key,frameY(3,(position-1)*3+1));
66 | % r(1,1)=mod(r(1,1),2);
67 | r(1,2)=xor(xor_key,frameY(3,(position-1)*3+2));
68 | % r(1,2)=mod(r(1,2),2);
69 | r(1,3)=xor(xor_key,frameY(3,(position-1)*3+3));
70 | % r(1,3)=mod(r(1,3),2);
71 | r(1,4)=xor(xor_key,frameU(3,(position-1)*2+1));
72 | % r(1,4)=mod(r(1,4),2);
73 | r(1,5)=xor(xor_key,frameU(3,(position-1)*2+2));
74 | % r(1,5)=mod(r(1,5),2);
75 | r(1,6)=xor(xor_key,frameV(3,(position-1)*2+1));
76 | % r(1,6)=mod(r(1,6),2);
77 | r(1,7)=xor(xor_key,frameV(3,(position-1)*2+2));
78 | % r(1,7)=mod(r(1,7),2);
79 |
80 |
81 | % Calculating syndrome
82 | z = r * ht;
83 |
84 | z(1,1)=mod(z(1,1),2);
85 | z(1,2)=mod(z(1,2),2);
86 | z(1,3)=mod(z(1,3),2);
87 | z
88 |
89 | %=== Hamming (7, 4) correction ===%
90 | % Making corrections using syndrome
91 | if (z(1,1)==0) && (z(1,2)==0) && (z(1,3)==0)
92 | % No error
93 | count_diff = count_diff + 1;
94 | read_message(count) =r(1,4);
95 | read_message(count+1)=r(1,5);
96 | read_message(count+2)=r(1,6);
97 | read_message(count+3)=r(1,7);
98 |
99 | % Making corrections using syndrome
100 | elseif (z(1,1)==1) && (z(1,2)==1) && (z(1,3)==0)
101 | % Error in 1st bit
102 | read_message(count) =~r(1,4);
103 | read_message(count+1)=r(1,5);
104 | read_message(count+2)=r(1,6);
105 | read_message(count+3)=r(1,7);
106 |
107 | % Making corrections
108 | elseif (z(1,1)==0) && (z(1,2)==1) && (z(1,3)==1)
109 | % Error in 2nd bit
110 | read_message(count) =r(1,4);
111 | read_message(count+1)=~r(1,5);
112 | read_message(count+2)=r(1,6);
113 | read_message(count+3)=r(1,7);
114 |
115 | % Making corrections
116 | elseif (z(1,1)==1) && (z(1,2)==1) && (z(1,3)==1)
117 | % Error in 3rd bit
118 | read_message(count) =r(1,4);
119 | read_message(count+1)=r(1,5);
120 | read_message(count+2)=~r(1,6);
121 | read_message(count+3)=r(1,7);
122 |
123 | % Making corrections
124 | elseif (z(1,1)==1) && (z(1,2)==0) && (z(1,3)==1)
125 | % Error in 4th bit
126 | read_message(count) =r(1,4);
127 | read_message(count+1)=r(1,5);
128 | read_message(count+2)=r(1,6);
129 | read_message(count+3)=~r(1,7);
130 |
131 | % Making corrections
132 | else
133 | % Error in the redundant bits
134 | read_message(count) =r(1,4);
135 | read_message(count+1)=r(1,5);
136 | read_message(count+2)=r(1,6);
137 | read_message(count+3)=r(1,7);
138 |
139 | end
140 | count = count + 4;
141 | position = position + 1;
142 |
143 | end
144 |
145 |
146 | % Performing cyclic shift of image pixels using key
147 | temp = read_message(27996:28000,1);
148 | for i= 27995:-1:1
149 | read_message(i+5,1)=read_message(i,1);
150 | end
151 | read_message(1,1)=temp(1,1);
152 | read_message(2,1)=temp(2,1);
153 | read_message(3,1)=temp(3,1);
154 | read_message(4,1)=temp(4,1);
155 | read_message(5,1)=temp(5,1);
156 |
157 |
158 | % Constructing the image
159 | xe = zeros(140,200);
160 | count=1;
161 |
162 | for i = 1:140
163 | for j = 1:200
164 | xe(i,j) = read_message(count,1);
165 | count = count + 1;
166 | end
167 | end
168 | figure, imshow(xe)
169 | imwrite(xe, 'r_message.png');
170 | % xe - message
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Data Communications (CO250): Mini-Project
2 |
3 | **Title:**
4 |
5 | A Highly Secure Video Steganography using Hamming Code (7, 4)
6 |
7 | **Members:**
8 |
9 | Dibyadarshan Hota (16C0154) -
10 |
11 | Omkar Prabhu (16C0233) -
12 |
13 | **Abstract:**
14 |
15 | Preventing unauthorized access, use, disclosure or destruction of data is gaining importance in the Digital world. Steganography and data hiding have become necessary for information security. Steganography is the practice of concealing a file, message, image, or video within another file, message, image, or video.
16 |
17 | The paper referenced has proposed a secure video steganography algorithm using linear block code. The algorithm requires a video to be converted into frames and changing the pixel positions. The message which is to be transmitted must be converted into one-dimension, XOR and Hamming code are applied to this message. Then this encoded message is embedded in the scrambled video frames. These frames are reconstructed and sent to the receiver. The receiver can extract information using the same key as the sender side. The receiver has to disassemble the video, use XOR and hamming code to reconstruct the correct intended message.
18 |
19 |
20 | **Objectives:**
21 | * Implement the following in MATLAB:
22 |
23 | At sender's side:
24 |
25 | * Conversion of video frames into a YUV format.
26 |
27 | * Applying (7, 4) Hamming code to 1D structure of message which is a image to obtain the codeword.
28 |
29 | * Embedding the message codeword into the video frames.
30 |
31 | * Recontruct the video from the frames.
32 |
33 | At receiver's side:
34 |
35 | * Split the received video into frames and convert them to YUV format.
36 |
37 | * Retrieve back the message codeword from the frames.
38 |
39 | * Retrieve back original message from the message codeword by using decoding for hamming code.
40 |
41 |
42 | **References:**
43 |
44 | Ramadhan J. Mstafa, Khaled M. Elleithy, "A highly secure video steganography using Hamming code (7, 4)," presented at Systems, Applications and Technology Conference (LISAT), 2014 IEEE Long Island, Farmingdale, NY, USA, May 2-2, 2014.
45 |
46 | [View Paper](http://ieeexplore.ieee.org/document/6845191/)
47 |
48 |
49 | ## Usage
50 |
51 | * Specify the video to be used in the files: `main.m`, `frames_to_video.m` and `receiver_retrieve.m`
52 |
53 | * Specify the key to be used in the file `main.m`
54 |
55 | * Run the following files in order
56 |
57 | 1. `main.m` : In the `frames` directory the following would be present
58 | * `framesRGB` : RGB frames of the video `small.mp4` or `large.mp4`
59 | * `framesY` : srambled Y components for RGB frames
60 | * `framesU` : srambled U components for RGB frames
61 | * `framesV` : srambled V components for RGB frames
62 |
63 | 2. `embed_message.m` : The binary image `message.png` will be embedded into the scrambled Y, U, V components.
64 |
65 | 3. `combine_frames.m` : In the directory `frames\embeddedFramesRGB`, the embedded RGB frames will be created.
66 |
67 | 4. `frames_to_video.m` : Video named `em_small.avi` will be created from the embedded RGB frames.
68 |
69 | 5. `receiver_retrieve.m` : From the video `em_small.avi` the message will be constructed back and displayed.
70 |
71 | 6. `psnr.m` : Displays the PSNR value comparing the original and retrieved image message.
72 |
73 |
74 | ## Results
75 |
76 | Original message:
77 |
78 | 
79 |
80 | * Using `large.mp4` the retrieved message and PSNR is: infintiy
81 |
82 | 
83 |
84 | * Using `small.mp4` the retrieved message and PSNR is: 13.9140
85 |
86 | 
87 |
88 |
89 | ## File Structure
90 |
91 | * `Introduction.md` - Explains theoretical aspects of the mini project.
92 |
93 | * `Design.md` - Explains design aspects of the mini project.
94 |
95 | * `main.m` - Main module of the implementation.
96 |
97 | * `construct_frames.m` - Construct RGB frames from the video and get their Y, U, V components. Save them in the mentioned location.
98 |
99 | * `embed_message.m` - Applying (7, 4) Hamming Code to the message and embed the same into the scrambled Y, U, V frames.
100 |
101 | * `combine_frames.m` - Combine the embedded Y, U, V frames into their embedded RGB frame.
102 |
103 | * `frames_to_video.m` - Construct the video from the embedded RGB frames.
104 |
105 | * `receiver_retrieve.m` - From the constructed video after embedding, it will retrieve the message back after applying Hamming correction.
106 |
107 | * `psnr.m` - Calculate Peak signal-to-noise ratio.
108 |
109 | * `scramble.m` - Scrambles all the Y, U, V frames given their directory based on a key.
110 |
111 | * `unscramble.m` - Unscrambles all the Y, U, V frames given their directory based on a key.
112 |
113 | * `yuv2rgb.m` - Converts Y, U, V components into a single RGB frame.
114 |
115 | * `rgb2yuv.m` - Converts a RGB frame to its Y, U, V components.
116 |
117 | * `small.mp4` - Video used to embed message into.
118 |
119 | * `large.mp4` - Video used to embed message into.
120 |
121 | * `message.png` - Binary image to be sent after embedding it into small.mp4 video and retreived at the other end.
122 |
123 |
124 |
--------------------------------------------------------------------------------
/unscramble.m:
--------------------------------------------------------------------------------
1 | % Unscrambles a frame based on the key
2 | function unscramble(key, height, width, noOfFrames, workingDir, frameLocationY, frameLocationU, frameLocationV)
3 | % Following the reverse procedure of scrambling
4 |
5 | % Determine number of slots
6 | cycle = floor(width/key);
7 |
8 | % Making number of cycles even
9 | if mod(cycle,2) == 1
10 | cycle = cycle - 1;
11 | end
12 |
13 | for i = 1:noOfFrames
14 | % Read images from 1 to noOfFrames
15 | filename = [sprintf('%d',i) '.bmp'];
16 | fullname = fullfile(workingDir,frameLocationV,filename);
17 | frame = imread(fullname);
18 | for j = 1:cycle/2
19 | endpart1 = cycle - j;
20 | endpart = (endpart1*key)+1;
21 |
22 | % Skipping odd slots
23 | if mod(j,2) == 1
24 | continue;
25 | end
26 |
27 | % Swapping of slots
28 | temp = frame(:,(j-1)*key+1:j*key);
29 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1);
30 | frame(:,endpart:endpart+key-1) = temp;
31 | end
32 | %figure, imshow(frame);
33 | imwrite(frame,fullname);
34 |
35 | end
36 |
37 | % Determine number of slots
38 |
39 | cycle = floor(height/key);
40 |
41 | % Making number of cycles even
42 | if mod(cycle,2) == 1
43 | cycle = cycle - 1;
44 | end
45 |
46 | for i = 1:noOfFrames
47 | % Read images from 1 to noOfFrames
48 |
49 | filename = [sprintf('%d',i) '.bmp'];
50 | fullname = fullfile(workingDir,frameLocationV,filename);
51 | frame = imread(fullname);
52 | abc = frame;
53 | for j = 1:cycle/2
54 | endpart1 = cycle - j;
55 | endpart = (endpart1*key)+1;
56 | % Skipping odd slots
57 |
58 | if mod(j,2) == 1
59 | continue;
60 | end
61 | % Swapping of slots
62 |
63 | temp = frame((j-1)*key+1:j*key,:);
64 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:);
65 | frame(endpart:endpart+key-1,:) = temp;
66 | end
67 | imwrite(frame,fullname);
68 | end
69 |
70 | % Determine number of slots
71 |
72 | cycle = floor(width/key);
73 |
74 | % Making number of cycles even
75 | if mod(cycle,2) == 1
76 | cycle = cycle - 1;
77 | end
78 |
79 | for i = 1:noOfFrames
80 | % Read images from 1 to noOfFrames
81 |
82 | filename = [sprintf('%d',i) '.bmp'];
83 | fullname = fullfile(workingDir,frameLocationU,filename);
84 | frame = imread(fullname);
85 | for j = 1:cycle/2
86 | endpart1 = cycle - j;
87 | endpart = (endpart1*key)+1;
88 | % Skipping odd slots
89 |
90 | if mod(j,2) == 1
91 | continue;
92 | end
93 | % Swapping of slots
94 |
95 | temp = frame(:,(j-1)*key+1:j*key);
96 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1);
97 | frame(:,endpart:endpart+key-1) = temp;
98 | end
99 | %figure, imshow(frame);
100 | imwrite(frame,fullname);
101 |
102 | end
103 |
104 | % Determine number of slots
105 |
106 | cycle = floor(height/key);
107 |
108 | % Making number of cycles even
109 | if mod(cycle,2) == 1
110 | cycle = cycle - 1;
111 | end
112 |
113 | for i = 1:noOfFrames
114 | % Read images from 1 to noOfFrames
115 |
116 | filename = [sprintf('%d',i) '.bmp'];
117 | fullname = fullfile(workingDir,frameLocationU,filename);
118 | frame = imread(fullname);
119 | abc = frame;
120 | for j = 1:cycle/2
121 | endpart1 = cycle - j;
122 | endpart = (endpart1*key)+1;
123 | % Skipping odd slots
124 |
125 | if mod(j,2) == 1
126 | continue;
127 | end
128 | % Swapping of slots
129 |
130 | temp = frame((j-1)*key+1:j*key,:);
131 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:);
132 | frame(endpart:endpart+key-1,:) = temp;
133 | end
134 | imwrite(frame,fullname);
135 | end
136 |
137 | % Determine number of slots
138 |
139 | cycle = floor(width/key);
140 |
141 | % Making number of cycles even
142 | if mod(cycle,2) == 1
143 | cycle = cycle - 1;
144 | end
145 |
146 | for i = 1:noOfFrames
147 | % Read images from 1 to noOfFrames
148 |
149 | filename = [sprintf('%d',i) '.bmp'];
150 | fullname = fullfile(workingDir,frameLocationY,filename);
151 | frame = imread(fullname);
152 | for j = 1:cycle/2
153 | endpart1 = cycle - j;
154 | endpart = (endpart1*key)+1;
155 | % Skipping odd slots
156 |
157 | if mod(j,2) == 1
158 | continue;
159 | end
160 | % Swapping of slots
161 |
162 | temp = frame(:,(j-1)*key+1:j*key);
163 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1);
164 | frame(:,endpart:endpart+key-1) = temp;
165 | end
166 | %figure, imshow(frame);
167 | imwrite(frame,fullname);
168 |
169 | end
170 |
171 | % Determine number of slots
172 |
173 | cycle = floor(height/key);
174 |
175 | % Making number of cycles even
176 | if mod(cycle,2) == 1
177 | cycle = cycle - 1;
178 | end
179 |
180 | for i = 1:noOfFrames
181 | % Read images from 1 to noOfFrames
182 |
183 | filename = [sprintf('%d',i) '.bmp'];
184 | fullname = fullfile(workingDir,frameLocationY,filename);
185 | frame = imread(fullname);
186 | abc = frame;
187 | for j = 1:cycle/2
188 | endpart1 = cycle - j;
189 | endpart = (endpart1*key)+1;
190 | % Skipping odd slots
191 |
192 | if mod(j,2) == 1
193 | continue;
194 | end
195 | % Swapping of slots
196 |
197 | temp = frame((j-1)*key+1:j*key,:);
198 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:);
199 | frame(endpart:endpart+key-1,:) = temp;
200 | end
201 | imwrite(frame,fullname);
202 | end
203 | end
204 |
--------------------------------------------------------------------------------
/scramble.m:
--------------------------------------------------------------------------------
1 | % Scrambles a frame based on the key
2 | function scramble(key, height, width , noOfFrames, workingDir, frameLocationY, frameLocationU, frameLocationV)
3 | % Determining the number of slots based on key
4 | cycle = floor(height/key);
5 |
6 | % Making sure that there are even slots
7 | if mod(cycle,2) == 1
8 | cycle = cycle - 1;
9 | end
10 |
11 | for i = 1:noOfFrames
12 | % Reading images from 1 to noOfFrames
13 | filename = [sprintf('%d',i) '.bmp'];
14 | fullname = fullfile(workingDir, frameLocationV, filename);
15 | frame = imread(fullname);
16 | abc = frame;
17 |
18 | % Iterating from 1st to cycle/2 slots
19 | for j = 1:cycle/2
20 | endpart1 = cycle - j;
21 | endpart = (endpart1*key)+1;
22 |
23 | % Skipping odd slots
24 | if mod(j,2) == 1
25 | continue;
26 | end
27 |
28 | % Swapping xth slot with cycle-x th slot
29 | temp = frame((j-1)*key+1:j*key,:);
30 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:);
31 | frame(endpart:endpart+key-1,:) = temp;
32 | end
33 | imwrite(frame,fullname);
34 | end
35 |
36 | % Repeating the swapping procedure column wise
37 |
38 | % Determining the number of slots based on key
39 |
40 | cycle = floor(width/key);
41 |
42 | % Making sure that there are even slots
43 |
44 | if mod(cycle,2) == 1
45 | cycle = cycle - 1;
46 | end
47 |
48 | for i = 1:noOfFrames
49 | % Reading images from 1 to noOfFrames
50 |
51 | filename = [sprintf('%d',i) '.bmp'];
52 | fullname = fullfile(workingDir,frameLocationV,filename);
53 | frame = imread(fullname);
54 | % Iterating from 1st to cycle/2 slots
55 |
56 | for j = 1:cycle/2
57 | endpart1 = cycle - j;
58 | endpart = (endpart1*key)+1;
59 | if mod(j,2) == 1
60 | continue;
61 | end
62 | % Swapping xth slot with cycle-x th slot
63 |
64 | temp = frame(:,(j-1)*key+1:j*key);
65 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1);
66 | frame(:,endpart:endpart+key-1) = temp;
67 | end
68 | %figure, imshow(frame);
69 | imwrite(frame,fullname);
70 |
71 | end
72 |
73 | % Repeating the scrambling procedure for Y and U as well
74 |
75 | % Determining the number of slots based on key
76 |
77 | cycle = floor(height/key);
78 |
79 | % Making sure that there are even slots
80 |
81 | if mod(cycle,2) == 1
82 | cycle = cycle - 1;
83 | end
84 |
85 | for i = 1:noOfFrames
86 | % Reading images from 1 to noOfFrames
87 |
88 | filename = [sprintf('%d',i) '.bmp'];
89 | fullname = fullfile(workingDir,frameLocationU,filename);
90 | frame = imread(fullname);
91 | abc = frame;
92 | % Iterating from 1st to cycle/2 slots
93 |
94 | for j = 1:cycle/2
95 | endpart1 = cycle - j;
96 | endpart = (endpart1*key)+1;
97 | if mod(j,2) == 1
98 | continue;
99 | end
100 | % Swapping xth slot with cycle-x th slot
101 |
102 | temp = frame((j-1)*key+1:j*key,:);
103 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:);
104 | frame(endpart:endpart+key-1,:) = temp;
105 | end
106 | imwrite(frame,fullname);
107 | end
108 |
109 | % Determining the number of slots based on key
110 |
111 | cycle = floor(width/key);
112 |
113 | % Making sure that there are even slots
114 |
115 | if mod(cycle,2) == 1
116 | cycle = cycle - 1;
117 | end
118 |
119 | for i = 1:noOfFrames
120 | % Reading images from 1 to noOfFrames
121 |
122 | filename = [sprintf('%d',i) '.bmp'];
123 | fullname = fullfile(workingDir,frameLocationU,filename);
124 | frame = imread(fullname);
125 | % Iterating from 1st to cycle/2 slots
126 |
127 | for j = 1:cycle/2
128 | endpart1 = cycle - j;
129 | endpart = (endpart1*key)+1;
130 | if mod(j,2) == 1
131 | continue;
132 | end
133 | % Swapping xth slot with cycle-x th slot
134 |
135 | temp = frame(:,(j-1)*key+1:j*key);
136 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1);
137 | frame(:,endpart:endpart+key-1) = temp;
138 | end
139 | %figure, imshow(frame);
140 | imwrite(frame,fullname);
141 |
142 | end
143 |
144 | % Determining the number of slots based on key
145 |
146 | cycle = floor(height/key);
147 |
148 | % Making sure that there are even slots
149 |
150 | if mod(cycle,2) == 1
151 | cycle = cycle - 1;
152 | end
153 |
154 | for i = 1:noOfFrames
155 | % Reading images from 1 to noOfFrames
156 |
157 | filename = [sprintf('%d',i) '.bmp'];
158 | fullname = fullfile(workingDir,frameLocationY,filename);
159 | frame = imread(fullname);
160 | abc = frame;
161 | % Iterating from 1st to cycle/2 slots
162 |
163 | for j = 1:cycle/2
164 | endpart1 = cycle - j;
165 | endpart = (endpart1*key)+1;
166 | if mod(j,2) == 1
167 | continue;
168 | end
169 | % Swapping xth slot with cycle-x th slot
170 |
171 | temp = frame((j-1)*key+1:j*key,:);
172 | frame((j-1)*key+1:j*key,:) = frame(endpart:endpart+key-1,:);
173 | frame(endpart:endpart+key-1,:) = temp;
174 | end
175 | imwrite(frame,fullname);
176 | end
177 |
178 | % Determining the number of slots based on key
179 |
180 | cycle = floor(width/key);
181 |
182 | % Making sure that there are even slots
183 |
184 | if mod(cycle,2) == 1
185 | cycle = cycle - 1;
186 | end
187 |
188 | for i = 1:noOfFrames
189 | % Reading images from 1 to noOfFrames
190 |
191 | filename = [sprintf('%d',i) '.bmp'];
192 | fullname = fullfile(workingDir,frameLocationY,filename);
193 | frame = imread(fullname);
194 | % Iterating from 1st to cycle/2 slots
195 |
196 | for j = 1:cycle/2
197 | endpart1 = cycle - j;
198 | endpart = (endpart1*key)+1;
199 | if mod(j,2) == 1
200 | continue;
201 | end
202 | % Swapping xth slot with cycle-x th slot
203 |
204 | temp = frame(:,(j-1)*key+1:j*key);
205 | frame(:,(j-1)*key+1:j*key) = frame(:,endpart:endpart+key-1);
206 | frame(:,endpart:endpart+key-1) = temp;
207 | end
208 | %figure, imshow(frame);
209 | imwrite(frame,fullname);
210 | end
211 | end
212 |
--------------------------------------------------------------------------------