Merge branch 'feat/isp_dpc_support_v6.0' into 'release/v6.0'

feat(isp): support isp dpc dead pixel correction (v6.0)

See merge request espressif/esp-idf!51470
This commit is contained in:
morris
2026-09-08 15:06:44 +08:00
24 changed files with 2234 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ This example demonstrates how to use the ISP (image signal processor) to work wi
- ISP AF (auto-focus) feature
- ISP BF (bayer denoise) feature
- ISP BLC (black level correction) feature
- ISP DPC (dead pixel correction) feature
- ISP Sharpen feature
- ISP Demosaic feature
- ISP GAMMA feature

View File

@@ -2,7 +2,8 @@ set(srcs "isp_dsi_main.c"
"example_buffer.c"
"example_af.c"
"example_awb.c"
"example_pipelines.c")
"example_pipelines.c"
"example_dpc.c")
if(CONFIG_EXAMPLE_ISP_CROP_ENABLE)
list(APPEND srcs "example_crop.c")

View File

@@ -53,6 +53,24 @@ menu "Example Configuration"
Enable ISP crop functionality. When enabled, you can configure
the crop area for the ISP pipeline.
config EXAMPLE_ISP_ENABLE_DPC
depends on (ESP32P4_REV_MIN_FULL >= 300)
bool "Enable ISP dead pixel correction"
default y
help
Enable the ISP Dead Pixel Correction (DPC) example. This feature
requires ESP32-P4 revision v3.0 or later.
config EXAMPLE_ISP_DPC_STATIC_CALIBRATION
depends on EXAMPLE_ISP_ENABLE_DPC
bool "Enable ISP DPC static calibration"
default n
help
Enable static DPC calibration using camera input. At startup, the
example prompts the user to provide uniform white and black images,
then press Enter after each image is ready.
Dynamic DPC remains enabled regardless of this option.
menu "ISP Crop Configuration"
visible if EXAMPLE_ISP_CROP_ENABLE

View File

@@ -0,0 +1,130 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <inttypes.h>
#include <stdio.h>
#include "esp_log.h"
#include "esp_check.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/isp_dpc.h"
#include "example_dpc.h"
static const char *TAG = "isp_dpc";
#define EXAMPLE_DPC_WHITE_THRESHOLD 0xf0
#define EXAMPLE_DPC_BLACK_THRESHOLD 0x0a
#define EXAMPLE_DPC_CALIBRATION_TIMEOUT_MS 5000
static esp_isp_dpc_calibration_ref_t s_white_calibration_ref;
static esp_isp_dpc_calibration_ref_t s_black_calibration_ref;
/* Wait for the user to prepare the requested calibration image. */
static void s_example_dpc_wait_for_calibration_image(const char *image_name)
{
ESP_LOGI(TAG, "Present a uniform %s image to the camera, then press Enter", image_name);
int c;
do {
c = getchar();
if (c == EOF) {
vTaskDelay(pdMS_TO_TICKS(10));
}
} while (c != '\n');
}
/* Capture white and black calibration frames, then merge their bad-pixel lists. */
esp_err_t example_isp_dpc_calibrate_static(isp_proc_handle_t isp_proc, esp_isp_dpc_calibration_ref_t *calibration_ref)
{
ESP_RETURN_ON_FALSE(isp_proc && calibration_ref, ESP_ERR_INVALID_ARG, TAG, "invalid arguments");
esp_isp_dpc_calibration_config_t calibration_config = {
.enable_output = true,
};
s_example_dpc_wait_for_calibration_image("white");
calibration_config.threshold = EXAMPLE_DPC_WHITE_THRESHOLD;
ESP_RETURN_ON_ERROR(esp_isp_dpc_static_calibration_start_once(isp_proc, ESP_ISP_DPC_CALIBRATION_IMAGE_WHITE, &calibration_config),
TAG, "failed to start white-frame DPC calibration");
ESP_RETURN_ON_ERROR(esp_isp_dpc_calibration_read_result(isp_proc, EXAMPLE_DPC_CALIBRATION_TIMEOUT_MS, &s_white_calibration_ref),
TAG, "failed to read white-frame DPC calibration result");
s_example_dpc_wait_for_calibration_image("black");
calibration_config.threshold = EXAMPLE_DPC_BLACK_THRESHOLD;
ESP_RETURN_ON_ERROR(esp_isp_dpc_static_calibration_start_once(isp_proc, ESP_ISP_DPC_CALIBRATION_IMAGE_BLACK, &calibration_config),
TAG, "failed to start black-frame DPC calibration");
ESP_RETURN_ON_ERROR(esp_isp_dpc_calibration_read_result(isp_proc, EXAMPLE_DPC_CALIBRATION_TIMEOUT_MS, &s_black_calibration_ref),
TAG, "failed to read black-frame DPC calibration result");
const esp_isp_dpc_calibration_ref_t *refs[] = {
&s_white_calibration_ref,
&s_black_calibration_ref,
};
ESP_RETURN_ON_ERROR(esp_isp_dpc_calibration_merge_result(refs, sizeof(refs) / sizeof(refs[0]), calibration_ref),
TAG, "failed to merge DPC calibration results");
ESP_LOGI(TAG, "DPC static calibration done, %" PRIu32 " dead pixels found", calibration_ref->dead_pixel_count);
return ESP_OK;
}
/* Configure static correction when available, followed by dynamic correction. */
esp_err_t example_isp_dpc_init(isp_proc_handle_t isp_proc, const esp_isp_dpc_calibration_ref_t *calibration_ref)
{
ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "Invalid arguments: isp_proc is NULL");
if (calibration_ref) {
esp_isp_dpc_static_config_t static_config = {
.dead_pixel_coords = calibration_ref->dead_pixel_coords,
.dead_pixel_count = calibration_ref->dead_pixel_count,
};
esp_err_t ret = esp_isp_dpc_static_configure(isp_proc, &static_config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to configure static DPC: %d", ret);
return ret;
}
ESP_LOGI(TAG, "DPC static correction configured");
}
esp_isp_dpc_dynamic_config_t dpc_config = {
.method = ESP_ISP_DPC_DYNAMIC_METHOD_1,
.method_1 = {
.high_threshold = 48,
.low_threshold = 48,
},
};
esp_err_t ret = esp_isp_dpc_dynamic_configure(isp_proc, &dpc_config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to configure DPC: %d", ret);
return ret;
}
esp_isp_dpc_config_t common_config = {
.flags.update_once_configured = true,
};
ret = esp_isp_dpc_configure(isp_proc, &common_config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to configure common DPC settings: %d", ret);
return ret;
}
ESP_LOGI(TAG, "DPC module initialized");
return ESP_OK;
}
/* Enable the configured DPC module. */
esp_err_t example_isp_dpc_enable(isp_proc_handle_t isp_proc)
{
ESP_RETURN_ON_FALSE(isp_proc, ESP_ERR_INVALID_ARG, TAG, "Invalid arguments: isp_proc is NULL");
esp_err_t ret = esp_isp_dpc_enable(isp_proc);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to enable DPC: %d", ret);
return ret;
}
ESP_LOGI(TAG, "DPC module enabled");
return ESP_OK;
}

