你的位置:EETOP 赛灵思(Xilinx) 社区 >> >> 全部 >> 详细内容

FPGA图像处理系列——RGB转HSV

发布者:jackzhang 时间:2015-11-04 17:13:05

通常来说,记录及显示彩色图像时,RGB是最常见的一种方 案。但是RGB色彩空间注重颜色的合成而将颜色的属性相混合,在某些图像处理中,如果不均匀改变RGB,会改变亮度和饱和度,由此带来的RGB比例改变甚 至会改变色调。HSV(Hue, Saturation, Value)是一种比较直观的颜色模型,它将颜色的亮度、色调和饱和度属性分离,因此采用HSV颜色空间来实现颜色的检测效果会更好。

   RGB色空间和HSV空间之间的转换为非线性的,硬件实现需要考虑时钟同步、算法优化、实时性等问题。本实例通过调用了低延迟的除法器实现Hue分量与Saturation分量的高速计算,从而实现了RGB转换成HSV。

   色彩空间从RGB到HSV的转换公式如下:设(r,g,b)是颜色的红绿蓝坐标,取值范围都是[0,1]。设max为r,g,b中最大值,min为最小值。设色调值h范围[0,360),s,l∈[0,1]分别是饱和度和亮度。




 实现转换操作最重要的是除法运算,本实例调用了一个低延迟的移位减法除法器(延迟时间不到两个像素时钟)来实现高速除法,得到h、s的值。最后要注意保证h,s,v三个分量的延迟都一致。用Verilog实现RGB转HSV的流程如下:

verilog源码如下:

