Showing Posts From

Isp

详细总结图像ISP处理流程之Gamma校正

本文详细总结了图像ISP处理流程中的Gamma校正模块,解释了在ISP处理流程中要包含Gamma校正模块的原因,以及主流ISP在进行Gamma校正的处理过程中的主要思路和工作流程。 Gamma校正存在的意义 在ISP对于Sensor输出RAW图像的处理流程中,Gamma校正模块是其中一个非常重要的图像亮度非线性变换模块。Gamma模块存在的意义,主要是解决图像传感器感光性能的线性,与人眼/显示设备感知和显示图像的非线性之间的匹配问题。 具体而言,图像传感器在曝光的过程中,对于光线强度和曝光时间长短的响应基本上是线性的,也就是说,光照强度增加一倍,图像传感器所输出的电信号也就增加一倍。 显示设备的输出电压与亮度效果的呈现之间存在的非线性关系,这一点要从古老的CRT显示器说起。对于CRT显示器而言,其显示亮度与输入电压之间成 γ≈2.2 的幂律关系,如果把图像传感器采集到的线性亮度信号直接输入到CRT显示器上显示的话,显示出来的效果会呈现出图像的暗部细节损失严重,整体画面偏暗,而亮部的对比度压缩,高光部分的层次感减弱。所以,为了能够在CRT显示器上把图像传感器采集的线性亮度图像以线性的方式呈现出来,就需要在把图像在CRT上进行显示之前,先进行一个Gamma Encode的运算,即对图像传感器的线性亮度图像进行一个 γ=0.45 的Gamma映射,然后把这个处理过的图像送入CRT显示器,CRT显示器显示出来的图像就可以把线性亮度还原回来。整体的流程如下图所示: !image.png CRT显示器早已经被淘汰了,而目前主流的LCD/OLCD液晶显示器的亮度响应实际上是接近于线性的,所以理论上讲,直接把图像传感器采集的原始亮度图像,直接显示在液晶显示器上,就可以免去上面的Gamma映射的繁琐流程了。但问题是,这样的话,之前CRT时代所积累的大量图像文件(以前在进行图像压缩之前提前进行了Gamma Encode的运算处理),显示在LCD/OLCD显示器上就会有问题了。所以为了兼容CRT时代所积累的历史内容,现代的LCD显示器都会额外内置一个 的校正,这样就可以继续保持之前的线性图像-编码gamma(0.45)处理-显示gamma(2.2)-线性图像的闭环。 人眼对于光照亮度的感知与以上逻辑类似,也是非线性的,其亮度感知规律符合韦伯-费希纳定律,具体来讲就是,人眼对于光照的暗区更加敏感,因此在低照度的情况下,人眼可以分辨极其微小的亮度变化;而对于光照的亮区就没有那么敏感了,在高亮度的情况下,人眼对光照亮度的变化往往很难察觉。 !image.png Gamma校正的流程 基于以上所描述的在ISP端进行的Gamma Encode处理和显示器端自动进行的Gamma Decode处理流程可知,在ISP处理流程中所执行的gamma encode需要对RGB三通道的亮度进行以下处理: 在ISP实际进行Gamma处理的计算流程中,因为直接计算各个像素的幂函数耗时高,所以实际工程中采用预计算LUT查找表实现来实时Gamma操作的幂映射。 Gamma校正模块的输入数据为经过Demosaic和CCM处理后的RGB域数据,每个像素都包含了RGB三个通道,但为了保证三个通道的色彩平衡,所以一般情况下对三个通道数据使用统一的Gamma映射表来进行Gamma转换操作。 - 以上提到的这种三个颜色通道共用同一组LUT表的处理方式也成为1D LUT,实际上就是Gamma亮度变换。在部分ISP或者图像处理流程中,还有一个3D LUT的概念,RGB三个通道使用各自的LUT表,一般用于实现一些色彩风格个性化的功能。 为了应对各种复杂的光照场景(如逆光、夜景),以及更好的适应人眼感知特性的非线性,对图像素质要求较高的主流ISP往往还会采用分段式可编程LUT表来实现更为精细化的控制。例如,分段式Gamma LUT将输入亮度范围(如0~255)划分为暗部(0~20%)、中灰(20%~70%)、高光(70%~100%)三个亮度区间,然后为每个区间独立配置不同的Gamma映射函数: - 暗部:采用低 值,斜率平缓,拉伸暗区细节 - 中灰:采用标准 值,维持自然的对比度 - 高光:采用高 值或对数压缩,斜率陡峭,抑制过曝 !image.png 这个分段LUT的设计可以很好的适应人眼的亮度响应,在暗部拉伸图像的亮度响应以保留更多的暗部细节,在亮部则压缩响应范围抑制过曝。 参考资料 - ISP算法——Gamma校正、Degamma校正 - 【基础】一文搞懂伽玛(Gamma)校正

