2023年9月6日 星期三

RGB to YCbCr

 轉換公式很多,以下取轉換後為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轉回幾乎無差異。



加密時,把角度0~360對應0~255,採用加法把數字加上。
因色彩取8 bits,故解密時亦採加法,加上 256-x,利用溢位的方式,即可用加法替代原先的減法解密。
加密且還原的程式如下:

%%%%% 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








2023年8月10日 星期四

Lichee Tang Nano 4K FPGA 開發板

開發板介紹 Gowin網頁
http://www.gowinsemi.com.cn/clients_view.aspx?TypeId=21&Id=957&FId=t19:21:19

WiKi網頁 (原廠?)
https://wiki.sipeed.com/hardware/zh/tang/Tang-Nano-4K/Nano-4K.html

軟體下載
http://www.gowinsemi.com.cn/faq.aspx

有FPGA和MCU兩個軟體需下載,參考下面安裝指南

安裝指南
https://blog.51cto.com/u_15468736/5926584

教破解license的方法
http://bbs.eeworld.com.cn/thread-1188683-1-1.html

FPGA編譯燒錄基本操作
https://blog.51cto.com/u_15468736/5807065?articleABtest=1

高雲IP使用,以及使用這些IP時的ModelSim模擬方式
https://blog.51cto.com/u_15468736/5979151?articleABtest=1

內建邏輯分析儀(類似SignalTap)
https://blog.51cto.com/u_15468736/5807063?articleABtest=1 

軟硬整合:ARM Cortex-M3的呼叫與使用
https://blog.51cto.com/u_15468736/5807064

FPGA硬核與軟核區別
https://mp.weixin.qq.com/s/Y2cHZ6VYFngVPwO9upr69g

2023年7月15日 星期六

量子邏輯閘 模擬 數位邏輯閘

Hadamard Gate:若是由0|>或1|>開始,經過Hadamard Gate後可用來產生0和1位元,機率各為1/2;原則上等效於由+|>或-|>開始

AND: 可利用CNOT的糾纏態

OR: 在同一位元的所有輸出即為OR,相當於wired or的功能

1 bit

NOT: CNOT + X




2 bit
AND: CCNOT









NAND: CCNOT+X








OR: NAND的反相

 or q[2] = q[0] or q[1] or q[1]q[0]





NOR:



or





XOR:






XNOR: