当前位置:   article > 正文

使用 Verilog HDL 在 FPGA 上进行图像处理_去图像坏点 verilog

去图像坏点 verilog

来源:Hack电子

FPGA项目旨在详细展示如何使用Verilog处理图像,从Verilog中读取输入位图图像(.bmp),处理并将处理结果写入Verilog中的输出位图图像。提供了用于读取图像、图像处理和写入图像的完整 Verilog 代码 。

在这个FPGA Verilog项目中,一些简单的处理操作都是在Verilog中实现的,比如反相、亮度控制和阈值操作。图像处理操作由“parameter.v”文件选择,然后将处理后的图像数据写入位图图像 output.bmp 以供验证。所述图像读取Verilog代码作为图像传感器/摄像机的模型的Verilog,它可以是用于在实时的功能验证真正有用的操作FPGA图像处理项目。当您想查看 BMP 格式的输出图像时,图像写入部分对于测试也非常有用。在这个项目中,我在阅读部分添加了一些简单的图像处理代码来制作图像处理的示例,但是您可以轻松地将其删除以获得原始图像数据。学生提出的所有相关问题都在本文底部得到解答。首先,Verilog 不能直接读取图像。要在 Verilog 中读取 .bmp 图像,需要将图像从位图格式转换为十六进制格式。下面是将位图图像转换为 .hex 文件的 Matlab 示例代码。输入图像大小为 768x512,图像 .hex 文件包括位图图像的 R、G、B 数据。

  1. b=imread('kodim24.bmp'); % 24-bit BMP image RGB888 
  2. k=1;
  3. for i=512:-1:1 % image is written from the last row to the first row
  4. for j=1:768
  5. a(k)=b(i,j,1);
  6. a(k+1)=b(i,j,2);
  7. a(k+2)=b(i,j,3);
  8. k=k+3;
  9. end
  10. end
  11. fid = fopen('kodim24.hex''wt');
  12. fprintf(fid, '%x\n', a);
  13. disp('Text file write done');disp(' ');
  14. fclose(fid);

要读取图像十六进制数据文件,Verilog 使用以下命令:或readmemb 如果图像数据在二进制文本文件中。读取图像.hex 文件后,将RGB 图像数据保存到内存中并读出进行处理。

