Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
bebop_ae_awb.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) Freek van Tienen
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
26 #include "bebop_ae_awb.h"
27 #include "boards/bebop.h"
28 #include "boards/bebop/mt9f002.h"
29 #include "lib/isp/libisp.h"
30 
31 #define MAX_HIST_Y 255
32 
33 #define sgn(x) (float)((x < 0) ? -1 : (x > 0))
34 
35 #ifndef BEBOP_AUTO_EXPOSURE
36 #define BEBOP_AUTO_EXPOSURE true
37 #endif
38 
39 #ifndef BEBOP_AUTO_WHITE_BALANCE
40 #define BEBOP_AUTO_WHITE_BALANCE true
41 #endif
42 
43 #define BEBOP_AWB_MIN_GAIN 2
44 #define BEBOP_AWB_MAX_GAIN 75
45 
46 void bebop_ae_awb_init(void) {}
47 
49 {
50  struct isp_yuv_stats_t yuv_stats;
51 
52  if (isp_get_statistics_yuv(&yuv_stats) == 0) {
53 #if BEBOP_AUTO_EXPOSURE
54  // Calculate the CDF based on the histogram
55  uint32_t cdf[MAX_HIST_Y];
56  cdf[0] = yuv_stats.ae_histogram_Y[0];
57  for (int i = 1; i < MAX_HIST_Y; i++) {
58  cdf[i] = cdf[i - 1] + yuv_stats.ae_histogram_Y[i];
59  }
60 
61  // Calculate bright and saturated pixels
62  uint32_t bright_pixels = cdf[MAX_HIST_Y - 1] - cdf[MAX_HIST_Y - 26]; // Top 25 bins
63  uint32_t saturated_pixels = cdf[MAX_HIST_Y - 1] - cdf[MAX_HIST_Y - 6]; // top 5 bins
64  uint32_t target_bright_pixels = yuv_stats.nb_valid_Y / 20; // 5%
65  uint32_t max_saturated_pixels = yuv_stats.nb_valid_Y / 100; // 1%
66  float adjustment = 1.0f;
67 
68  if (saturated_pixels + max_saturated_pixels / 10 > max_saturated_pixels) {
69  // Fix saturated pixels
70  adjustment = 1.0f - (float)saturated_pixels / yuv_stats.nb_valid_Y;
71  adjustment *= adjustment * adjustment; // speed up
72  } else if (bright_pixels + target_bright_pixels / 10 < target_bright_pixels) {
73  // increase brightness to try and hit the desired number of well exposed pixels
74  int l = MAX_HIST_Y - 1;
75  while (bright_pixels < target_bright_pixels && l > 0) {
76  bright_pixels += cdf[l];
77  bright_pixels -= cdf[l - 1];
78  l--;
79  }
80 
81  adjustment = (float)MAX_HIST_Y / (l + 1);
82  } else if (bright_pixels - target_bright_pixels / 10 > target_bright_pixels) {
83  // decrease brightness to try and hit the desired number of well exposed pixels
84  int l = MAX_HIST_Y - 20;
85  while (bright_pixels > target_bright_pixels && l < MAX_HIST_Y) {
86  bright_pixels -= cdf[l];
87  bright_pixels += cdf[l - 1];
88  l++;
89  }
90 
91  adjustment = (float)(MAX_HIST_Y - 20) / l;
92  adjustment *= adjustment; // speedup
93  }
94 
95  // Calculate exposure
96  Bound(adjustment, 1 / 16.0f, 4.0);
99 #endif
100 
101 #if BEBOP_AUTO_WHITE_BALANCE
102  // It is very important that the auto exposure converges faster than the color correction
103  // Calculate AWB and project from original scale [0,255] onto more typical scale[-0.5,0.5]
104  float avgU = ((float) yuv_stats.awb_sum_U / (float) yuv_stats.awb_nb_grey_pixels) / 256. - 0.5;
105  float avgV = ((float) yuv_stats.awb_sum_V / (float) yuv_stats.awb_nb_grey_pixels) / 256. - 0.5;
106  float threshold = 0.002f;
107  float gain = 0.5;
108  bool changed = false;
109 
110  if (fabs(avgU) > threshold) {
111  mt9f002.gain_blue -= gain * avgU;
112  changed = true;
113  }
114  if (fabs(avgV) > threshold) {
115  mt9f002.gain_red -= gain * avgV;
116  changed = true;
117  }
118 
119  if (changed) {
120  Bound(mt9f002.gain_blue, 2, 75);
121  Bound(mt9f002.gain_red, 2, 75);
123  }
124 #endif
125  }
126 }
uint32_t nb_valid_Y
Definition: libisp.h:99
void mt9f002_set_exposure(struct mt9f002_t *mt)
Set the exposure configuration Depends on the blanking (and therefore the FPS)
Definition: mt9f002.c:659
#define MAX_HIST_Y
Definition: bebop_ae_awb.c:31
int isp_get_statistics_yuv(struct isp_yuv_stats_t *yuv_stats)
Definition: libisp.c:201
float gain_blue
Gain for the Blue pixels [1.5 -> 63.50].
Definition: mt9f002.h:137
uint32_t awb_nb_grey_pixels
Definition: libisp.h:98
void bebop_ae_awb_init(void)
Definition: bebop_ae_awb.c:46
void bebop_ae_awb_periodic(void)
Definition: bebop_ae_awb.c:48
unsigned long uint32_t
Definition: types.h:18
uint32_t awb_sum_V
Definition: libisp.h:97
uint32_t awb_sum_U
Definition: libisp.h:96
void mt9f002_set_gains(struct mt9f002_t *mt)
Sets the GreenR, Blue, Red and GreenB gains.
Definition: mt9f002.c:765
float gain_red
Gain for the Red pixels [1.5 -> 63.50].
Definition: mt9f002.h:138
Initialization and configuration of the MT9F002 CMOS Chip.
float real_exposure
Real exposure time in ms.
Definition: mt9f002.h:134
struct mt9f002_t mt9f002
Definition: board.c:39
uint32_t ae_histogram_Y[256]
Definition: libisp.h:100
float target_exposure
Target exposure time in ms.
Definition: mt9f002.h:133