mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge 0c1d134a84 into daf26f9fc8
This commit is contained in:
commit
6a921d4e93
81
common/average.c
Normal file
81
common/average.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2013-2025 OpenMV, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Averaging utility functions.
|
||||
*/
|
||||
#include "average.h"
|
||||
#include <string.h>
|
||||
|
||||
void rgb_moving_average_init(rgb_moving_average_t *ma, uint32_t max_ms,
|
||||
size_t size, rgb_moving_average_val_t *buffer) {
|
||||
memset(ma, 0, sizeof(rgb_moving_average_t));
|
||||
ma->size = size;
|
||||
ma->max_ms = max_ms;
|
||||
ma->buffer = buffer;
|
||||
}
|
||||
|
||||
void rgb_moving_average_update(rgb_moving_average_t *ma,
|
||||
uint32_t *r_value, uint32_t *g_value, uint32_t *b_value,
|
||||
uint32_t current_ms) {
|
||||
if (!ma->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Drop if the buffer is full and all values older than max_ms (handles wrap-around correctly).
|
||||
while (ma->count == ma->size ||
|
||||
(ma->count > 0 && (current_ms - ma->buffer[ma->head].timestamp_ms) > ma->max_ms)) {
|
||||
rgb_moving_average_val_t *val = &ma->buffer[ma->head];
|
||||
ma->r_sum -= val->r_value;
|
||||
ma->g_sum -= val->g_value;
|
||||
ma->b_sum -= val->b_value;
|
||||
ma->head = (ma->head + 1) % ma->size;
|
||||
ma->count--;
|
||||
}
|
||||
|
||||
// Add the new value.
|
||||
rgb_moving_average_val_t *val = &ma->buffer[ma->tail];
|
||||
val->r_value = *r_value;
|
||||
val->g_value = *g_value;
|
||||
val->b_value = *b_value;
|
||||
val->timestamp_ms = current_ms;
|
||||
ma->tail = (ma->tail + 1) % ma->size;
|
||||
ma->count++;
|
||||
ma->r_sum += val->r_value;
|
||||
ma->g_sum += val->g_value;
|
||||
ma->b_sum += val->b_value;
|
||||
|
||||
// Return the current average.
|
||||
*r_value = (ma->r_sum / ma->count);
|
||||
*g_value = (ma->g_sum / ma->count);
|
||||
*b_value = (ma->b_sum / ma->count);
|
||||
}
|
||||
|
||||
void rgb_moving_average_get(rgb_moving_average_t *ma, uint32_t *r_value, uint32_t *g_value, uint32_t *b_value) {
|
||||
if (!ma->size || ma->count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
*r_value = (ma->r_sum / ma->count);
|
||||
*g_value = (ma->g_sum / ma->count);
|
||||
*b_value = (ma->b_sum / ma->count);
|
||||
}
|
||||
57
common/average.h
Normal file
57
common/average.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2013-2025 OpenMV, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Averaging utility functions.
|
||||
*/
|
||||
#ifndef __AVERAGE_H__
|
||||
#define __AVERAGE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct rgb_moving_average_val {
|
||||
uint32_t r_value;
|
||||
uint32_t g_value;
|
||||
uint32_t b_value;
|
||||
uint32_t timestamp_ms;
|
||||
} rgb_moving_average_val_t;
|
||||
|
||||
typedef struct rgb_moving_average {
|
||||
size_t size;
|
||||
size_t tail;
|
||||
size_t head;
|
||||
size_t count;
|
||||
uint32_t max_ms;
|
||||
rgb_moving_average_val_t *buffer;
|
||||
uint64_t r_sum;
|
||||
uint64_t g_sum;
|
||||
uint64_t b_sum;
|
||||
} rgb_moving_average_t;
|
||||
|
||||
void rgb_moving_average_init(rgb_moving_average_t *ma, uint32_t max_ms,
|
||||
size_t size, rgb_moving_average_val_t *buffer);
|
||||
void rgb_moving_average_update(rgb_moving_average_t *ma,
|
||||
uint32_t *r_value, uint32_t *g_value, uint32_t *b_value,
|
||||
uint32_t current_ms);
|
||||
void rgb_moving_average_get(rgb_moving_average_t *ma, uint32_t *r_value, uint32_t *g_value, uint32_t *b_value);
|
||||
#endif // __AVERAGE_H__
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
COMMON_SRC_C += \
|
||||
array.c \
|
||||
average.c \
|
||||
dma_alloc.c \
|
||||
fb_alloc.c \
|
||||
file_utils.c \
|
||||
|
||||
@ -65,6 +65,8 @@
|
||||
#define OMV_CSI_CLK_TOLERANCE (500000)
|
||||
#endif
|
||||
|
||||
#define OMV_CSI_RGB_AVG_MAX_MS (250)
|
||||
|
||||
#ifndef __weak
|
||||
#define __weak __attribute__((weak))
|
||||
#endif
|
||||
@ -322,6 +324,12 @@ __weak int omv_csi_reset(omv_csi_t *csi, bool hard) {
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
#if defined(OMV_CSI_RGB_AVG_SIZE)
|
||||
// Setup AWB moving average.
|
||||
csi->awb_enabled = true;
|
||||
rgb_moving_average_init(&csi->rgb_avg, OMV_CSI_RGB_AVG_MAX_MS, OMV_CSI_RGB_AVG_SIZE, csi->rgb_avg_buf);
|
||||
#endif // defined(OMV_CSI_RGB_AVG_SIZE)
|
||||
|
||||
// Restore shutdown state on reset.
|
||||
if (!csi->power_on) {
|
||||
omv_csi_shutdown(csi, false);
|
||||
|
||||
@ -652,6 +652,23 @@ static int get_exposure_us(omv_csi_t *csi, int *exposure_us) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_auto_whitebal(omv_csi_t *csi, int enable, float r_gain_db, float g_gain_db, float b_gain_db) {
|
||||
csi->awb_enabled = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_rgb_gain_db(omv_csi_t *csi, float *r_gain_db, float *g_gain_db, float *b_gain_db) {
|
||||
uint32_t r_avg, g_avg, b_avg;
|
||||
rgb_moving_average_get(&csi->rgb_avg, &r_avg, &g_avg, &b_avg);
|
||||
float g_avg_f = (float) g_avg;
|
||||
|
||||
*r_gain_db = 20.0f * log10f(g_avg_f / r_avg);
|
||||
*g_gain_db = 0.0f;
|
||||
*b_gain_db = 20.0f * log10f(g_avg_f / b_avg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_hmirror(omv_csi_t *csi, int enable) {
|
||||
uint8_t reg;
|
||||
int ret = omv_i2c_readb2(csi->i2c, csi->slv_addr, TG_FLIP, ®);
|
||||
@ -723,6 +740,8 @@ int pag7936_init(omv_csi_t *csi) {
|
||||
csi->get_gain_db = get_gain_db;
|
||||
csi->set_auto_exposure = set_auto_exposure;
|
||||
csi->get_exposure_us = get_exposure_us;
|
||||
csi->set_auto_whitebal = set_auto_whitebal;
|
||||
csi->get_rgb_gain_db = get_rgb_gain_db;
|
||||
csi->set_hmirror = set_hmirror;
|
||||
csi->set_vflip = set_vflip;
|
||||
|
||||
|
||||
@ -1442,6 +1442,23 @@ static int get_exposure_us(omv_csi_t *csi, int *exposure_us) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_auto_whitebal(omv_csi_t *csi, int enable, float r_gain_db, float g_gain_db, float b_gain_db) {
|
||||
csi->awb_enabled = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_rgb_gain_db(omv_csi_t *csi, float *r_gain_db, float *g_gain_db, float *b_gain_db) {
|
||||
uint32_t r_avg, g_avg, b_avg;
|
||||
rgb_moving_average_get(&csi->rgb_avg, &r_avg, &g_avg, &b_avg);
|
||||
float g_avg_f = (float) g_avg;
|
||||
|
||||
*r_gain_db = 20.0f * log10f(g_avg_f / r_avg);
|
||||
*g_gain_db = 0.0f;
|
||||
*b_gain_db = 20.0f * log10f(g_avg_f / b_avg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_hmirror(omv_csi_t *csi, int enable) {
|
||||
uint8_t reg1, reg2;
|
||||
uint16_t hsize;
|
||||
@ -1590,6 +1607,8 @@ int ps5520_init(omv_csi_t *csi) {
|
||||
csi->get_gain_db = get_gain_db;
|
||||
csi->set_auto_exposure = set_auto_exposure;
|
||||
csi->get_exposure_us = get_exposure_us;
|
||||
csi->set_auto_whitebal = set_auto_whitebal;
|
||||
csi->get_rgb_gain_db = get_rgb_gain_db;
|
||||
csi->set_hmirror = set_hmirror;
|
||||
csi->set_vflip = set_vflip;
|
||||
|
||||
|
||||
@ -559,6 +559,10 @@ static inline v128_t vdebayer_to_cr(vrgb_pixels_t pixels) {
|
||||
return pixels.r;
|
||||
}
|
||||
|
||||
// FIXME: This needs to be placed in the DTCM. .bss is in the DTCM on Alif. But, this is not portable.
|
||||
// Move this to a proper DTCM section for other platforms.
|
||||
static uint8_t gamma_lut[256];
|
||||
|
||||
// In the case of vectors larger than 32-bits the pattern is repeated for every 32-bits.
|
||||
//
|
||||
// pixels.r = MSB [0, R1, 0, R0] LSB pixels where each pixel is 8-bits.
|
||||
@ -569,6 +573,9 @@ static inline v128_t vdebayer_to_cr(vrgb_pixels_t pixels) {
|
||||
static inline vrgb_pixels_t vdebayer_apply_rb_gain(vrgb_pixels_t pixels, uint32_t red_gain, uint32_t blue_gain) {
|
||||
pixels.r = vusat_s16_narrow_u8_lo(pixels.r, vmul_n_u32(pixels.r, red_gain), 5);
|
||||
pixels.b = vusat_s16_narrow_u8_lo(pixels.b, vmul_n_u32(pixels.b, blue_gain), 5);
|
||||
pixels.r = vldr_u8_gather(gamma_lut, pixels.r);
|
||||
pixels.g = vldr_u8_gather(gamma_lut, pixels.g);
|
||||
pixels.b = vldr_u8_gather(gamma_lut, pixels.b);
|
||||
return pixels;
|
||||
}
|
||||
|
||||
@ -2291,13 +2298,19 @@ static void vdebayer_rggb_to_rgb565_awb_quarter(image_t *src, image_t *dst, uint
|
||||
// GRAYSCALE: src->data == dst->data
|
||||
// RGB565: src->data == dst->data + image_size(src)
|
||||
// YUV422: Not supported
|
||||
void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out) {
|
||||
void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out,
|
||||
float brightness, float contrast, float gamma) {
|
||||
uint32_t red_gain = IM_DIV(g_out * 32, r_out);
|
||||
red_gain = IM_MIN(red_gain, 128U);
|
||||
|
||||
uint32_t blue_gain = IM_DIV(g_out * 32, b_out);
|
||||
blue_gain = IM_MIN(blue_gain, 128U);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
int v = fast_roundf(((fast_powf(i * (1.0f / 255.0f), gamma) * contrast) + brightness) * 255.0f);
|
||||
gamma_lut[i] = IM_CLAMP(v, 0, 255);
|
||||
}
|
||||
|
||||
if (fast) {
|
||||
switch (src->pixfmt) {
|
||||
case PIXFORMAT_BAYER_BGGR: {
|
||||
|
||||
@ -1207,7 +1207,8 @@ pixformat_t imlib_bayer_shift(pixformat_t pixfmt, int x, int y, bool transpose);
|
||||
void imlib_debayer_ycbcr(image_t *src, rectangle_t *roi, int8_t *Y0, int8_t *CB, int8_t *CR);
|
||||
void imlib_debayer_line(int x_start, int x_end, int y_row, void *dst_row_ptr, pixformat_t pixfmt, image_t *src);
|
||||
void imlib_debayer_image(image_t *dst, image_t *src);
|
||||
void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out);
|
||||
void imlib_debayer_image_awb(image_t *dst, image_t *src, bool fast, uint32_t r_out, uint32_t g_out, uint32_t b_out,
|
||||
float brightness, float contrast, float gamma);
|
||||
|
||||
// YUV Image Processing
|
||||
pixformat_t imlib_yuv_shift(pixformat_t pixfmt, int x);
|
||||
|
||||
@ -1514,6 +1514,19 @@ static inline v128_t vldr_u8_pred(const uint8_t *p, v128_predicate_t pred) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline v128_t vldr_u8_gather(const uint8_t *p, v128_t offsets) {
|
||||
#if (__ARM_ARCH >= 8)
|
||||
return (v128_t) vldrbq_gather_offset(p, offsets.u8);
|
||||
#else
|
||||
v128_t v0;
|
||||
v0.u8[0] = *(p + offsets.u8[0]);
|
||||
v0.u8[1] = *(p + offsets.u8[1]);
|
||||
v0.u8[2] = *(p + offsets.u8[2]);
|
||||
v0.u8[3] = *(p + offsets.u8[3]);
|
||||
return v0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline v128_t vldr_u8_widen_u32_gather_pred(const uint8_t *p,
|
||||
v128_t offsets,
|
||||
v128_predicate_t pred) {
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
#include "omv_gpu.h"
|
||||
#include "omv_i2c.h"
|
||||
#include "omv_csi.h"
|
||||
#include "average.h"
|
||||
#include "unaligned_memcpy.h"
|
||||
|
||||
// Bits missing from cpi.h
|
||||
@ -230,10 +231,7 @@ static uint32_t omv_csi_get_fb_offset(omv_csi_t *csi) {
|
||||
int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
|
||||
CPI_Type *cpi = csi->base;
|
||||
framebuffer_t *fb = csi->fb;
|
||||
|
||||
vbuffer_t *buffer = NULL;
|
||||
static uint32_t frames = 0;
|
||||
static uint32_t r_stat, gb_stat, gr_stat, b_stat;
|
||||
|
||||
// Configure and re/start the capture if it's not alrady active
|
||||
// and there are no pending buffers (from non-blocking capture).
|
||||
@ -390,13 +388,23 @@ int alif_csi_snapshot(omv_csi_t *csi, image_t *dst_image, uint32_t flags) {
|
||||
// Set the target pixel format before debayer.
|
||||
dst_image->pixfmt = fb->pixfmt;
|
||||
|
||||
// Update AWB stats every n frames.
|
||||
if ((frames++ % 100) == 0) {
|
||||
omv_csi_ioctl(csi, OMV_CSI_IOCTL_GET_RGB_STATS, &r_stat, &gb_stat, &gr_stat, &b_stat);
|
||||
uint32_t r_stat, g_stat, b_stat;
|
||||
if (csi->awb_enabled) {
|
||||
uint32_t gb_stat, gr_stat;
|
||||
int ret = omv_csi_ioctl(csi, OMV_CSI_IOCTL_GET_RGB_STATS, &r_stat, &gb_stat, &gr_stat, &b_stat);
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
g_stat = (gb_stat + gr_stat) / 2;
|
||||
rgb_moving_average_update(&csi->rgb_avg, &r_stat, &g_stat, &b_stat, mp_hal_ticks_ms());
|
||||
} else {
|
||||
rgb_moving_average_get(&csi->rgb_avg, &r_stat, &g_stat, &b_stat);
|
||||
}
|
||||
|
||||
// Debayer frame.
|
||||
imlib_debayer_image_awb(dst_image, &src_image, false, r_stat, (gb_stat + gr_stat) / 2, b_stat);
|
||||
imlib_debayer_image_awb(dst_image, &src_image, false, r_stat, g_stat, b_stat, 0.0f, 1.0f, 0.5f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#define __OMV_PORTCONFIG_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "average.h"
|
||||
#include "clk.h"
|
||||
#include "i2c.h"
|
||||
#include "i3c.h"
|
||||
@ -137,9 +138,14 @@ struct { \
|
||||
uint8_t datasize; \
|
||||
};
|
||||
|
||||
#define OMV_CSI_RGB_AVG_SIZE (60)
|
||||
|
||||
#define OMV_CSI_PORT_BITS \
|
||||
struct { \
|
||||
CPI_Type *base; \
|
||||
bool awb_enabled; \
|
||||
rgb_moving_average_t rgb_avg; \
|
||||
rgb_moving_average_val_t rgb_avg_buf[OMV_CSI_RGB_AVG_SIZE]; \
|
||||
};
|
||||
|
||||
#endif // __OMV_PORTCONFIG_H__
|
||||
|
||||
@ -751,7 +751,7 @@ static int stm_csi_snapshot(omv_csi_t *csi, image_t *image, uint32_t flags) {
|
||||
|
||||
#if USE_DCMIPP
|
||||
if (csi->raw_output) {
|
||||
float luminance = stm_isp_update_awb(&csi->dcmipp, DCMIPP_PIPE, fb->u * fb->v);
|
||||
float luminance = stm_isp_update_awb(csi, DCMIPP_PIPE, fb->u * fb->v);
|
||||
if (csi->ioctl) {
|
||||
omv_csi_ioctl(csi, OMV_CSI_IOCTL_UPDATE_AGC_AEC, fast_floorf(luminance));
|
||||
}
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
#define __OMV_PORTCONFIG_H__
|
||||
#include STM32_HAL_H
|
||||
|
||||
#include "average.h"
|
||||
|
||||
// GPIO speeds.
|
||||
#define OMV_GPIO_SPEED_LOW GPIO_SPEED_FREQ_LOW
|
||||
#define OMV_GPIO_SPEED_MED GPIO_SPEED_FREQ_MEDIUM
|
||||
@ -147,12 +149,15 @@ typedef I2C_HandleTypeDef *omv_i2c_dev_t;
|
||||
#define OMV_CSI_PORT_BITS_MDMA
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(STM32N6)
|
||||
#define OMV_CSI_RGB_AVG_SIZE (120)
|
||||
#define OMV_CSI_PORT_BITS_DCMIPP \
|
||||
struct { \
|
||||
DCMIPP_HandleTypeDef dcmipp; \
|
||||
DMA_QListTypeDef dma_queue; \
|
||||
bool awb_enabled; \
|
||||
rgb_moving_average_t rgb_avg; \
|
||||
rgb_moving_average_val_t rgb_avg_buf[OMV_CSI_RGB_AVG_SIZE]; \
|
||||
};
|
||||
#else
|
||||
#define OMV_CSI_PORT_BITS_DCMIPP
|
||||
|
||||
@ -33,18 +33,21 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "imlib.h"
|
||||
#include "average.h"
|
||||
#include "py/mphal.h"
|
||||
#include "stm_isp.h"
|
||||
#include "omv_boardconfig.h"
|
||||
|
||||
#ifdef DCMIPP
|
||||
float stm_isp_update_awb(DCMIPP_HandleTypeDef *dcmipp, uint32_t pipe, uint32_t n_pixels) {
|
||||
float stm_isp_update_awb(omv_csi_t *csi, uint32_t pipe, uint32_t n_pixels) {
|
||||
uint32_t avg[3];
|
||||
uint32_t shift[3];
|
||||
uint32_t multi[3];
|
||||
|
||||
if (csi->awb_enabled) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// DCMIPP_STATEXT_MODULE1
|
||||
HAL_DCMIPP_PIPE_GetISPAccumulatedStatisticsCounter(dcmipp, pipe, i + 1, &avg[i]);
|
||||
HAL_DCMIPP_PIPE_GetISPAccumulatedStatisticsCounter(&csi->dcmipp, pipe, i + 1, &avg[i]);
|
||||
}
|
||||
|
||||
// Averages are collected from bayer components (4R 2G 4B).
|
||||
@ -52,6 +55,11 @@ float stm_isp_update_awb(DCMIPP_HandleTypeDef *dcmipp, uint32_t pipe, uint32_t n
|
||||
avg[1] = OMV_MAX((avg[1] * 256 * 2) / n_pixels, 1);
|
||||
avg[2] = OMV_MAX((avg[2] * 256 * 4) / n_pixels, 1);
|
||||
|
||||
rgb_moving_average_update(&csi->rgb_avg, &avg[0], &avg[1], &avg[2], mp_hal_ticks_ms());
|
||||
} else {
|
||||
rgb_moving_average_get(&csi->rgb_avg, &avg[0], &avg[1], &avg[2]);
|
||||
}
|
||||
|
||||
// Compute global luminance
|
||||
float luminance = avg[0] * 0.299 + avg[1] * 0.587 + avg[2] * 0.114;
|
||||
|
||||
@ -75,7 +83,7 @@ float stm_isp_update_awb(DCMIPP_HandleTypeDef *dcmipp, uint32_t pipe, uint32_t n
|
||||
.MultiplierBlue = multi[2],
|
||||
};
|
||||
|
||||
HAL_DCMIPP_PIPE_SetISPExposureConfig(dcmipp, pipe, &expcfg);
|
||||
HAL_DCMIPP_PIPE_SetISPExposureConfig(&csi->dcmipp, pipe, &expcfg);
|
||||
|
||||
return luminance;
|
||||
}
|
||||
@ -159,6 +167,10 @@ int stm_isp_config_pipeline(DCMIPP_HandleTypeDef *dcmipp, uint32_t pipe,
|
||||
}
|
||||
}
|
||||
|
||||
if (HAL_DCMIPP_PIPE_EnableGammaConversion(dcmipp, pipe) != HAL_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // DCMIPP
|
||||
|
||||
@ -35,11 +35,12 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include STM32_HAL_H
|
||||
#include "omv_csi.h"
|
||||
|
||||
#ifdef DCMIPP
|
||||
int stm_isp_config_pipeline(DCMIPP_HandleTypeDef *dcmipp, uint32_t pipe,
|
||||
pixformat_t pixformat, bool raw_output);
|
||||
float stm_isp_update_awb(DCMIPP_HandleTypeDef *dcmipp, uint32_t pipe, uint32_t n_pixels);
|
||||
float stm_isp_update_awb(omv_csi_t *csi, uint32_t pipe, uint32_t n_pixels);
|
||||
#endif
|
||||
|
||||
#endif // __STM_ISP_H__
|
||||
|
||||
Loading…
Reference in New Issue
Block a user