下面是图像读取和处理部分的Verilog代码:

  1. /***************************************************** *****************************/ 
  2. /******************** 模块用于读取和处理图像 **************/ 
  3. /***************************** ****************************************************/ 
  4. /******************************************************************************/
  5. /******************  Module for reading and processing image     **************/
  6. /******************************************************************************/
  7. `include "parameter.v"       // Include definition file
  8. // fpga4student.com: FPGA projects for students
  9. // FPGA project: Image processing in Verilog
  10. module image_read
  11. #(
  12.   parameter     WIDTH  = 768,   // Image width
  13.          HEIGHT  = 512,   // Image height
  14.   INFILE  = "./img/kodim01.hex",  // image file
  15.   START_UP_DELAY = 100, // Delay during start up time
  16.   HSYNC_DELAY = 160,// Delay between HSYNC pulses 
  17.   VALUE= 100, // value for Brightness operation
  18.   THRESHOLD= 90, // Threshold value for Threshold operation
  19.   SIGN=1         // Sign value using for brightness operation
  20.   // SIGN = 0: Brightness subtraction           
  21.   // SIGN = 1: Brightness addition
  22. )
  23. (
  24.   input HCLK,          // clock     
  25.   input HRESETn,         // Reset (active low)
  26.   output VSYNC,        // Vertical synchronous pulse
  27.  // This signal is often a way to indicate that one entire image is transmitted.
  28.  // Just create and is not used, will be used once a video or many images are transmitted.
  29.   output reg HSYNC,        // Horizontal synchronous pulse
  30.  // An HSYNC indicates that one line of the image is transmitted.
  31.  // Used to be a horizontal synchronous signals for writing bmp file.
  32.   output reg [7:0]  DATA_R0,  // 8 bit Red data (even)
  33.   output reg [7:0]  DATA_G0,  // 8 bit Green data (even)
  34.   output reg [7:0]  DATA_B0,  // 8 bit Blue data (even)
  35.   output reg [7:0]  DATA_R1,  // 8 bit Red  data (odd)
  36.   output reg [7:0]  DATA_G1,  // 8 bit Green data (odd)
  37.   output reg [7:0]  DATA_B1,  // 8 bit Blue data (odd)
  38.   // Process and transmit 2 pixels in parallel to make the process faster, you can modify to transmit 1 pixels or more if needed
  39.   output     ctrl_done     // Done flag
  40. );   
  41. //-------------------------------------------------
  42. // Internal Signals
  43. //-------------------------------------------------
  44. parameter sizeOfWidth = 8;   // data width
  45. parameter sizeOfLengthReal = 1179648;   // image data : 1179648 bytes: 512 * 768 *3 
  46. // local parameters for FSM
  47. localparam  ST_IDLE  = 2'b00,// idle state
  48.    ST_VSYNC = 2'b01,// state for creating vsync 
  49.    ST_HSYNC = 2'b10,// state for creating hsync 
  50.    ST_DATA  = 2'b11;// state for data processing 
  51. reg [1:0] cstate,   // current state
  52. nstate;    // next state   
  53. reg start;         // start signal: trigger Finite state machine beginning to operate
  54. reg HRESETn_d;   // delayed reset signal: use to create start signal
  55. reg   ctrl_vsync_run; // control signal for vsync counter  
  56. reg [8:0] ctrl_vsync_cnt; // counter for vsync
  57. reg   ctrl_hsync_run; // control signal for hsync counter
  58. reg [8:0] ctrl_hsync_cnt; // counter  for hsync
  59. reg   ctrl_data_run; // control signal for data processing
  60. reg [7 : 0]   total_memory [0 : sizeOfLengthReal-1];// memory to store  8-bit data image
  61. // temporary memory to save image data : size will be WIDTH*HEIGHT*3
  62. integer temp_BMP   [0 : WIDTH*HEIGHT*3 - 1];   
  63. integer org_R  [0 : WIDTH*HEIGHT - 1];  // temporary storage for R component
  64. integer org_G  [0 : WIDTH*HEIGHT - 1]; // temporary storage for G component
  65. integer org_B  [0 : WIDTH*HEIGHT - 1]; // temporary storage for B component
  66. // counting variables
  67. integer i, j;
  68. // temporary signals for calculation: details in the paper.
  69. integer tempR0,tempR1,tempG0,tempG1,tempB0,tempB1; // temporary variables in contrast and brightness operation
  70. integer value,value1,value2,value4;// temporary variables in invert and threshold operation
  71. reg [ 9:0] row; // row index of the image
  72. reg [10:0] col; // column index of the image
  73. reg [18:0] data_count; // data counting for entire pixels of the image
  74. //-------------------------------------------------//
  75. // -------- Reading data from input file ----------//
  76. //-------------------------------------------------//
  77. initial begin
  78.     $readmemh(INFILE,total_memory,0,sizeOfLengthReal-1); // read file from INFILE
  79. end
  80. // use 3 intermediate signals RGB to save image data
  81. always@(start) begin
  82.     if(start == 1'b1) begin
  83.         for(i=0; i<WIDTH*HEIGHT*3 ; i=i+1) begin
  84.             temp_BMP[i] = total_memory[i+0][7:0]; 
  85.         end
  86.         
  87.         for(i=0; i<HEIGHT; i=i+1) begin
  88.             for(j=0; j<WIDTH; j=j+1) begin
  89.      // Matlab code writes image from the last row to the first row
  90.      // Verilog code does the same in reading to correctly save image pixels into 3 separate RGB mem
  91.                 org_R[WIDTH*i+j] = temp_BMP[WIDTH*3*(HEIGHT-i-1)+3*j+0]; // save Red component
  92.                 org_G[WIDTH*i+j] = temp_BMP[WIDTH*3*(HEIGHT-i-1)+3*j+1];// save Green component
  93.                 org_B[WIDTH*i+j] = temp_BMP[WIDTH*3*(HEIGHT-i-1)+3*j+2];// save Blue component
  94.             end
  95.         end
  96.     end
  97. end
  98. //----------------------------------------------------//
  99. // ---Begin to read image file once reset was high ---//
  100. // ---by creating a starting pulse (start)------------//
  101. //----------------------------------------------------//
  102. always@(posedge HCLK, negedge HRESETn)
  103. begin
  104.     if(!HRESETn) begin
  105.         start <= 0;
  106.   HRESETn_d <= 0;
  107.     end
  108.     else begin           //          ______     
  109.         HRESETn_d <= HRESETn;       //        |  |
  110.   if(HRESETn == 1'b1 && HRESETn_d == 1'b0)  // __0___| 1 |___0____ : starting pulse
  111.    start <= 1'b1;
  112.   else
  113.    start <= 1'b0;
  114.     end
  115. end
  116. //-----------------------------------------------------------------------------------------------//
  117. // Finite state machine for reading RGB888 data from memory and creating hsync and vsync pulses --//
  118. //-----------------------------------------------------------------------------------------------//
  119. always@(posedge HCLK, negedge HRESETn)
  120. begin
  121.     if(~HRESETn) begin
  122.         cstate <= ST_IDLE;
  123.     end
  124.     else begin
  125.         cstate <= nstate; // update next state 
  126.     end
  127. end
  128. //-----------------------------------------//
  129. //--------- State Transition --------------//
  130. //-----------------------------------------//
  131. // IDLE . VSYNC . HSYNC . DATA
  132. always @(*) begin
  133.  case(cstate)
  134.   ST_IDLE: begin
  135.    if(start)
  136.     nstate = ST_VSYNC;
  137.    else
  138.     nstate = ST_IDLE;
  139.   end   
  140.   ST_VSYNC: begin
  141.    if(ctrl_vsync_cnt == START_UP_DELAY) 
  142.     nstate = ST_HSYNC;
  143.    else
  144.     nstate = ST_VSYNC;
  145.   end
  146.   ST_HSYNC: begin
  147.    if(ctrl_hsync_cnt == HSYNC_DELAY) 
  148.     nstate = ST_DATA;
  149.    else
  150.     nstate = ST_HSYNC;
  151.   end  
  152.   ST_DATA: begin
  153.    if(ctrl_done)
  154.     nstate = ST_IDLE;
  155.    else begin
  156.     if(col == WIDTH - 2)
  157.      nstate = ST_HSYNC;
  158.     else
  159.      nstate = ST_DATA;
  160.    end
  161.   end
  162.  endcase
  163. end
  164. // ------------------------------------------------------------------- //
  165. // --- counting for time period of vsync, hsync, data processing ----  //
  166. // ------------------------------------------------------------------- //
  167. always @(*) begin
  168.  ctrl_vsync_run = 0;
  169.  ctrl_hsync_run = 0;
  170.  ctrl_data_run  = 0;
  171.  case(cstate)
  172.   ST_VSYNC:  begin ctrl_vsync_run = 1; end  // trigger counting for vsync
  173.   ST_HSYNC:  begin ctrl_hsync_run = 1; end // trigger counting for hsync
  174.   ST_DATA:  begin ctrl_data_run  = 1; end // trigger counting for data processing
  175.  endcase
  176. end
  177. // counters for vsync, hsync
  178. always@(posedge HCLK, negedge HRESETn)
  179. begin
  180.     if(~HRESETn) begin
  181.         ctrl_vsync_cnt <= 0;
  182.   ctrl_hsync_cnt <= 0;
  183.     end
  184.     else begin
  185.         if(ctrl_vsync_run)
  186.    ctrl_vsync_cnt <= ctrl_vsync_cnt + 1; // counting for vsync
  187.   else 
  188.    ctrl_vsync_cnt <= 0;
  189.    
  190.         if(ctrl_hsync_run)
  191.    ctrl_hsync_cnt <= ctrl_hsync_cnt + 1; // counting for hsync  
  192.   else
  193.    ctrl_hsync_cnt <= 0;
  194.     end
  195. end
  196. // counting column and row index  for reading memory 
  197. always@(posedge HCLK, negedge HRESETn)
  198. begin
  199.     if(~HRESETn) begin
  200.         row <= 0;
  201.   col <= 0;
  202.     end
  203.  else begin
  204.   if(ctrl_data_run) begin
  205.    if(col == WIDTH - 2) begin
  206.     row <= row + 1;
  207.    end
  208.    if(col == WIDTH - 2) 
  209.     col <= 0;
  210.    else 
  211.     col <= col + 2; // reading 2 pixels in parallel
  212.   end
  213.  end
  214. end
  215. //-------------------------------------------------//
  216. //----------------Data counting---------- ---------//
  217. //-------------------------------------------------//
  218. always@(posedge HCLK, negedge HRESETn)
  219. begin
  220.     if(~HRESETn) begin
  221.         data_count <= 0;
  222.     end
  223.     else begin
  224.         if(ctrl_data_run)
  225.    data_count <= data_count + 1;
  226.     end
  227. end
  228. assign VSYNC = ctrl_vsync_run;
  229. assign ctrl_done = (data_count == 196607)? 1'b1: 1'b0; // done flag
  230. //-------------------------------------------------//
  231. //-------------  Image processing   ---------------//
  232. //-------------------------------------------------//
  233. always @(*) begin
  234.  
  235.  HSYNC   = 1'b0;
  236.  DATA_R0 = 0;
  237.  DATA_G0 = 0;
  238.  DATA_B0 = 0;                                       
  239.  DATA_R1 = 0;
  240.  DATA_G1 = 0;
  241.  DATA_B1 = 0;                                         
  242.  if(ctrl_data_run) begin
  243.   
  244.   HSYNC   = 1'b1;
  245.   `ifdef BRIGHTNESS_OPERATION 
  246.   /**************************************/  
  247.   /*  BRIGHTNESS ADDITION OPERATION */
  248.   /**************************************/
  249.   if(SIGN == 1) begin
  250.   // R0
  251.   tempR0 = org_R[WIDTH * row + col   ] + VALUE;
  252.   if (tempR0 > 255)
  253.    DATA_R0 = 255;
  254.   else
  255.    DATA_R0 = org_R[WIDTH * row + col   ] + VALUE;
  256.   // R1 
  257.   tempR1 = org_R[WIDTH * row + col+1   ] + VALUE;
  258.   if (tempR1 > 255)
  259.    DATA_R1 = 255;
  260.   else
  261.    DATA_R1 = org_R[WIDTH * row + col+1   ] + VALUE; 
  262.   // G0 
  263.   tempG0 = org_G[WIDTH * row + col   ] + VALUE;
  264.   if (tempG0 > 255)
  265.    DATA_G0 = 255;
  266.   else
  267.    DATA_G0 = org_G[WIDTH * row + col   ] + VALUE;
  268.   tempG1 = org_G[WIDTH * row + col+1   ] + VALUE;
  269.   if (tempG1 > 255)
  270.    DATA_G1 = 255;
  271.   else
  272.    DATA_G1 = org_G[WIDTH * row + col+1   ] + VALUE;  
  273.   // B
  274.   tempB0 = org_B[WIDTH * row + col   ] + VALUE;
  275.   if (tempB0 > 255)
  276.    DATA_B0 = 255;
  277.   else
  278.    DATA_B0 = org_B[WIDTH * row + col   ] + VALUE;
  279.   tempB1 = org_B[WIDTH * row + col+1   ] + VALUE;
  280.   if (tempB1 > 255)
  281.    DATA_B1 = 255;
  282.   else
  283.    DATA_B1 = org_B[WIDTH * row + col+1   ] + VALUE;
  284.  end
  285.  else begin
  286.  /**************************************/  
  287.  /* BRIGHTNESS SUBTRACTION OPERATION */
  288.  /**************************************/
  289.   // R0
  290.   tempR0 = org_R[WIDTH * row + col   ] - VALUE;
  291.   if (tempR0 < 0)
  292.    DATA_R0 = 0;
  293.   else
  294.    DATA_R0 = org_R[WIDTH * row + col   ] - VALUE;
  295.   // R1 
  296.   tempR1 = org_R[WIDTH * row + col+1   ] - VALUE;
  297.   if (tempR1 < 0)
  298.    DATA_R1 = 0;
  299.   else
  300.    DATA_R1 = org_R[WIDTH * row + col+1   ] - VALUE; 
  301.   // G0 
  302.   tempG0 = org_G[WIDTH * row + col   ] - VALUE;
  303.   if (tempG0 < 0)
  304.    DATA_G0 = 0;
  305.   else
  306.    DATA_G0 = org_G[WIDTH * row + col   ] - VALUE;
  307.   tempG1 = org_G[WIDTH * row + col+1   ] - VALUE;
  308.   if (tempG1 < 0)
  309.    DATA_G1 = 0;
  310.   else
  311.    DATA_G1 = org_G[WIDTH * row + col+1   ] - VALUE;  
  312.   // B
  313.   tempB0 = org_B[WIDTH * row + col   ] - VALUE;
  314.   if (tempB0 < 0)
  315.    DATA_B0 = 0;
  316.   else
  317.    DATA_B0 = org_B[WIDTH * row + col   ] - VALUE;
  318.   tempB1 = org_B[WIDTH * row + col+1   ] - VALUE;
  319.   if (tempB1 < 0)
  320.    DATA_B1 = 0;
  321.   else
  322.    DATA_B1 = org_B[WIDTH * row + col+1   ] - VALUE;
  323.   end
  324.   `endif
  325.          /**************************************/  
  326.   /*  INVERT_OPERATION       */
  327.   /**************************************/
  328.   `ifdef INVERT_OPERATION 
  329.    value2 = (org_B[WIDTH * row + col  ] + org_R[WIDTH * row + col  ] +org_G[WIDTH * row + col  ])/3;
  330.    DATA_R0=255-value2;
  331.    DATA_G0=255-value2;
  332.    DATA_B0=255-value2;
  333.    value4 = (org_B[WIDTH * row + col+1  ] + org_R[WIDTH * row + col+1  ] +org_G[WIDTH * row + col+1  ])/3;
  334.    DATA_R1=255-value4;
  335.    DATA_G1=255-value4;
  336.    DATA_B1=255-value4;  
  337.   `endif
  338.   /**************************************/  
  339.   /********THRESHOLD OPERATION  *********/
  340.   /**************************************/
  341.   `ifdef THRESHOLD_OPERATION
  342.   value = (org_R[WIDTH * row + col   ]+org_G[WIDTH * row + col   ]+org_B[WIDTH * row + col   ])/3;
  343.   if(value > THRESHOLD) begin
  344.    DATA_R0=255;
  345.    DATA_G0=255;
  346.    DATA_B0=255;
  347.   end
  348.   else begin
  349.    DATA_R0=0;
  350.    DATA_G0=0;
  351.    DATA_B0=0;
  352.   end
  353.   value1 = (org_R[WIDTH * row + col+1   ]+org_G[WIDTH * row + col+1   ]+org_B[WIDTH * row + col+1   ])/3;
  354.   if(value1 > THRESHOLD) begin
  355.    DATA_R1=255;
  356.    DATA_G1=255;
  357.    DATA_B1=255;
  358.   end
  359.   else begin
  360.    DATA_R1=0;
  361.    DATA_G1=0;
  362.    DATA_B1=0;
  363.   end  
  364.   `endif
  365.  end
  366. end
  367. endmodule

“parameter.v”文件也是定义输入输出文件的路径和名称。对图像进行处理后,需要将处理后的数据写入输出图像进行验证。

以下Verilog代码是将处理后的图像数据写入位图图像进行验证:

  1. /******************** 写入.bmp图像的模块************/  
  2. /********** ****************************************************/  
  3. module image_write #(parameter 
  4. WIDTH = 768// Image width 
  5. HEIGHT = 512// Image height 
  6. INFILE = "output.bmp"// Output image 
  7. BMP_HEADER_NUM = 54 // Header for bmp image 
  8. input HCLK, // Clock input 
  9. HRESETn, // Reset active low 
  10. input hsync, // Hsync pulse 
  11. input [7:0] DATA_WRITE_R0, // Red 8-bit data (odd) 
  12. input [7:0] DATA_WRITE_G0, // Green 8-bit data (odd) 
  13. input [7:0] DATA_WRITE_B0, // Blue 8-bit data (odd) 
  14. input [7:0] DATA_WRITE_R1, // Red 8-bit data (even) 
  15. input [7:0] DATA_WRITE_G1, // Green 8-bit data (even) 
  16. input [7:0] DATA_WRITE_B1, // Blue 8-bit data (even) 
  17. output reg Write_Done 
  18. ); 
  19. // fpga4student.com FPGA projects, Verilog projects, VHDL projects
  20. //-----------------------------------// 
  21. //-------Header data for bmp image-----// 
  22. //-------------------------------------// 
  23. // Windows BMP files begin with a 54-byte header
  24. initial  begin 
  25. BMP_header[ 0] = 66;BMP_header[28] =24
  26. BMP_header[ 1] = 77;BMP_header[29] = 0
  27. BMP_header[ 2] = 54;BMP_header[30] = 0
  28. BMP_header[ 3] = 0;BMP_header[31] = 0;
  29. BMP_header[ 4] = 18;BMP_header[32] = 0;
  30. BMP_header[ 5] = 0;BMP_header[33] = 0
  31. BMP_header[ 6] = 0;BMP_header[34] = 0
  32. BMP_header[ 7] = 0;BMP_header[35] = 0
  33. BMP_header[ 8] = 0;BMP_header[36] = 0
  34. BMP_header[ 9] = 0;BMP_header[37] = 0
  35. BMP_header[10] = 54;BMP_header[38] = 0
  36. BMP_header[11] = 0;BMP_header[39] = 0
  37. BMP_header[12] = 0;BMP_header[40] = 0
  38. BMP_header[13] = 0;BMP_header[41] = 0
  39. BMP_header[14] = 40;BMP_header[42] = 0
  40. BMP_header[15] = 0;BMP_header[43] = 0
  41. BMP_header[16] = 0;BMP_header[44] = 0
  42. BMP_header[17] = 0;BMP_header[45] = 0
  43. BMP_header[18] = 0;BMP_header[46] = 0
  44. BMP_header[19] = 3;BMP_header[47] = 0;
  45. BMP_header[20] = 0;BMP_header[48] = 0;
  46. BMP_header[21] = 0;BMP_header[49] = 0
  47. BMP_header[22] = 0;BMP_header[50] = 0
  48. BMP_header[23] = 2;BMP_header[51] = 0
  49. BMP_header[24] = 0;BMP_header[52] = 0
  50. BMP_header[25] = 0;BMP_header[53] = 0
  51. BMP_header[26] = 1; BMP_header[27] = 0
  52. end
  53. //---------------------------------------------------------//
  54. //--------------Write .bmp file  ----------------------//
  55. //----------------------------------------------------------//
  56. initial begin
  57.     fd = $fopen(INFILE, "wb+");
  58. end
  59. always@(Write_Done) begin // once the processing was done, bmp image will be created
  60.     if(Write_Done == 1'b1) begin
  61.         for(i=0; i<BMP_HEADER_NUM; i=i+1) begin
  62.             $fwrite(fd, "%c", BMP_header[i][7:0]); // write the header
  63.         end
  64.         
  65.         for(i=0; i<WIDTH*HEIGHT*3; i=i+6) begin
  66.   // write R0B0G0 and R1B1G1 (6 bytes) in a loop
  67.             $fwrite(fd, "%c", out_BMP[i  ][7:0]);
  68.             $fwrite(fd, "%c", out_BMP[i+1][7:0]);
  69.             $fwrite(fd, "%c", out_BMP[i+2][7:0]);
  70.             $fwrite(fd, "%c", out_BMP[i+3][7:0]);
  71.             $fwrite(fd, "%c", out_BMP[i+4][7:0]);
  72.             $fwrite(fd, "%c", out_BMP[i+5][7:0]);
  73.         end
  74.     end
  75. end

位图图像的标头数据非常重要,在这里发布。如果没有标题数据,则无法正确显示写入的图像。在 Verilog HDL 中,$fwrite 命令用于将数据写入文件。

接下来,让我们编写一个测试平台 Verilog 代码来验证图像处理操作。

  1. `timescale 1ns/1ps /**************************************************/ 
  2. /******* Testbench for simulation ****************/
  3. /*********************************************/ 
  4.  // fpga4student.com FPGA projects, Verilog projects, VHDL projects
  5. // Verilog project: Image processing in Verilog
  6. `include "parameter.v" // include definition file module tb_simulation; 
  7. //------------------ // Internal Signals 
  8. //------------------------------------------------- 
  9. reg HCLK, HRESETn; 
  10. wire vsync; 
  11. wire hsync;
  12. wire [ 7 : 0] data_R0; 
  13. wire [ 7 : 0] data_G0; 
  14. wire [ 7 : 0] data_B0; 
  15. wire [ 7 : 0] data_R1; 
  16. wire [ 7 : 0] data_G1; 
  17. wire [ 7 : 0] data_B1; 
  18. wire enc_done; 
  19. image_read #(.INFILE(`INPUTFILENAME)) 
  20. u_image_read 
  21. ( .HCLK (HCLK ), 
  22. .HRESETn (HRESETn ),
  23.  .VSYNC (vsync ), 
  24. .HSYNC (hsync ), 
  25. .DATA_R0 (data_R0 ),
  26.  .DATA_G0 (data_G0 ), 
  27. .DATA_B0 (data_B0 ), 
  28. .DATA_R1 (data_R1 ), 
  29. .DATA_G1 (data_G1 ), 
  30. .DATA_B1 (data_B1 ), 
  31. .ctrl_done (enc_done) 
  32. ); 
  33. image_write #(.INFILE(`OUTPUTFILENAME)) 
  34. u_image_write ( 
  35. .HCLK(HCLK), 
  36. .HRESETn(HRESETn),
  37.  .hsync(hsync), 
  38. .DATA_WRITE_R0(data_R0),
  39.  .DATA_WRITE_G0(data_G0),
  40.  .DATA_WRITE_B0(data_B0), 
  41. .DATA_WRITE_R1(data_R1), 
  42. .DATA_WRITE_G1(data_G1), 
  43. .DATA_WRITE_B1(data_B1),
  44.  .Write_Done()
  45.  ); 
  46. //------------- // Test Vectors 
  47. //------------------------------------- 
  48. initial 
  49. begin 
  50. HCLK = 0
  51. forever #10 HCLK = ~HCLK; 
  52. end 
  53. initial 
  54. begin 
  55. HRESETn = 0
  56. #25 HRESETn = 1
  57. end endmodule

