ISP主要坐下面的工作:

AEC(自动曝光控制)、AGC(自动增益控制)、AWB(自动白平衡)、AF(自动对焦)色彩校正、Lens Shading、Gamma 校正、祛除坏点、Auto Black Level、Auto White Level

可以参考:

ISP(图像信号处理)

功能描述

  1. lens 将光信号投射到 sensor 的感光区域后,
  2. sensor 经过光电转换,
  3. 将 Bayer 格式的原始图像送给 ISP,
  4. ISP 经过算法处理,
  5. 输出 RGB 空间域的图像给后端的视频采集单元。
  • 在这个过程中, ISP 通过运行在其上的 firmware 对 ISP逻辑, lens 和 sensor 进行相应控制,进而完成自动光圈、自动曝光、自动白平衡等功能。
  • 其中, firmware 的运转靠视频采集单元的中断驱动。
  • PQ Tools 工具通过网口或者串口完成对 ISP 的在线图像质量调节。

ISP 由 ISP 逻辑及运行在其上的 Firmware 组成,逻辑单元除了完成一部分算法处理外,还可以统计出当前图像的实时信息。 Firmware 通过获取 ISP 逻辑的图像统计信息,重新计算,反馈控制 lens、 sensor 和 ISP 逻辑,以达到自动调节图像质量的目的。

6 海思Hi3518E的ISP及其3A_基础算法

设计思路

ISP 的 Firmware 包含三部分:

  • 一部分是 ISP 控制单元和基础算法单元,即 ISP 库。
  • 一部分是 AE/AWB/AF 算法库。
  • 一部分是 sensor 库。

Firmware 设计的基本思想是单独提供 3A 算法库,由 ISP 控制单元调度基础算法单元和 3A 算法库,同时 sensor 库分别向ISP 库和 3A 算法库注册函数回调,以实现差异化的 sensor 适配。 ISP firmware 设计思路如图所示。

6 海思Hi3518E的ISP及其3A_基础算法_02

不同的 sensor 都向 ISP 库和 3A 算法库注册控制函数,这些函数都以回调函数的形式存在。 ISP 控制单元调度基础算法单元和 3A 算法库时,将通过这些回调函数获取初始化参数,并控制 sensor,如调节曝光时间、模拟增益、数字增益,控制 lens 步进聚焦或旋转光圈等。

注意:Sensor 3A只是为3A lib 提供最基本的操作,而不是一个完整的3A算法。

Firmware 内部流程

首先完成 Firmware 控制单元的初始化、基础算法单元的初始化、 3A 算法库的初始化,包括调用 sensor 的回调获取 sensor 差异化的初始
化参数。当初始化完成之后, Firmware 由中断驱动,每帧从内核态获取统计信息,并驱动基础算法单元和 3A 算法库完成计算,并反馈计算结果,配置 ISP 寄存器和 sensor寄存器。
同时用户可以通过 ISP 的 MPI,控制和改变 Firmware 中包含的基础算法单元的内部数据和状态,定制自己的图像质量效果。如果用户使用海思提供的 3A 算法库,可以通过3A 算法库的 MPI,改变 3A 算法库的内部数据和状态,调节曝光、白平衡和色彩还原。
ISP firmware 内部流程                                                               ISP firmware 软件结构

6 海思Hi3518E的ISP及其3A_图像质量_036 海思Hi3518E的ISP及其3A_图像质量_04

软件流程

ISP 作为图像前处理部分,需要和视频采集单元(VIU)协同工作。 ISP 初始化和基本配置完成后,需要 VIU 进行接口时序匹配。一是为了匹配不同 sensor 的输入时序,二是为 ISP 配置正确的输入时序。待时序配置完成后, ISP 就可以启动 Run 来进行动态图像质量调节。此时输出的图像被 VIU 采集,进而送去显示或编码。软件使用流程如图所示。

ISP firmware 使用流程
6 海思Hi3518E的ISP及其3A_图像质量_05

代码示例:

HI_S32 s32Ret;
ALG_LIB_S stLib;
ISP_PUB_ATTR_S stPubAttr;
pthread_t isp_pid;
/* 注册sensor库 */
s32Ret = sensor_register_callback();
if (HI_SUCCESS != s32Ret)
{
printf(”register sensor failed!\n”);
return s32Ret;
}

/* 注册海思AE算法库 */
stLib.s32Id = 0;
strcpy(stLib.acLibName, HI_AE_LIB_NAME);
s32Ret = HI_MPI_AE_Register(&stLib);
if (HI_SUCCESS != s32Ret)
{
printf(”register ae lib failed!\n”);
return s32Ret;
}

/* 注册海思AWB算法库 */
stLib.s32Id = 0;
strcpy(stLib.acLibName, HI_AWB_LIB_NAME);
s32Ret = HI_MPI_AWB_Register(&stLib);
if (HI_SUCCESS != s32Ret)
{
printf(”register awb lib failed!\n”);
return s32Ret;
}

/* 注册海思AF算法库 */
stLib.s32Id = 0;
strcpy(stLib.acLibName, HI_AF_LIB_NAME);
s32Ret = HI_MPI_AF_Register(&stLib);
if (HI_SUCCESS != s32Ret)
{
printf(”register af lib failed!\n”);
return s32Ret;
}

/* 初始化ISP外部寄存器 */
s32Ret = HI_MPI_ISP_MemInit(IspDev);
if (s32Ret != HI_SUCCESS)
{
printf("%s: HI_MPI_ISP_Init failed!\n", __FUNCTION__);
return s32Ret;
}

/* 配置ISP宽动态模式 */
ISP_WDR_MODE_S stWdrMode;
stWdrMode.enWDRMode = enWDRMode;
s32Ret = HI_MPI_ISP_SetWDRMode(0, &stWdrMode);
if (HI_SUCCESS != s32Ret)
{
printf("start ISP WDR failed!\n");
return s32Ret;
}

/* 配置图像公共属性 */
s32Ret = HI_MPI_ISP_SetPubAttr(IspDev, &stPubAttr);
if (s32Ret != HI_SUCCESS)
{
printf("%s: HI_MPI_ISP_SetPubAttr failed with %#x!\n", __FUNCTION__,
s32Ret);
return s32Ret;
}

/* 初始化ISP Firmware */
s32Ret = HI_MPI_ISP_Init();
if (HI_SUCCESS != s32Ret)
{
printf(”isp init failed!\n”);
return s32Ret;
}

/* HI_MPI_ISP_Run单独启动线程运行 */
if (0 != pthread_create(&isp_pid, 0, ISP_Run, NULL))
{
printf("create isp running thread failed!\n");
return HI_FAILURE;
}

/* 启动VI/VO等业务 */
……
/* 停止VI/VO等业务 */
s32Ret = HI_MPI_ISP_Exit();
if (HI_SUCCESS != s32Ret)
{
printf(”isp exit failed!\n”);
return s32Ret;
}
pthread_join(isp_pid, 0);
return HI_SUCCESS;