首页 > 其他分享 >fpga图像处理实战-RGB与HSV互转

fpga图像处理实战-RGB与HSV互转

时间:2024-08-09 08:54:57浏览次数:10  
标签:fpga Max var RGB valid del 互转 reg 255

HSV颜色模型

        HSV(Hue, Saturation, Value)颜色模型是一种常用的色彩表示方式,特别适用于图像处理、计算机图形学和色彩选取工具中。它通过将颜色的表示从传统的RGB(红、绿、蓝)模型转换为更符合人类视觉感知的方式来描述颜色。以下是HSV模型的三个主要分

        Hue(色调,H):色调表示颜色的种类,通常用角度来表示,范围从0°到360°。在HSV模型的色轮中:0°代表红色,120°代表绿色,240°代表蓝色。其他角度代表这些基本颜色之间的过渡色,例如30°为橙色,60°为黄色。

        Saturation(饱和度,S):饱和度描述颜色的纯度或浓度,表示色彩的鲜艳程度。S的取值范围是从0到100%,或者在某些情况下是0到1。
        当S为0时,颜色是完全无色的(灰色),这意味着色调无关紧要。
        当S为100%(或1)时,颜色是完全饱和的,这意味着没有混入任何白色。


        Value(明度,V):明度表示颜色的亮度,取值范围也是0到100%或0到1。
        当V为0时,颜色是完全黑色的。
        当V为100%(或1)时,颜色是最亮的,显示的是色调本身的颜色。

