轉換公式很多,以下取轉換後為0~255的一種,小數部分無條件捨去。
此公式較為對稱,且符合原始YCbCr定義
但稍微修改係數,可避免RGB出現負數,簡化轉換程式
R = 1*Y + + 1.398*(Cr-128)
G = 1*Y - 0.34414*(Cb-128) - 0.71414*(Cr-128)
B = 1*Y + 1.749*(Cb-128)
移8位元,計算完除256,以下列係數,值在0~255
Y = 77*R + 150*G + 29*B
Cb = -43*R - 84*G + 128*B + 128*256
Cr = 128*R - 107*G - 21*B + 128*256
R = 256*Y + 357*(Cr-128)
G = 256*Y - 88*(Cb-128) -183*(Cr-128)
B = 256*Y + 447*(Cb-128)
以下使用matlab程式,首先驗證YCbCr444以及YCbCr422的正確性。從中間列可看出,YCbCr422一次取Cb一次取Cr。
由YCbCr444轉換回RGB後與原圖幾乎無差異,由YCbCr422轉回RGB後圖形顏色有差,但可解釋。
改為Lena人像圖測試,由YCbCr444或YCbCr422轉回幾乎無差異。
加密且還原的程式如下:
%%%%% YCbCr encoder parameter
tic
Y_theta_angle = 180; % 0 ~ 359
CbCr_phi_angle = 305; % 0 ~ 359
Y_en = round(Y_theta_angle/360*255);
CbCr_en = round(Y_theta_angle/360*255);
Y_dec = 256 - Y_en;
CbCr_dec = 256 - CbCr_en;
R = [ 0 0 0 0 255 255 255 255];
G = [ 0 0 255 255 0 0 255 255];
B = [ 0 255 0 255 0 255 0 255];
% RGB = cat(3, R, G, B);
RGB = imread('lena.jpg');
% RGB = imread('baboon.png');
R = single(RGB(:, :, 1));
G = single(RGB(:, :, 2));
B = single(RGB(:, :, 3));
%%%% generate YCbCr444
Y_444 = floor((( 77*R + 150*G + 29*B))/256) ;
Cb_444 = floor(((-43*R - 84*G + 128*B))/256) + 128;
Cr_444 = floor(((128*R - 107*G - 21*B))/256) + 128;
%%%% restore from YCbCr444
R_444 = Y_444 + floor(( 357*(Cr_444-128))/256);
G_444 = Y_444 + floor((-88*(Cb_444-128) - 183*(Cr_444-128))/256);
B_444 = Y_444 + floor((447*(Cb_444-128) )/256);
%{
%%%% generate YCbCr422
Y_422 = Y_444;
[M, N] = size(Y_422);
CbCr_422 = [];
for i = 1: 2: N
CbCr_422 = [CbCr_422 Cb_444(:, i)];
CbCr_422 = [CbCr_422 Cr_444(:, i+1)];
end
%%%% restore from YCbCr422
Cb_422 = [];
Cr_422 = [];
for i = 1: 2: N
Cb_422 = [Cb_422 CbCr_422(:, i) CbCr_422(:, i) ];
Cr_422 = [Cr_422 CbCr_422(:, i+1) CbCr_422(:, i+1)];
end
R_422 = Y_422 + floor(( 357*(Cr_422-128))/256);
G_422 = Y_422 + floor((-88*(Cb_422-128) - 183*(Cr_422-128))/256);
B_422 = Y_422 + floor((447*(Cb_422-128) )/256);
%}
%%%% generate YCbCr422
[M, N] = size(Y_444);
Y_422 = zeros(M,N);
CbCr_422 = zeros(M,N);
for i = 1: M
for j = 1: N
Y_422(i,j) = Y_444(i,j) + Y_en;
if (Y_422(i,j)>255)
Y_422(i,j) = Y_422(i,j) - 256;
endif
if ( mod(j,2)==1)
CbCr_422(i,j) = Cb_444(i,j) + CbCr_en;
else
CbCr_422(i,j) = Cr_444(i,j) + CbCr_en;
endif
if (CbCr_422(i,j)>255)
CbCr_422(i,j) = CbCr_422(i,j) - 256;
endif
endfor
endfor
%%%% restore from YCbCr422
Cb_422 = [];
Cr_422 = [];
for i = 1: 2: N
Cb_422 = [Cb_422 CbCr_422(:, i) CbCr_422(:, i) ];
Cr_422 = [Cr_422 CbCr_422(:, i+1) CbCr_422(:, i+1)];
end
Y_422d = Y_422;
Cb_422d = Cb_422;
Cr_422d = Cr_422;
for i = 1: M
for j = 1: N
Y_422d(i,j) = Y_422(i,j) + Y_dec;
if (Y_422d(i,j)>255)
Y_422d(i,j) = Y_422d(i,j) - 256;
endif
Cb_422d(i,j) = Cb_422(i,j) + CbCr_dec;
if (Cb_422d(i,j)>255)
Cb_422d(i,j) = Cb_422d(i,j) - 256;
endif
Cr_422d(i,j) = Cr_422(i,j) + CbCr_dec;
if (Cr_422d(i,j)>255)
Cr_422d(i,j) = Cr_422d(i,j) - 256;
endif
endfor
endfor
R_422d = Y_422d + floor(( 357*(Cr_422d-128))/256);
G_422d = Y_422d + floor((-88*(Cb_422d-128) - 183*(Cr_422d-128))/256);
B_422d = Y_422d + floor((447*(Cb_422d-128) )/256);
R_422 = Y_422 + floor(( 357*(Cr_422-128))/256);
G_422 = Y_422 + floor((-88*(Cb_422-128) - 183*(Cr_422-128))/256);
B_422 = Y_422 + floor((447*(Cb_422-128) )/256);
subplot(3, 3, 1);
imshow(RGB);
title('oringal')
subplot(3, 3, 2);
imshow(cat(3, uint8(Y_444), uint8(Cb_444), uint8(Cr_444)))
title('YCbCr444')
subplot(3, 3, 5);
imshow( [uint8(Y_444); uint8(Cb_444); uint8(Cr_444)])
title('YCbCr444')
subplot(3, 3, 8);
imshow(cat(3, uint8(R_444), uint8(G_444), uint8(B_444)))
title('YCbCr444 => RGB')
subplot(3, 3, 3);
imshow(cat(3, uint8(Y_422), uint8(Cb_422), uint8(Cr_422)))
title('YCbCr422')
subplot(3, 3, 6);
imshow( cat(3, uint8(R_422), uint8(G_422), uint8(B_422)))
title('YCbCr422')
subplot(3, 3, 9);
imshow(cat(3, uint8(R_422d), uint8(G_422d), uint8(B_422d)))
title('YCbCr422 => RGB')
toc
結果如下:
圖 左上為正確YCbCr444,左下為還原圖;右上為加密的YCbCr422,右中為加密還原的RGB,右下為正確解密還原的RGB
圖 左上為正確YCbCr444,左下為還原圖;右上為加密的YCbCr422,右中為加密還原的RGB,右下為正確解密還原的RGB。不同參數的結果
圖 左上為正確YCbCr444,左下為還原圖;右上為加密的YCbCr422,右中為加密還原的RGB,右下為正確解密還原的RGB