最后,我们拥有一切来运行模拟来验证图像处理代码。让我们使用下图作为输入位图文件:

运行仿真 6ms,关闭仿真并打开输出图像以检查结果。以下是参数.v中选定操作处理的输出图像:

反转后输出位图图像

阈值操作后输出位图图像

减去亮度后输出位图图像

由于读取代码是为了模拟目的而对图像传感器/相机进行建模,因此建议不要合成代码。如果你真的想综合处理代码并直接在FPGA上运行,你需要将代码中的这些图像数组(total_memory、temp_BMP、org_R、org_B、org_G)替换为块存储器(RAM)和设计地址生成器来读取图像块内存中的数据。

问题的答案:

  1. 此图像处理项目的完整 Verilog 代码可在此处下载。运行模拟大约 6ms 并关闭模拟,然后您将能够看到输出图像。

https://github.com/suisuisi/FPGAandImage/blob/main/Image/012_Others/Verilog_Image_Processing.zip

  1. 读取部分作为图像传感器/相机的 Verilog 模型运行(输出 RGB 数据、HSYNC、VSYNC、HCLK)。Verilog 图像读取代码对于实时 FPGA 图像/视频项目中的功能验证非常有用。

3.在这个项目中,我添加了图像处理部分,做一个图像增强的例子。如果您只想使用图像传感器模型来验证您的图像处理设计,您可以轻松移除处理部分以仅获取原始图像数据。