[plain] view plaincopy
  1. module rgb2hsv_top(  
  2. input pclk,  
  3. input [23:0]RGB24,  
  4. output[23:0]HSV24  
  5.     );  
  6. reg [7:0]max,min;  
  7.   
  8. //input rgb  
  9. wire [7:0] Red,Green,Blue;  
  10. reg [7:0]R_reg,G_reg,B_reg;  
  11. assign Red = RGB24[23:16];  
  12. assign Green = RGB24[15:8];  
  13. assign Blue = RGB24[7:0];  
  14.   
  15.   
  16. reg [7:0] Hue,Saturation,Value;  
  17. assign HSV24[23:16] = Hue;  
  18. assign HSV24[15:8] = Saturation;  
  19. assign HSV24[7:0] = Value;  
  20.   
  21.   
  22. always@(posedge pclk)begin   
  23. R_reg <= Red;  
  24. G_reg <= Green;   
  25. B_reg <= Blue;  
  26. end  
  27. /*************find max,min***********/  
  28. always@(posedge pclk)begin  
  29.  if(Red >= Green)  
  30.    begin  
  31.      if(Red >= Blue)  
  32.      max <= Red;  
  33.      else //r<b  
  34.      max <= Blue;  
  35.     end  
  36.  else //r<g  
  37.    begin   
  38.     if(Green >= Blue)  
  39.      max <= Green;  
  40.      else //g<b  
  41.      max <= Blue;  
  42.     end   
  43. end  
  44.   
  45. always@(posedge pclk)begin  
  46.  if(Red <= Green)  
  47.    begin  
  48.      if(Red <= Blue)  
  49.      min <= Red;  
  50.      else //r<b  
  51.      min <= Blue;  
  52.     end  
  53.  else //r>g  
  54.    begin   
  55.     if(Green <= Blue)  
  56.      min <= Green;  
  57.      else //g>b  
  58.      min <= Blue;  
  59.     end   
  60. end  
  61.   
  62. reg [14:0] h_dividend;  
  63. reg [7:0]  h_divisor;  
  64. wire [14:0] h_quotient;  
  65. reg [8:0]  h_add;  
  66. reg [16:0]  s_dividend;  
  67. reg [7:0]  s_divisor;  
  68. wire [16:0]  s_quotient;  
  69. reg [7:0]  v;  
  70. reg sign_flag;  
  71. always@(posedge pclk)begin  
  72.  if(max == min)  
  73.   begin  
  74.    sign_flag <= 0;  
  75.    h_dividend <= 0;  
  76.    h_divisor <= 1;//  
  77.    h_add <= 0;  
  78.    s_dividend <= 0;  
  79.    s_divisor <= 1;  
  80.     v <= max;  
  81.   end  
  82.  else if(max == R_reg && G_reg >= B_reg)  
  83.   begin  
  84.    sign_flag <= 0;  
  85.    h_dividend <= 60 * (G_reg - B_reg);  
  86.     h_divisor <= max - min;  
  87.     h_add <= 0;  
  88.     s_dividend <= 255 * (max - min);  
  89.     s_divisor <= max;   
  90.     v <= max;  
  91.   end  
  92.  else if(max == R_reg && G_reg < B_reg )  
  93.   begin  
  94.    sign_flag <= 1;  
  95.    h_dividend <= 60 * (B_reg - G_reg);  
  96.     h_divisor <= max - min;  
  97.     h_add <= 360;  
  98.     s_dividend <= 255 * (max - min);  
  99.     s_divisor <= max;  
  100.     v <= max;  
  101.   end   
  102.  else if(max == G_reg)  
  103.   begin  
  104.    if(B_reg >= R_reg)  
  105.     begin  
  106.     sign_flag <= 0;  
  107.     h_dividend <= 60 * (B_reg - R_reg);  
  108.     end  
  109.     else  
  110.     begin   
  111.     sign_flag <= 1;  
  112.    h_dividend <= 60 * (R_reg - B_reg);  
  113.     end  
  114.       
  115.     h_divisor <= max - min;  
  116.     h_add <= 120;  
  117.     s_dividend <= 255 * (max - min) ;  
  118.     s_divisor <= max;  
  119.     v <= max;  
  120.   end  
  121.   else if(max == B_reg)  
  122.   begin  
  123.    if(R_reg >= G_reg)  
  124.     begin  
  125.     sign_flag <= 0;  
  126.     h_dividend <= 60 * (R_reg - G_reg);  
  127.     end  
  128.     else  
  129.     begin   
  130.     sign_flag <= 1;  
  131.    h_dividend <= 60 * (G_reg - R_reg);  
  132.     end  
  133.       
  134.     h_divisor <= max - min;  
  135.     h_add <= 240;  
  136.     s_dividend <= 255 * (max - min);  
  137.     s_divisor <= max;  
  138.     v <= max;  
  139.   end  
  140. end  
  141. wire [31:0]yshang_h,yshang_s;  
  142. div_rill u_div_h (  
  143.     .a({17'b0,h_dividend}),   
  144.     .b({24'b0,h_divisor}),   
  145.     .yshang(yshang_h),   
  146.     .yyushu()  
  147. );  
  148. assign h_quotient = yshang_h[14:0];  
  149. div_rill u_div_s (  
  150.     .a({15'b0,s_dividend}),    
  151.     .b({24'b0,s_divisor}),   
  152.     .yshang(yshang_s),   
  153.     .yyushu()  
  154. );    
  155. assign s_quotient = yshang_s[16:0];  
  156.   
  157. always@(posedge pclk)begin  
  158.     if(sign_flag == 0)  
  159.         Hue <= (h_quotient + h_add)/2;  
  160.     else  
  161.         Hue <= (h_add - h_quotient)/2;  
  162.         Saturation <= s_quotient;  
  163.         Value <= v;  
  164. end  
  165.   
  166. endmodule 

最新课程

  • 深入浅出玩儿转FPGA

    本视频基于Xilinx公司的Artix-7FPGA器件以及各种丰富的入门和进阶外设,提供了一些典型的工程实例,帮助读者从FPGA基础知识、逻辑设计概念

  • 从零开始大战FPGA基础篇

    本课程为“从零开始大战FPGA”系列课程的基础篇。课程通俗易懂、逻辑性强、示例丰富,课程中尤其强调在设计过程中对“时序”和“逻辑”的把控,以及硬件描述语言与硬件电路相对应的“

  • Verilog基础及典型数字

    课程中首先会给大家讲解在企业中一般数字电路从算法到流片这整个过程中会涉及到哪些流程,都分别使用什么工具,以及其中每个流程都分别做了