• FPGA_verilog_RGB转YUV代码分享


    关于RGB和YUV的基本概念,请自行百度,此文略,本文主要讲一下转换的部分代码。

    在做视频处理的时候,经常要用到色域的转换,RGB转YUV是非常常见的一种转换,那么我们在实际工程中应该怎么做呢?(注:本文的RGB转YUV是12bit转12bit的)

    首先是找打转换的公式,这里我用的是如下的公式:

    数字 RGB 转为数字 YCbCr计算公式:
    Y = (0.299R + 0.587G + 0.114B);
    Cb = (-0.172R - 0.339G + 0.511B) + 128;
    Cr = (0.511R - 0.428G - 0.083B) + 128;

    1.但是我们知道,在fpga中是不能做浮点运算的,也就是不能直接用小数运算,那么我们应该怎么处理这些小数呢,我这里用的方法是将小数放大为一定的整数(量化),然后计算,最后在通过移位操作得到我们的结果。如下:

    我这里是直接乘以2的10次方,部分代码如下:

    parameter Y_M_0 = 12'd306; //0.299*1024
    parameter Y_M_1 = 12'd601; //0.587*1024
    parameter Y_M_2 = 12'd117; //0.114*1024
    parameter Y_A_3 = 0; //0

    parameter CB_M_0 = 12'hf_50;//-176; //-0.172*1024
    parameter CB_M_1 = 12'he_a5;//-347; //-0.339*1024
    parameter CB_M_2 = 12'd523; //0.511*1024
    parameter CB_A_3 = 12'd128; //128

    parameter CR_M_0 = 12'd523; //0.511*1024
    parameter CR_M_1 = 12'he_4a;//-438; //-0.428*1024
    parameter CR_M_2 = 12'hf_ab;//-85; //-0.083*1024
    parameter CR_A_3 = 128; //128

    2.接着需要用3个乘加器,得到三个结果:y_muladd, cb_muladd,cr_muladd ,如下所示:

    wire [25:0] y_muladd /*synthesis keep*/;
    wire [25:0] cb_muladd /*synthesis keep*/;
    wire [25:0] cr_muladd /*synthesis keep*/;

    /******** 先做乘加 *****/
    //乘加会延迟3个clk
    multadd3_12b multadd3_12b_u0(
    .dataa_0(in_r),
    .dataa_1(in_g),
    .dataa_2(in_b),
    .datab_0(Y_M_0),
    .datab_1(Y_M_1),
    .datab_2(Y_M_2),
    .result(y_muladd),
    .aclr0(~rst_n),
    .clock0(clk));

    multadd3_12b multadd3_12b_u1(
    .dataa_0(in_r),
    .dataa_1(in_g),
    .dataa_2(in_b),
    .datab_0(CB_M_0),
    .datab_1(CB_M_1),
    .datab_2(CB_M_2),
    .result(cb_muladd),
    .aclr0(~rst_n),
    .clock0(clk));

    multadd3_12b multadd3_12b_u2(
    .dataa_0(in_r),
    .dataa_1(in_g),
    .dataa_2(in_b),
    .datab_0(CR_M_0),
    .datab_1(CR_M_1),
    .datab_2(CR_M_2),
    .result(cr_muladd),
    .aclr0(~rst_n),
    .clock0(clk));

    3.最后在把数据缩小2的10次方倍,然后判断一下就ok了,代码如下所示:

    /******** 再加上第四个数 *****/
    //延迟一个clk
    reg [15:0] y_out;
    reg [15:0] cb_out;
    reg [15:0] cr_out;
    always@(posedge clk or negedge rst_n)
    begin
    if (~rst_n) begin
    y_out <= 0;
    cb_out <= 0;
    cr_out <= 0;
    end
    else begin
    y_out <= (y_muladd + Y_A_3 ) >> 10;
    cb_out <= (cb_muladd + CB_A_3) >> 10;
    cr_out <= (cr_muladd + CR_A_3) >> 10;
    end
    end

    assign out_y = y_out[15] ? 12'h000 : (y_out[14:12 ]==2'd0 ? y_out[11:0] : 12'hfff);
    assign out_cb = cb_out[15] ? 12'h000 : (cb_out[14:12]==2'd0 ? cb_out[11:0] : 12'hfff);
    assign out_cr = cr_out[15] ? 12'h000 : (cr_out[14:12]==2'd0 ? cr_out[11:0] : 12'hfff);

    最后的out_y,out_cb,out_cr就是我们要的结果了。是不是很简单呢,其实其他数字的运算也是一个道理。嘻嘻

  • 相关阅读:
    Siege 3.0 正式版发布,压力测试工具
    Pomm 1.1.2 发布,专为 PG 设计的 ORM 框架
    Whonix 0.5.6 发布,匿名通用操作系统
    国内开源 java cms,Jspxcms 2.0 发布
    EZNamespaceExtensions.Net v2013增加对上下文菜单、缩略图、图标、属性表的支持
    GNU Guile 2.0.9 发布,Scheme 实现
    jdao 1.0.4 发布 轻量级的orm工具包
    OpenSearchServer 1.4 RC4 发布
    Percona Server for MySQL 5.5.3030.2
    Samba 4.0.5 发布
  • 原文地址:https://www.cnblogs.com/cofin/p/6785108.html
Copyright © 2020-2023  润新知