Codificación de Vídeo en MATLAB: Práctica 4 con Compensación de Movimiento (MCP)
Práctica 4
Función codVideo
function [MSE, bits] = codVideo(fiIn, fiOut, ImIni, nIms, nImsGop, B, p, rIntra, rRes, satRes)
nFils = 288;
nCols = 352;
fps = 30;
fid = fopen(fiOut, 'w');
fwrite(fid, nIms, 'uint16');
fwrite(fid, nImsGop, 'uint8');
fwrite(fid, nFils, 'uint16');
fwrite(fid, nCols, 'uint16');
fwrite(fid, fps, 'uint8');
fwrite(fid, B, 'uint8');
fwrite(fid, p, 'uint8');
fwrite(fid, rIntra, 'uint8');
fwrite(fid, rRes, 'uint8');
fwrite(fid, satRes, 'uint8');
precisImI = ['ubit' num2str(rIntra)];
nBitsCompVM = ceil(log2(2*p+1));
precisCompVM = ['ubit' num2str(nBitsCompVM)];
precisImRes = ['ubit' num2str(rRes)];
nPixelsIm = nFils*nCols;
rInter = rRes + (2*nBitsCompVM)/(B*B);
for iIm = 1:nIms
[x, u, v] = leeYCbCr(fiIn, nFils, nCols, iIm+ImIni-1);
if (mod(iIm-1, nImsGop) == 0)
xInt = uint8(x);
xInt = bitsrl(xInt, 8-rIntra);
count = fwrite(fid, xInt, precisImI);
xInt = bitsll(uint8(xInt), 8-rIntra);
ImDec = bitset(xInt, 8-rIntra);
ImDec = double(ImDec);
bits(iIm) = rIntra*nPixelsIm;
else
[VM1, VM2] = estMov(x, ImDec, B, p);
xCom = predCompMov(VM1, VM2, ImDec);
VM1 = uint8(VM1+p);
VM2 = uint8(VM2+p);
count = fwrite(fid, VM1, precisCompVM);
count = fwrite(fid, VM2, precisCompVM);
ImRes = x - xCom;
k = cu(ImRes, -satRes, satRes, rRes);
ImResQ = du(k, -satRes, satRes, rRes);
count = fwrite(fid, k, precisImRes);
ImDec = double(uint8(xCom+ImResQ));
bits(iIm) = rInter*nPixelsIm;
end
eRec = x - ImDec;
PotE = sum(sum(eRec.*eRec))/(nPixelsIm);
MSE(iIm) = 10*log10(PotE);
fprintf('--- Imagen: %03d MSE: %2.2f dB Bits: %d
', iIm, MSE(iIm), bits(iIm));
imshow(uint8(ImDec));
pause(0.1);
end
fclose(fid);
Los argumentos de la función codVideo son:
- fiVid: cadena con el nombre del fichero de la secuencia de vídeo a codificar.
- fiOut: cadena con el nombre del fichero de la secuencia de vídeo codificada.
- ImIni: número de la imagen de la secuencia fiVid por la que se empieza a codificar.
- nIms: número de imágenes de la secuencia que se codificarán.
- nImsGop: número de imágenes que contiene cada GOP (nImsGop ∈ {1, 2, ..., 300}).
- B: tamaño del lado de los bloques utilizado en la MCP (B ∈ {2, 4, 8, 16, 32}).
- p: valor máximo de δ1 y δ2 (p ∈ {0, 1, 2, ..., 255}).
- rIntra: tasa binaria (en bpp) de las imágenes intra (rIntra ∈ {1, 2, ..., 8}).
- rRes: tasa binaria (en bpp) de las imágenes residuo (rRes ∈ {1, 2, ..., 7}).
- satRes: valor de saturación del cuantificador de las imágenes residuo (satRes ∈ {1, 2, ..., 64}).
La función codVideo devuelve:
- MSE: vector con el error de reconstrucción cuadrático medio (en dB) de cada imagen.
- bits: vector con el número de bits invertidos en la codificación de cada imagen.
Cada vez que se codifica una imagen de la secuencia de vídeo, codVideo muestra la correspondiente imagen decodificada en pantalla.
Función decVideo
Dec.Video
function [] = decVideo(fiIn)
% Resumen de la función.
% Explicación detallada.
fid = fopen(fiIn, 'r');
nIms = fread(fid, 1, 'uint16')
nImsGop = fread(fid, 1, 'uint8')
nFils = fread(fid, 1, 'uint16')
nCols = fread(fid, 1, 'uint16')
fps = fread(fid, 1, 'uint8')
B = fread(fid, 1, 'uint8')
p = fread(fid, 1, 'uint8')
rIntra = fread(fid, 1, 'uint8')
nIntRes = fread(fid, 1, 'uint8')
satRes = fread(fid, 1, 'uint8')
precisImI = ['ubit' num2str(rIntra)]; % copiado tal cual
nBitsCompVM = ceil(log2(2*p+1));
precisCompVM = ['ubit' num2str(nBitsCompVM)];
rRes = ceil(log2(nIntRes));
precisImRes = ['ubit' num2str(rRes)];
delta = (2*satRes)/nIntRes;
nPixelsIm = nFils*nCols;
rInter = rRes + (2*nBitsCompVM)/(B*B);
% Implementación del decodificador
ImIntra = fread(fid, [nFils nCols], precisImI);
ImIntra = bitsll(uint8(ImIntra), 8-rIntra);
ImDec = bitset(ImIntra, 8-rIntra);
% ImDec = double(ImDec); % pasa de 8 a 16 bits; uint8() pasa de 16 a 8.
imshow(ImDec);
VM1 = fread(fid, [nFils nCols]/B, precisCompVM);
VM2 = fread(fid, 1, precisCompVM);
VM1 = VM1 - p;
VM2 = VM2 - p;
end
Predicción compensada en movimiento
La función estMov, cuya declaración es [VM1, VM2] = estMov(Im, ImRef, b, p), realiza la estimación de movimiento entre una imagen (Im) y una imagen de referencia (ImRef).
A partir de los vectores podemos generar la predicción de Im, llamada imagen compensada en movimiento, ImComp, usando la función predCompMov, cuya declaración es:
ImComp = predCompMov(VM1, VM2, ImRef)
Esta función desplaza los bloques de ImRef de acuerdo con los vectores de movimiento especificados en las matrices VM1 y VM2.
La función imsMcp, cuya declaración es MSE = imsMcp(fiVid, ImIni, nIms, b, p), utiliza internamente estMov y predComp para visualizar las imágenes que intervienen o se generan en la MCP.