海思35XX系列HiMPP框架开发参考之VI模块

主要参考文件:《HiMPP V3.0媒体处理软件开发参考》。 文档版本:21. 文档发布日期:2019-09-30. 本文档基于对海思官方SDK提供的HiMPP开发参考文件的学习,整理了该平台下视频输入接口VI模块在开发过程中流程以及主要概念。 VI模块的主要功能 VI模块能够支持从BT656/BT601/BT1120以及Digital Camera接口上接收外部传过来的YUV格式视频数据,保存在内部的指定内存区域中。 除以上简单的接收YUV视频数据以为,VI能够实现的额外功能: - 对接收到的原始视频图像进行裁剪Crop; - 水平/垂直缩小处理Scale down; - 水平/垂直反转操作(Mirror,Flip); - 可以把输入的一路或者多路原始视频图像,合并/分割为一路/多路视频图像。 接口/设备/通道 海思35XX系列的各个芯片对于VI模块的支持情况不同,需要参考具体芯片的配置。 总的来讲,HI35xx芯片的VI接口和设备均以8bit为单位进行组织和编号,1个8bit接口就对应一个VI设备。 两个8bit的VI可以合并组成一个16bit BT1120接口,所以一个芯片上有n组16bit的BT1120接口,就会有2*n个8bit的VI设备。 - 当两个8bit接口拼接在一起作为一个16bit接口使用的时候,这两个8bit接口对应的VI设备就只有1个设备可用; 此外,每个VI接口和设备固定对应包含4个VI通道,可以把VI接口通过时分复用方式接收到的数据映射到不同的通道进行单独处理。因此对于VI模块的后级处理而言,就是从各个通道上读取数据。 Hi3520DV400和HI3521DV100的接口/设备/通道的对应情况: - Hi3520DV400有两组8bit接口VI0和VI1,也就分别对应两个VI设备,也就是dev0和dev1; - 两组8bit接口可以合并为一个16bit BT1120接口使用,此时就只有dev0可以使用; - Dev0对应的通道是Chn0,Chn1,Chn2,Chn3; - Dev1对应的通道是Chn4,Chn5,Chn6,Chn7; - HI3521DV100包含有4组8bit接口:VI0,VI1,VI2,VI3,也就是dev0,dev1,dev2,dev3; - VI0+VI1以及VI2+VI3分别可以合并起来作为一个独立的16bit BT1120接口使用,此时就只有dev0和dev2可以使用; - Dev0对应的通道是Chn0,Chn1,Chn2,Chn3; - Dev1对应的通道是Chn4,Chn5,Chn6,Chn7; - Dev2对应的通道是Chn8,Chn9,Chn10,Chn11; - Dev3对应的通道是Chn12,Chn13,Chn14,Chn15; 接口与设备的接收能力 当VI接口和设备配置为8bit模式使用时,可以支持: - 可以支持1/2/4路D1、960H复合模式输入; - 即1路8bit VI接口可以通过分时的方式支持最多4路D1和960H的视频; - 因此一个芯片的VI模块有N路8bit VI接口,最多就可以支持4*N路D1和960H分辨率图像的复合模式输入; - 可以支持2路720P复合模式输入; - 即1路8bit VI接口可以通过分时的方式支持最多2路720P的视频; - 因此一个芯片的VI模块有N路8bit VI接口,最多就可以支持2*N路720P分辨率图像的复合模式输入; - 可以支持1路1080P30输入; - 每个1080P30摄像头连接1路8bit接口(即YC复用模式),使用BT1120 148.5MHz时钟;(单路接口不复用,每个8bit接口只接入1路1080P30视频输入) - 配置为这种模式下,一个芯片的VI模块有N路8bit VI接口,就可以支持N路1080P30分辨率图像的输入; - 通过双沿采样方式支持2路1080P30输入; - 每个1080P30摄像头连接1路8bit接口(即YC复用模式),使用BT1120 148.5MHz时钟,在上升沿和下降沿同时进行采样可以支持两路1080P30视频的同时输入; - 因此一个芯片的VI模块有N路8bit VI接口,最多就可以支持2*N路1080P分辨率图像的复合模式输入; - 还可以支持1路4M 30fps输入; - 1个4M 30fps摄像头连接1路8bit接口,设置为BT1120 148.5MHz时钟+双沿采样方式; - 因此一个芯片的VI模块有N路8bit VI接口,最多就可以支持N路4M 30fps分辨率图像的输入; 两个8bit接口合并在一起组成一个16bit接口: - 可以支持1路1080P30输入; - 1个1080P30摄像头连接一个16bit接口,同时传输YC数据,使用BT1120 74.24MHz时钟; - 配置为这种模式下,一个芯片的VI模块有N路16bit VI接口,就可以支持N路1080P30分辨率图像的输入; - 从以上的总结来看,无论是接入标清还是高清分辨率视频,最简单灵活的方式就是把VI模块的接口按照8bit来进行配置就好,设置为16bit的意义不大。 VI模块的掩码设置 VI模块的掩码用于定义VI模块的各个设备所使用的外部接口; 每个VI设备对应两个掩码:掩码0和掩码1。 VI设备和接口按照8bit的模式进行配置的情况: - 只需要设置掩码0,把掩码1设置为0即可; - 设备号为0/2/4/6等偶数编号的情况下,掩码0设置为0x00FF0000; - 设备号为1/3/5/7等奇数编号的情况下,掩码0设置为0xFF000000; VI设备和接口按照16bit的模式进行配置的情况: - 需要同时设置掩码0和掩码1; - 此时设备号为1/3/5/7等奇数编号的设备不可用,只能使用设备号为0/2/4/6等偶数编号的设备; - 所有设备号为0/2/4/6等偶数编号的设备,掩码0设置为0xFF000000,掩码1设置为0x00FF0000; 常用API总结 - 设置和获取VI设备属性 - HI_MPI_VI_SetDevAttr; - HI_MPI_VI_GetDevAttr; - 启用和禁用VI设备; - HI_MPI_VI_EnableDev; - HI_MPI_VI_DisableDev; - 设置和获取VI通道属性 - HI_MPI_VI_SetChnAttr; - HI_MPI_VI_GetChnAttr; - 启用和禁用VI通道 - HI_MPI_VI_EnableChn; - HI_MPI_VI_DisableChn; - 调用HI_MPI_VI_EnableChn之后实际上VI模块已经开始正常的接收接口进来的图像数据了; - 读取VI模块接收到的图像数据: - HI_MPI_VI_GetFrame; - 一般不需要直接调用这个接口来获取Frame,VI模块连接的后续模块会自动接收并处理,除非需要对VI模块接收到的图像数据做自定义的处理; - 释放VI图像数据所占的缓存 - HI_MPI_VI_ReleaseFrame; - 绑定/解绑VI通道/获取当前通道绑定关系 - HI_MPI_VI_BindChn; - HI_MPI_VI_UnBindChn; - HI_MPI_VI_GetChnBind; - 如果使用系统默认的设备与通道的绑定关系的话,系统启动的时候自动就绑定好了。除非需要修改默认的绑定关系,才需要调用这两个接口先解除之前的默认绑定关系,再重新绑定; VI模块的基本工作流程: - 设置VI设备属性:HI_MPI_VI_SetDevAttr - 使能VI设备:HI_MPI_VI_EnableDev - 设置VI通道属性:HI_MPI_VI_SetChnAttr - 使能VI通道:HI_MPI_VI_EnableChn - 至此VI部分的图像流已经正常工作,pipeline的下游设备可以从对应的VI通道中读取到图像流。