esp-idf/docs/zh_CN/api-reference/peripherals/isp.rst

827 wiersze
34 KiB
ReStructuredText
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

图像信号处理器 (ISP)
====================
:link_to_translation:`en:[English]`
简介
----
{IDF_TARGET_NAME} 内含图像信号处理器 (ISP)是由众多图像处理算法组成的流水线。ISP 从 DVP 摄像头、MIPI-CSI 摄像头或系统存储处接收图像数据,并通过 DMA 将处理后的图像数据写入系统存储。ISP 需要与其他摄像头控制器模块协同工作,无法独立工作。
术语表
------
.. list::
- MIPI-CSI符合 MIPI 规范的高速串行摄像头接口
- DVP数字视频并行接口通常由 vsync、hsync、de 和 data 信号组成
- RAW直接从图像传感器输出的未处理数据通常分为 R、Gr、Gb 和 B 四个通道,按位宽分为 RAW8、RAW10、RAW12 等不同格式
- RGB由红、绿、蓝三种颜色组成的彩色图像格式按每种颜色的位宽分为 RGB888、RGB565 等格式
- YUV由亮度和色度组成的彩色图像格式按数据排列方式分为 YUV444、YUV422、YUV420 等格式
- AF自动对焦
- AWB自动白平衡
- AE自动曝光
- HIST直方图
- BF拜耳域降噪
- CCM色彩校正矩阵
ISP 流水线
----------
.. blockdiag::
:scale: 100%
:caption: ISP 流水线
:align: center
blockdiag isp_pipeline {
orientation = portrait;
node_height = 30;
node_width = 120;
span_width = 100;
default_fontsize = 16;
isp_header [label = "ISP Header"];
isp_tail [label = "ISP Tail"];
isp_chs [label = "对比度 &\n 色调 & 饱和度", width = 150, height = 70];
isp_yuv [label = "YUV 限制\n YUB2RGB", width = 120, height = 70];
isp_header -> BF -> 去马赛克 -> CCM -> gamma 校正 -> RGB 转 YUV -> 锐化 -> isp_chs -> isp_yuv -> isp_tail;
BF -> HIST
去马赛克 -> AWB
去马赛克 -> AE
去马赛克 -> HIST
CCM -> AWB
gamma 校正 -> AE
RGB 转 YUV -> HIST
RGB 转 YUV -> AF
}
功能概述
--------
ISP 驱动程序提供以下服务:
- :ref:`isp-resource-allocation` - 涵盖如何通过正确的配置来分配 ISP 资源,以及完成工作后如何回收资源。
- :ref:`isp-enable-disable` - 涵盖如何启用和禁用 ISP 处理器。
- :ref:`isp-af-statistics` - 涵盖如何单次或连续获取 AF 统计信息。
- :ref:`isp-awb-statistics` - 涵盖如何单次或连续获取 AWB 白块统计信息。
- :ref:`isp-ae-statistics` - 涵盖如何单次或连续获取 AE 统计信息。
- :ref:`isp-hist-statistics` - 涵盖如何单次或连续获取直方图统计信息。
- :ref:`isp-bf` - 涵盖如何启用和配置 BF 功能。
- :ref:`isp-ccm-config` - 涵盖如何配置 CCM。
- :ref:`isp-demosaic` - 涵盖如何配置去马赛克功能。
- :ref:`isp-gamma-correction` - 涵盖如何启用和配置 gamma 校正。
- :ref:`isp-sharpen` - 涵盖如何配置锐化功能。
- :ref:`isp-callback` - 涵盖如何将用户特定代码挂接到 ISP 驱动事件回调。
- :ref:`isp-thread-safety` - 列出了驱动程序中线程安全的 API。
- :ref:`isp-kconfig-options` - 列出了支持的 Kconfig 选项,这些选项可以对驱动程序产生不同影响。
- :ref:`isp-iram-safe` - 描述了当 cache 被禁用时,如何使 ISP 中断和控制功能正常工作。
.. _isp-resource-allocation:
资源分配
^^^^^^^^
安装 ISP 驱动程序
~~~~~~~~~~~~~~~~~
ISP 驱动程序需要由 :cpp:type:`esp_isp_processor_cfg_t` 指定配置。
指定 :cpp:type:`esp_isp_processor_cfg_t` 中的配置后,可以调用 :cpp:func:`esp_isp_new_processor` 来分配和初始化 ISP 处理器。如果函数运行正常,将返回一个 ISP 处理器句柄。请参考以下代码:
.. code-block:: c
esp_isp_processor_cfg_t isp_config = {
.clk_src = ISP_CLK_SRC_DEFAULT,
...
};
isp_proc_handle_t isp_proc = NULL;
ESP_ERROR_CHECK(esp_isp_new_processor(&isp_config, &isp_proc));
使用上述句柄,可以启用/禁用 ISP 驱动程序,也可以安装其他 ISP 模块。
安装 ISP 自动对焦 (AF) 驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP 自动对焦 (AF) 驱动程序需要由 :cpp:type:`esp_isp_af_config_t` 指定配置。
指定 :cpp:type:`esp_isp_af_config_t` 中的配置后,可以调用 :cpp:func:`esp_isp_new_af_controller` 来分配和初始化 ISP AF 控制器。如果函数运行正常,将返回一个 ISP AF 控制器句柄。请参考以下代码:
.. code-block:: c
esp_isp_af_config_t af_config = {
.edge_thresh = 128,
};
isp_af_ctlr_t af_ctrlr = NULL;
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
使用上述句柄,可以启用/禁用 ISP AF 驱动程序,也可以安装 ISP AF 环境检测模块。
安装 ISP 自动白平衡 (AWB) 驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP 自动白平衡 (AWB) 驱动程序需要由 :cpp:type:`esp_isp_awb_config_t` 指定配置。
指定 :cpp:type:`esp_isp_awb_config_t` 中的配置后,可以调用 :cpp:func:`esp_isp_new_awb_controller` 来分配和初始化 ISP AWB 控制器。如果函数运行正常,将返回一个 ISP AWB 控制器句柄。请参考以下代码:
.. code-block:: c
isp_awb_ctlr_t awb_ctlr = NULL;
uint32_t image_width = 800;
uint32_t image_height = 600;
/* AWB 配置,请参考 API 注释来调整参数 */
esp_isp_awb_config_t awb_config = {
.sample_point = ISP_AWB_SAMPLE_POINT_AFTER_CCM,
...
};
ESP_ERROR_CHECK(esp_isp_new_awb_controller(isp_proc, &awb_config, &awb_ctlr));
其他 AWB API 和 AWB 方案也需要此步骤中创建的 AWB 句柄。
安装 ISP 自动曝光 (AE) 驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP 自动曝光 (AE) 驱动程序需要由 :cpp:type:`esp_isp_ae_config_t` 指定配置。
指定 :cpp:type:`esp_isp_ae_config_t` 中的配置后,可以调用 :cpp:func:`esp_isp_new_ae_controller` 来分配和初始化 ISP AE 控制器。如果函数运行正常,将返回一个 ISP AE 控制器句柄。请参考以下代码:
.. code-block:: c
esp_isp_ae_config_t ae_config = {
.sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC,
...
};
isp_ae_ctlr_t ae_ctlr = NULL;
ESP_ERROR_CHECK(esp_isp_new_ae_controller(isp_proc, &ae_config, &ae_ctlr));
使用上述句柄,可以启用/禁用 ISP AE 驱动程序,也可以设置 ISP AE 环境检测器。
安装 ISP 直方图 (HIST) 驱动程序
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP 直方图 (HIST) 驱动程序需要由 :cpp:type:`esp_isp_hist_config_t` 指定配置。
指定 :cpp:type:`esp_isp_hist_config_t` 中的配置后,可以调用 :cpp:func:`esp_isp_new_hist_controller` 来分配和初始化 ISP 直方图控制器。如果此函数运行正常,将返回一个 ISP HIST 控制器句柄。请参考以下代码。
.. list::
- 所有子窗口权重的十进制值之和应为 256否则统计数据将较小并且整数值应为 0。
- 所有 RGB 系数的十进制值之和应为 256否则统计数据将较小并且整数值应为 0。
- segment_threshold 必须在 0~255 之间且按顺序排列。
.. code:: c
esp_isp_hist_config_t hist_cfg = {
.segment_threshold = {16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240},
.hist_mode = ISP_HIST_SAMPLING_RGB,
.rgb_coefficient.coeff_r = {
.integer = 0,
.decimal = 86,
},
.rgb_coefficient.coeff_g = {
.integer = 0,
.decimal = 85,
},
.rgb_coefficient.coeff_b = {
.integer = 0,
.decimal = 85,
},
.window_weight = {
{{16, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}},
{{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}},
{{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}},
{{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}},
{{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}}, {{10, 0}},
},
};
isp_hist_ctlr_t hist_ctlr_ctlr = NULL;
ESP_ERROR_CHECK(esp_isp_new_hist_controller(isp_proc, &hist_config, &hist_ctlr));
使用上述句柄,可以启用/禁用 ISP HIST 驱动程序的设置。
卸载 ISP 驱动程序
~~~~~~~~~~~~~~~~~
如果不再需要先前安装的 ISP 驱动程序,建议通过调用 API 来回收资源,并释放底层硬件:
.. list::
- :cpp:func:`esp_isp_del_processor`,用于 ISP 核心处理器。
- :cpp:func:`esp_isp_del_af_controller`,用于 ISP AF 控制器。
- :cpp:func:`esp_isp_del_awb_controller`,用于 ISP AWB 控制器。
- :cpp:func:`esp_isp_del_ae_controller`,用于 ISP AE 控制器。
- :cpp:func:`esp_isp_del_hist_controller`,用于 ISP 直方图控制器。
.. _isp-enable-disable:
启用和禁用 ISP
^^^^^^^^^^^^^^
ISP
~~~
在进行 ISP 流水线操作之前,需要先调用 :cpp:func:`esp_isp_enable` 函数来启用 ISP 处理器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
ISP AF 控制器
~~~~~~~~~~~~~
在进行 ISP AF 操作之前,需要先调用 :cpp:func:`esp_isp_af_controller_enable` 函数来启用 ISP AF 控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_af_controller_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
.. _isp-af-statistics:
单次与连续 AF 数据统计
^^^^^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_af_controller_get_oneshot_statistics` 可获取单次 AF 统计结果,请参考以下代码。
除此之外ISP AF 驱动程序还可以连续获取 AF 统计信息。调用 :cpp:func:`esp_isp_af_controller_start_continuous_statistics` 可启动连续统计,调用 :cpp:func:`esp_isp_af_controller_stop_continuous_statistics` 可停止统计。
若想启用连续统计,需要先注册回调函数 :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_statistics_done`:cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_change` 以获取统计数据。有关如何注册回调函数,请参见 :ref:`isp-callback`
.. note::
使用连续统计时AF 环境检测器将失效。
.. code-block:: c
esp_isp_af_config_t af_config = {
.edge_thresh = 128,
};
isp_af_ctlr_t af_ctrlr = NULL;
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
ESP_ERROR_CHECK(esp_isp_af_controller_enable(af_ctrlr));
isp_af_result_t result = {};
/* 触发单次 AF 统计并获取结果,超时时长为 2000 ms */
ESP_ERROR_CHECK(esp_isp_af_controller_get_oneshot_statistics(af_ctrlr, 2000, &result));
/* 启动连续 AF 数据统计 */
ESP_ERROR_CHECK(esp_isp_af_controller_start_continuous_statistics(af_ctrlr));
// 可在此进行其他操作,统计结果可从回调函数中获取
// ......
// vTaskDelay(pdMS_TO_TICKS(1000));
/* 停止连续 AF 数据统计 */
ESP_ERROR_CHECK(esp_isp_af_controller_stop_continuous_statistics(af_ctrlr));
/* 禁用 AF 控制器 */
ESP_ERROR_CHECK(esp_isp_af_controller_disable(af_ctrlr));
/* 删除 AF 控制器并释放资源 */
ESP_ERROR_CHECK(esp_isp_del_af_controller(af_ctrlr));
设置 AF 环境检测器
^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_af_controller_set_env_detector` 来设置 ISP AF 环境检测器,请参考以下代码:
.. code-block:: c
esp_isp_af_env_config_t env_config = {
.interval = 10,
};
isp_af_ctlr_t af_ctrlr = NULL;
ESP_ERROR_CHECK(esp_isp_new_af_controller(isp_proc, &af_config, &af_ctrlr));
ESP_ERROR_CHECK(esp_isp_af_controller_set_env_detector(af_ctrlr, &env_config));
设置 AF 环境检测器阈值
^^^^^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_af_controller_set_env_detector_threshold` 来设置 ISP AF 环境检测器的阈值。
.. code-block:: c
int definition_thresh = 0;
int luminance_thresh = 0;
ESP_ERROR_CHECK(esp_isp_af_env_detector_set_threshold(env_detector, definition_thresh, luminance_thresh));
ISP AWB 控制器
~~~~~~~~~~~~~~
在进行 ISP AWB 操作之前,需要先调用 :cpp:func:`esp_isp_awb_controller_enable` 以启用 ISP AWB 控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_awb_controller_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
.. _isp-awb-statistics:
单次与连续 AWB 数据统计
^^^^^^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_awb_controller_get_oneshot_statistics` 可获取单次 AWB 白块统计结果,请参考以下代码。
除此之外ISP AWB 驱动程序还可以连续获取 AWB 统计信息。调用 :cpp:func:`esp_isp_awb_controller_start_continuous_statistics` 可启动连续统计,调用 :cpp:func:`esp_isp_awb_controller_stop_continuous_statistics` 可停止统计。
若想启用连续统计,需要先注册回调函数 :cpp:member:`esp_isp_awb_cbs_t::on_statistics_done` 以获取统计结果。有关如何注册回调函数,请参见 :ref:`isp-callback`
.. code-block:: c
bool example_isp_awb_on_statistics_done_cb(isp_awb_ctlr_t awb_ctlr, const esp_isp_awb_evt_data_t *edata, void *user_data);
// ...
isp_awb_ctlr_t awb_ctlr = NULL;
uint32_t image_width = 800;
uint32_t image_height = 600;
/* AWB 配置,请参考 API 注释来调整参数 */
esp_isp_awb_config_t awb_config = {
.sample_point = ISP_AWB_SAMPLE_POINT_AFTER_CCM,
...
};
isp_awb_stat_result_t stat_res = {};
/* 创建 AWB 控制器 */
ESP_ERROR_CHECK(esp_isp_new_awb_controller(isp_proc, &awb_config, &awb_ctlr));
/* 注册 AWB 回调函数 */
esp_isp_awb_cbs_t awb_cb = {
.on_statistics_done = example_isp_awb_on_statistics_done_cb,
};
ESP_ERROR_CHECK(esp_isp_awb_register_event_callbacks(awb_ctlr, &awb_cb, NULL));
/* 启用 AWB 控制器 */
ESP_ERROR_CHECK(esp_isp_awb_controller_enable(awb_ctlr));
/* 获取单次 AWB 统计结果 */
ESP_ERROR_CHECK(esp_isp_awb_controller_get_oneshot_statistics(awb_ctlr, -1, &stat_res));
/* 启动连续 AWB 数据统计,注意在此之前需要先注册 `on_statistics_done` 回调函数 */
ESP_ERROR_CHECK(esp_isp_awb_controller_start_continuous_statistics(awb_ctlr));
// 可在此进行其他操作,统计结果可从回调函数中获取
// ......
// vTaskDelay(pdMS_TO_TICKS(1000));
/* 停止连续 AWB 数据统计 */
ESP_ERROR_CHECK(esp_isp_awb_controller_stop_continuous_statistics(awb_ctlr));
/* 禁用 AWB 控制器 */
ESP_ERROR_CHECK(esp_isp_awb_controller_disable(awb_ctlr));
/* 删除 AWB 控制器并释放资源 */
ESP_ERROR_CHECK(esp_isp_del_awb_controller(awb_ctlr));
ISP AE 控制器
~~~~~~~~~~~~~
在进行 ISP AE 操作之前,需要先调用 :cpp:func:`esp_isp_ae_controller_enable` 来启用 ISP AE 控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_ae_controller_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
.. _isp-ae-statistics:
单次与连续 AE 数据统计
^^^^^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_ae_controller_get_oneshot_statistics` 可获取单次 AE 统计结果,请参考以下代码。
使用单次 AE 数据统计时,需要禁用连续 AE 模式,否则结果可能会被环境检测器覆盖。完成单次操作后,请重新启动连续模式。
除了上述单次统计 API 外ISP AE 驱动程序还可以连续获取 AE 统计信息。调用 :cpp:member:`esp_isp_ae_env_detector_evt_cbs_t::on_env_statistics_done` 可启动连续统计,调用 :cpp:member:`esp_isp_ae_env_detector_evt_cbs_t::on_env_change` 可停止统计。
若想启用连续统计,需要先注册回调函数 :cpp:member:`esp_isp_ae_env_detector_evt_cbs_t::on_env_statistics_done`:cpp:member:`esp_isp_ae_env_detector_evt_cbs_t::on_env_change` 以获取统计数据。有关如何注册回调函数,请参见 :ref:`isp-callback`
.. note::
使用单次统计时AE 环境检测器将暂时失效,并在完成单次操作后自动恢复。
.. code-block:: c
esp_isp_ae_config_t ae_config = {
.sample_point = ISP_AE_SAMPLE_POINT_AFTER_DEMOSAIC,
};
isp_ae_ctlr_t ae_ctlr = NULL;
ESP_ERROR_CHECK(esp_isp_new_ae_controller(isp_proc, &ae_config, &ae_ctlr));
ESP_ERROR_CHECK(esp_isp_ae_controller_enable(ae_ctlr));
isp_ae_result_t result = {};
/* 触发单次 AE 统计并获取结果,超时时长为 2000 ms */
ESP_ERROR_CHECK(esp_isp_ae_controller_get_oneshot_statistics(ae_ctlr, 2000, &result));
/* 启动连续 AE 数据统计 */
ESP_ERROR_CHECK(esp_isp_ae_controller_start_continuous_statistics(ae_ctlr));
// 可在此进行其他操作,统计结果可从回调函数中获取
// ......
// vTaskDelay(pdMS_TO_TICKS(1000));
/* 停止连续 AE 数据统计 */
ESP_ERROR_CHECK(esp_isp_ae_controller_stop_continuous_statistics(ae_ctlr));
/* 禁用 AE 控制器 */
ESP_ERROR_CHECK(esp_isp_ae_controller_disable(ae_ctlr));
/* 删除 AE 控制器并释放资源 */
ESP_ERROR_CHECK(esp_isp_del_ae_controller(ae_ctlr));
设置 AE 环境检测器
^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_ae_controller_set_env_detector` 来设置 ISP AE 环境检测器,请参考以下代码:
.. code:: c
esp_isp_ae_env_config_t env_config = {
.interval = 10,
};
ESP_ERROR_CHECK(esp_isp_ae_controller_set_env_detector(ae_ctlr, &env_config));
设置 AE 环境检测器阈值
^^^^^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_ae_controller_set_env_detector_threshold` 来设置 ISP AE 环境检测器的阈值 (1-255)。
.. code:: c
esp_isp_ae_env_thresh_t env_thresh = {
.low_thresh = 110,
.high_thresh = 130,
};
ESP_ERROR_CHECK(esp_isp_ae_controller_set_env_detector_threshold(ae_ctlr, env_thresh));
.. _isp-hist:
ISP 直方图控制器
~~~~~~~~~~~~~~~~
在进行 ISP 直方图统计之前,需要先调用 :cpp:func:`esp_isp_hist_controller_enable` 以启用 ISP 直方图控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_hist_controller_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
.. _isp-hist-statistics:
单次与连续直方图数据统计
^^^^^^^^^^^^^^^^^^^^^^^^
调用 :cpp:func:`esp_isp_hist_controller_get_oneshot_statistics` 可获取单次直方图统计结果,请参考以下代码。
除此之外ISP 直方图驱动程序还可以连续获取直方图统计信息。调用 :cpp:func:`esp_isp_hist_controller_start_continuous_statistics` 可启动连续统计,调用 :cpp:func:`esp_isp_hist_controller_stop_continuous_statistics` 可停止连续统计。
若想启用连续统计,需要先注册回调函数 :cpp:member:`esp_isp_hist_cbs_t::on_statistics_done` 以获取统计结果。有关如何注册回调函数,请参见 :ref:`isp-callback`
.. code:: c
static bool s_hist_scheme_on_statistics_done_callback(isp_hist_ctlr_t awb_ctrlr, const esp_isp_hist_evt_data_t *edata, void *user_data)
{
for(int i = 0; i < 16; i++) {
esp_rom_printf(DRAM_STR("val %d is %x\n"), i, edata->hist_result.hist_value[i]); // 获取直方图统计值
}
return true;
}
esp_isp_hist_cbs_t hist_cbs = {
.on_statistics_done = s_hist_scheme_on_statistics_done_callback,
};
esp_isp_hist_register_event_callbacks(hist_ctlr, &hist_cbs, hist_ctlr);
esp_isp_hist_controller_enable(hist_ctlr);
.. _isp-bf:
ISP BF 控制器
~~~~~~~~~~~~~
此流水线用于在拜耳模式下进行图像输入降噪。
可调用 :cpp:func:`esp_isp_bf_configure` 函数配置 BF 功能,请参考以下代码:
.. code-block:: c
esp_isp_bf_config_t bf_config = {
.denoising_level = 5,
.bf_template = {
{1, 2, 1},
{2, 4, 2},
{1, 2, 1},
},
...
};
ESP_ERROR_CHECK(esp_isp_bf_configure(isp_proc, &bf_config));
ESP_ERROR_CHECK(esp_isp_bf_enable(isp_proc));
:cpp:member:`esp_isp_bf_config_t::bf_template` 用于拜耳域降噪。可以通过高斯滤波器模板或均值滤波器模板来设置 :cpp:member:`esp_isp_bf_config_t::bf_template`
调用 :cpp:func:`esp_isp_bf_configure` 后,需要通过调用 :cpp:func:`esp_isp_bf_enable` 来启用 ISP BF 控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_bf_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
.. _isp-color:
ISP 色彩控制器
~~~~~~~~~~~~~~
该流水线用于调整图像的对比度、饱和度、色调和亮度。
可调用 :cpp:func:`esp_isp_color_configure` 函数配置色彩功能,请参考以下代码。
{IDF_TARGET_SOC_ISP_COLOR_CONTRAST_MAX:default="1.0", esp32p4="1.0"}
{IDF_TARGET_SOC_ISP_COLOR_CONTRAST_DEFAULT:default="1.0", esp32p4="1.0"}
{IDF_TARGET_SOC_ISP_COLOR_SATURATION_MAX:default="1.0", esp32p4="1.0"}
{IDF_TARGET_SOC_ISP_COLOR_SATURATION_DEFAULT:default="1.0", esp32p4="1.0"}
{IDF_TARGET_SOC_ISP_COLOR_HUE_MAX:default="360", esp32p4="360"}
{IDF_TARGET_SOC_ISP_COLOR_HUE_DEFAULT:default="0", esp32p4="0"}
{IDF_TARGET_SOC_ISP_COLOR_BRIGHTNESS_MIN:default="-127", esp32p4="-127"}
{IDF_TARGET_SOC_ISP_COLOR_BRIGHTNESS_MAX:default="128", esp32p4="128"}
{IDF_TARGET_SOC_ISP_COLOR_BRIGHTNESS_DEFAULT:default="0", esp32p4="0"}
.. list::
- 对比度应为 0 ~ {IDF_TARGET_SOC_ISP_COLOR_CONTRAST_MAX},默认值为 {IDF_TARGET_SOC_ISP_COLOR_CONTRAST_DEFAULT}
- 饱和度应为 0 ~ {IDF_TARGET_SOC_ISP_COLOR_SATURATION_MAX},默认值为 {IDF_TARGET_SOC_ISP_COLOR_SATURATION_DEFAULT}
- 色调应为 0 ~ {IDF_TARGET_SOC_ISP_COLOR_HUE_MAX},默认值为 {IDF_TARGET_SOC_ISP_COLOR_HUE_DEFAULT}
- 亮度应为 {IDF_TARGET_SOC_ISP_COLOR_BRIGHTNESS_MIN} ~ {IDF_TARGET_SOC_ISP_COLOR_BRIGHTNESS_MAX},默认值为 {IDF_TARGET_SOC_ISP_COLOR_BRIGHTNESS_DEFAULT}
.. code:: c
esp_isp_color_config_t color_config = {
.color_contrast = {
.integer = 1,
.decimal = 0,
},
.color_saturation = {
.integer = 1,
.decimal = 0,
},
.color_hue = 0,
.color_brightness = 0,
};
ESP_ERROR_CHECK(esp_isp_color_configure(isp_proc, &color_config));
ESP_ERROR_CHECK(esp_isp_color_enable(isp_proc));
调用 :cpp:func:`esp_isp_color_configure` 后,需要通过调用 :cpp:func:`esp_isp_color_enable` 来启用 ISP 色彩控制器。此函数:
* 将驱动程序状态从 **init** 切换为 **enable**
调用 :cpp:func:`esp_isp_color_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
.. _isp-ccm-config:
配置 CCM
^^^^^^^^
色彩校正矩阵可以调整 RGB888 像素格式的颜色比例,可用于通过算法调整图像颜色(例如,使用 AWB 计算结果进行白平衡),或者通过滤波算法用作过滤器。
调整色彩校正矩阵的公式如下:
.. code-block:: none
[ R' ] [ RR RG RB ] [ R ]
[ G' ] = [ GR GG GB ] * [ G ]
[ B' ] [ BR BG BB ] [ B ]
可以参考以下代码进行配置:
.. code-block:: c
// ...
// 配置 CCM
esp_isp_ccm_config_t ccm_cfg = {
.matrix = {
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
},
.saturation = false,
...
};
ESP_ERROR_CHECK(esp_isp_ccm_configure(isp_proc, &ccm_cfg));
// 启用 CCM 模块后,配置好的 CCM 将应用到图像上
ESP_ERROR_CHECK(esp_isp_ccm_enable(isp_proc));
// CCM 也可以在启用后进行配置
ccm_cfg.matrix[0][0] = 2.0;
ESP_ERROR_CHECK(esp_isp_ccm_configure(isp_proc, &ccm_cfg));
// 如果不再需要 CCM则禁用它
ESP_ERROR_CHECK(esp_isp_ccm_disable(isp_proc));
.. _isp-demosaic:
ISP 去马赛克控制器
~~~~~~~~~~~~~~~~~~~~~~
此流水线用于执行图像去马赛克算法,将 RAW 图像转换为 RGB 模式。
可调用 :cpp:func:`esp_isp_demosaic_configure` 来配置去马赛克功能,请参考以下代码:
.. code:: c
esp_isp_demosaic_config_t demosaic_config = {
.grad_ratio = {
.integer = 2,
.decimal = 5,
},
...
};
ESP_ERROR_CHECK(esp_isp_demosaic_configure(isp_proc, &sharpen_config));
ESP_ERROR_CHECK(esp_isp_demosaic_enable(isp_proc));
调用 :cpp:func:`esp_isp_demosaic_configure` 后,需要通过调用 :cpp:func:`esp_isp_demosaic_enable` 来启用 ISP 去马赛克控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_demosaic_disable` 会执行相反的操作,即将驱动程序恢复到 **init** 状态。
即使驱动程序处于 **init** 状态,也可以调用 :cpp:func:`esp_isp_demosaic_configure`,但去马赛克配置只有在 **enable** 状态下才会生效。
.. _isp-gamma-correction:
启用 gamma 校正
^^^^^^^^^^^^^^^
人眼的视觉系统对物理亮度的感知是非线性的。将 gamma 校正添加到 ISP 流水线中,可以将 RGB 坐标转换为坐标与主观亮度成正比的空间。
驱动程序提供了帮助函数 :cpp:func:`esp_isp_gamma_fill_curve_points`,用于填充 :cpp:type:`isp_gamma_curve_points_t`,这是描述 gamma 校正曲线的点集合。也可以通过手动声明点来获得期望的 gamma 校正曲线。每个 R/G/B 分量有自己的 gamma 校正曲线,可以通过调用 :cpp:func:`esp_isp_gamma_configure` 来配置。
以下是一个典型的代码示例:
.. code:: c
#include <math.h>
// 设置相机 gamma 为 0.7gamma 校正曲线为 y = 256 * (x / 256) ^ 0.7
static uint32_t s_gamma_curve(uint32_t x)
{
return pow((double)x / 256, 0.7) * 256;
}
isp_gamma_curve_points_t pts = {};
ESP_ERROR_CHECK(esp_isp_gamma_fill_curve_points(s_gamma_curve, &pts));
ESP_ERROR_CHECK(esp_isp_gamma_configure(isp_proc, COLOR_COMPONENT_R, &pts));
ESP_ERROR_CHECK(esp_isp_gamma_configure(isp_proc, COLOR_COMPONENT_G, &pts));
ESP_ERROR_CHECK(esp_isp_gamma_configure(isp_proc, COLOR_COMPONENT_B, &pts));
// 配置完曲线参数后启用 gamma 模块
ESP_ERROR_CHECK(esp_isp_gamma_enable(isp_proc));
// 如果不再需要,则禁用 gamma
ESP_ERROR_CHECK(esp_isp_gamma_disable(isp_proc));
.. _isp-sharpen:
ISP 锐化控制器
~~~~~~~~~~~~~~
此流水线用于在 YUV 模式下锐化输入图像。
调用 :cpp:func:`esp_isp_sharpen_configure` 来配置锐化功能,请参考以下代码。
.. code:: c
esp_isp_sharpen_config_t sharpen_config = {
.h_thresh = 255,
.sharpen_template = {
{1, 2, 1},
{2, 4, 2},
{1, 2, 1},
},
...
};
ESP_ERROR_CHECK(esp_isp_sharpen_configure(isp_proc, &sharpen_config));
ESP_ERROR_CHECK(esp_isp_sharpen_enable(isp_proc));
调用 :cpp:member:`esp_isp_sharpen_config_t::sharpen_template` 进行锐化。可以通过高斯滤波器模板或均值滤波器模板来设置 :cpp:member:`esp_isp_sharpen_config_t::sharpen_template`
调用 :cpp:func:`esp_isp_sharpen_configure` 后,需要通过调用 :cpp:func:`esp_isp_sharpen_enable` 以启用 ISP 锐化控制器。此函数:
* 将驱动程序状态从 **init** 切换到 **enable**
调用 :cpp:func:`esp_isp_sharpen_disable` 函数会执行相反的操作,即将驱动程序恢复到 **init** 状态。
即使驱动程序处于 **init** 状态,也可以调用 :cpp:func:`esp_isp_sharpen_configure`,但锐化配置只有在 **enable** 状态下才会生效。
.. _isp-callback:
注册事件回调函数
^^^^^^^^^^^^^^^^
ISP 模块启动后,会动态生成特定事件。
你也可以通过参数 ``user_data`` 将自己的上下文保存到回调函数中,用户数据将直接传递给回调函数。
.. note::
下文中提到的回调函数在 ISR 上下文中被调用,必须确保这些函数不会尝试阻塞(例如,确保只从函数中调用带有 ``ISR`` 后缀的 FreeRTOS API
注册 ISP 处理器事件回调函数
~~~~~~~~~~~~~~~~~~~~~~~~~~~
启用 ISP 处理器后,会动态生成多个 ISP 子模块的事件。可以通过调用 :cpp:func:`esp_isp_register_event_callbacks` 将函数挂接到中断服务例程。所有支持的事件回调函数可参见 :cpp:type:`esp_isp_evt_cbs_t`
- :cpp:member:`esp_isp_evt_cbs_t::on_sharpen_frame_done` 在完成锐化帧后设置回调函数。ISP 锐化子模块完成一帧的操作后会调用此函数。函数原型在 :cpp:type:`esp_isp_sharpen_callback_t` 中声明。
注册 ISP AF 环境检测器事件回调函数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP AF 环境检测器启动后,将动态生成特定事件。若想在事件发生时调用某些函数,请通过调用 :cpp:func:`esp_isp_af_env_detector_register_event_callbacks` 将目标函数挂接到中断服务程序中。所有支持的事件回调函数可参见 :cpp:type:`esp_isp_af_env_detector_evt_cbs_t`
- :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_statistics_done` 为环境统计完成事件设置回调函数。该函数原型在 :cpp:type:`esp_isp_af_env_detector_callback_t` 中声明。
- :cpp:member:`esp_isp_af_env_detector_evt_cbs_t::on_env_change` 为环境变化事件设置回调函数。该函数原型在 :cpp:type:`esp_isp_af_env_detector_callback_t` 中声明。
注册 ISP AWB 统计完成事件回调函数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP AWB 控制器完成白块数据统计后,将动态生成特定事件。若想在统计完成时收到通知,请通过调用 :cpp:func:`esp_isp_awb_register_event_callbacks` 将目标函数挂接到中断服务程序中。所有支持的事件回调函数可参见 :cpp:type:`esp_isp_awb_cbs_t`
- :cpp:member:`esp_isp_awb_cbs_t::on_statistics_done` 在白块数据统计完成后设置回调函数。该函数原型在 :cpp:type:`esp_isp_awb_callback_t` 中声明。
注册 ISP AE 环境检测器事件回调函数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP AE 环境检测器启动后,将动态生成特定事件。若想在事件发生时调用某些函数,请通过调用 :cpp:func:`esp_isp_ae_env_detector_register_event_callbacks` 将目标函数挂接到中断服务程序中。所有支持的事件回调函数可参见 :cpp:type:`esp_isp_ae_env_detector_evt_cbs_t`
- :cpp:member:`esp_isp_ae_env_detector_evt_cbs_t::on_env_statistics_done` 为环境统计完成事件设置回调函数。该函数原型在 :cpp:type:`esp_isp_ae_env_detector_callback_t` 中声明。
- :cpp:member:`esp_isp_ae_env_detector_evt_cbs_t::on_env_change` 为环境变化事件设置回调函数。该函数原型在 :cpp:type:`esp_isp_ae_env_detector_callback_t` 中声明。
注册 ISP HIST 统计完成事件回调函数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ISP HIST 控制器完成亮度统计后,将动态生成特定事件。若想在统计完成时收到通知,请通过调用 :cpp:func:`esp_isp_hist_register_event_callbacks` 将目标函数挂挂接到中断服务程序。所有支持的事件回调函数可参见 :cpp:type:`esp_isp_hist_cbs_t`
- :cpp:member:`esp_isp_hist_cbs_t::on_statistics_done` 在完成亮度统计时设置回调函数。该函数原型在 :cpp:type:`esp_isp_hist_callback_t` 中声明。
.. _isp-thread-safety:
线程安全
^^^^^^^^
驱动程序会确保以下工厂函数的线程安全:
.. list::
- :cpp:func:`esp_isp_new_processor`
- :cpp:func:`esp_isp_del_processor`
- :cpp:func:`esp_isp_new_af_controller`
- :cpp:func:`esp_isp_del_af_controller`
- :cpp:func:`esp_isp_new_awb_controller`
- :cpp:func:`esp_isp_del_awb_controller`
- :cpp:func:`esp_isp_new_ae_controller`
- :cpp:func:`esp_isp_del_ae_controller`
- :cpp:func:`esp_isp_new_hist_controller`
- :cpp:func:`esp_isp_del_hist_controller`
使用时,可以直接从不同的 RTOS 任务中调用此类函数,无需额外锁保护。其他 API 无法确保线程安全。
.. _isp-kconfig-options:
Kconfig 选项
^^^^^^^^^^^^
- :ref:`CONFIG_ISP_ISR_IRAM_SAFE` 控制默认的 ISR 句柄在 cache 被禁用时是否可以正常工作。
.. _isp-iram-safe:
IRAM 安全
^^^^^^^^^
默认情况下,当 cache 因写入或擦除 flash 等原因而被禁用时ISP 的中断将会延迟。
Kconfig 选项 :ref:`CONFIG_ISP_ISR_IRAM_SAFE` 支持:
- 即使 cache 被禁用也能启用中断
- 将 ISR 使用的所有函数放入 IRAM
- 将驱动程序对象放入 DRAM以防意外映射到 PSRAM
启用上述 Kconfig 选项,保证 cache 被禁用时中断可以正常运行,但这会增加 IRAM 使用量。启用此选项后,当 cache 被禁用时ISR 回调函数将继续运行。因此,必须确保回调函数及其上下文也是 IRAM 安全的。
Kconfig 选项 :ref:`CONFIG_ISP_CTRL_FUNC_IN_IRAM` 支持:
- 将一些 ISP 控制函数放入 IRAM函数列表请参见
.. list::
- :cpp:func:`esp_isp_sharpen_configure`
- :cpp:func:`esp_isp_demosaic_configure`
应用示例
--------
* :example:`peripherals/isp/multi_pipelines` 演示了如何使用 ISP 流水线处理来自摄像头传感器的图像信号,并通过 DSI 外设在 LCD 屏幕上显示视频。
API 参考
--------
.. include-build-file:: inc/isp.inc
.. include-build-file:: inc/isp_af.inc
.. include-build-file:: inc/isp_ae.inc
.. include-build-file:: inc/isp_awb.inc
.. include-build-file:: inc/isp_bf.inc
.. include-build-file:: inc/isp_ccm.inc
.. include-build-file:: inc/isp_demosaic.inc
.. include-build-file:: inc/isp_sharpen.inc
.. include-build-file:: inc/isp_gamma.inc
.. include-build-file:: inc/isp_hist.inc
.. include-build-file:: inc/isp_color.inc
.. include-build-file:: inc/isp_core.inc
.. include-build-file:: inc/components/esp_driver_isp/include/driver/isp_types.inc
.. include-build-file:: inc/components/hal/include/hal/isp_types.inc