当前位置:   article > 正文

基于FPGA的自动白平衡算法的实现

fpga白平衡算法

基于FPGA自动白平衡算法的实现

1 白平衡介绍

    对于白平衡基本概念的详细介绍请查看文章《白平衡初探》,白平衡算法主要的作用是将偏暖或者偏冷的色调自动恢复到正常色调,是图像看起来更加色彩饱满正常。

      如上图所示,左1色温偏冷,中间色温正常,右一色温偏暖。上图比较直观的展示了色温的概念。偏冷的色温会给人一种还冷的感觉,偏暖的色温会给人一种温暖的感觉。

2 白平衡算法以及matlab实现

   1)原始的灰度世界算法 

 

灰度世界算法(Gray World)是以灰度世界假设为基础的,该假设认为对于一幅有着大量色彩变化的图像, R、 G、 B 三个分量的平均值趋于同一个灰度K。一般有两种方法来确定该灰度。

(1)直接给定为固定值, 取其各通道最大值的一半,即取为127或128;

(2)令 K = (Raver+Gaver+Baver)/3,其中Raver,Gaver,Baver分别表示红、 绿、 蓝三个通道的平均值。

算法的第二步是分别计算各通道的增益:

    Kr=K/Raver;

    Kg=K/Gaver;

    Kb=K/Baver; 

算法第三步为根据Von Kries 对角模型,对于图像中的每个像素R、G、B,计算其结果值:

    Rnew = R * Kr; 

    Gnew = G * Kg; 

    Bnew = B * Kb; 

 对于上式,计算中可能会存在溢出(>255,不会出现小于0的)现象,处理方式有两种。

     a、 直接将像素设置为255,这可能会造成图像整体偏白。

    b、 计算所有Rnew、Gnew、Bnew的最大值,然后利用该最大值将将计算后数据重新线性映射到[0,255]内。实践证明这种方式将会使图像整体偏暗,建议采用第一种方案。

2)完美反射算法

原理:完美全反射理论perfect Reflector假设图像上最亮点就是白点,并以此白点为参考对图像进行自动白平衡,最亮点定义为R+G+B的最大值,具体编码步骤如下: 

(1)计算每个像素的R\G\B之和,并保存到一临时内存块中。

(2)按R+G+B值的大小计算出其前10%或其他Ratio的白色参考点的的阈值T。

(3)遍历图像中的每个点,计算其中R+G+B值大于T的所有点的R\G\B分量的累积和的平均值。

(4)对每个点将像素量化到[0,255]之间。

3)动态阈值法

(1).  把图像w*h从RGB空间转换到YCrCb空间。

(2).  选择参考白色点:

  a. 把图像分成宽高比为4:3个块(块数可选)。

  b. 对每个块,分别计算Cr,Cb的平均值Mr,Mb。

  c. 对每个块,根据Mr,Mb,用下面公式分别计算Cr,Cb的方差Dr,Db。

  d. 判定每个块的近白区域(near-white region)。

判别表达式为:

设一个“参考白色点”的亮度矩阵RL,大小为w*h。

若符合判别式,则作为“参考白色点”,并把该点(i,j)的亮度(Y分量)值赋给RL(i,j);

 若不符合,则该点的RL(i,j)值为0。

(3).  选取参考“参考白色点”中最大的10%的亮度(Y分量)值,并选取其中的最小值Lu_min.

(4).  调整RL,若RL(i,j)<Lu_min,  RL(i,j)=0; 否则,RL(i,j)=1;

(5). 分别把R,G,B与RL相乘,得到R2,G2,B2。 分别计算R2,G2,B2的平均值,Rav,Gav,Bav;

(6).  得到调整增益:

    Ymax=double(max(max(Y)))/5;

    Rgain=Ymax/Rav;

    Ggain=Ymax/Gav;

    Bgain=Ymax/Bav;

(7).  调整原图像:

   Ro= R*Rgain; 

   Go= G*Ggain; 

   Bo= B*Bgain;

FPGA的实现采用灰度世界算法。

Matlab代码:

  1. close all
  2. clear all
  3. clc
  4. I=imread('test1.jpg');
  5. [H,W,L]=size(I);%得到图像长宽高
  6. Rsum = 0;
  7. Gsum = 0;
  8. Bsum = 0;
  9. Rsum = double(Rsum);
  10. Gsum = double(Gsum);
  11. Bsum = double(Bsum);
  12. for i = 1 : H
  13. for j = 1 :W
  14. Rsum = Rsum + double(I(i,j,1));
  15. Gsum = Gsum + double(I(i,j,2));
  16. Bsum = Bsum + double(I(i,j,3));
  17. end
  18. end
  19. Raver = Rsum / (H*W);
  20. Gaver = Gsum / (H*W);
  21. Baver = Bsum / (H*W);
  22. %K=128;%第一种K取值方法
  23. K = (Raver+Gaver+Baver)/3;%第二种方法
  24. Rgain = K / Raver;
  25. Ggain = K / Gaver;
  26. Bgain = K / Baver;
  27. Iwb(:,:,1) = I(:,:,1) * Rgain;
  28. Iwb(:,:,2) = I(:,:,2) * Ggain;
  29. Iwb(:,:,3) = I(:,:,3) * Bgain;
  30. imwrite(Iwb,'Result1.jpg');
  31. figure(1),
  32. subplot(121),imshow(I),title('原始图像');
  33. subplot(122),imshow(Iwb),title('自动白平衡图像');