FPGA 实现

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/01/28 01:40:35
// Design Name: 
// Module Name: divide
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 除法
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module divide#(
    parameter   I_W = 32,
    parameter   D_W = 9,
    parameter   O_W = I_W - D_W
)
(
    input clk,
    input reset,
    input valid_i,
    input [I_W - 1 : 0] dividend, //被除数
    input [D_W - 1 : 0]divisor, //除数
    output valid_o,
    output [O_W - 1 : 0]quotient,//商
    output [D_W - 1 : 0]remaind  //余数
);
    
      //变量声明
    localparam B_W = I_W + 1;
    genvar i;
    reg [D_W-1:0] divisor_buf [0:O_W+1];
    reg valid_buf [0:O_W+1];
    reg [B_W-1:0] dividend_buf [0:O_W+1];
    reg [O_W:0] quotient_buf [0:O_W+1];
    
    //赋初值
    always @(*) begin
        dividend_buf[0] = {1'b0, dividend};
        divisor_buf[0] = divisor;
        valid_buf[0] = valid_i;
        quotient_buf[0] = 0;
    end    

   
    //除法计算
    generate for(i=1;i<=(O_W+1);i=i+1)
	begin
    
    always @(posedge clk or posedge reset) begin
        if(reset) begin
            dividend_buf[i] <= 'b0;
		    quotient_buf[i] <= 'b0;
        end else if(valid_buf[i-1]) begin 
            if(divisor_buf[i-1] == 'b0) begin //除数为0的情况
               dividend_buf[i] <= 'b0;
		       quotient_buf[i] <= 'b0;
		    end else if(dividend_buf[i-1][B_W-1:O_W] >= {1'b0, divisor_buf[i-1]}) begin //可能出现上一步的余数最高位也是1的情况
			   dividend_buf[i][B_W-1:O_W+1] <= dividend_buf[i-1][B_W-1:O_W] - divisor_buf[i-1];
			   dividend_buf[i][O_W:0] <= {dividend_buf[i-1][O_W-1:0], 1'b0};
			   quotient_buf[i] <= {quotient_buf[i-1][O_W:0],1'b1};
			end else begin
			   dividend_buf[i][B_W-1:O_W+1] <= dividend_buf[i-1][B_W-1:O_W];
			   dividend_buf[i][O_W:0] <= {dividend_buf[i-1][O_W-1:0], 1'b0};
			   quotient_buf[i] <= {quotient_buf[i-1][O_W:0],1'b0};
			end
        end else begin
            dividend_buf[i] <= 'b0;
		    quotient_buf[i] <= 'b0;        
        end
    end

    always @(posedge clk ) begin
        valid_buf[i] <= valid_buf[i-1];
        divisor_buf[i] <= divisor_buf[i-1];
    end    
    
    end
    endgenerate    
    
    assign valid_o = valid_buf[O_W+1];
    assign quotient = quotient_buf[O_W+1];
    assign remaind = dividend_buf[O_W+1][B_W-1:O_W+1];  
    
    
endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/08/07 19:14:25
// Design Name: 
// Module Name: image_rgb_to_hsv
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module image_rgb_to_hsv(
    input                               clk                        ,
    input                               rst                        ,
    input              [  23: 0]        img_data_i                 ,
    input                               valid_i                    ,
    output             [  23: 0]        img_data_o                 ,
    output                              valid_o                     
);

    /*
        R,Gand Binput range=0- 255
        H,Sand Voutputrange=0- 1.0

        var_R=(R/255)
        var_G=(G/255)
        var_B=(B/255)

        var_Min=min(var_R,var_G,var_B)                              //Min. value of RGB
        var_Max=max(var_R,var_G,var_B)                              //Max. value of RGB
        del_Max=var_Max-var_Min                                     //Delta RGB value

        V  = var_Max

        if(del_Max ==0)  This is a gray,no chroma.
            H =0
            S=0
        else   Chromatic data...
            S= del_Max/var_Max
            del_R=(((var_Max-var_R)/6)+(del_Max/2))/ del_Max
            de1_G=(((var_Max-var_G)/6)+(del_Max/2))/ del_Max
            del_B=(((var_Max-var_B)/6)+(del_Max/2))/ del_Max
            
        if (var_R==var_Max)
            H=del_B-del_G
        else if(var_G==var_Max)
            H=(1/3)+ del_R- del_B
        else if(var_B==var_Max)
            H=(2/3)+ del_G- del_R
        if(H<0)  H+= 1
        if(H>1)  H-= 1



    转换成整数运算,所有运算常量都乘以255

    //R, G and B input range = 0 ~ 255
    //H, S and V output range = 0 ~ 255

    var_R = R
    var_G = G
    var_B = B

    var_Min = min( var_R, var_G, var_B )    //Min. value of RGB
    var_Max = max( var_R, var_G, var_B )    //Max. value of RGB
    del_Max = var_Max - var_Min             //Delta RGB value

    V = var_Max

    if ( del_Max == 0 )                     //This is a gray, no chroma...
    {
        H = 0
        S = 0
    }
    else                                    //Chromatic data...
    {
        S = (del_Max / var_Max) * 255

        del_R = ( ( ( var_Max - var_R ) / 6 ) + ( del_Max / 2 ) ) / del_Max * 255
        del_G = ( ( ( var_Max - var_G ) / 6 ) + ( del_Max / 2 ) ) / del_Max * 255
        del_B = ( ( ( var_Max - var_B ) / 6 ) + ( del_Max / 2 ) ) / del_Max * 255

        if      ( var_R == var_Max ) H = del_B - del_G
        else if ( var_G == var_Max ) H = ( 1 / 3 )*255 + del_R - del_B
        else if ( var_B == var_Max ) H = ( 2 / 3 )*255 + del_G - del_R

        if ( H < 0 ) H += 1
        if ( H > 1 ) H -= 1
    }  

    //简化公式
        del_R = ( var_Max - var_R + 3*del_Max) / (6*del_Max) * 255
        del_G = ( var_Max - var_G + 3*del_Max) / (6*del_Max) * 255
        del_B = ( var_Max - var_B + 3*del_Max) / (6*del_Max) * 255   

        if      ( var_R == var_Max ) H = del_B - del_G = ( var_G - var_B)/ (6*del_Max) * 255
        else if ( var_G == var_Max ) H = ( 1 / 3 )*255 + del_R - del_B = 85 + ( var_B - var_R)/ (6*del_Max) * 255
        else if ( var_B == var_Max ) H = ( 2 / 3 )*255 + del_G - del_R = 170 + ( var_R - var_G)/ (6*del_Max) * 255
   
    //最后简化公式为
       var_R = R
       var_G = G
       var_B = B

       var_Min = min( var_R, var_G, var_B )    //Min. value of RGB
       var_Max = max( var_R, var_G, var_B )    //Max. value of RGB
       del_Max = var_Max - var_Min             //Delta RGB value

        if      ( var_R == var_Max ) H = ( var_G - var_B)/ (6*del_Max) * 255
        else if ( var_G == var_Max ) H = ( 2*del_Max + var_B - var_R)/ (6*del_Max) * 255
        else if ( var_B == var_Max ) H = ( 4*del_Max + var_R - var_G)/ (6*del_Max) * 255
        
        S = (del_Max / var_Max) * 255

        V = var_Max
    */


    wire               [   7: 0]        R,G,B                      ;
    assign                              {R,G,B}                   = img_data_i;

    reg                                 valid_d1                   ;
    reg                                 valid_d2                   ;
    reg                                 valid_d3                   ;
    reg                [   7: 0]        var_min                    ;
    reg                [   7: 0]        var_max                    ;
    reg                [   8: 0]        var_ext                    ;
    reg                [   1: 0]        var_max_id                 ;
    reg                [   7: 0]        R_d1,G_d1,B_d1             ;
    wire               [   7: 0]        del_max_w                  ;
    reg                [  15: 0]        del_max_m255               ;
    reg                [  10: 0]        del_max_m6                 ;
    reg                [   7: 0]        var_max_d1                 ;
    wire               [  10: 0]        h_w                        ;
    reg                [  18: 0]        h_del                      ;
    reg                [8*9-1: 0]       var_max_d1_shift_r         ;
    wire                                s_div_valid_w              ;
    wire               [   7: 0]        S                          ;
    wire                                h_div_valid_w              ;
    wire               [   7: 0]        H                          ;
    wire               [   7: 0]        V                          ;

    always @ (posedge clk or posedge rst)
    if (rst)begin
        valid_d1 <= 0;
        var_min <= 0;
        var_max <= 0;
        var_ext <= 0;
        var_max_id <= 0;
        {R_d1,G_d1,B_d1} <= 0;
    end else begin
        valid_d1 <= valid_i;
        if (valid_i)begin
            var_min <= (R > G) ? ((G > B)? B : R) :((R > B) ? B:R);
            if (R > G)begin
                if (R > B)begin
                    var_max <= R;
                    var_max_id <= 0;
                    var_ext <= (G > B) ? G - B : 0;
                end
            else begin
                var_max <= B;
                var_max_id <= 2;
                var_ext <= R - {1'b0,G};
            end
            end
        else if (G > B)begin
            var_max <= G ;
            var_max_id <= 1;
            var_ext <= B - {1'b0,R};
        end else begin
            var_max <= B ;
            var_max_id <= 2;
            var_ext <= R - {1'b0,G};
        end
        end
        {R_d1,G_d1,B_d1} <= {R,G,B};
    end

    //计算最大差值 
    assign                              del_max_w                 = var_max - var_min;
   //有符号数运算
    assign  h_w = (var_max_id == 0) ? {2'b0, var_ext} : (var_max_id == 1) ?
     ({del_max_w, 1'b0} + {{2{var_ext[8]}}, var_ext}) : ({del_max_w, 2'b0} + {{2{var_ext[8]}}, var_ext});

    always @ (posedge clk or posedge rst)
    if (rst)begin
        valid_d2 <= 0;
        del_max_m255 <= 0;
        del_max_m6 <= 0;
        h_del <= 0;
        var_max_d1 <= 0;
    end else begin
        valid_d2 <= valid_d1;
        if (valid_d1)begin
            del_max_m255 <= {del_max_w, 8'b0} - del_max_w;
            del_max_m6 <= {del_max_w, 2'b0} + {del_max_w, 1'b0};
            h_del <= h_w[10]||(del_max_w == 0) ? 0 : {h_w, 8'b0} - h_w;
        end
        var_max_d1 <= var_max;
    end

    //VarMax做延时处理
    always @(posedge clk)
        var_max_d1_shift_r <= {var_max_d1_shift_r,var_max_d1};

     //除法计算
    //计算S,延时16-8+1=9
    divide#(
    .I_W                                (16                        ),
    .D_W                                (8                         ) 
    )u_divide0(
    .clk                                (clk                       ),
    .reset                              (rst                       ),
    .valid_i                            (valid_d2                  ),
    .dividend                           (del_max_m255              ),
    .divisor                            (var_max_d1                ),
    .valid_o                            (s_div_valid_w             ),
    .quotient                           (S                         ),
    .remaind                            (                          ) 
    );

    //计算H,延时19-11+1=9
    divide#(
    .I_W                                (19                        ),
    .D_W                                (11                        ) 
    )u_divide1(
    .clk                                (clk                       ),
    .reset                              (rst                       ),
    .valid_i                            (valid_d2                  ),
    .dividend                           (h_del                     ),
    .divisor                            (del_max_m6                ),
    .valid_o                            (h_div_valid_w             ),
    .quotient                           (H                         ),
    .remaind                            (                          ) 
    );

    //计算V
    assign                              V                         = var_max_d1_shift_r[8*9-1:8*8];
    assign                              valid_o                   = s_div_valid_w;
    assign                              img_data_o                = {H, S, V};
    
endmodule

 

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/01/28 12:45:31
// Design Name: 
// Module Name: image_hsv_to_rgb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module image_hsv_to_rgb(
    input                               clk                        ,
    input                               rst                        ,
    input              [  23: 0]        img_data_i                 ,
    input                               valid_i                    ,
    output             [  23: 0]        img_data_o                 ,
    output                              valid_o                     
);
    /*
    HSV转RGB
    H,S and V  input  range=0/1.0
    R,GandB    output range=0/255
    if(S==0){
        R=V* 255
        G=V* 255
        B=V* 255
    J
    else
        var_h =H* 6
        if(var_h==6)var_h= 0
        var_i = int(var_h )
        var_1=V*(1-S)
        var_2=V*(1-S*(var_h-var_i))
        var_3=V*(1-S*(1-(var_h-var_i)))

        if      (var_i ==0){var_r =V       var_g=var_3  var b=var_1}
        else if (var_i ==1){var_r =var_2   var_g=V      var_b=var 1}
        else if (var_i ==2){var_r =var_1   var_g=V      var_b=var 3}
        else if (var_i ==3){var_r =var_1   var_g=var_2  var_b=V    }
        else if (var_i ==4){var_r =var_3   var_g=var_1  var_b=V    }
        else               {var_r =V       var_g=var_1  var b=var_2}

        R= var_r * 255
        G= var_g * 255
        B= var b * 255
   

    简化公式,我们的HSV都是整数
    if ( S == 0 )
    {
       R = V
       G = V
       B = V
    }
    else
    {
       var_h = H * 6
       if ( H == 255 ) var_h = 0                                    //H must be < 1
       var_i = var_h[10:8]                                          //Or ... var_i = floor( var_h )
       var_1 = V * ( 1 - S ) = V - V*S/255
       var_2 = V * ( 1 - S * ( var_h - var_i ) ) = V - V*S*( var_h - var_i )/255/255
       var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) ) = V - V*S/255 + V*S*( var_h - var_i )/255/255

       if      ( var_i == 0 ) { R = V     ; G = var_3 ; B = var_1 }
       else if ( var_i == 1 ) { R = var_2 ; G = V     ; B = var_1 }
       else if ( var_i == 2 ) { R = var_1 ; G = V     ; B = var_3 }
       else if ( var_i == 3 ) { R = var_1 ; G = var_2 ; B = V     }
       else if ( var_i == 4 ) { R = var_3 ; G = var_1 ; B = V     }
       else                   { R = V     ; G = var_1 ; B = var_2 }
    }
     */

    wire               [   7: 0]        H,S,V                      ;
    assign                              {H,S,V }                  = img_data_i;
    reg                                 valid_d1                   ;
    reg                                 valid_d2                   ;
    reg                                 valid_d3                   ;
    reg                                 valid_d4                   ;
    wire               [  10: 0]        var_h                      ;
    assign                              var_h                     = (H == 'd255) ? 0 : {H, 2'b0} + {H, 1'b0};
    reg                [   2: 0]        var_i                      ;
    reg                [   7: 0]        var_h_sub_var_i            ;
    reg                [  15: 0]        V_m_S                      ;
    reg                [   7: 0]        V_d1                       ;
    reg                                 S_zero                     ;
    reg                [  23: 0]        V_m_S_m_h                  ;
    reg                [  15: 0]        V_m_S_d1                   ;
    reg                [   7: 0]        V_d2                       ;
    reg                [   2: 0]        var_i_d1                   ;
    reg                                 S_zero_d1                  ;

    reg                [   7: 0]        var_1,var_2,var_3          ;
    reg                [   2: 0]        var_i_d2                   ;
    reg                [   7: 0]        V_d3                       ;
    reg                                 S_zero_d2                  ;
    reg                [   7: 0]        R,G,B                      ;

    always @ (posedge clk or posedge rst)
    if (rst)begin
        valid_d1 <= 0;
        var_i <= 0;
        var_h_sub_var_i <= 0;
        V_m_S <= 0;
        S_zero <= 0;
        V_d1 <= 0;
    end else begin
        valid_d1 <= valid_i;
        var_i <= var_h[10:8];
        var_h_sub_var_i <= var_h - var_i;
        V_m_S <= V*S;
        S_zero <= (S == 0) ? 1'b1 : 1'b0;
        V_d1 <= V;
    end

    always @ (posedge clk or posedge rst)
    if (rst)begin
        valid_d2 <= 0;
        V_m_S_m_h <= 0;
        V_m_S_d1 <= 0;
        V_d2 <= 0;
        var_i_d1 <= 0;
        S_zero_d1 <= 0;
    end else begin
        valid_d2 <= valid_d1;
        V_m_S_m_h <= V_m_S*var_h_sub_var_i;
        V_m_S_d1 <= V_m_S;
        V_d2 <= V_d1;
        var_i_d1 <= var_i;
        S_zero_d1 <= S_zero;
    end

    always @ (posedge clk or posedge rst)
    if (rst)begin
        valid_d3 <= 0;
        {var_1,var_2,var_3 } <= 0;
        var_i_d2 <= 0;
        V_d3 <= 0;
        S_zero_d2 <= 0;
    end else begin
        valid_d3 <= valid_d2;
         //简化除法运算,1/255直接等效于1/256
        //var_1 = V * ( 1 - S ) = V - V*S/255
        var_1 <= V_d2 - V_m_S_d1[15:8];
        //var_2 = V * ( 1 - S * ( var_h - var_i ) ) = V - V*S*( var_h - var_i )/255/255
        var_2 <= V_d2 - V_m_S_m_h[23:16];
        //var_3 = V * ( 1 - S * ( 1 - ( var_h - var_i ) ) ) = V - V*S/255 + V*S*( var_h - var_i )/255/255
        var_3 <= V_d2 - V_m_S_d1[15:8] + V_m_S_m_h[23:16];
        var_i_d2 <= var_i_d1;
        V_d3 <= V_d2;
        S_zero_d2 <= S_zero_d1;
    end


    always @ (posedge clk or posedge rst)
    if (rst)begin
        valid_d4 <= 0;
        {R,G,B } <= 0;
    end else begin
        valid_d4 <= valid_d3;
        if (S_zero_d2)begin
             {R, G, B} <= {3{V_d3}};
        end else begin
            case (var_i_d2)
                0: begin R <= V_d3  ; G <= var_3 ; B <= var_1; end
                1: begin R <= var_2 ; G <= V_d3  ; B <= var_1; end
                2: begin R <= var_1 ; G <= V_d3  ; B <= var_3; end
                3: begin R <= var_1 ; G <= var_2 ; B <= V_d3 ; end
                4: begin R <= var_3 ; G <= var_1 ; B <= V_d3 ; end
                default: begin R <= V_d3 ; G <= var_1 ; B <= var_2; end
            endcase
        end
    end

    assign                              valid_o                   = valid_d4;
    assign                              img_data_o                = {R, G, B};
       
endmodule

仿真

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/08/01 20:54:28
// Design Name: 
// Module Name: tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
`define INPUT_FILE "../../../../test_img/in/1024x600.bmp"           //input image
`define IMG_WIDTH 1024                                              //Image width
`define IMG_HEIGHT  600                                             //Image height
`define H_BLANK 400                                                 //横向消影区,仿真可自由设定
`define V_BLANK 30                                                  //纵向消影区,仿真可自由设定
 
`define OUTPUT_FILE "../../../../test_img/out/result.bmp"           //result image frame1
`define LEN_HEADER    54                                            // 0x33
`define IMG_ALL    (`IMG_HEIGHT*`IMG_WIDTH*3)
`define IMG_SIZE (`IMG_HEIGHT*`IMG_WIDTH)
`define IMG_BMP_SIZE (`IMG_ALL + `LEN_HEADER)
`define NULL 0
`define DATA_WIDTH  8
`define SEEK_SET 0
`define SEEK_CUR 1
`define SEEK_END 2

module tb;

    parameter                           TIME                      = 2     ;
    integer                             fdI                        ;
    integer                             fdO                        ;
    integer                             ret,                     i,j,idx,file_end_offset,zero_len;
    reg                [`DATA_WIDTH-1: 0]bmp_head_r[0:`LEN_HEADER-1]  ;//Image 1 Header
    reg                [`DATA_WIDTH-1: 0]imgR_r[0:`IMG_SIZE-1]     ;//Image-- R Channel
    reg                [`DATA_WIDTH-1: 0]imgG_r[0:`IMG_SIZE-1]     ;//Image-- G Channel
    reg                [`DATA_WIDTH-1: 0]imgB_r[0:`IMG_SIZE-1]     ;//Image-- B Channel  
    
    wire               [  31: 0]        bmp_size,                bmp_width,bmp_height;
    reg                                 init_r                     ;
        
    reg                                 clk                      =1'b0;
    reg                                 rst                        ;
    
    reg                [  31: 0]        h_cnt_r,                 v_cnt_r;
    reg                [  31: 0]        data_cnt_r                 ;
    reg                [  31: 0]        addr_r                     ;
    
    wire                                valid_i                    ;
    wire               [`DATA_WIDTH*3-1: 0]img_data_i              ;
    wire                                valid_o                    ;
    wire               [`DATA_WIDTH*3-1: 0]img_data_o              ;

    reg                [  31: 0]        out_data_cnt_r             ;
    reg                                 valid_o_r                  ;

    wire               [`DATA_WIDTH-1: 0]R_o_w,                  G_o_w,B_o_w;
    
    always
    begin
        #(TIME/2) clk = ~clk;
    end

    initial begin
    rst = 1'b1;
    zero_len = 'b0;
    #(TIME*10);
    rst = 1'b0;
    wait(init_r);
    $display("> Initial Done");
    wait(out_data_cnt_r == (`IMG_SIZE-1));                          //检测一幅图像完成?
    #(TIME*2);
    //文件末尾补0
    $fseek(fdO, 0, `SEEK_END);
    zero_len = $ftell(fdO);
    zero_len = 4- zero_len[1:0];
    for(i=0;i < zero_len;i=i+1)
        $fwrite(fdO, "%c", 0);
    $fclose(fdO);
    $display("> Simulate Done");
    $stop;
    end

    ///读取BMP文件
    assign                              bmp_size                  = {bmp_head_r[5], bmp_head_r[4], bmp_head_r[3], bmp_head_r[2]};
    assign                              bmp_width                 = {bmp_head_r[21], bmp_head_r[20], bmp_head_r[19], bmp_head_r[18]};
    assign                              bmp_height                = {bmp_head_r[25], bmp_head_r[24], bmp_head_r[23], bmp_head_r[22]};

    initial begin
    init_r = 1'b0;
    for (i = 0; i < `IMG_SIZE; i=i+1)begin
        imgB_r[i] = 0;
        imgG_r[i] = 0;
        imgR_r[i] = 0;
    end
			
    fdI = $fopen(`INPUT_FILE,"rb");
    if (fdI == `NULL) begin
        $display("> OPEN FAIL: The file not exist !!!");
    end else begin
        $display("> OPEN file SUCCESS !");
		//读取bmp文件头		
        ret = $fread(bmp_head_r, fdI, 0, `LEN_HEADER);
	    //读取图像RGB分量值?
        //BMP倒序存储数据时,从下到上,从左到右
        for(i=`IMG_HEIGHT - 1;i >= 0;i=i-1)
            for(j=0;j <`IMG_WIDTH;j=j+1) begin
                idx = i*`IMG_WIDTH + j;
                imgB_r[idx] = $fgetc(fdI);                          //b
                imgG_r[idx] = $fgetc(fdI);                          //g
                imgR_r[idx] = $fgetc(fdI);                          //r                
        end
        $display("> Read b,g,r Successful !");
    end
		
    fdO = $fopen(`OUTPUT_FILE,"wb");

    //写入文件头   
    for(i=0;i < `LEN_HEADER;i=i+1)   begin
        $fwrite(fdO, "%c", bmp_head_r[i]);
    end

    //移动到图片数据最后一行起始位置
    file_end_offset = `IMG_ALL + `LEN_HEADER - `IMG_WIDTH*3;
    $fseek(fdO, file_end_offset, `SEEK_SET);
    init_r = 1'b1;
    end

    wire               [  23: 0]        img_data_hsv               ;
    wire                                valid_hsv                  ;

image_rgb_to_hsv image_rgb_to_hsv(
    .clk                                (clk                       ),
    .rst                                (rst                       ),
    .img_data_i                         (img_data_i                ),
    .valid_i                            (valid_i                   ),
    .img_data_o                         (img_data_hsv              ),
    .valid_o                            (valid_hsv                 ) 
);


image_hsv_to_rgb u_image_hsv_to_rgb(
    .clk                                (clk                       ),
    .rst                                (rst                       ),
    .img_data_i                         (img_data_hsv              ),
    .valid_i                            (valid_hsv                 ),
    .img_data_o                         (img_data_o                ),
    .valid_o                            (valid_o                   ) 
);



    always @(posedge clk or posedge rst) begin
        if (rst) begin
            {h_cnt_r, v_cnt_r} <= 'b0;
            addr_r <= 'b0;
            data_cnt_r <= 'b0;
        end else begin
            h_cnt_r <= (h_cnt_r == `IMG_WIDTH + `H_BLANK - 1) ? 'b0 : h_cnt_r + 1'b1;
            v_cnt_r <= (h_cnt_r == `IMG_WIDTH + `H_BLANK - 1) ? ((v_cnt_r == `IMG_HEIGHT + `V_BLANK - 1) ? 'b0 : v_cnt_r + 1'b1) : v_cnt_r;
            addr_r <= (addr_r == `IMG_SIZE - 1) ?  'b0 : valid_i ? (addr_r + 'd1) : addr_r;
            data_cnt_r <= valid_i ? ((data_cnt_r == `IMG_WIDTH - 1) ? 'b0 : data_cnt_r + 1) : data_cnt_r;
        end
    end
    
    assign                              valid_i                   = (h_cnt_r < `IMG_WIDTH)&&(v_cnt_r < `IMG_HEIGHT) ? 1'b1 : 1'b0;
    assign                              img_data_i                = {imgR_r[addr_r], imgG_r[addr_r], imgB_r[addr_r]};
    
    
///写入BMP文件

    assign                              {R_o_w, G_o_w, B_o_w}     = img_data_o;

    always @(posedge clk or posedge rst) begin
        if (rst) begin
            out_data_cnt_r <= 'b0;
            valid_o_r <= 'b0;
        end else begin
            valid_o_r <= valid_o;
            if(valid_o) begin
                $fwrite(fdO, "%c", B_o_w);
                $fwrite(fdO, "%c", G_o_w);
                $fwrite(fdO, "%c", R_o_w);
                out_data_cnt_r <= out_data_cnt_r + 1'b1;
            end else if(valid_o_r) begin                            //行结束
                file_end_offset = file_end_offset - `IMG_WIDTH*3;
                $fseek(fdO, file_end_offset, `SEEK_SET);
            end
        end
    end


endmodule

 结果

原图

仿真图 

标签:fpga,Max,var,RGB,valid,del,互转,reg,255
From: https://blog.csdn.net/weixin_62953178/article/details/141035265

相关文章

  • fpga图像处理实战-YCBCR转RGB
    计算公式    R=Y+1.402*(V-128)=Y+1.402*CR-1.402*128  G=Y-0.344*(U-128)-0.714*(V-128)=Y-0.344*CB-0.714*CR+1.058*128   B=Y+1.772*(U-128)=Y+1.772*CB-1.772*128FPGA实现`timescale1ns/1ps////Company://......
  • String和StringBuffer的相互转换
    packagecom.shujia.day11;/*String和StringBuffer的相互转换A->BB->A*/publicclassStringBufferDemo4{publicstaticvoidmain(String[]args){//String->StringBuffer//可以通过构造方法来转换,将String作为参数传递......
  • 【教程4>第3章>第5节】8ASK解调系统的FPGA开发与matlab验证
    本课程学习成果预览 欢迎订阅FPGA/MATLAB/Simulink系列教程《★教程1:matlab入门100例》《★教程2:fpga入门100例》《★教程3:simulink入门60例》《★教程4:FPGA/MATLAB/Simulink联合开发入门与进阶X例》目录1.软件版本2.8ASK解调理论简介3.8ASK解调过程的MATLA......
  • Python 汉字区位码、字符串 相互转换
    Python汉字区位码、字符串相互转换区位码简介GB2312所有字符放在一张94x94的矩阵中,矩阵中的每个位置对应一个字符(有的位置是空的,没有字符)。区位码为十进制四位数,前后两位分别代表该字符在矩阵中的行、列坐标(均从1算起),如4528“图”字,为45行、28列上的字符。能通过对区位码进......
  • C++ char*类型与vector类型的相互转换
    char*类型与vector<char>类型的相互转换很多时候需要使用动态的字符串,但是char*难以完成相应的扩容操作,而动态数组vector则可以简单地完成,结合二者特性就可以完成动态字符串,同时,也需要二者类型的相互转换:char*转vector<char> vector<char>buffer(ch,ch+4);vector<cha......
  • 8 Python字符串与二进制文本相互转换
     欢迎来到@一夜看尽长安花博客,您的点赞和收藏是我持续发文的动力对于文章中出现的任何错误请大家批评指出,一定及时修改。有任何想要讨论的问题可联系我:[email protected]。发布文章的风格因专栏而异,均自成体系,不足之处请大家指正。   专栏:java全栈C&C++PythonAIP......
  • 第6章>>实验6:PS(ARM)端Linux RT与PL端FPGA之间(通过Reg寄存器进行通信和交互)-《LabVIEW Z
    1、实验内容       前面第五章入门实验和上一个实验5里面我们向大家展示通过了布尔类型的Reg寄存器通道实现了ZYNQPS端ARM和PL端FPGA二者之间的开关量交互,抛砖引玉。       从本节实验开始,接下来4个实验我们将着重向大家讲解更为通用和更为全面的4种交互方......
  • FPGA设计之跨时钟域(CDC)设计篇(5)----同步FIFO的两种设计方法(计数器法/高位扩展法 | 手撕
    1、什么是FIFO?        FIFO(FirstInFirstOut)是一种先进先出的数据缓存器,在逻辑设计里面用的非常多。它是一种存储器结构,被广泛应用于芯片设计中。FIFO由存储单元队列或阵列构成,第一个被写入队列的数据也是第一个从队列中读出的数据。        FIFO设计可......
  • FPGA MIPI DSI LCD彩条显示
    1MIPI简介MIPI(MobileIndustryProcessorInterface)是一种针对移动设备和嵌入式系统的接口标准,由MIPI联盟制定。其主要目的是提高移动设备之间的通信效率,降低功耗,并支持高速数据传输。MIPI的主要标准包括:MIPIDSI(DisplaySerialInterface):用于连接显示模块,支持高清视......
  • GD32使用PWM+DMA调试WS2812-RGB灯调试记录(附GD32中的TIMER定时器和DMA的踩坑记录)
    一、前言目的:对于使用STM32驱动WS2812-RGB灯,已经有很多大佬进行了分享,同时写得很好!但是对于GD32的调试WS2812确实偏少,刚好最近的项目有用到,顺便记录一下踩过的坑。开源不易,谢谢大家!感谢:特别感谢三位大佬的的博文贡献;1.GD32F470通过DMA输出PWM_gd32pwmdma-CSDN博客2.基于G......