mirror of
https://github.com/espressif/esp-idf.git
synced 2025-12-05 08:27:30 +00:00
change(isp): rename isp_af example to isp example
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
set(srcs)
|
||||
|
||||
list(APPEND srcs "src/isp_af_scheme.c"
|
||||
"src/isp_af_scheme_sa.c")
|
||||
|
||||
set(priv_requires "esp_driver_isp")
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "include" "interface"
|
||||
PRIV_REQUIRES ${priv_requires})
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Type of ISP AF scheme handle
|
||||
*/
|
||||
typedef struct isp_af_scheme_t *isp_af_scheme_handle_t;
|
||||
|
||||
/**
|
||||
* @brief ISP AF process, which is used to calculate definition threshold and luminance threshold for AF environment detector to detect environment change
|
||||
*
|
||||
* @param[in] scheme AF scheme handle
|
||||
* @param[out] out_definition_thresh Calculated definition threshold
|
||||
* @param[out] out_luminance_thresh Calculated luminance threshold
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
* - ESP_ERR_INVALID_STATE Driver state is invalid.
|
||||
*/
|
||||
esp_err_t isp_af_process(isp_af_scheme_handle_t scheme, int *out_definition_thresh, int *out_luminance_thresh);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "isp_af_scheme.h"
|
||||
#include "driver/isp_af.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ISP AF Step Approximation Scheme (SA Scheme)
|
||||
---------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
int first_step_val; ///< Step of the camera sensor focus value for first stage approximation
|
||||
int first_approx_cycles; ///< First stage approximation cycles
|
||||
int second_step_val; ///< Step of the camera sensor focus value for second stage approximation
|
||||
int second_approx_cycles; ///< Second stage approximation cycles
|
||||
} isp_af_sa_scheme_config_t;
|
||||
|
||||
typedef struct {
|
||||
int focus_val_max; ///< Max camera sensor focus value
|
||||
} isp_af_sa_scheme_sensor_info_t;
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Sensor driver API to set sensor focus value
|
||||
*
|
||||
* @param[in] focus_val Camera sensor focus value
|
||||
* @param[in] arg User arg
|
||||
*/
|
||||
esp_err_t (*af_sensor_set_focus)(int focus_val, void *arg);
|
||||
|
||||
} isp_af_sa_scheme_sensor_drv_t;
|
||||
|
||||
/**
|
||||
* @brief Create an AF step approximation scheme
|
||||
*
|
||||
* @param[in] af_ctrlr AF controller handle
|
||||
* @param[in] config AF SA scheme configurations, see `isp_af_sa_scheme_config_t`
|
||||
* @param[out] ret_scheme AF scheme handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid
|
||||
* - ESP_ERR_INVALID_STATE Invalid state
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
*/
|
||||
esp_err_t isp_af_create_sa_scheme(isp_af_ctlr_t af_ctrlr, const isp_af_sa_scheme_config_t *config, isp_af_scheme_handle_t *ret_scheme);
|
||||
|
||||
/**
|
||||
* @brief Delete an AF step approximation scheme
|
||||
*
|
||||
* @param[in] scheme AF scheme handle
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid
|
||||
* - ESP_ERR_INVALID_STATE Invalid state
|
||||
* - ESP_ERR_NO_MEM If out of memory
|
||||
*/
|
||||
esp_err_t isp_af_delete_sa_scheme(isp_af_scheme_handle_t scheme);
|
||||
|
||||
/**
|
||||
* @brief Register camera sensor driver to the SA scheme
|
||||
*
|
||||
* @param[in] scheme AF scheme handle
|
||||
* @param[in] sensor_drv Sensor driver, see `isp_af_sa_scheme_sensor_drv_t`
|
||||
* @param[in] info Sensor info
|
||||
* @param[in] arg User arg
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK On success
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid
|
||||
* - ESP_ERR_INVALID_STATE Invalid state
|
||||
*/
|
||||
esp_err_t isp_af_sa_scheme_register_sensor_driver(isp_af_scheme_handle_t scheme, const isp_af_sa_scheme_sensor_drv_t *sensor_drv, const isp_af_sa_scheme_sensor_info_t *info, void *arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct isp_af_scheme_t isp_af_scheme_t;
|
||||
|
||||
/**
|
||||
* @brief ISP AF Scheme Interface
|
||||
*/
|
||||
struct isp_af_scheme_t {
|
||||
/**
|
||||
* @brief Do AF
|
||||
*
|
||||
* @param[in] arg ISP AF scheme specific context
|
||||
* @param[out] definition_thresh Definition thresh that is updated according to the current definition, this can be used to set to the ISP AF Env detector
|
||||
* @param[out] luminance_thresh Luminance thresh that is updated according to the current luminance, this can be used to set to the ISP AF Env detector
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
esp_err_t (*af_process)(void *arg, int *out_definition_thresh, int *out_luminance_thresh);
|
||||
|
||||
/**
|
||||
* @brief ISP AF scheme specific contexts
|
||||
* Can be customized to difference AF schemes
|
||||
*/
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "esp_types.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "isp_af_scheme.h"
|
||||
#include "isp_af_scheme_interface.h"
|
||||
|
||||
const static char *TAG = "AF_SCHEME";
|
||||
|
||||
esp_err_t isp_af_process(isp_af_scheme_handle_t scheme, int *out_definition_thresh, int *out_luminance_thresh)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(scheme, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
ESP_RETURN_ON_FALSE(scheme->ctx, ESP_ERR_INVALID_STATE, TAG, "no scheme registered, create a scheme first");
|
||||
|
||||
return scheme->af_process(scheme->ctx, out_definition_thresh, out_luminance_thresh);
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "driver/isp_af.h"
|
||||
#include "isp_af_scheme_sa.h"
|
||||
#include "isp_af_scheme_interface.h"
|
||||
|
||||
#define ISP_AF_SCHEME_SA_DEFAULT_WINDOW_NUMS 3
|
||||
#define ISP_AF_SCHEME_SA_ENV_THRESH_SEARCH_NUMS 30
|
||||
|
||||
static const char *TAG = "AF_SCHEME";
|
||||
|
||||
typedef struct {
|
||||
isp_af_ctlr_t af_ctlr;
|
||||
int first_step_val;
|
||||
int first_approx_cycles;
|
||||
int second_step_val;
|
||||
int second_approx_cycles;
|
||||
|
||||
isp_af_sa_scheme_sensor_info_t sensor_info;
|
||||
isp_af_sa_scheme_sensor_drv_t sensor_drv;
|
||||
void *arg;
|
||||
} af_scheme_context_t;
|
||||
|
||||
/* ------------------------ Interface Functions --------------------------- */
|
||||
static esp_err_t s_af_process(void *arg, int *out_definition_thresh, int *out_luminance_thresh);
|
||||
|
||||
/* ------------------------- Public API ------------------------------------- */
|
||||
esp_err_t isp_af_create_sa_scheme(isp_af_ctlr_t af_ctlr, const isp_af_sa_scheme_config_t *config, isp_af_scheme_handle_t *ret_scheme)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
ESP_RETURN_ON_FALSE(af_ctlr && config && ret_scheme, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
|
||||
|
||||
isp_af_scheme_t *scheme = (isp_af_scheme_t *)heap_caps_calloc(1, sizeof(isp_af_scheme_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_RETURN_ON_FALSE(scheme, ESP_ERR_NO_MEM, TAG, "no mem for scheme");
|
||||
|
||||
af_scheme_context_t *ctx = (af_scheme_context_t *)heap_caps_calloc(1, sizeof(af_scheme_context_t), MALLOC_CAP_DEFAULT);
|
||||
ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, err, TAG, "no mem scheme context");
|
||||
|
||||
scheme->af_process = s_af_process;
|
||||
scheme->ctx = ctx;
|
||||
|
||||
ctx->af_ctlr = af_ctlr;
|
||||
ctx->first_step_val = config->first_step_val;
|
||||
ctx->first_approx_cycles = config->first_approx_cycles;
|
||||
ctx->second_step_val = config->second_step_val;
|
||||
ctx->second_approx_cycles = config->second_approx_cycles;
|
||||
|
||||
*ret_scheme = scheme;
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
free(scheme);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t isp_af_delete_sa_scheme(isp_af_scheme_handle_t scheme)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(scheme, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
|
||||
|
||||
free(scheme->ctx);
|
||||
scheme->ctx = NULL;
|
||||
|
||||
free(scheme);
|
||||
scheme = NULL;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t isp_af_sa_scheme_register_sensor_driver(isp_af_scheme_handle_t scheme, const isp_af_sa_scheme_sensor_drv_t *sensor_drv, const isp_af_sa_scheme_sensor_info_t *info, void *arg)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(scheme, ESP_ERR_INVALID_ARG, TAG, "invalid arg: null pointer");
|
||||
ESP_RETURN_ON_FALSE(scheme->ctx, ESP_ERR_INVALID_STATE, TAG, "no scheme created yet");
|
||||
|
||||
af_scheme_context_t *ctx = scheme->ctx;
|
||||
ctx->sensor_drv.af_sensor_set_focus = sensor_drv->af_sensor_set_focus;
|
||||
ctx->sensor_info.focus_val_max = info->focus_val_max;
|
||||
ctx->arg = arg;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* ------------------------ Interface Functions --------------------------- */
|
||||
static esp_err_t s_af_process(void *arg, int *out_definition_thresh, int *out_luminance_thresh)
|
||||
{
|
||||
//arg pointer is checked in the upper layer
|
||||
|
||||
af_scheme_context_t *ctx = arg;
|
||||
ESP_RETURN_ON_FALSE(ctx->af_ctlr, ESP_ERR_INVALID_STATE, TAG, "no AF controller registered");
|
||||
ESP_RETURN_ON_FALSE(ctx->sensor_drv.af_sensor_set_focus, ESP_ERR_INVALID_STATE, TAG, "no sensor driver function `af_sensor_set_focus` registered");
|
||||
|
||||
int af_sum = 0;
|
||||
int af_lum = 0;
|
||||
int af_sum_max = 0;
|
||||
|
||||
int af_current_base = 0;
|
||||
int af_current = 0;
|
||||
int af_current_best = 0;
|
||||
|
||||
int af_sum_env_th = 0;
|
||||
int af_lum_env_th = 0;
|
||||
int af_sum_tmp[ISP_AF_SCHEME_SA_ENV_THRESH_SEARCH_NUMS] = {0};
|
||||
int af_lum_tmp[ISP_AF_SCHEME_SA_ENV_THRESH_SEARCH_NUMS] = {0};
|
||||
|
||||
int ref_x = ISP_AF_SCHEME_SA_ENV_THRESH_SEARCH_NUMS;
|
||||
int ref_x_fallback = ISP_AF_SCHEME_SA_ENV_THRESH_SEARCH_NUMS - 1;
|
||||
|
||||
isp_af_result_t result = {};
|
||||
|
||||
ESP_RETURN_ON_ERROR(ctx->sensor_drv.af_sensor_set_focus(0, ctx->arg), TAG, "sensor set focus val fail");
|
||||
|
||||
ESP_LOGV(TAG, "//----------- af start ----------//");
|
||||
|
||||
// first search
|
||||
ESP_LOGV(TAG, "//----------- first search ----------//");
|
||||
af_sum_max = 0;
|
||||
af_current_base = 0;
|
||||
|
||||
for (int x = 0; x <= ctx->first_approx_cycles; x++) {
|
||||
af_current = af_current_base + x * ctx->first_step_val;
|
||||
ESP_RETURN_ON_ERROR(ctx->sensor_drv.af_sensor_set_focus(af_current, ctx->arg), TAG, "sensor set focus val fail");
|
||||
ESP_RETURN_ON_ERROR(esp_isp_af_controller_get_oneshot_result(ctx->af_ctlr, &result), TAG, "get AF result fail");
|
||||
af_sum = result.definition[0] + result.definition[1] + result.definition[2];
|
||||
if (af_sum > af_sum_max) {
|
||||
af_sum_max = af_sum;
|
||||
af_current_best = af_current;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "af_sum: %d, af_current: %d.%d", af_sum, (int)af_current, (int)((int)(af_current * 1000) % 1000));
|
||||
}
|
||||
|
||||
// second search
|
||||
ESP_LOGV(TAG, "//----------- second search ----------//");
|
||||
af_sum_max = 0;
|
||||
af_current_base = af_current_best + 10;
|
||||
|
||||
if (af_current_base > ctx->sensor_info.focus_val_max) {
|
||||
af_current_base = ctx->sensor_info.focus_val_max;
|
||||
}
|
||||
|
||||
for (int x = 0; x <= ctx->second_approx_cycles; x++) {
|
||||
af_current = af_current_base - x * ctx->second_step_val;
|
||||
if (af_current < 0) {
|
||||
af_current = 0;
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(ctx->sensor_drv.af_sensor_set_focus(af_current, ctx->arg), TAG, "sensor set focus val fail");
|
||||
ESP_RETURN_ON_ERROR(esp_isp_af_controller_get_oneshot_result(ctx->af_ctlr, &result), TAG, "get AF result fail");
|
||||
af_sum = result.definition[0] + result.definition[1] + result.definition[2];
|
||||
if (af_sum > af_sum_max) {
|
||||
af_sum_max = af_sum;
|
||||
af_current_best = af_current;
|
||||
}
|
||||
ESP_LOGV(TAG, "af_sum: %d, af_current: %d.%d", af_sum, (int)af_current, (int)((int)(af_current * 1000) % 1000));
|
||||
}
|
||||
|
||||
// af done
|
||||
ESP_LOGV(TAG, "//----------- af done ----------//");
|
||||
ESP_LOGV(TAG, "af_sum_max: %d, af_current_best: %d.%d", af_sum_max, (int)af_current_best, (int)((int)(af_current_best * 1000) % 1000));
|
||||
ESP_RETURN_ON_ERROR(ctx->sensor_drv.af_sensor_set_focus(af_current_best, ctx->arg), TAG, "sensor set focus val fail");
|
||||
|
||||
// update env threshold
|
||||
ESP_LOGV(TAG, "//------- update env threshold -------//");
|
||||
|
||||
bool use_fallback_th = true;
|
||||
for (int x = 0; x < ref_x; x++) {
|
||||
ESP_RETURN_ON_ERROR(esp_isp_af_controller_get_oneshot_result(ctx->af_ctlr, &result), TAG, "get AF result fail");
|
||||
af_sum_tmp[x] = result.definition[0] + result.definition[1] + result.definition[2];
|
||||
af_lum_tmp[x] = result.luminance[0] + result.luminance[1] + result.luminance[2];
|
||||
|
||||
if ((x >= 1) && (abs(af_sum_tmp[x] - af_sum_max) < af_sum_max * 0.3) && (abs(af_sum_tmp[x - 1] - af_sum_max) < af_sum_max * 0.3)) {
|
||||
ref_x = x;
|
||||
use_fallback_th = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_fallback_th) {
|
||||
ref_x = ref_x_fallback;
|
||||
}
|
||||
|
||||
af_sum = af_sum_tmp[ref_x];
|
||||
af_lum = af_lum_tmp[ref_x];
|
||||
af_sum_env_th = af_sum * 0.5;
|
||||
af_lum_env_th = af_lum * 0.05;
|
||||
*out_definition_thresh = af_sum_env_th;
|
||||
*out_luminance_thresh = af_lum_env_th;
|
||||
|
||||
for (int x = 0; x < ref_x; x++) {
|
||||
ESP_LOGV(TAG, "af_sum[%d]: %d, af_lum[%d]: %d", x, af_sum_tmp[x], x, af_lum_tmp[x]);
|
||||
}
|
||||
ESP_LOGV(TAG, "//------- update af env threshold done -------//");
|
||||
ESP_LOGV(TAG, "af_sum: %d, af_sum_env_th: %d", af_sum, af_sum_env_th);
|
||||
ESP_LOGV(TAG, "af_lum: %d, af_lum_env_th: %d", af_lum, af_lum_env_th);
|
||||
ESP_LOGV(TAG, "//----------- af update done ----------//\n\n");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user