Add white balance control.

You can now get white balance gains from the camera chip and set the
camera to then use these gains again in a new enviorment.
This commit is contained in:
Kwabena W. Agyeman 2017-12-31 19:55:15 -05:00
parent 92c7900039
commit 30ecbdc4f8
11 changed files with 217 additions and 43 deletions

View File

@ -210,12 +210,12 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
ret |= cambus_writew(sensor->slv_addr, MT9V034_AEC_AGC_ENABLE,
(reg & (~MT9V034_AGC_ENABLE)) | ((enable != 0) ? MT9V034_AGC_ENABLE : 0));
if ((enable == 0) && (gain_db >= 0)) {
if ((enable == 0) && (!isnanf(gain_db))) {
int gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((gain_db / 20.0) * fast_log(10.0)) * 16.0), 127), 0);
ret |= cambus_readw(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, &reg);
ret |= cambus_writew(sensor->slv_addr, MT9V034_ANALOG_GAIN_CONTROL, (reg & 0xFF80) | gain);
} else if ((enable != 0) && (gain_db_ceiling >= 0)) {
} else if ((enable != 0) && (!isnanf(gain_db_ceiling))) {
int gain_ceiling = IM_MAX(IM_MIN(fast_roundf(fast_expf((gain_db_ceiling / 20.0) * fast_log(10.0)) * 16.0), 127), 16);
ret |= cambus_readw(sensor->slv_addr, MT9V034_MAX_GAIN, &reg);
@ -273,7 +273,12 @@ static int get_exposure_us(sensor_t *sensor, int *exposure_us)
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{
return 0;
}
static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db)
{
return 0;
}
@ -329,6 +334,7 @@ int mt9v034_init(sensor_t *sensor)
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->get_rgb_gain_db = get_rgb_gain_db;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;
sensor->set_special_effect = set_special_effect;

View File

@ -610,7 +610,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
ret |= cambus_readb(sensor->slv_addr, COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, COM8, (reg & (~COM8_AGC_EN)) | ((enable != 0) ? COM8_AGC_EN : 0));
if ((enable == 0) && (gain_db >= 0)) {
if ((enable == 0) && (!isnanf(gain_db))) {
float gain = IM_MAX(IM_MIN(fast_expf((gain_db / 20.0) * fast_log(10.0)), 32.0), 0.0);
int gain_hi = 15;
@ -624,7 +624,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
}
ret |= cambus_writeb(sensor->slv_addr, GAIN, (gain_hi << 4) | (gain_lo << 0));
} else if ((enable != 0) && (gain_db_ceiling >= 0)) {
} else if ((enable != 0) && (!isnanf(gain_db_ceiling))) {
float gain_ceiling = IM_MAX(IM_MIN(fast_expf((gain_db_ceiling / 20.0) * fast_log(10.0)), 128.0), 2.0);
ret |= cambus_readb(sensor->slv_addr, COM9, &reg);
@ -756,22 +756,40 @@ static int get_exposure_us(sensor_t *sensor, int *exposure_us)
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{
uint8_t reg;
/* Switch to SENSOR register bank */
int ret = cambus_writeb(sensor->slv_addr, BANK_SEL, BANK_SEL_DSP);
/* Update CTRL1 */
int ret = cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
ret |= cambus_readb(sensor->slv_addr, CTRL1, &reg);
ret |= cambus_writeb(sensor->slv_addr, CTRL1, (reg & (~CTRL1_AWB)) | ((enable != 0) ? CTRL1_AWB : 0));
if (enable) {
reg |= CTRL1_AWB;
} else {
reg &= ~CTRL1_AWB;
if ((enable == 0) && (!isnanf(r_gain_db)) && (!isnanf(g_gain_db)) && (!isnanf(b_gain_db))) {
}
return cambus_writeb(sensor->slv_addr, CTRL1, reg) | ret;
return ret;
}
static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db)
{
uint8_t reg;
int ret = cambus_readb(sensor->slv_addr, BANK_SEL, &reg);
ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg & (~BANK_SEL_SENSOR));
ret |= cambus_readb(sensor->slv_addr, CTRL1, &reg);
// DISABLED
// if (reg & CTRL1_AWB) {
// ret |= cambus_writeb(sensor->slv_addr, CTRL1, reg & (~CTRL1_AWB));
// }
// DISABLED
// DISABLED
// if (reg & CTRL1_AWB) {
// ret |= cambus_writeb(sensor->slv_addr, CTRL1, reg | CTRL1_AWB);
// }
// DISABLED
return ret;
}
static int set_hmirror(sensor_t *sensor, int enable)
@ -829,6 +847,7 @@ int ov2640_init(sensor_t *sensor)
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->get_rgb_gain_db = get_rgb_gain_db;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;

