mirror of
https://github.com/espressif/esp-idf.git
synced 2026-01-20 03:18:48 +00:00
Merge branch 'fix/awb_subwindow_v6.0' into 'release/v6.0'
fix(isp): Added subwindow configuration for AWB (v6.0) See merge request espressif/esp-idf!44218
This commit is contained in:
@@ -27,12 +27,18 @@ typedef struct {
|
||||
* If your camera doesn't support the manual gain or don't want to change the camera configuration,
|
||||
* then you can choose to sample after CCM, and set the calculated gain to the CCM
|
||||
*/
|
||||
isp_window_t window; /*!< Statistic window of AWB.
|
||||
isp_window_t window; /*!< Statistic main window of AWB.
|
||||
* Suggest to set it at the middle of the image and a little smaller than the whole image.
|
||||
* It will be more reliable because the edges of image are easily to be overexposure,
|
||||
* the overexposure pixels are almost at maximum luminance,
|
||||
* which are not good references to calculate the gain for white balance.
|
||||
*/
|
||||
isp_window_t subwindow; /*!< Statistic subwindow of AWB.
|
||||
* Need to be set no greater than the main window.
|
||||
* It will be evenly divided into a grid of ISP_AWB_WINDOW_X_NUM * ISP_AWB_WINDOW_Y_NUM blocks.
|
||||
* The blocks share the same restrictions in R/G, B/G and luminance range as the main window.
|
||||
* The statistics result of each block will be returned in the `isp_awb_stat_result_t::subwin_result` field.
|
||||
*/
|
||||
struct {
|
||||
isp_u32_range_t luminance; /*!< Luminance range of the white patch. Range [0, 255 * 3]
|
||||
* Not suggest to set the max value to 255 * 3,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "driver/isp_awb.h"
|
||||
#include "esp_private/isp_private.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
typedef struct isp_awb_controller_t {
|
||||
_Atomic isp_fsm_t fsm;
|
||||
@@ -71,14 +72,58 @@ static esp_err_t s_esp_isp_awb_config_hardware(isp_proc_handle_t isp_proc, const
|
||||
{
|
||||
isp_ll_awb_set_sample_point(isp_proc->hal.hw, awb_cfg->sample_point);
|
||||
ESP_RETURN_ON_FALSE(isp_hal_awb_set_window_range(&isp_proc->hal, &awb_cfg->window),
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid window");
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid window range");
|
||||
|
||||
// Subwindow feature is only supported on REV >= 3.0
|
||||
if (efuse_hal_chip_revision() < 300) {
|
||||
bool subwindow_is_zero = awb_cfg->subwindow.top_left.x == 0 &&
|
||||
awb_cfg->subwindow.top_left.y == 0 &&
|
||||
awb_cfg->subwindow.btm_right.x == 0 &&
|
||||
awb_cfg->subwindow.btm_right.y == 0;
|
||||
if (!subwindow_is_zero) {
|
||||
ESP_LOGW(TAG, "Subwindow feature is not supported on REV < 3.0, subwindow will not be configured");
|
||||
}
|
||||
}
|
||||
|
||||
isp_window_t subwindow = awb_cfg->subwindow;
|
||||
ESP_RETURN_ON_FALSE(
|
||||
(subwindow.top_left.x >= awb_cfg->window.top_left.x) &&
|
||||
(subwindow.top_left.y >= awb_cfg->window.top_left.y) &&
|
||||
(subwindow.btm_right.x <= awb_cfg->window.btm_right.x) &&
|
||||
(subwindow.btm_right.y <= awb_cfg->window.btm_right.y),
|
||||
ESP_ERR_INVALID_ARG, TAG, "subwindow exceeds window range"
|
||||
);
|
||||
|
||||
if ((subwindow.btm_right.x - subwindow.top_left.x + 1) / ISP_AWB_WINDOW_X_NUM < 4 ||
|
||||
(subwindow.btm_right.y - subwindow.top_left.y + 1) / ISP_AWB_WINDOW_Y_NUM < 4) {
|
||||
ESP_LOGE(TAG, "subwindow block size is too small: width and height must be at least 4 (got %d x %d)",
|
||||
(subwindow.btm_right.x - subwindow.top_left.x + 1) / ISP_AWB_WINDOW_X_NUM,
|
||||
(subwindow.btm_right.y - subwindow.top_left.y + 1) / ISP_AWB_WINDOW_Y_NUM);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int size_x = subwindow.btm_right.x - subwindow.top_left.x + 1;
|
||||
int size_y = subwindow.btm_right.y - subwindow.top_left.y + 1;
|
||||
if ((size_x % ISP_AWB_WINDOW_X_NUM != 0) || (size_y % ISP_AWB_WINDOW_Y_NUM != 0)) {
|
||||
ESP_LOGW(TAG, "subwindow size (%d x %d) is not divisible by AWB subwindow blocks grid (%d x %d). \
|
||||
Resolution will be floored to the nearest divisible value.",
|
||||
size_x, size_y, ISP_AWB_WINDOW_X_NUM, ISP_AWB_WINDOW_Y_NUM);
|
||||
// floor to the nearest divisible value
|
||||
subwindow.btm_right.x -= size_x % ISP_AWB_WINDOW_X_NUM;
|
||||
subwindow.btm_right.y -= size_y % ISP_AWB_WINDOW_Y_NUM;
|
||||
}
|
||||
ESP_RETURN_ON_FALSE(isp_hal_awb_set_subwindow_range(&isp_proc->hal, &subwindow),
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid subwindow range");
|
||||
|
||||
isp_u32_range_t lum_range = awb_cfg->white_patch.luminance;
|
||||
ESP_RETURN_ON_FALSE(isp_hal_awb_set_luminance_range(&isp_proc->hal, lum_range.min, lum_range.max),
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid luminance range");
|
||||
|
||||
isp_float_range_t rg_range = awb_cfg->white_patch.red_green_ratio;
|
||||
ESP_RETURN_ON_FALSE(rg_range.min < rg_range.max && rg_range.min >= 0 &&
|
||||
isp_hal_awb_set_rg_ratio_range(&isp_proc->hal, rg_range.min, rg_range.max),
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid range of Red Green ratio");
|
||||
|
||||
isp_float_range_t bg_range = awb_cfg->white_patch.blue_green_ratio;
|
||||
ESP_RETURN_ON_FALSE(bg_range.min < bg_range.max && bg_range.min >= 0 &&
|
||||
isp_hal_awb_set_bg_ratio_range(&isp_proc->hal, bg_range.min, bg_range.max),
|
||||
|
||||
@@ -2499,6 +2499,23 @@ static inline void isp_ll_hist_set_rgb_coefficient(isp_dev_t *hw, const isp_hist
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
/**
|
||||
* @brief Set AWB subwindow range
|
||||
*
|
||||
* @param[in] hw Hardware instance address
|
||||
* @param[in] top_left_x Top left pixel x axis value
|
||||
* @param[in] top_left_y Top left pixel y axis value
|
||||
* @param[in] sub_window_xsize Subwindow x size (minimum 4)
|
||||
* @param[in] sub_window_ysize Subwindow y size (minimum 4)
|
||||
*/
|
||||
static inline void isp_ll_awb_set_subwindow_range(isp_dev_t *hw, uint32_t top_left_x, uint32_t top_left_y, uint32_t sub_window_xsize, uint32_t sub_window_ysize)
|
||||
{
|
||||
hw->awb_bx.awb_x_start = top_left_x;
|
||||
hw->awb_bx.awb_x_bsize = sub_window_xsize;
|
||||
hw->awb_by.awb_y_start = top_left_y;
|
||||
hw->awb_by.awb_y_bsize = sub_window_ysize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set crop clock control mode
|
||||
*
|
||||
@@ -2581,6 +2598,11 @@ static inline void isp_ll_crop_clear_error(isp_dev_t *hw)
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void isp_ll_awb_set_subwindow_range(isp_dev_t *hw, uint32_t top_left_x, uint32_t top_left_y, uint32_t sub_window_xsize, uint32_t sub_window_ysize)
|
||||
{
|
||||
// for compatibility
|
||||
}
|
||||
|
||||
static inline void isp_ll_crop_set_clk_ctrl_mode(isp_dev_t *hw, isp_ll_pipeline_clk_ctrl_t mode)
|
||||
{
|
||||
// for compatibility
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -132,6 +132,17 @@ void isp_hal_ae_window_config(isp_hal_context_t *hal, const isp_window_t *window
|
||||
*/
|
||||
bool isp_hal_awb_set_window_range(isp_hal_context_t *hal, const isp_window_t *win);
|
||||
|
||||
/**
|
||||
* @brief Set the subwindow range of the AWB
|
||||
*
|
||||
* @param[in] hal Context of the HAL layer
|
||||
* @param[in] win Pointer to the subwindow of the AWB
|
||||
* @return
|
||||
* - true Set success
|
||||
* - false Invalid arg
|
||||
*/
|
||||
bool isp_hal_awb_set_subwindow_range(isp_hal_context_t *hal, const isp_window_t *win);
|
||||
|
||||
/**
|
||||
* @brief Set the luminance range of the white patch
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -66,6 +66,24 @@ bool isp_hal_awb_set_window_range(isp_hal_context_t *hal, const isp_window_t *wi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isp_hal_awb_set_subwindow_range(isp_hal_context_t *hal, const isp_window_t *win)
|
||||
{
|
||||
if (win->top_left.x > win->btm_right.x ||
|
||||
win->top_left.y > win->btm_right.y ||
|
||||
win->btm_right.x > ISP_LL_AWB_WINDOW_MAX_RANGE ||
|
||||
win->btm_right.y > ISP_LL_AWB_WINDOW_MAX_RANGE) {
|
||||
return false;
|
||||
}
|
||||
isp_ll_awb_set_subwindow_range(
|
||||
hal->hw,
|
||||
win->top_left.x,
|
||||
win->top_left.y,
|
||||
(win->btm_right.x - win->top_left.x) / SOC_ISP_AWB_WINDOW_X_NUMS,
|
||||
(win->btm_right.y - win->top_left.y) / SOC_ISP_AWB_WINDOW_Y_NUMS
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isp_hal_awb_set_luminance_range(isp_hal_context_t *hal, uint32_t lum_min, uint32_t lum_max)
|
||||
{
|
||||
if (lum_min > lum_max || lum_max > ISP_LL_AWB_LUM_MAX_RANGE) {
|
||||
|
||||
Reference in New Issue
Block a user