4.图像保存到三个独立的RGB mem中:由于Matlab代码是将图像16进制文件从最后一行写到第一行,所以RGB保存代码(org_R, org_B, org_G)在读取temp_BMP内存时也是这样做的,保存RGB数据正确。如果您想以不同的方式进行,您可以相应地更改它。

  1. 如果您想更改图像大小,您可能会发现以下对 BMP 标题的解释很有用:

  1. 图像大小 = 768*512*31179648 字节
  2. BMP 标题 = 54 字节
  3. BMP 文件大小 = 图像大小 + BMP 标题 = 1179702 字节 
  4. 将其转换为十六进制数:1179702 in Decimal = 120036 in Hexade
  5. 然后 BMP 文件的 4 字节大小:00H, 12 in Hexa = 18 Decimal, 00H, 36 in Hexa = 54 Decimal
  6. 这就是我们如何得到以下值:
  7. BMP_header[2] = 54;
  8. BMP_header[3] = 0;
  9. BMP_header[4] = 18;
  10. BMP_header[5] = 0;
  11. 图像宽度 = 768 => 十六进制:0x0300。图像宽度的 4 个字节是
  12. 0300。这就是您获得以下值的方式:BMP_header[18] = 0;
  13. BMP_header[19] = 3;
  14. BMP_header[20] = 0;
  15. BMP_header[21] = 0
  16. 图像高度 = 512 => 十六进制:0x0200。图像宽度的 4 个字节是 0, 2, 0, 0。这就是我们如何得到以下值:
  17. BMP_header[22] = 0;
  18. BMP_header[23] = 2;
  19. BMP_header[24] = 0;
  20. BMP_header[25] = 0;
  1. 您不应综合此代码,因为它不是为在 FPGA 上运行而设计的,而是用于功能验证目的. 如果你真的想合成这段代码(读取和处理)并将图像加载到 FPGA中直接在 FPGA 上处理,请将所有 temp. 变量 (org_R, org_B, org_G, tmp_BMP = total_memory) 并生成地址以读取图像数据(删除 always @(start) 和所有“for 循环” - 这些用于模拟目的)。有两种方式:1. 写一段RAM代码,用$readmemh将图像数据初始化到内存中;2. 使用 Xilinx Core Generator 或 Altera MegaFunction 生成块存储器并将图像数据加载到存储器的初始值(Xilinx Core Gen. 为 .coe 文件,Altera MegaFunction 为 .mif 文件),然后从存储器中读取图像数据并处理它(FSM 设计)。

  2. 在这个项目中,为了加快处理速度,同时读取两个偶数和旧像素,但您可以根据您的设计更改正在读取的像素数。

  3. 编写Verilog代码对于测试目的也非常有帮助,因为您可以看到BMP 格式的输出。

