static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain_db_ceiling) { uint8_t reg; int ret = cambus_readb(sensor->slv_addr, BANK_SEL, ®); ret |= cambus_writeb(sensor->slv_addr, BANK_SEL, reg | BANK_SEL_SENSOR); ret |= cambus_readb(sensor->slv_addr, COM8, ®); ret |= cambus_writeb(sensor->slv_addr, COM8, (reg & (~COM8_AGC_EN)) | ((enable != 0) ? COM8_AGC_EN : 0)); if ((enable == 0) && (!isnanf(gain_db)) && (!isinff(gain_db))) { float gain = IM_MAX(IM_MIN(fast_expf((gain_db / 20.0) * fast_log(10.0)), 32.0), 1.0); int gain_temp = fast_roundf(fast_log2(IM_MAX(gain / 2.0, 1.0))); int gain_hi = 0xF >> (4 - gain_temp); int gain_lo = IM_MIN(fast_roundf(((gain / (1 << gain_temp)) - 1.0) * 16.0), 15); ret |= cambus_writeb(sensor->slv_addr, GAIN, (gain_hi << 4) | (gain_lo << 0)); } else if ((enable != 0) && (!isnanf(gain_db_ceiling)) && (!isinff(gain_db_ceiling))) {
static int set_auto_gain(sensor_t *sensor, int enable, float gain_db, float gain_db_ceiling) { uint8_t reg; int ret = cambus_readb(sensor->slv_addr, REG_COM8, ®); ret |= cambus_writeb(sensor->slv_addr, REG_COM8, (reg & (~REG_COM8_AGC)) | ((enable != 0) ? REG_COM8_AGC : 0)); if ((enable == 0) && (!isnanf(gain_db)) && (!isinf(gain_db))) { float gain = IM_MAX(IM_MIN(fast_expf((gain_db / 20.0) * fast_log(10.0)), 128.0), 1.0); int gain_temp = fast_roundf(fast_log2(IM_MAX(gain / 2.0, 1.0))); int gain_hi = 0x3F >> (6 - gain_temp); int gain_lo = IM_MIN(fast_roundf(((gain / (1 << gain_temp)) - 1.0) * 16.0), 15); ret |= cambus_writeb(sensor->slv_addr, REG_GAIN, ((gain_hi & 0x0F) << 4) | (gain_lo << 0)); ret |= cambus_readb(sensor->slv_addr, REG_VREF, ®); ret |= cambus_writeb(sensor->slv_addr, REG_VREF, ((gain_hi & 0x30) << 2) | (reg & 0x3F)); } else if ((enable != 0) && (!isnanf(gain_db_ceiling)) && (!isinf(gain_db_ceiling))) {
array_t *imlib_detect_objects(image_t *image, cascade_t *cascade, rectangle_t *roi) { // Integral images mw_image_t sum; mw_image_t ssq; // Detected objects array array_t *objects; // Allocate the objects array array_alloc(&objects, xfree); // Set cascade image pointers cascade->img = image; cascade->sum = ∑ cascade->ssq = &ssq; // Set scanning step. // Viola and Jones achieved best results using a scaling factor // of 1.25 and a scanning factor proportional to the current scale. // Start with a step of 5% of the image width and reduce at each scaling step cascade->step = (roi->w*50)/1000; // Make sure step is less than window height + 1 if (cascade->step > cascade->window.h) { cascade->step = cascade->window.h; } // Allocate integral images imlib_integral_mw_alloc(&sum, roi->w, cascade->window.h+1); imlib_integral_mw_alloc(&ssq, roi->w, cascade->window.h+1); // Iterate over the image pyramid for(float factor=1.0f; ; factor *= cascade->scale_factor) { // Set the scaled width and height int szw = roi->w/factor; int szh = roi->h/factor; // Break if scaled image is smaller than feature size if (szw < cascade->window.w || szh < cascade->window.h) { break; } // Set the integral images scale imlib_integral_mw_scale(roi, &sum, szw, szh); imlib_integral_mw_scale(roi, &ssq, szw, szh); // Compute new scaled integral images imlib_integral_mw_ss(image, &sum, &ssq, roi); // Scale the scanning step cascade->step = cascade->step/factor; cascade->step = (cascade->step == 0) ? 1 : cascade->step; // Process image at the current scale // When filter window shifts to borders, some margin need to be kept int y2 = szh - cascade->window.h; int x2 = szw - cascade->window.w; // Shift the filter window over the image. for (int y=0; y<y2; y+=cascade->step) { for (int x=0; x<x2; x+=cascade->step) { point_t p = {x, y}; // If an object is detected, record the coordinates of the filter window if (run_cascade_classifier(cascade, p) > 0) { array_push_back(objects, rectangle_alloc(fast_roundf(x*factor) + roi->x, fast_roundf(y*factor) + roi->y, fast_roundf(cascade->window.w*factor), fast_roundf(cascade->window.h*factor))); } } // If not last line, shift integral images if ((y+cascade->step) < y2) { imlib_integral_mw_shift_ss(image, &sum, &ssq, roi, cascade->step); } } } imlib_integral_mw_free(&ssq); imlib_integral_mw_free(&sum); if (array_length(objects) > 1) { // Merge objects detected at different scales objects = rectangle_merge(objects); } return objects; }