ISP主要坐下面的工作:
AEC(自动曝光控制)、AGC(自动增益控制)、AWB(自动白平衡)、AF(自动对焦)色彩校正、Lens Shading、Gamma 校正、祛除坏点、Auto Black Level、Auto White Level
可以参考:
ISP(图像信号处理)
功能描述
- lens 将光信号投射到 sensor 的感光区域后,
- sensor 经过光电转换,
- 将 Bayer 格式的原始图像送给 ISP,
- ISP 经过算法处理,
- 输出 RGB 空间域的图像给后端的视频采集单元。
- 在这个过程中, ISP 通过运行在其上的 firmware 对 ISP逻辑, lens 和 sensor 进行相应控制,进而完成自动光圈、自动曝光、自动白平衡等功能。
- 其中, firmware 的运转靠视频采集单元的中断驱动。
- PQ Tools 工具通过网口或者串口完成对 ISP 的在线图像质量调节。
ISP 由 ISP 逻辑及运行在其上的 Firmware 组成,逻辑单元除了完成一部分算法处理外,还可以统计出当前图像的实时信息。 Firmware 通过获取 ISP 逻辑的图像统计信息,重新计算,反馈控制 lens、 sensor 和 ISP 逻辑,以达到自动调节图像质量的目的。
设计思路
ISP 的 Firmware 包含三部分:
- 一部分是 ISP 控制单元和基础算法单元,即 ISP 库。
- 一部分是 AE/AWB/AF 算法库。
- 一部分是 sensor 库。
Firmware 设计的基本思想是单独提供 3A 算法库,由 ISP 控制单元调度基础算法单元和 3A 算法库,同时 sensor 库分别向ISP 库和 3A 算法库注册函数回调,以实现差异化的 sensor 适配。 ISP firmware 设计思路如图所示。
不同的 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 软件结构
软件流程
ISP 作为图像前处理部分,需要和视频采集单元(VIU)协同工作。 ISP 初始化和基本配置完成后,需要 VIU 进行接口时序匹配。一是为了匹配不同 sensor 的输入时序,二是为 ISP 配置正确的输入时序。待时序配置完成后, ISP 就可以启动 Run 来进行动态图像质量调节。此时输出的图像被 VIU 采集,进而送去显示或编码。软件使用流程如图所示。
ISP firmware 使用流程
代码示例:
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;