View File

@ -358,7 +358,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
int ret = cambus_readb(sensor->slv_addr, COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AGC(reg, (enable != 0)));
if ((enable == 0) && (gain_db >= 0)) {
if ((enable == 0) && (!isnanf(gain_db))) {
float gain = IM_MAX(IM_MIN(fast_expf((gain_db / 20.0) * fast_log(10.0)), 32.0), 0.0);
int gain_hi = 15;
@ -372,7 +372,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
}
ret |= cambus_writeb(sensor->slv_addr, GAIN, (gain_hi << 4) | (gain_lo << 0));
} else if ((enable != 0) && (gain_db_ceiling >= 0)) {
} else if ((enable != 0) && (!isnanf(gain_db_ceiling))) {
float gain_ceiling = IM_MAX(IM_MIN(fast_expf((gain_db_ceiling / 20.0) * fast_log(10.0)), 32.0), 2.0);
ret |= cambus_readb(sensor->slv_addr, COM9, &reg);
@ -491,24 +491,59 @@ static int get_exposure_us(sensor_t *sensor, int *exposure_us)
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{
uint8_t reg;
int ret = cambus_readb(sensor->slv_addr, COM8, &reg);
// Set AWB on/off
reg = COM8_SET_AWB(reg, enable);
ret |= cambus_writeb(sensor->slv_addr, COM8, reg);
ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AWB(reg, (enable != 0)));
if (enable == 0 && r_gain >= 0 && g_gain >=0 && b_gain >=0) {
// Set value manually.
if ((enable == 0) && (!isnanf(r_gain_db)) && (!isnanf(g_gain_db)) && (!isnanf(b_gain_db))) {
ret |= cambus_readb(sensor->slv_addr, AWB_CTRL1, &reg);
float gain_div = (reg & 0x2) ? 64.0 : 128.0;
int r_gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((r_gain_db / 20.0) * fast_log(10.0)) * gain_div), 255), 0);
int g_gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((g_gain_db / 20.0) * fast_log(10.0)) * gain_div), 255), 0);
int b_gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((b_gain_db / 20.0) * fast_log(10.0)) * gain_div), 255), 0);
ret |= cambus_writeb(sensor->slv_addr, BLUE, b_gain);
ret |= cambus_writeb(sensor->slv_addr, RED, r_gain);
ret |= cambus_writeb(sensor->slv_addr, GREEN, g_gain);
ret |= cambus_writeb(sensor->slv_addr, BLUE, b_gain);
}
return ret;
}
static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db)
{
uint8_t reg, blue, red, green;
int ret = cambus_readb(sensor->slv_addr, COM8, &reg);
// DISABLED
// if (reg & COM8_AWB_EN) {
// ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AWB(reg, 0));
// }
// DISABLED
ret |= cambus_readb(sensor->slv_addr, BLUE, &blue);
ret |= cambus_readb(sensor->slv_addr, RED, &red);
ret |= cambus_readb(sensor->slv_addr, GREEN, &green);
// DISABLED
// if (reg & COM8_AWB_EN) {
// ret |= cambus_writeb(sensor->slv_addr, COM8, COM8_SET_AWB(reg, 1));
// }
// DISABLED
ret |= cambus_readb(sensor->slv_addr, AWB_CTRL1, &reg);
float gain_div = (reg & 0x2) ? 64.0 : 128.0;
*r_gain_db = 20.0 * (fast_log(red / gain_div) / fast_log(10.0));
*g_gain_db = 20.0 * (fast_log(green / gain_div) / fast_log(10.0));
*b_gain_db = 20.0 * (fast_log(blue / gain_div) / fast_log(10.0));
return ret;
}
static int set_hmirror(sensor_t *sensor, int enable)
{
uint8_t reg;
@ -578,6 +613,7 @@ int ov7725_init(sensor_t *sensor)
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->get_rgb_gain_db = get_rgb_gain_db;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;
sensor->set_special_effect = set_special_effect;

View File

@ -334,7 +334,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
int ret = cambus_readb(sensor->slv_addr, REG_COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_COM8, (reg & (~REG_COM8_AGC)) | ((enable != 0) ? REG_COM8_AGC : 0));
if ((enable == 0) && (gain_db >= 0)) {
if ((enable == 0) && (!isnanf(gain_db))) {
float gain = IM_MAX(IM_MIN(fast_expf((gain_db / 20.0) * fast_log(10.0)), 128.0), 0.0);
int gain_hi = 63;
@ -350,7 +350,7 @@ static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain
ret |= cambus_writeb(sensor->slv_addr, REG_GAIN, ((gain_hi & 0x0F) << 4) | (gain_lo << 0));
ret |= cambus_readb(sensor->slv_addr, REG_VREF, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_VREF, ((gain_hi & 0x30) << 2) | (reg & 0x3F));
} else if ((enable != 0) && (gain_db_ceiling >= 0)) {
} else if ((enable != 0) && (!isnanf(gain_db_ceiling))) {
float gain_ceiling = IM_MAX(IM_MIN(fast_expf((gain_db_ceiling / 20.0) * fast_log(10.0)), 128.0), 2.0);
ret |= cambus_readb(sensor->slv_addr, REG_COM9, &reg);
@ -459,15 +459,47 @@ static int get_exposure_us(sensor_t *sensor, int *exposure_us)
return ret;
}
static int set_auto_whitebal(sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain)
static int set_auto_whitebal(sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{
uint8_t val;
cambus_readb(sensor->slv_addr, REG_COM8, &val);
uint8_t reg;
int ret = cambus_readb(sensor->slv_addr, REG_COM8, &reg);
ret |= cambus_writeb(sensor->slv_addr, REG_COM8, (reg & (~REG_COM8_AWB)) | ((enable != 0) ? REG_COM8_AWB : 0));
cambus_writeb(sensor->slv_addr, REG_COM8,
enable ? (val | REG_COM8_AWB) : (val & ~REG_COM8_AWB));
if ((enable == 0) && (!isnanf(r_gain_db)) && (!isnanf(g_gain_db)) && (!isnanf(b_gain_db))) {
int r_gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((r_gain_db / 20.0) * fast_log(10.0)) * 128.0), 255), 0);
int b_gain = IM_MAX(IM_MIN(fast_roundf(fast_expf((b_gain_db / 20.0) * fast_log(10.0)) * 128.0), 255), 0);
return 0;
ret |= cambus_writeb(sensor->slv_addr, REG_BLUE, b_gain);
ret |= cambus_writeb(sensor->slv_addr, REG_RED, r_gain);
}
return ret;
}
static int get_rgb_gain_db(sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db)
{
uint8_t reg, blue, red;
int ret = cambus_readb(sensor->slv_addr, REG_COM8, &reg);
// DISABLED
// if (reg & REG_COM8_AWB) {
// ret |= cambus_writeb(sensor->slv_addr, REG_COM8, reg & (~REG_COM8_AWB));
// }
// DISABLED
ret |= cambus_readb(sensor->slv_addr, REG_BLUE, &blue);
ret |= cambus_readb(sensor->slv_addr, REG_RED, &red);
// DISABLED
// if (reg & REG_COM8_AWB) {
// ret |= cambus_writeb(sensor->slv_addr, REG_COM8, reg | REG_COM8_AWB);
// }
// DISABLED
*r_gain_db = 20.0 * (fast_log(red / 128.0) / fast_log(10.0));
*b_gain_db = 20.0 * (fast_log(blue / 128.0) / fast_log(10.0));
return ret;
}
static int set_hmirror(sensor_t *sensor, int enable)
@ -503,6 +535,7 @@ int ov9650_init(sensor_t *sensor)
sensor->set_auto_exposure = set_auto_exposure;
sensor->get_exposure_us = get_exposure_us;
sensor->set_auto_whitebal = set_auto_whitebal;
sensor->get_rgb_gain_db = get_rgb_gain_db;
sensor->set_hmirror = set_hmirror;
sensor->set_vflip = set_vflip;