View File

@@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file example_dpc.h
* @brief Dead Pixel Correction (DPC) Functionality
*/
#pragma once
#include "esp_err.h"
#include "driver/isp.h"
#include "driver/isp_dpc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialize DPC module
*
* @param[in] isp_proc ISP processor handle
* @param[in] calibration_ref Static calibration coordinate reference, or NULL to skip static correction
* @return
* - ESP_OK: Success
* - ESP_ERR_INVALID_ARG: Invalid arguments
* - ESP_ERR_INVALID_STATE: DPC is already enabled
* - ESP_ERR_NOT_SUPPORTED: Not supported on this chip revision
*/
esp_err_t example_isp_dpc_init(isp_proc_handle_t isp_proc, const esp_isp_dpc_calibration_ref_t *calibration_ref);
/**
* @brief Calibrate static DPC using the active CSI ISP processor
*
* The function prompts the user to present uniform white and black images to the
* camera and press Enter after each image is ready, then captures one frame of
* each to produce a merged calibration result.
* DPC must be disabled before calling this function.
*
* @param[in] isp_proc ISP processor handle receiving CSI input
* @param[out] calibration_ref Merged static calibration coordinate reference
* @return
* - ESP_OK: Success
* - ESP_ERR_INVALID_ARG: Invalid arguments
* - ESP_ERR_TIMEOUT: Calibration frame was not received in time
*/
esp_err_t example_isp_dpc_calibrate_static(isp_proc_handle_t isp_proc, esp_isp_dpc_calibration_ref_t *calibration_ref);
/**
* @brief Enable DPC module
*
* @param[in] isp_proc ISP processor handle
* @return
* - ESP_OK: Success
* - ESP_ERR_INVALID_ARG: Invalid arguments
* - ESP_ERR_INVALID_STATE: Invalid state
*/
esp_err_t example_isp_dpc_enable(isp_proc_handle_t isp_proc);
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -28,6 +28,7 @@
#include "example_af.h"
#include "example_awb.h"
#include "example_pipelines.h"
#include "example_dpc.h"
#ifdef CONFIG_EXAMPLE_ISP_CROP_ENABLE
#include "example_crop.h"
#endif
@@ -266,6 +267,33 @@ void app_main(void)
return;
}
#if CONFIG_EXAMPLE_ISP_ENABLE_DPC
const esp_isp_dpc_calibration_ref_t *dpc_calibration_ref = NULL;
#if CONFIG_EXAMPLE_ISP_DPC_STATIC_CALIBRATION
static esp_isp_dpc_calibration_ref_t static_dpc_calibration_ref;
// The calibration function prompts the user to present uniform white and black images.
ret = example_isp_dpc_calibrate_static(isp_proc, &static_dpc_calibration_ref);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "DPC static calibration fail[%d]", ret);
return;
}
dpc_calibration_ref = &static_dpc_calibration_ref;
#endif /* CONFIG_EXAMPLE_ISP_DPC_STATIC_CALIBRATION */
//---------------DPC Init and Enable------------------//
ret = example_isp_dpc_init(isp_proc, dpc_calibration_ref);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "DPC init fail[%d]", ret);
return;
}
ret = example_isp_dpc_enable(isp_proc);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "DPC enable fail[%d]", ret);
return;
}
#endif /* CONFIG_EXAMPLE_ISP_ENABLE_DPC */
example_dpi_panel_init(mipi_dpi_panel);
ESP_LOGI(TAG, "ISP DSI example started");