效果展示:

3 FPGA实现自动白平衡灰度世界法

灰度世界法Verilog代码:

  1. /**********************************
  2. copyright@FPGA OPEN SOURCE STUDIO
  3. 微信公众号:FPGA开源工作室
  4. Algorithm:Auto White balance
  5. Gray World
  6. 800X600X255=480000
  7. ***********************************/
  8. `define XLEN 32
  9. `define N(n) [(n)-1:0]
  10. module White_balance#(
  11. parameter DW = 24
  12. )(
  13. input pixelclk,
  14. input reset_n,
  15. input [DW-1:0] din, //rgb in
  16. input i_hsync,
  17. input i_vsync,
  18. input i_de,
  19. output [DW-1:0] dout, //gray out
  20. output o_hsync,
  21. output o_vsync,
  22. output o_de
  23. );
  24. localparam STAGE_LIST = 32'h0101_0101;//32'b00000000_00000000_00000000_00000000;
  25. localparam divisor = 32'h0007_5300;//800*600
  26. localparam divisorK = 32'h0000_0003;//800*600
  27. wire [7:0] R,G,B;
  28. reg [27:0] sumr,sumg,sumb;
  29. reg [27:0] sumr_r,sumg_r,sumb_r;
  30. wire [9:0] Kave;
  31. wire [7:0] K;
  32. wire Rack;
  33. wire `N(`XLEN) Rquo,Rrem;
  34. wire Gack;
  35. wire `N(`XLEN) Gquo,Grem;
  36. wire Back;
  37. wire `N(`XLEN) Bquo,Brem;
  38. wire Kack;
  39. wire `N(`XLEN) Kquo,Krem;
  40. wire GRack;
  41. wire `N(`XLEN) GRquo,GRrem;
  42. wire GGack;
  43. wire `N(`XLEN) GGquo,GGrem;
  44. wire GBack;
  45. wire `N(`XLEN) GBquo,GBrem;
  46. reg [39:0] R_r,G_r,B_r;
  47. wire [7:0] RO,GO,BO;
  48. reg hsync_r1;
  49. reg vsync_r1;
  50. reg de_r1;
  51. reg i_vsync_r;
  52. reg vsync_neg_r;
  53. wire vsync_neg=(i_vsync_r&(~i_vsync));
  54. assign Kave=(Rquo+Gquo+Bquo);
  55. assign K=Kquo[7:0];
  56. assign R=din[23:16];
  57. assign G=din[15:8];
  58. assign B=din[7:0];
  59. assign o_hsync = hsync_r1;
  60. assign o_vsync = vsync_r1;
  61. assign o_de = de_r1;
  62. assign RO=(R_r[18:10]>255)?255:R_r[17:10];
  63. assign GO=(G_r[18:10]>255)?255:G_r[17:10];
  64. assign BO=(B_r[18:10]>255)?255:B_r[17:10];
  65. assign dout={RO,GO,BO};
  66. //synchronization
  67. always @(posedge pixelclk) begin
  68. hsync_r1 <= i_hsync;
  69. vsync_r1 <= i_vsync;
  70. de_r1 <= i_de;
  71. end
  72. always @(posedge pixelclk or negedge reset_n)begin
  73. if(!reset_n)begin
  74. sumr<=28'd0;< span="">
  75. sumg<=28'd0;< span="">
  76. sumb<=28'd0;< span="">
  77. sumr_r<=28'd0;< span="">
  78. sumg_r<=28'd0;< span="">
  79. sumb_r<=28'd0;< span="">
  80. i_vsync_r<=1'b0;< span="">
  81. vsync_neg_r<=1'b0;< span="">
  82. R_r<=40'b0;< span="">
  83. G_r<=40'b0;< span="">
  84. B_r<=40'b0;< span="">
  85. end
  86. else begin
  87. i_vsync_r<=i_vsync;< span="">
  88. vsync_neg_r<=vsync_neg;< span="">
  89. R_r<=r*grquo;< span="">
  90. G_r<=g*ggquo;< span="">
  91. B_r<=b*gbquo;< span="">
  92. if(vsync_neg==1'b1) begin
  93. sumr_r<=sumr;< span="">
  94. sumg_r<=sumg;< span="">
  95. sumb_r<=sumb;< span="">
  96. end
  97. if(i_vsync==1'b1) begin
  98. if(i_de==1'b1) begin
  99. sumr<=sumr+r;< span="">
  100. sumg<=sumg+g;< span="">
  101. sumb<=sumb+b;< span="">
  102. end
  103. else begin
  104. sumr<=sumr;< span="">
  105. sumg<=sumg;< span="">
  106. sumb<=sumb;< span="">
  107. end
  108. end
  109. else begin
  110. sumr<=28'd0;< span="">
  111. sumg<=28'd0;< span="">
  112. sumb<=28'd0;< span="">
  113. end
  114. end
  115. end
  116. //Rave
  117. divfunc
  118. #(
  119. .XLEN ( `XLEN ),
  120. .STAGE_LIST ( STAGE_LIST )
  121. ) i_divR (
  122. .clk ( pixelclk ),
  123. .rst ( ~reset_n ),
  124. .a ( {4'b0,sumr_r} ),
  125. .b ( divisor ),
  126. .vld ( vsync_neg_r ),
  127. .quo ( Rquo ),
  128. .rem ( Rrem ),
  129. .ack ( Rack )
  130. );
  131. //Gave
  132. divfunc
  133. #(
  134. .XLEN ( `XLEN ),
  135. .STAGE_LIST ( STAGE_LIST )
  136. ) i_divG (
  137. .clk ( pixelclk ),
  138. .rst ( ~reset_n ),
  139. .a ( {4'b0,sumg_r} ),
  140. .b ( divisor ),
  141. .vld ( vsync_neg_r ),
  142. .quo ( Gquo ),
  143. .rem ( Grem ),
  144. .ack ( Gack )
  145. );
  146. //Bave
  147. divfunc
  148. #(
  149. .XLEN ( `XLEN ),
  150. .STAGE_LIST ( STAGE_LIST )
  151. ) i_divB (
  152. .clk ( pixelclk ),
  153. .rst ( ~reset_n ),
  154. .a ( {4'b0,sumb_r} ),
  155. .b ( divisor ),
  156. .vld ( vsync_neg_r ),
  157. .quo ( Bquo ),
  158. .rem ( Brem ),
  159. .ack ( Back )
  160. );
  161. //K
  162. divfunc
  163. #(
  164. .XLEN ( `XLEN ),
  165. .STAGE_LIST ( STAGE_LIST )
  166. ) i_divK (
  167. .clk ( pixelclk ),
  168. .rst ( ~reset_n ),
  169. .a ( {22'b0,Kave} ),
  170. .b ( divisorK ),
  171. .vld ( Back ),
  172. .quo ( Kquo ),
  173. .rem ( Krem ),
  174. .ack ( Kack )
  175. );
  176. //RGain
  177. divfunc
  178. #(
  179. .XLEN ( `XLEN ),
  180. .STAGE_LIST ( STAGE_LIST )
  181. ) i_divGR (
  182. .clk ( pixelclk ),
  183. .rst ( ~reset_n ),
  184. .a ( {14'b0,K,10'b0} ),
  185. .b ( Rquo ),
  186. .vld ( Kack ),
  187. .quo ( GRquo ),
  188. .rem ( GRrem ),
  189. .ack ( GRack )
  190. );
  191. //GGain
  192. divfunc
  193. #(
  194. .XLEN ( `XLEN ),
  195. .STAGE_LIST ( STAGE_LIST )
  196. ) i_divGG (
  197. .clk ( pixelclk ),
  198. .rst ( ~reset_n ),
  199. .a ( {14'b0,K,10'b0} ),
  200. .b ( Gquo ),
  201. .vld ( Kack ),
  202. .quo ( GGquo ),
  203. .rem ( GGrem ),
  204. .ack ( GGack )
  205. );
  206. //BGAIN
  207. divfunc
  208. #(
  209. .XLEN ( `XLEN ),
  210. .STAGE_LIST ( STAGE_LIST )
  211. ) i_divGB (
  212. .clk ( pixelclk ),
  213. .rst ( ~reset_n ),
  214. .a ( {14'b0,K,10'b0} ),
  215. .b ( Bquo ),
  216. .vld ( Kack ),
  217. .quo ( GBquo ),
  218. .rem ( GBrem ),
  219. .ack ( GBack )
  220. );
  221. endmodule

1)仿真效果

原始图像

经过灰度世界法的白平衡仿真效果

2)下板验证模型以及实现效果

下板验证图像由笔记本电脑通过HDMI输入到FPGA芯片,经过FPGA算法处理后在通过HDMI将图像送到显示屏展示处理效果。

笔记本电脑显示图片

经过FPGA处理后的显示效果


视频效果

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

闽ICP备14008679号