View File

@ -41,6 +41,19 @@ void py_helper_lookup_int_array(mp_map_t *kw_args, mp_obj_t kw, int *x, int size
}
}
void py_helper_lookup_float_array(mp_map_t *kw_args, mp_obj_t kw, float *x, int size)
{
mp_map_elem_t *kw_array = mp_map_lookup(kw_args, kw, MP_MAP_LOOKUP);
if (kw_array != NULL) {
mp_obj_t *arg_array;
mp_obj_get_array_fixed_n(kw_array->value, size, &arg_array);
for (int i=0; i<size; i++) {
x[i] = mp_obj_get_float(arg_array[i]);
}
}
}
int py_helper_lookup_color(mp_map_t *kw_args, int default_color)
{
mp_map_elem_t *kw_color = mp_map_lookup(kw_args,

View File

@ -13,6 +13,7 @@
int py_helper_lookup_int(mp_map_t *kw_args, mp_obj_t kw, int default_val);
float py_helper_lookup_float(mp_map_t *kw_args, mp_obj_t kw, float default_val);
void py_helper_lookup_int_array(mp_map_t *kw_args, mp_obj_t kw, int *x, int size);
void py_helper_lookup_float_array(mp_map_t *kw_args, mp_obj_t kw, float *x, int size);
int py_helper_lookup_color(mp_map_t *kw_args, int default_color);
void py_helper_lookup_offset(mp_map_t *kw_args, image_t *img, point_t *p);
void py_helper_lookup_rectangle(mp_map_t *kw_args, image_t *img, rectangle_t *r);

View File

@ -346,8 +346,8 @@ static mp_obj_t py_sensor_set_colorbar(mp_obj_t enable) {
static mp_obj_t py_sensor_set_auto_gain(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
int enable = mp_obj_get_int(args[0]);
float gain_db = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_gain_db), -1);
float gain_db_ceiling = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_gain_db_ceiling), -1);
float gain_db = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_gain_db), NAN);
float gain_db_ceiling = py_helper_lookup_float(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_gain_db_ceiling), NAN);
if (sensor_set_auto_gain(enable, gain_db, gain_db_ceiling) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sensor control failed!"));
}
@ -380,12 +380,20 @@ static mp_obj_t py_sensor_get_exposure_us() {
static mp_obj_t py_sensor_set_auto_whitebal(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
int enable = mp_obj_get_int(args[0]);
int value[3] = {-1, -1, -1};
py_helper_lookup_int_array(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_value), value, 3);
if (sensor_set_auto_whitebal(enable, value[0], value[1], value[2]) != 0) {
return mp_const_false;
float rgb_gain_db[3] = {NAN, NAN, NAN};
py_helper_lookup_float_array(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_rgb_gain_db), rgb_gain_db, 3);
if (sensor_set_auto_whitebal(enable, rgb_gain_db[0], rgb_gain_db[1], rgb_gain_db[2]) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sensor control failed!"));
}
return mp_const_true;
return mp_const_none;
}
static mp_obj_t py_sensor_get_rgb_gain_db() {
float r_gain_db = 0.0, g_gain_db = 0.0, b_gain_db = 0.0;
if (sensor_get_rgb_gain_db(&r_gain_db, &g_gain_db, &b_gain_db) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sensor control failed!"));
}
return mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_float(r_gain_db), mp_obj_new_float(g_gain_db), mp_obj_new_float(b_gain_db)});
}
static mp_obj_t py_sensor_set_hmirror(mp_obj_t enable) {
@ -463,6 +471,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_sensor_get_gain_db_obj, py_sensor_ge
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_sensor_set_auto_exposure_obj,1,py_sensor_set_auto_exposure);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_sensor_get_exposure_us_obj, py_sensor_get_exposure_us);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_sensor_set_auto_whitebal_obj,1,py_sensor_set_auto_whitebal);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_sensor_get_rgb_gain_db_obj, py_sensor_get_rgb_gain_db);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_hmirror_obj, py_sensor_set_hmirror);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_vflip_obj, py_sensor_set_vflip);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_sensor_set_special_effect_obj, py_sensor_set_special_effect);
@ -541,6 +550,7 @@ STATIC const mp_map_elem_t globals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_auto_exposure), (mp_obj_t)&py_sensor_set_auto_exposure_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_exposure_us), (mp_obj_t)&py_sensor_get_exposure_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_auto_whitebal), (mp_obj_t)&py_sensor_set_auto_whitebal_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_rgb_gain_db), (mp_obj_t)&py_sensor_get_rgb_gain_db_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_hmirror), (mp_obj_t)&py_sensor_set_hmirror_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_vflip), (mp_obj_t)&py_sensor_set_vflip_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_special_effect), (mp_obj_t)&py_sensor_set_special_effect_obj },

