ISP 笔记(1):一个 ISP 项目的流程梳理
通过学习 mushfiqulalam/isp 项目整理一下 ISP 的流程。虽然这类博文很多,但不自己写一下总感觉不扎实,而且很多博文没有代码只是概述,更觉得不扎实。
基本的印象
镜片阴影校正(Lens shading correction),话说最开始接触这个概念,还是在看介绍 Jinc 函数的 pdf 里。
最后的降噪和锐化,是我很熟悉的。降噪用了 sigma filter,代码还没有读,盲猜是 Gaussian?锐化用了 USM 锐化,或许我可以,用一些我熟悉的效果更明显的降噪方法。
流程梳理
1 |
|
全程在 32bit 下处理。其实原项目并不是这样,是每个处理单元内部使用 32bit 处理,而单元间的数据传递似乎还是 16bit。在之前的经验中,是不要反复转换位深;但看了下代码,32bit float 与 16bit int 间的转换无非就是np.float32()
与np.clip(image, 0, 65536)
的转换,好像也没有什么精度损失。
去马赛克(Demosaicing)
包含了后处理 local color ratio,用以增强锐度,因为插值之后的图像缺少锐度(文献 1:10.1109/TCSVT.2004.828316)。
我用简单的插值做去马赛克,效果和项目的中差别较大(我做得更亮),倒是和OpenCV自带的xxxxtorgb()
效果几乎一致。
Gamma校正
分两步进行,亮度调整(Luma adjustment)、量化(Equation)(另外两个by_value()
和by_table()
函数没有启用)。
亮度调整部分就是我们熟悉的加个系数、进行Gamma校正的过程,也就是提高亮度(Brightening)。项目给定的系数是log10(80)
,即1.903。
说起来平时做 Resize,需要 Gamma 校正的时候就只做这一步,亮度增强。有没有必要也模仿这样做后续的处理。另外,根据 AreaResize 的经验,在 32bit 做 Resize 不需要做 Gamma 校正/亮度增强,因为精度已经足够(对哦…在这里本来就是为了提高亮度,不处理是黑的…和处理精度没关系)。
色调映射(Tone Mapping)
项目包含了两种独立的方法,每个 ISP 流程只执行一种方法。
- 非线性mask(Nonlinear Masking)
- 动态范围压缩(Dynamic Range Compression)
在中文 wiki 中介绍了 Photographic 算法(英文 wiki 中没有对应的内容),从字面和算法含义两个方面,都可以理解成“摄影算法”,这种色调映射方法借助了摄影 or 照片冲洗的技巧。但我直观地看上去,就是动态范围压缩的路数。
通用的基础操作
限制像素值范围
不能让像素值越界。
在 C++ 中
在 C++17 中引入了std::clamp()
函数,用法和下面 Python 中的np.clip()
一样。不用 C++17 的话就自己定义一个~~
在 Python 中
1 |
|
数据类型
在 VapourSynth 内,16bit int 的像素值范围是[0, 65535],32bit float YUV 的像素值范围是[0.0, 1.0],32bit float RGB [-1.0, 1.0]。而在直接用 Python 和 NumPy 处理图像数据时,把输入数据升至float32
,只是单纯地数据类型的转变,其范围并没有变啊。别用 VapourSynth 用多了,习惯于高度封装的环境,结果忘了最基础的数据类型。
所以才需要量化(逃…