9.如果要做实时图像处理,可以查看camera接口代码这个:https://www.fpga4student.com/2018/08/basys-3-fpga-ov7670-camera.html

参考:https://www.fpga4student.com/2016/11/image-processing-on-fpga-verilog.html

NOW

学习Xilinx FPGA最好的资料其实就是官方手册,下表总结了部分手册的主要介绍内容,关注我,持续更新中......

文件名主标题内容简单介绍是否有中文版
UG4767 Series FPGAs GTX/GTH  TransceiversGTX和GTH介绍,PCIe、serdes等学习必备
UG4717 Series FPGAs SelectIO Resources描述 7 系列 FPGA 中可用的 SelectIO资源。
UG1114PetaLinux Tools DocumentatonPetaLinux 工具文档 参考指南是,V2019.2
UG949UltraFAST 设计方法指南(适用于 Vivado  Design Suite)赛灵思® UltraFast™  设计方法是用于为当今器件优化设计进程的一套最佳实践。这些设计的规模与复杂性需要执行特定的步骤与设计任务,从而确保设计每一个阶段的成功开展。依照这些步骤,并遵循最佳实践,将帮助您以最快的速度和最高的效率实现期望的设计目标是,V2018.1
IP手册pg057FIFO GeneratorFIFO生成器IP使用手册
pg104Complex Multiplier复数乘法器IP使用手册
pg122RAM-Based Shift Register 移位寄存器IP使用手册

