Advertisement
Guest User

Untitled

a guest
Dec 2nd, 2018
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.86 KB | None | 0 0
  1. % COMPE 565 Homework 4
  2. % 11/11/2018
  3. % Name: Paul Jerrold Biglete
  4. % REDID: 815430506
  5. % Email: pbiglete@gmail.com
  6. %
  7. % Name: Van Zumarraga
  8. % REDID: 818336877
  9. % Email: vzumarraga@yahoo.com
  10. %
  11. % Name: Trisha Tolentino
  12. % REDID: 818362695
  13. % Email: trishadtolentino@gmail.com
  14. %%
  15. clc;
  16. clear all;
  17. close all;
  18.  
  19. %%
  20. % Obtain video frames 6-10
  21. video = VideoReader('walk_qcif.avi');
  22. videoFrames = read(video, [6 10]);
  23.  
  24. % Convert RGB video frames to YCbCr
  25. for i = 1:5
  26. video_frames(:,:,:,i) = rgb2ycbcr(videoFrames(:,:,:,i));
  27. end
  28.  
  29. % Obtain video frame dimensions
  30. numFrames = get(video, 'NumberOfFrames');
  31. video_height = get(video, 'Height');
  32. video_width = get(video, 'Width');
  33. video_time = get(video, 'Duration');
  34.  
  35. % Variables & Objects
  36. x_pos = 1; % x-axis index of frame
  37. y_pos = 1; % y-axis index of frame
  38. MB_size = 16;
  39. P = 8; % displacement between MB and SW
  40. SW_height = 32;
  41. SW_width = 32;
  42. sum = 0;
  43. sw_count = 0; % debug var
  44. MB_count = 0; % debug var
  45. m = 1; % index SAD array
  46. n = 1; % index SAD array
  47. [frame_height,frame_width] = size(video_frames(:,:,1,1));
  48. SAD_Count = 0;
  49. TotalSADCount = 0;
  50. Minimums = [];
  51. Q28 = ones(8).*28;
  52.  
  53. %%
  54. % Set I and P Frames (IPPPP); iterate in order of frames 6-10
  55. for frameNum = 1:4
  56.  
  57. %Compute the 8x8 Block DCT transform coefficients of the luminance and chrominance components of the image.
  58. Y_Component = video_frames(:, :, 1, frameNum); % Seperate Y
  59. Cb_Component = video_frames(:, :, 2, frameNum); % Seperate Cb
  60. Cr_Component = video_frames(:, :, 3, frameNum); % Seperate Cr
  61.  
  62. % 4:2:0, Subsample Cb and Cr components
  63. Cb_Subsample = Cb_Component(1:2:frame_height, 1:2:frame_width);
  64. Cr_Subsample = Cr_Component(1:2:frame_height, 1:2:frame_width);
  65.  
  66. % Initialize blocks holding values of Y, Cb, and Cr blocks
  67. Y_Block = Y_Component;
  68. Cb_Block = Cb_Subsample;
  69. Cr_Block = Cr_Subsample;
  70.  
  71. % Separates entire image into 8x8 blocks
  72. DCT_Block = @(block_struct) dct2(block_struct.data);
  73.  
  74. DCT_Y_Block = blockproc(Y_Block, [8 8], DCT_Block);
  75. DCT_Cb_Block = blockproc(Cb_Block, [8 8], DCT_Block, 'PadPartialBlocks', true);
  76. DCT_Cr_Block = blockproc(Cr_Block, [8 8], DCT_Block, 'PadPartialBlocks', true);
  77.  
  78. % % 1st Block 4th Row
  79. % Display_Block_1 = DCT_Y_Block(25:32, 1:8);
  80. % fprintf('\nDCT Coefficients Matrix of MB')
  81. % display(Display_Block_1);
  82.  
  83. % Quantize blocks by dividing blocks by given matrices & rounding off
  84. Quantized_Y_Block = @(block_struct) round(block_struct.data ./ Q28);
  85. Quantized_Cb_Block = @(block_struct) round(block_struct.data ./ Q28);
  86. Quantized_Cr_Block = @(block_struct) round(block_struct.data ./ Q28);
  87.  
  88. % Apply values of processed quantized blocks to matrices
  89. Quantized_Luminance = blockproc(DCT_Y_Block, [8 8], Quantized_Y_Block);
  90. Quantized_Cb_Chrominance = blockproc(DCT_Cb_Block, [8 8], Quantized_Cb_Block);
  91. Quantized_Cr_Chrominance = blockproc(DCT_Cr_Block, [8 8], Quantized_Cr_Block);
  92.  
  93.  
  94. %%
  95. % Reference and current frames (Y_Component)
  96. ref_frame = double(video_frames(:,:,1,frameNum));
  97. current_frame = double(video_frames(:,:,1,frameNum+1));
  98. [ mV_X1, mV_Y1, mV_X2, mV_Y2 ] = motionVectors( ref_frame, current_frame, frame_height, frame_width, 8, 32);
  99.  
  100. %%
  101. figure
  102. quiver(mV_X1,mV_Y1,mV_X2,mV_Y2);
  103. axis([0 176 0 144]);
  104. title(sprintf('Motion Vectors: Frames %d to %d',frameNum+5,frameNum+6));
  105.  
  106. diff_frame = current_frame - ref_frame;
  107. % Display Reference
  108. figure
  109. subplot(1,2,1);
  110. imshow(uint8(ref_frame));
  111. title(sprintf('Reference Image for Frames %d-%d', frameNum+5, frameNum+6));
  112.  
  113. %Displays the Error image
  114. subplot(1,2,2);
  115. imshow(diff_frame);
  116. title(sprintf('Error Image %d-%d', frameNum+5,frameNum+6));
  117.  
  118. fprintf('\n\tFrames %d-%d', frameNum + 5, frameNum + 6);
  119.  
  120. %CPU time calculation
  121. time(frameNum) = cputime-time(frameNum);
  122. fprintf('\n\t\tCPU time: %.5f seconds', time(frameNum));
  123.  
  124. %PSNR / MSE
  125. sum = 0;
  126. for m = 1:144
  127. for n = 1:176
  128. sum = sum + (current_frame(m,n)-ref_frame(m,n))^2;
  129. end
  130. end
  131. MSE = sum/(144*176);
  132. PSNR(frameNum) = 10*log10(255*255/MSE);
  133.  
  134. AvgSADValue = mean(Minimums);
  135.  
  136. fprintf('\n\t\tMSE: %d', MSE);
  137. fprintf('\n\t\tPSNR: %d', PSNR(frameNum));
  138. fprintf('\n\t\tAverage SAD Value per MB: %d', AvgSADValue);
  139. fprintf('\n\t\tTotal SAD computations: %d\n', TotalSADCount);
  140.  
  141. TotalSADCount = 0; % Reset for each frame
  142. AvgSADValue = 0;
  143.  
  144. %%
  145. % Dequantize blocks by multiplying block data with given matrices for luminance and chrominance
  146. DeQuantized_Y_Block = @(block_struct) round(block_struct.data .* Q28);
  147. DeQuantized_Cb_Block = @(block_struct) round(block_struct.data .* Q28);
  148. DeQuantized_Cr_Block = @(block_struct) round(block_struct.data .* Q28);
  149.  
  150. % Apply values of dequantized blocks into matrices
  151. DeQuantized_Luminance = blockproc(Quantized_Luminance, [8 8], DeQuantized_Y_Block);
  152. DeQuantized_Cb_Chrominance = blockproc(Quantized_Cb_Chrominance, [8 8], DeQuantized_Cb_Block);
  153. DeQuantized_Cr_Chrominance = blockproc(Quantized_Cr_Chrominance, [8 8], DeQuantized_Cr_Block);
  154.  
  155. % Display_Block_3 = DeQuantized_Luminance(25:32, 1:8);
  156. % fprintf('Inverse Quantized DCT Matrix of 1st block in 4th row')
  157. % display(Display_Block_3);
  158.  
  159. % Apply inverse DCT to blocks & apply values into matrices
  160. InverseDCT = @(block_struct) idct2 (block_struct.data);
  161. Inverse_Y_Block = blockproc(DeQuantized_Luminance, [8 8], InverseDCT);
  162. Inverse_Cb_Block = blockproc(DeQuantized_Cb_Chrominance, [8 8], InverseDCT);
  163. Inverse_Cr_Block = blockproc(DeQuantized_Cr_Chrominance, [8 8], InverseDCT);
  164.  
  165. % Reconstructed Image
  166. % Perform Row Replication with the newly decoded block
  167. UpsampledRowRepImg(frame_height, frame_width, 3) = uint16(0);
  168.  
  169. for rows = 1:2:frame_height
  170. for columns = 1:2:frame_width % Load Cb and Cr Subsamples into Upsampled
  171. UpsampledRowRepImg(rows, columns, 2) = Inverse_Cb_Block((rows / 2) + 0.5, (columns / 2) + 0.5);
  172. UpsampledRowRepImg(rows, columns, 3)= Inverse_Cr_Block((rows / 2) + 0.5, (columns / 2) + 0.5);
  173. end
  174. end
  175.  
  176. for columns = 2:2:frame_width % Place odd column into even
  177. UpsampledRowRepImg(:, columns, 2) = UpsampledRowRepImg(:, columns - 1, 2);
  178. UpsampledRowRepImg(:, columns, 3) = UpsampledRowRepImg(:, columns - 1, 3);
  179. end
  180.  
  181. for rows = 2:2:frame_height % Place odd row into even
  182. UpsampledRowRepImg(rows, :, 2) = UpsampledRowRepImg(rows - 1, :, 2);
  183. UpsampledRowRepImg(rows, :, 3) = UpsampledRowRepImg(rows - 1, :, 3);
  184. end
  185.  
  186. % Reconstruct Image with Inverse_Y_Block
  187. UpsampledRowRepImg(:, :, 1) = Inverse_Y_Block;
  188. UpsampledRowRepRGBImg = uint8(UpsampledRowRepImg);
  189. UpsampledRowRepRGBImg = ycbcr2rgb(UpsampledRowRepRGBImg);
  190.  
  191. figure(1);
  192. subplot(1,2,2), imshow(UpsampledRowRepRGBImg), title('Reconstructed Image');
  193. subplot(1,2,1), imshow(ycbcr2rgb(video_frames(:,:,:,frameNum))), title('Original Image');
  194.  
  195. % Display Error Values for the Block, Reconstructed - Original
  196. Inverse_Y_Block = uint8(Inverse_Y_Block);
  197. Y_Block = uint8(Y_Block);
  198. Img_Error = Y_Block(25:32, 1:8) - Inverse_Y_Block(25:32, 1:8);
  199.  
  200. fprintf('Error Matrix');
  201. display(Img_Error);
  202.  
  203. % PSNR of Luminance Component
  204. % Tried calculating MSE using the equation but couldn't match the value
  205. % from using the immse function
  206. % Image_Error_Sum = (Inverse_Y_Block(25:32, 1:8) - Y_Block(25:32, 1:8)).^2
  207. % Image_Error_Sum = sum(sum(Image_Error_Sum)) / 64
  208.  
  209. MSE = immse(Inverse_Y_Block(25:32, 1:8), Y_Block(25:32, 1:8));
  210. peak_signal = 255 * 255;
  211. PSNR = 10 * log10((peak_signal.^2) / MSE);
  212.  
  213. fprintf('PSNR Value');
  214. display(PSNR);
  215. % PSNR = 87.4660
  216. end
  217.  
  218.  
  219. %%
  220. % Function to obtain macroblock given frame and its coordinates
  221. function [MB] = getMB(x_pos,y_pos,frame,frame_width,frame_height)
  222. x = 1;
  223. y = 1;
  224. MB_size = 16;
  225. P = 8; % displacement from edge of SW
  226.  
  227. % Check for edges when extracting macroblock
  228. if((x_pos+MB_size) > frame_width)
  229. x_pos = frame_width - MB_size + 1; % Shift x position to fit MB
  230. end
  231. if((y_pos+MB_size) > frame_height)
  232. y_pos = frame_height - MB_size + 1; % Shift y position to fit MB
  233. end
  234.  
  235. % Iterate through to instantiate MB
  236. for i = x_pos:x_pos+MB_size-1
  237. for j = y_pos:y_pos+MB_size-1
  238. MB(y,x) = frame(j,i); % Return specified macroblock
  239. y = y + 1;
  240. end
  241. y = 1;
  242. x = x + 1;
  243. end
  244. x = 1;
  245. end
  246.  
  247. %%
  248. % Function to obtain search window given frame and macroblock
  249. function [SW] = getSW(x_pos,y_pos,frame,frame_width,frame_height)
  250. x = 1;
  251. y = 1;
  252. P = 8; % displacement between MB and SW
  253. SW_height = 32;
  254. SW_width = 32;
  255.  
  256. % If first row or first column, truncate search window
  257. if(x_pos - P < 1)
  258. SW_width = SW_width - P;
  259. else
  260. x_pos = x_pos - P; % Shift search window to center MB
  261. end
  262. if(y_pos - P < 1)
  263. SW_height = SW_height - P;
  264. else
  265. y_pos = y_pos - P; % Shift search window to center MB
  266. end
  267.  
  268. % Check for edge when extracting search window from frame & MB
  269. if((x_pos + SW_width) > frame_width)
  270. SW_width = frame_width - x_pos + 1; % Truncate search window
  271. end
  272. if((y_pos + SW_height) > frame_height)
  273. SW_height = frame_height - y_pos + 1; % Truncate search window
  274. end
  275.  
  276. % Iterate through to instantiate SW
  277. for i = x_pos:x_pos+SW_width-1
  278. for j = y_pos:y_pos+SW_height-1
  279. SW(y,x) = frame(j,i); % Return specified search window
  280. y = y + 1;
  281. end
  282. y = 1;
  283. x = x + 1;
  284. end
  285. x = 1;
  286. end
  287.  
  288. %%
  289. % Function to obtain SAD value of macroblock (MB)
  290. function [sadValue, TotalSADCount] = getSAD_val(ref_MB,current_MB,SAD_Count,TotalSADCount)
  291. MB_size = 16;
  292. sum = 0; % Sum of pixel value differences between ref and curr frames
  293. SAD_Count = TotalSADCount;
  294.  
  295. % Iterate through MB & calculate SAD value
  296. for x = 1:MB_size
  297. for y = 1:MB_size
  298. sum = sum + abs((current_MB(y,x) - ref_MB(y,x)));
  299. SAD_Count = SAD_Count + 1;
  300. end
  301. sadValue = sum / (MB_size * MB_size);
  302. y = 1; % Reset to row 1 after each column
  303. end
  304. TotalSADCount = SAD_Count;
  305. sum = 0;
  306.  
  307. end
  308.  
  309. %%
  310. % Function to obtain position of minimum SAD value within search window
  311. function [x_diff,y_diff, TotalSADCount, minSAD] = getMin_pos(x_pos,y_pos,current_MB,SW,SAD_Count,TotalSADCount)
  312. [SW_height, SW_width] = size(SW);
  313.  
  314. x = 1;
  315. y = 1;
  316. MB_size = 16;
  317. SAD_array = ones(SW_height-MB_size+1, SW_width-MB_size+1) * (2^16);
  318.  
  319. for x = 1:SW_width-MB_size+1
  320. for y = 1:SW_height-MB_size+1
  321. ref_MB = getMB(x,y,SW,SW_width,SW_height); % Obtain ref macroblock from SW
  322. [SAD_val, TotalSADCount] = getSAD_val(ref_MB,current_MB,SAD_Count,TotalSADCount);
  323. SAD_array(y, x) = SAD_val;
  324. end
  325. end
  326.  
  327. % Obtain minimum SAD value (best matching MB) from SAD_array
  328. minSAD = min(min(SAD_array));
  329.  
  330. for u = 1:SW_width-MB_size+1
  331. for v = 1:SW_height-MB_size+1
  332. if(minSAD == SAD_array(v,u))
  333. x_diff = u;
  334. y_diff = v;
  335. end
  336. end
  337. end
  338.  
  339. x_diff = x_pos + x_diff - 1;
  340. y_diff = y_pos + y_diff - 1;
  341.  
  342. end
  343.  
  344. %%
  345. function [ mV_X1, mV_Y1, mV_X2, mV_Y2 ] = motionVectors( refFrame, curFrame, FRAME_HEIGHT, FRAME_WIDTH, MB_SIZE, SEARCH_WIN )
  346.  
  347. %% Motion vectors
  348. motionVectorsY = zeros(FRAME_HEIGHT/MB_SIZE,FRAME_WIDTH/MB_SIZE,2);
  349. motionVectorsX = zeros(FRAME_HEIGHT/MB_SIZE,FRAME_WIDTH/MB_SIZE,2);
  350.  
  351. %% Keep track of the sum of MAD for a frame
  352. frMadTotal = 0;
  353.  
  354. %% Error
  355. errImages = zeros(FRAME_HEIGHT,FRAME_WIDTH);
  356.  
  357. %% Motion vectors index
  358. rowIdx = 1;
  359. colIdx = 1;
  360.  
  361. %% Loop for searching block
  362. for blkRow=1:MB_SIZE:FRAME_HEIGHT
  363. for blkCol=1:MB_SIZE:FRAME_WIDTH
  364.  
  365. %% Original location of MB
  366. motionVectorsY(rowIdx,colIdx,1) = blkRow;
  367. motionVectorsX(rowIdx,colIdx,1) = blkCol;
  368.  
  369. %% Exact current MB from current frame
  370. curMB = curFrame(blkRow:blkRow+MB_SIZE-1, ...
  371. blkCol:blkCol+MB_SIZE-1);
  372.  
  373. %& Exact search window from current MB
  374. [top, left, right, bottom] = windowSearchEdges(blkRow, ...
  375. blkCol, MB_SIZE, SEARCH_WIN, FRAME_HEIGHT, FRAME_WIDTH);
  376.  
  377. %% Motion vector with Exhaustive Search
  378. [x1, y1, minMad] = exhaustiveSearch(...
  379. refFrame, curMB, top, left, right, bottom, MB_SIZE);
  380.  
  381. %% sum of MAD for a specific frame
  382. frMadTotal = frMadTotal + minMad;
  383. if (frMadTotal < 128)
  384. x1 = 0;
  385. y1 = 0;
  386. end
  387.  
  388. %% Best match location of MB
  389. motionVectorsY(rowIdx,colIdx,2) = y1;
  390. motionVectorsX(rowIdx,colIdx,2) = x1;
  391.  
  392. %% pick MB with minimum MAD
  393. targetMB = refFrame(y1:y1+MB_SIZE-1, x1:x1+MB_SIZE-1);
  394. errImages(blkRow:blkRow+MB_SIZE-1,blkCol:blkCol+MB_SIZE-1)...
  395. = int16(curMB) - int16(targetMB);
  396.  
  397. colIdx = colIdx+1; %index +1 after each iteration
  398. end
  399. colIdx = 1; %Reset after last column searched
  400. rowIdx = rowIdx+1; % index +1 after each iteration
  401. end
  402.  
  403.  
  404. %% Original
  405. mV_X1 = motionVectorsX(:, :, 2);
  406. mV_Y1 = motionVectorsY(:, :, 2);
  407. %% Best Match
  408. mV_X2 = motionVectorsX(:, :, 2);
  409. mV_Y2 = motionVectorsY(:, :, 2);
  410.  
  411. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement