• 色彩空间转换 rgb转ycbcr422/ycbcr422转rgb


    在图像处理过程中通常需要会对图像类型进行互相转换,在此给出两种转换的工程代码。

    1、在将ycbCr422转rgb时,通常先将ycbcr422转换成ycbcr444再讲ycbcr444转成rgb

    1.1  ycbcr422转换成ycbcr444

    `timescale 1ns/1ns
    module ZYP_YCbCr422_YCbCr444
    (
    //global clock
    input clk, //cmos video pixel clock
    input rst_n, //global reset

    //CMOS 16Bit YCbCr data input: {CbYCrYCbYCrY}
    input per_frame_vsync, //Prepared Image data vsync valid signal
    input per_frame_href, //Prepared Image data href vaild signal
    input per_frame_clken, //Prepared Image data output/capture enable clock
    input [15:0] per_frame_YCbCr, //Prepared Image data of YCbCr 4:2:2 {CbY} {CrY}

    //CMOS YCbCr444 data output
    output post_frame_vsync, //Processed Image data vsync valid signal
    output post_frame_href, //Processed Image data href vaild signal
    output post_frame_clken, //Processed Image data output/capture enable clock
    output reg [7:0] post_img_Y, //Processed Image data of YCbCr 4:4:4
    output reg [7:0] post_img_Cb, //Processed Image data of YCbCr 4:4:4
    output reg [7:0] post_img_Cr //Processed Image data of YCbCr 4:4:4
    );

    //------------------------------------------
    //lag n pixel clocks
    reg [4:0] post_frame_vsync_r;
    reg [4:0] post_frame_href_r;
    reg [4:0] post_frame_clken_r;
    always@(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    post_frame_vsync_r <= 0;
    post_frame_href_r <= 0;
    post_frame_clken_r <= 0;
    end
    else
    begin
    post_frame_vsync_r <= {post_frame_vsync_r[3:0], per_frame_vsync};
    post_frame_href_r <= {post_frame_href_r[3:0], per_frame_href};
    post_frame_clken_r <= {post_frame_clken_r[3:0], per_frame_clken};
    end
    end
    assign post_frame_vsync = post_frame_vsync_r[4];
    assign post_frame_href = post_frame_href_r[4];
    assign post_frame_clken = post_frame_clken_r[4];
    wire yuv_process_href = per_frame_href || post_frame_href_r[3];
    wire yuv_process_clken = per_frame_clken || post_frame_clken_r[3];

    //-------------------------------------------
    //convert YCbCr422 to YCbCr444
    reg [2:0] yuv_state;
    reg [7:0] mY0, mY1, mY2, mY3;
    reg [7:0] mCb0, mCb1;
    reg [7:0] mCr0, mCr1;
    always@(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    yuv_state <= 3'd0;
    {mY0, mCb0, mCr0} <= {8'h0, 8'h0, 8'h0};
    mY1 <= 8'h0;
    {mY2, mCb1, mCr1} <= {8'h0, 8'h0, 8'h0};
    mY3 <= 8'h0;
    {post_img_Y, post_img_Cb, post_img_Cr} <= {8'h0, 8'h0, 8'h0};
    end
    else if(yuv_process_href) //lag 2 data enable clock and need 2 more clocks
    begin
    if(yuv_process_clken) //lag 2 data enable clock and need 2 more clocks
    case(yuv_state) //{Cb,Y},{Cr,Y}---YCbCr
    3'd0: begin //reg p0
    yuv_state <= 3'd1;
    {mCb0, mY0} <= per_frame_YCbCr;
    end
    3'd1: begin //reg p1
    yuv_state <= 3'd2;
    {mCr0, mY1} <= per_frame_YCbCr;
    end

    3'd2: begin //p0; reg p2
    yuv_state <= 3'd3;
    {mCb1, mY2} <= per_frame_YCbCr;
    {post_img_Y, post_img_Cb, post_img_Cr} <= {mY0, mCb0, mCr0};
    end
    3'd3: begin //p1; reg p3
    yuv_state <= 3'd4;
    {mCr1, mY3} <= per_frame_YCbCr;
    {post_img_Y, post_img_Cb, post_img_Cr} <= {mY1, mCb0, mCr0};
    end
    3'd4: begin //p2; reg p0
    yuv_state <= 3'd5;
    {mCb0, mY0} <= per_frame_YCbCr;
    {post_img_Y, post_img_Cb, post_img_Cr} <= {mY2, mCb1, mCr1};
    end //p3; reg p1
    3'd5: begin
    yuv_state <= 3'd2;
    {mCr0, mY1} <= per_frame_YCbCr;
    {post_img_Y, post_img_Cb, post_img_Cr} <= {mY3, mCb1, mCr1};
    end
    endcase
    else
    begin
    yuv_state <= yuv_state;
    {mY0, mCb0, mCr0} <= {mY0, mCb0, mCr0};
    mY1 <= mY1;
    {mY2, mCb1, mCr1} <= {mY2, mCb1, mCr1};
    mY3 <= mY3;
    {post_img_Y, post_img_Cb, post_img_Cr} <= {post_img_Y, post_img_Cb, post_img_Cr};
    end
    end
    else
    begin
    yuv_state <= 3'd0;
    {mY0, mCb0, mCr0} <= {8'h0, 8'h0, 8'h0};
    {mY1, mCb1, mCr1} <= {8'h0, 8'h0, 8'h0};
    {post_img_Y, post_img_Cb, post_img_Cr} <= {8'h0, 8'h0, 8'h0};
    end
    end

    endmodule

    1.2  ycbcr444转成rgb

    `timescale 1ns/1ns
    module VIP_YCbCr444_RGB888
    (
    //global clock
    input clk, //cmos video pixel clock
    input rst_n, //global reset

    //CMOS YCbCr444 data output
    input per_frame_vsync, //Prepared Image data vsync valid signal
    input per_frame_href, //Prepared Image data href vaild signal
    input per_frame_clken, //Prepared Image data output/capture enable clock
    input [7:0] per_img_Y, //Prepared Image data of Y
    input [7:0] per_img_Cb, //Prepared Image data of Cb
    input [7:0] per_img_Cr, //Prepared Image data of Cr


    //CMOS RGB888 data output
    output post_frame_vsync, //Processed Image data vsync valid signal
    output post_frame_href, //Processed Image data href vaild signal
    output post_frame_clken, //Processed Image data output/capture enable clock
    output [7:0] post_img_red, //Prepared Image green data to be processed
    output [7:0] post_img_green, //Prepared Image green data to be processed
    output [7:0] post_img_blue //Prepared Image blue data to be processed
    );

    //--------------------------------------------
    /*********************************************
    R = 1.164(Y-16) + 1.596(Cr-128)
    G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128)
    B = 1.164(Y-16) + 2.018(Cb-128)
    ->
    R = 1.164Y + 1.596Cr - 222.912
    G = 1.164Y - 0.391Cb - 0.813Cr + 135.488
    B = 1.164Y + 2.018Cb - 276.928
    ->
    R << 9 = 596Y + 817Cr - 114131
    G << 9 = 596Y - 200Cb - 416Cr + 69370
    B << 9 = 596Y + 1033Cb - 141787
    **********************************************/
    reg [19:0] img_Y_r1; //8 + 9 + 1 = 18Bit
    reg [19:0] img_Cb_r1, img_Cb_r2;
    reg [19:0] img_Cr_r1, img_Cr_r2;
    always@(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    img_Y_r1 <= 0;
    img_Cb_r1 <= 0; img_Cb_r2 <= 0;
    img_Cr_r1 <= 0; img_Cr_r2 <= 0;
    end
    else
    begin
    img_Y_r1 <= per_img_Y * 18'd596;
    img_Cb_r1 <= per_img_Cb * 18'd200;
    img_Cb_r2 <= per_img_Cb * 18'd1033;
    img_Cr_r1 <= per_img_Cr * 18'd817;
    img_Cr_r2 <= per_img_Cr * 18'd416;
    end
    end

    //--------------------------------------------
    /**********************************************
    R << 9 = 596Y + 817Cr - 114131
    G << 9 = 596Y - 200Cb - 416Cr + 69370
    B << 9 = 596Y + 1033Cb - 141787
    **********************************************/
    reg [19:0] XOUT;
    reg [19:0] YOUT;
    reg [19:0] ZOUT;
    always@(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    XOUT <= 0;
    YOUT <= 0;
    ZOUT <= 0;
    end
    else
    begin
    XOUT <= (img_Y_r1 + img_Cr_r1 - 20'd114131)>>9;
    YOUT <= (img_Y_r1 - img_Cb_r1 - img_Cr_r2 + 20'd69370)>>9;
    ZOUT <= (img_Y_r1 + img_Cb_r2 - 20'd141787)>>9;
    end
    end

    //------------------------------------------
    //Divide 512 and get the result
    //{xx[19:11], xx[10:0]}
    reg [7:0] R, G, B;
    always@(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    R <= 0;
    G <= 0;
    B <= 0;
    end
    else
    begin
    R <= XOUT[10] ? 8'd0 : (XOUT[9:0] > 9'd255) ? 8'd255 : XOUT[7:0];
    G <= YOUT[10] ? 8'd0 : (YOUT[9:0] > 9'd255) ? 8'd255 : YOUT[7:0];
    B <= ZOUT[10] ? 8'd0 : (ZOUT[9:0] > 9'd255) ? 8'd255 : ZOUT[7:0];
    end
    end

    //------------------------------------------
    //lag n clocks signal sync
    reg [2:0] post_frame_vsync_r;
    reg [2:0] post_frame_href_r;
    reg [2:0] post_frame_clken_r;
    always@(posedge clk or negedge rst_n)
    begin
    if(!rst_n)
    begin
    post_frame_vsync_r <= 0;
    post_frame_href_r <= 0;
    post_frame_clken_r <= 0;
    end
    else
    begin
    post_frame_vsync_r <= {post_frame_vsync_r[1:0], per_frame_vsync};
    post_frame_href_r <= {post_frame_href_r[1:0], per_frame_href};
    post_frame_clken_r <= {post_frame_clken_r[1:0], per_frame_clken};
    end
    end
    assign post_frame_vsync = post_frame_vsync_r[2];
    assign post_frame_href = post_frame_href_r[2];
    assign post_frame_clken = post_frame_clken_r[2];
    assign post_img_red = post_frame_href ? R : 8'd0;
    assign post_img_green = post_frame_href ? G : 8'd0;
    assign post_img_blue = post_frame_href ? B : 8'd0;

    endmodule

    2、同样将rgb转ycbcr422时,也通常先将rgb转成ycbcr444,再讲ycbcr444在转成ycbcr422

    2.1  rgb转成ycbcr444

    `timescale 1ns/1ps
    module RGB_to_YCbCr444_Processor(
    input clk,
    input wire[7 : 0] i_r_8b,
    input wire[7 : 0] i_g_8b,
    input wire[7 : 0] i_b_8b,

    input wire i_h_sync,
    input wire i_v_sync,
    input wire i_data_en,

    output wire[7 : 0] o_y_8b,
    output wire[7 : 0] o_cb_8b,
    output wire[7 : 0] o_cr_8b,

    output reg o_h_sync,
    output reg o_v_sync,
    output reg o_data_en
    );

    /***************************************parameters*******************************************/
    //multiply 256
    /*
    parameter para_0183_10b = 10'd47;
    parameter para_0614_10b = 10'd157;
    parameter para_0062_10b = 10'd16;
    parameter para_0101_10b = 10'd26;
    parameter para_0338_10b = 10'd86;
    parameter para_0439_10b = 10'd112;
    parameter para_0399_10b = 10'd102;
    parameter para_0040_10b = 10'd10;
    */
    parameter para_0183_10b = 10'd66;
    parameter para_0614_10b = 10'd129;
    parameter para_0062_10b = 10'd25;
    parameter para_0101_10b = 10'd38;
    parameter para_0338_10b = 10'd74;
    parameter para_0439_10b = 10'd112;
    parameter para_0399_10b = 10'd94;
    parameter para_0040_10b = 10'd18;
    parameter para_16_18b = 18'd4096;
    parameter para_128_18b = 18'd32768;
    /********************************************************************************************/

    /***************************************signals**********************************************/
    wire sign_cb;
    wire sign_cr;
    reg[17: 0] mult_r_for_y_18b;
    reg[17: 0] mult_r_for_cb_18b;
    reg[17: 0] mult_r_for_cr_18b;

    reg[17: 0] mult_g_for_y_18b;
    reg[17: 0] mult_g_for_cb_18b;
    reg[17: 0] mult_g_for_cr_18b;

    reg[17: 0] mult_b_for_y_18b;
    reg[17: 0] mult_b_for_cb_18b;
    reg[17: 0] mult_b_for_cr_18b;

    reg[17: 0] add_y_0_18b;
    reg[17: 0] add_cb_0_18b;
    reg[17: 0] add_cr_0_18b;

    reg[17: 0] add_y_1_18b;
    reg[17: 0] add_cb_1_18b;
    reg[17: 0] add_cr_1_18b;

    reg[17: 0] result_y_18b;
    reg[17: 0] result_cb_18b;
    reg[17: 0] result_cr_18b;

    reg i_h_sync_delay_1;
    reg i_v_sync_delay_1;
    reg i_data_en_delay_1;

    reg i_h_sync_delay_2;
    reg i_v_sync_delay_2;
    reg i_data_en_delay_2;


    /********************************************************************************************/

    /***************************************initial**********************************************/
    initial
    begin
    mult_r_for_y_18b <= 18'd0;
    mult_r_for_cb_18b <= 18'd0;
    mult_r_for_cr_18b <= 18'd0;

    mult_g_for_y_18b <= 18'd0;
    mult_g_for_cb_18b <= 18'd0;
    mult_g_for_cr_18b <= 18'd0;

    mult_b_for_y_18b <= 18'd0;
    mult_g_for_cb_18b <= 18'd0;
    mult_b_for_cr_18b <= 18'd0;


    add_y_0_18b <= 18'd0;
    add_cb_0_18b <= 18'd0;
    add_cr_0_18b <= 18'd0;

    add_y_1_18b <= 18'd0;
    add_cb_1_18b <= 18'd0;
    add_cr_1_18b <= 18'd0;

    result_y_18b <= 18'd0;
    result_cb_18b <= 18'd0;
    result_cr_18b <= 18'd0;

    i_h_sync_delay_1 <= 1'd0;
    i_v_sync_delay_1 <= 1'd0;
    i_data_en_delay_1 <= 1'd0;

    i_h_sync_delay_2 <= 1'd0;
    i_v_sync_delay_2 <= 1'd0;
    i_data_en_delay_2 <= 1'd0;


    o_h_sync <= 1'd0;
    o_v_sync <= 1'd0;
    o_data_en <= 1'd0;
    end
    /********************************************************************************************/

    /***************************************arithmetic*******************************************/
    //LV1 pipeline : mult
    always @ (posedge clk)
    begin
    mult_r_for_y_18b <= i_r_8b * para_0183_10b;//*47
    mult_r_for_cb_18b <= i_r_8b * para_0101_10b;//*26
    mult_r_for_cr_18b <= i_r_8b * para_0439_10b;//*112
    end

    always @ (posedge clk)
    begin
    mult_g_for_y_18b <= i_g_8b * para_0614_10b;//*157
    mult_g_for_cb_18b <= i_g_8b * para_0338_10b;//*86
    mult_g_for_cr_18b <= i_g_8b * para_0399_10b;//*102
    end

    always @ (posedge clk)
    begin
    mult_b_for_y_18b <= i_b_8b * para_0062_10b;//*16
    mult_b_for_cb_18b <= i_b_8b * para_0439_10b;//*112
    mult_b_for_cr_18b <= i_b_8b * para_0040_10b;//*10
    end
    //LV2 pipeline : add
    always @ (posedge clk)
    begin
    add_y_0_18b <= mult_r_for_y_18b + mult_g_for_y_18b;
    add_y_1_18b <= mult_b_for_y_18b + para_16_18b;//+4096

    add_cb_0_18b <= mult_b_for_cb_18b + para_128_18b;//+32768
    add_cb_1_18b <= mult_r_for_cb_18b + mult_g_for_cb_18b;

    add_cr_0_18b <= mult_r_for_cr_18b + para_128_18b;//+32768
    add_cr_1_18b <= mult_g_for_cr_18b + mult_b_for_cr_18b;
    end
    //LV3 pipeline : y + cb + cr

    assign sign_cb = (add_cb_0_18b >= add_cb_1_18b);
    assign sign_cr = (add_cr_0_18b >= add_cr_1_18b);
    always @ (posedge clk)
    begin
    result_y_18b = add_y_0_18b + add_y_1_18b;
    result_cb_18b = sign_cb ? (add_cb_0_18b - add_cb_1_18b) : 18'd0;
    result_cr_18b = sign_cr ? (add_cr_0_18b - add_cr_1_18b) : 18'd0;
    end

    //output
    assign o_y_8b = (result_y_18b[17:16] == 2'b00) ? result_y_18b[15 : 8] : 8'hFF;
    assign o_cb_8b = (result_cb_18b[17:16] == 2'b00) ? result_cb_18b[15 : 8] : 8'hFF;
    assign o_cr_8b = (result_cr_18b[17:16] == 2'b00) ? result_cr_18b[15 : 8] : 8'hFF;
    /********************************************************************************************/

    /***************************************timing***********************************************/
    always @ (posedge clk)
    begin
    i_h_sync_delay_1 <= i_h_sync;
    i_v_sync_delay_1 <= i_v_sync;
    i_data_en_delay_1 <= i_data_en;

    i_h_sync_delay_2 <= i_h_sync_delay_1;
    i_v_sync_delay_2 <= i_v_sync_delay_1;
    i_data_en_delay_2 <= i_data_en_delay_1;

    o_h_sync <= i_h_sync_delay_2;
    o_v_sync <= i_v_sync_delay_2;
    o_data_en <= i_data_en_delay_2;
    end

    endmodule

    2.2  ycbcr444在转成ycbcr422

    `timescale 1ns/1ps

    module ycbcr444_to_ycbcr422(
    input sys_clk, /*系统时钟*/
    input i_hs, /*视频输入行同步*/
    input line_end, /*在某些情况下可能没有行同步信号,只能自己生成一个行结束信号 */
    input i_vs,
    input i_de, /*视频数据有效*/
    input [7:0] i_y, /*视频输入Y分量 */
    input [7:0] i_cb, /*视频输入Cb(U)分量 */
    input [7:0] i_cr, /*视频输入Cr(V)分量 */
    output o_hs,
    output o_vs,
    output o_de, /* 输出数据有效*/
    output[7:0] o_y, /* 输出视频Y分量*/
    output[7:0] o_c, /*输出视频CbCr分量复合,先输出Cb,后输出Cr */
    output[19:0] data_out
    );
    reg i_de_d0 = 1'b0;
    reg i_de_d1 = 1'b0;
    reg i_hs_d0 = 1'b0;
    reg i_hs_d1 = 1'b0;

    reg i_vs_d0 = 1'b0;
    reg i_vs_d1 = 1'b0;

    reg [7:0] i_y_d0 = 8'd0;
    reg [7:0] i_y_d1 = 8'd0;
    reg [7:0] i_cb_d0 = 8'd0;
    reg [7:0] i_cr_d0 = 8'd0;
    reg [7:0] cb = 8'd0;
    reg [7:0] cr = 8'd0;
    reg [7:0] cr_d0 = 8'd0;
    reg line_end_d0;
    reg line_end_d1;
    wire[8:0] cb_add;
    wire[8:0] cr_add;
    reg c_flag = 1'b0;
    assign cb_add = {1'b0,i_cb} + {1'b0,i_cb_d0}; /*两个像素的cb相加,待求平均值 */
    assign cr_add = {1'b0,i_cr} + {1'b0,i_cr_d0}; /*两个像素的cr相加,待求平均值 */

    always@(posedge sys_clk)
    begin
    if(i_hs | i_vs)
    begin
    i_y_d0 <= 8'h10;
    i_cb_d0 <= 8'h80;
    i_cr_d0 <= 8'h80;
    line_end_d0 <= 1'b0;
    end
    else if(i_de)
    begin
    i_y_d0 <= i_y;
    i_cb_d0 <= i_cb;
    i_cr_d0 <= i_cr;
    line_end_d0 <= line_end;
    end
    else
    begin
    i_y_d0 <= i_y_d0;
    i_cb_d0 <= i_cb_d0;
    i_cr_d0 <= i_cr_d0;
    line_end_d0 <= line_end_d0;
    end
    i_de_d0 <= i_de;
    end

    always@(posedge sys_clk)
    begin
    if(i_hs | i_vs)
    begin
    i_y_d1 <= 8'h10;
    cb <= 8'h80;
    cr <= 8'h80;
    line_end_d1 <= 1'b0;
    end
    else if(i_de_d0)
    begin
    i_y_d1 <= i_y_d0;
    cb <= cb_add[8:1];
    cr <= cr_add[8:1];
    line_end_d1 <= line_end_d0;
    end
    else
    begin
    i_y_d1 <= i_y_d1;
    cb <= cb;
    cr <= cr;
    line_end_d1 <= line_end_d1;
    end
    i_de_d1 <= i_de_d0;
    end

    always@(posedge sys_clk)
    begin
    i_hs_d0 <= i_hs;
    i_hs_d1 <= i_hs_d0;
    end
    always@(posedge sys_clk)
    begin
    i_vs_d0 <= i_vs;
    i_vs_d1 <= i_vs_d0;
    end

    always@(posedge sys_clk)
    begin
    if((i_hs_d0 & ~i_hs_d1) | line_end_d1)
    begin
    c_flag <= 1'b0;
    end
    else if(i_de_d1)///////////////////////////
    begin
    c_flag <= ~c_flag;/*该寄存器标记C(色度信号)取Cb还是Cr */
    end
    else
    begin
    c_flag <= c_flag;
    end
    end
    always@(posedge sys_clk)
    begin
    if(i_de_d1)
    cr_d0 <= cr;
    else
    cr_d0 <= cr_d0;
    end
    assign o_c = c_flag ? cr_d0 : cb;/*C(色度信号)的选取 */
    assign o_y = i_y_d1;/////////////////
    assign o_de = i_de_d1;/////////////////
    assign o_hs = i_hs_d1;
    assign o_vs = i_vs_d1;

    assign data_out[19:10] = {i_y_d1, 2'b0};
    assign data_out[9:0] = {c_flag ? cr_d0 : cb, 2'b0};
    endmodule

  • 相关阅读:
    初级模拟电路:8-1 运算放大器概述
    初级模拟电路:6-1 FET概述
    初级模拟电路:5-5 甲乙类功率放大器
    初级模拟电路:5-4 乙类功率放大器
    初级模拟电路:5-3 变压器耦合型甲类功放
    初级模拟电路:5-2 串馈型甲类功放
    μC/OS-II系统中事件标志的使用
    STM32-SPI读写外部FLASH(W25Q64)
    STM32-定时器输出比较模式输出方波(DMA方式)
    STM32-定时器输出比较模式输出方波(中断方式)
  • 原文地址:https://www.cnblogs.com/VagueCheung/p/12899888.html
Copyright © 2020-2023  润新知