推荐阅读

【Vivado那些事】如何查找官网例程及如何使用官网例程

【Vivado使用误区与进阶】总结篇

【Vivado那些事】Vivado中常用的快捷键(二)其他常用快捷键

SystemVerilog数字系统设计_夏宇闻 PDF

图书推荐|ARM Cortex-M0 全可编程SoC原理及实现

简谈:如何学习FPGA

1202年了,还在使用虚拟机吗?Win10安装Ubuntu子系统及图形化界面详细教程

Github 上有哪些优秀的 VHDL/Verilog/FPGA 项目

AD936x+ZYNQ搭建收音机(一)

AD936x+ZYNQ搭建OpenWIFI

无招胜有招-Vivado非工程模式下的详细设计

追寻ARM的起源-Acorn电脑简史及FPGA实现

面试中经常会遇到的FPGA基本概念,你会几个?

Xilinx FPGA MIPI 接口简单说明

介绍一些新手入门FPGA的优秀网站

Vivado ML(机器学习) 2021尝鲜

推荐一些可以获取免费的国外的原版书籍(电子版)网站

【Vivado那些事】FPGA的配置方式

FPGA 的重构

浅析FPGA局部动态可重构技术

ISP(图像信号处理)算法概述、工作原理、架构、处理流程

国产CPU概括

从电子游戏历史看IC发展的助推剂

80年代电子游戏及电脑游戏的发展历史

PCIe总线的基础知识

万字长文带你回顾电子游戏的七十多年历史(完整版)

FPGA中异步复位,同步释放的理解

OpenFPGA系列文章总结

用Verilog设计一个16 位 RISC 处理器

介绍一些新手入门FPGA的优秀网站(新增)

Verilog数字系统基础设计-CRC

FPGA 的布局规划艺术

Verilog数字系统基础设计-奇偶校验

建立和保持时间及时序简单理解

(Xilinx)FPGA中LVDS差分高速传输的实现

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/321412
推荐阅读
相关标签
  

闽ICP备14008679号