View File

@ -229,6 +229,8 @@ Q(set_auto_exposure)
Q(exposure_us)
Q(get_exposure_us)
Q(set_auto_whitebal)
Q(rgb_gain_db)
Q(get_rgb_gain_db)
Q(set_hmirror)
Q(set_vflip)
Q(set_special_effect)

View File

@ -569,11 +569,22 @@ int sensor_get_exposure_us(int *exposure_us)
return 0;
}
int sensor_set_auto_whitebal(int enable, int r_gain, int g_gain, int b_gain)
int sensor_set_auto_whitebal(int enable, float r_gain_db, float g_gain_db, float b_gain_db)
{
/* call the sensor specific function */
if (sensor.set_auto_whitebal == NULL
|| sensor.set_auto_whitebal(&sensor, enable, r_gain, g_gain, b_gain) != 0) {
|| sensor.set_auto_whitebal(&sensor, enable, r_gain_db, g_gain_db, b_gain_db) != 0) {
/* operation not supported */
return -1;
}
return 0;
}
int sensor_get_rgb_gain_db(float *r_gain_db, float *g_gain_db, float *b_gain_db)
{
/* call the sensor specific function */
if (sensor.get_rgb_gain_db == NULL
|| sensor.get_rgb_gain_db(&sensor, r_gain_db, g_gain_db, b_gain_db) != 0) {
/* operation not supported */
return -1;
}

View File

@ -139,7 +139,8 @@ typedef struct _sensor {
int (*get_gain_db) (sensor_t *sensor, float *gain_db);
int (*set_auto_exposure) (sensor_t *sensor, int enable, int exposure_us);
int (*get_exposure_us) (sensor_t *sensor, int *exposure_us);
int (*set_auto_whitebal) (sensor_t *sensor, int enable, int r_gain, int g_gain, int b_gain);
int (*set_auto_whitebal) (sensor_t *sensor, int enable, float r_gain_db, float g_gain_db, float b_gain_db);
int (*get_rgb_gain_db) (sensor_t *sensor, float *r_gain_db, float *g_gain_db, float *b_gain_db);
int (*set_hmirror) (sensor_t *sensor, int enable);
int (*set_vflip) (sensor_t *sensor, int enable);
int (*set_special_effect) (sensor_t *sensor, sde_t sde);
@ -214,7 +215,10 @@ int sensor_set_auto_exposure(int enable, int exposure_us);
int sensor_get_exposure_us(int *get_exposure_us);
// Enable auto white balance or set value manually.
int sensor_set_auto_whitebal(int enable, int r_gain, int g_gain, int b_gain);
int sensor_set_auto_whitebal(int enable, float r_gain_db, float g_gain_db, float b_gain_db);
// Get the rgb gain values.
int sensor_get_rgb_gain_db(float *r_gain_db, float *g_gain_db, float *b_gain_db);
// Enable/disable the hmirror mode.
int sensor_set_hmirror(int enable);

View File

@ -0,0 +1,39 @@
# Sensor Manual Whitebal Control
#
# This example shows off how to control the camera sensor's
# white balance gain manually versus letting the AWB control run.
# White balance is achieve by adjusting R/G/B gain values
# such that the average color of the image is gray. The
# automatic white balance (AWB) algorithm does this for
# you but usually ends up with a different result each
# time you turn the camera on making it hard to get
# color tracking settings right. By manually recording
# the gain values you like and then forcing them to
# the sensor on startup you can control the colors
# the camera sees.
import sensor, image, time
sensor.reset() # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA) # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000) # Wait for settings take effect.
clock = time.clock() # Create a clock object to track the FPS.
# You can control the white balance gains here. The first value is the
# R gain in db, and then the G gain in db, followed by the B gain in db.
#
# Uncomment the below line with gain values you like (get them from the print out).
#
# sensor.set_auto_whitebal(False, rgb_gain_db = (0.0, 0.0, 0.0))
# Note: Putting (0.0, 0.0, 0.0) for the gain results in something close to zero
# comming out. Do not expect the exact value going in to be equal to the value
# comming out.
while(True):
clock.tick() # Update the FPS clock.
img = sensor.snapshot() # Take a picture and return the image.
print(clock.fps(), \
sensor.get_rgb_gain_db()) # Prints the AWB current RGB gains.