文章目录
- 前言
- 1. ISP芯片
- 2. Sensor知识
- 3. RAW数据
- 4. ISP Pipeline
- 5. AI-ISP
- 结束语
前言
本篇文章只干一件事:AI-ISP
:手机相机是如何将风景变成图片的?
1. ISP芯片
一颗小小的SoC
芯片(10mm x 10mm)
上集成了一百多亿个晶体管(Kirin 9000有153亿)
,其集成的各个模块共同支撑手机功能实现,如负责手机应用流畅切换的CPU
、支持游戏画面快速加载的GPU
,专门负责实现AI
运算和AI
应用实现的NPU
以及手机拍照担当的ISP
等等。按照书上的介绍,大致绘制了一块SoC
预览图:
ISP(Image Signal Processor)
,即图像信号处理器的缩写,主要用来处理前端图像信号,它能够将光信号变成电信号,是图像处理的核心器件。因此其性能会直接影响手机的拍照、摄像效果。
当打开手机准备拍照时,镜头(Lens)
会首先把被摄景物投影在图像传感器(Sensor)
上。与此同时,影像处理器(ISP)
会通过测光、测距算出合适的参数并指示镜头对焦。随着拍照键的按下,Sensor
会完成一次曝光,并通过ISP
的处理将其变成图片。大致流程如下:
所以呢,本篇侧重点在ISP
是如何将Sensor
的输出数据转换成RGB
图像的。
2. Sensor知识
参考文章:CMOS图像传感器
CMOS(Complementary Metal Oxide Semiconductor)
,即互补金属氧化物半导体,是一种可记录光线变化的半导体,主要利用硅和锗做成的半导体,使其在CMOS
上共存着N
型和P
型半导体,这两个互补效应所产生的电流即可被处理芯片记录和解读称图像(数电书中也有介绍)。CMOS
图像传感器(CMOS imager Sensor )
,简称CIS
,即采用CMOS
工艺的图像传感器,一种利用光电技术原理所制造的图像传感元件。
按道理Sensor
输出的是RGB
的raw data
,每个像素点都感知RGB
3
个分量的数字这样最准确。但是这样需要3
套感光板,而且RGB
的3
套数据还需要时间同步和对齐,这样成本高,难度大。所以,实际中通常采用一个叫Bayer
色彩滤波阵列(Bayer Color Filter Array, CFA)
的滤光板,放在一个感光板上。CFA(Color Filter Array)
,即彩色滤波列阵,由于CIS
本身是无法感受光的波长,也就是不能感知颜色,CFA
的作用是为了让CIS
能够感受色彩,目前主流采用Bayer
阵列,也称RGGB
或者RGB Bayer
,一般有四种Bayer Pattern
:BGGR
,GBRG
,GRBG
,RGGB
。比如下面的BGGR
模式:
像素
(Pixel)
,是图像传感器的最小感光单元,像素阵列排列在一起形成了图像传感器的感光区域。
像素尺寸(Pixel Size)
,是指图像传感器单个感光元件的尺寸,一般我们能看到两种表述,比如1.12μm
或者1.12μm×1.12μm
。像素的尺寸越大,接收光子的数量就越多,同光照条件和曝光时间内产生的电荷也越多。
3. RAW数据
博主我从手机里导出了.jpg
和对应的.dng
数据:
左侧为原始的RAW
数据(76.2MB)
,右侧为手机相机(ISP)
自动处理后的RGB
数据(4.74MB)
。
下面使用库读取RAW
数据来看一下详细的信息:
import rawpy
raw_file = '../raws/IMG_20230418_143110.dng'
raw_data = rawpy.imread(raw_file)
# 查看有木有缩略图
try:
thumb = raw_data.extract_thumb()
except rawpy.LibRawNoThumbnailError:
print('no thumbnail found')
# 返回给定坐标相对于完整 RAW 大小的颜色索引
color_index = raw_data.raw_color(0, 0)
print(color_index)
# 返回相对于完整RAW图像的给定位置的RAW值
raw_value = raw_data.raw_value(0, 0)
print(raw_value)
# 返回相对于图像可见区域的给定位置的RAW值
raw_value = raw_data.raw_value_visible(0, 0)
print(raw_value)
根据color_desc
和raw_pattern
两个属性可知,此RAW
数据的Bayer
模式为BGGR
,推理如下:
color_desc
值为RGBG
,对应索引为0123
,而raw_pattern
的值为2310
,转换为颜色值就是BGGR
。
局部放大RAW
图像,代码及结果如下:
import rawpy
import matplotlib.pyplot as plt
import seaborn as sns
raw_file = '../raws/IMG_20230418_143110.dng'
raw_data = rawpy.imread(raw_file)
# plt.imshow(raw_data.raw_image_visible)
sns.heatmap(raw_data.raw_image_visible[:10, :10], cmap=plt.cm.binary)
# plt.savefig('../raws/ori_raw_10x10.png')
plt.show()
以下是rawpy.RawPy
对象的所有属性,更详细的可以参考官方的文档:
属性 | 含义 |
---|---|
black_level_per_channel | 每通道黑电平校正 |
camera_white_level_per_channel | 从原始文件元数据读取的每通道饱和度,没有就是None |
camera_whitebalance | 白平衡系数 |
color_desc | 编号从 0 到 3 的颜色(RGBG、RGBE、GMCY or GBTG) 的字符串说明。需要注意的是,相同的字母可能表示不同的颜色 |
color_matrix | 颜色矩阵,从某些相机的文件中读取,为其他相机计算。颜色矩阵的shape 为[3, 4] |
daylight_whitebalance | 日光的白平衡系数(daylight balance) 。从文件中读取,或根据文件数据计算, 或取自硬编码常量 |
num_colors | 颜色数量。 请注意,例如,对于RGBG,这可能是3或4,具体取决于相机型号, 因为有些人使用两种不同的绿色 |
raw_colors | RAW 图像中每个像素的颜色索引数组。 相当于为每个像素调用 raw_color(y, x) |
raw_colors_visible | 像 raw_colors ,但是没有margin |
raw_image | RAW 图像,包括margin ,对于Bayer 图像,将返回 2D ndarray 。 对于Foveon 和其他RGB 类型的图像,将返回3D ndarray 。 请注意,可能有 4 个颜色通道,其中第 4 个通道可以是0 |
raw_image_visible | 像 raw_image ,但是没有margin |
raw_pattern | Bayer 阵列的模式 |
raw_type | 返回RAW 数据的类型,比如RawType.Flat |
rgb_xyz_matrix | 相机 RGB - XYZ 转换矩阵。 此矩阵是常数(不同型号不同),RGB 相机的最后一行为零,不同颜色型号(比如CMYG 等)的最后一行为非零,转换矩阵的shape 为[4, 3] |
sizes | 返回RAW 图像和后处理(postprocessed) 图像的信息,包含在rawpy.ImageSizes 对象中 |
tone_curve | 相机色调曲线,从尼康,索尼和其他一些相机的文件中读取。长度为65536 |
white_level | 原始像素值被认为饱和的级别 |
4. ISP Pipeline
看了相关的参考资料,这里的情况很复杂,内容太多太多啦,博主我就简单的梳理了以下,仅供参考:
这里根据网上的一些博客做了整理:
1.
BLC(Black Level Correction)
黑电平校正,由于Sensor
漏电流存在,把镜头放入一个全黑的环境,Sensor
输出的原始数据不为0
,而我们希望全黑时原始数据为0
。
2.
LSC(Lens Shade Correction)
镜头阴影校正,由于随着视场角慢慢增大,能够通过照相机镜头的斜光束将慢慢减少,导致Senor
捕获的图像中间亮度高,周围边缘亮度低。
3.
BPC(Bad Point Correction)
坏点校正,也叫Defect Pixel Correction(DPC)
,由于Sensor
是物理器件,有坏点是难以避免的;而且使用时间长了坏点会越来越多。通过在全黑环境下观察输出的彩点和亮点,或在白色物体下观察输出的彩点和黑点,就可以看到无规律的散落在各处的坏点。
4.
Demosaic
去马赛克,对空白部分进行线性插值,也叫颜色插值,使其具有颜色(就是每个像素点具有三种颜色)。
5.
DR(Denoise)
去除噪声,具体也有很多中,比如2DNR
,3DNR
等,Senor
的感光器件包含模拟部分,所以信号中的噪声很难避免,ADC
器件本身也会引入噪声。另外,当光线较暗时,整个系统需要将信号放大,这样噪声也跟着放大。
6.
AWB(Automatic White Balance)
自动白平衡,人类的视觉系统有一定的颜色恒常性特点,不会受到光源颜色的影响。实际生活中,不论是晴天、阴天、室内白炽灯或日光灯下,人们所看到的白色物体总是是白色的,这就是视觉修正的结果。人脑对物体的颜色有一定先验知识,可识别物体并且更正这种色差。但是Sensor
不具备这样的特点,比如一张白纸,在不同光线下,Sensor
输出的是不同颜色,在低色温下偏黄,在高色温下偏蓝。如白炽灯照明下拍出的照片易偏黄;而在户外日光充足则拍摄出来景物也会偏蓝。我们就需要,让不同色温光线条件下白色物体,Sensor
的输出都转换为更接近白色。
7.
CCM(Color Correction Matrix
)
颜色校正,Sensor
图像传感器获取的图像,与人们期望的颜色有距离,必须矫正。AWB
已经将白色校准了,CCM
就是用来校准除白色以外其他颜色的准确度的。
8.
RGB Gamma
Gamma
校正,人眼不同于摄像机,接收光子来感知光线。比如:在一间小黑屋中每增加一盏灯,摄像机都能线性增加亮度。但是人眼在黑暗时增加一盏灯时感受明显,往后随着灯的个数增长人眼并不会有明显感受。(人眼非线性)
9.
CSC(Color Space Conversion)
色彩空间转换,在YUV
色彩空间上进行彩色噪声去除、 边缘增强等更方便,且YUV
存储和传输时更省带宽。比如,RGBToYUV
。
10.
HDR(High-Dynamic Range)
高动态范围,自然界的中光强度很宽,而人眼对高亮,极暗环境的细节分辨能力相对较窄,而摄像头记录的范围更窄,真正的HDR
技术就是记录视觉范围内高亮,极暗环境的中的细节分辨率。为保证人眼看到的世界和显示器或者摄像头采集的图像的亮度范围相差无几,甚至更好,需要通过tone mapping
,将暗处和亮出细节再现。这是一种纯粹为了视觉感受而进行的处理,并非真正的HDR
。简而言之,宽动态技术可以使场景中特别亮的区域和特别暗的区域在最终成像中同时看清楚。
11.
Color denoise / Sharpness
锐化,主要是对YUV
降噪处理,同时为了消除降噪过程中对图像细节的损失,需要对图像进行锐化处理,还原图像的相关细节。因为在YUV
色彩空间,这些处理更方便。
12.
AEC(Automatic Exposure Control)
自动曝光,不同场景下,光照的强度有着很大的差别。人眼有着自适应的能力因此可以很快的调整,使自己可以感应到合适的亮度,而图像传感器却不具有这种自适应能力,因此必须使用自动曝光功能来确保拍摄的照片获得准确的曝光从而具有合适的亮度。
篇幅有限,下面就仅看一下Demosaic
是如何进行操作的。正如上述所说,再具体一点,就是将无颜色的RAW
图像转为RGB
三通道的彩色图像,示例图如下:
代码实现如下:
import rawpy
import cv2
import numpy as np
import matplotlib.pyplot as plt
raw_file = '../raws/IMG_20230418_143110.dng'
raw_data = rawpy.imread(raw_file)
# rawpy内置VNG-Demosaic算法
rgb_data = raw_data.postprocess(demosaic_algorithm=rawpy.DemosaicAlgorithm(1))
# print(rgb_data.shape)
plt.imshow(rgb_data)
plt.savefig('../raws/isp_rgb.png')
with rawpy.imread(raw_file) as raw:
bayer_img = raw.raw_image.copy()
bayer_img = np.uint8(bayer_img) # uint16 --> uint8
# opencv内置VNG-Demosaic算法
rgb_img = cv2.demosaicing(bayer_img, cv2.COLOR_BAYER_BG2RGB_VNG)
# print(rgb_img.shape)
plt.imshow(rgb_data)
plt.savefig('../raws/isp_rgb_cv2.png')
效果如下:
参考博客如下:
1. ISP全流程简介:https://www.ngui.cc/article/show-954304.html
2. 我收藏的几篇知乎文章:https://www.zhihu.com/collection/865188946
5. AI-ISP
AI ISP
是最近几年才出来的一个新的技术概念,当面对越来越高的场景复杂度和特殊的图像质量要求时,传统ISP
正面临了参数库逐渐庞大、调试困难、开发周期逐步拉长等挑战。以AI
技术为辅助,通过机器学习的方法来强化ISP
的功能就成为技术发展的重要方向,由此诞生了AI ISP
。
在2018
年,英特尔实验室的《Learning to see in the dark》论文中提出,可以通过整个神经网络来实现ISP
的全部功能。在这篇论文中,通过一个RAW
图进入,然后输出RGB
或者YUV
图像。到目前为止,还没有听说哪家的ISP产品是由整个神经网络完成的。
在爱芯的Pipeline
中,只将其中重要的模块进行AI
化,将有限的算力集中于整个AI ISP
中,最关键、人眼最可知的这些功能中,比如像HDR
、去噪的3DNR
、tone mapping
,还有demosaic
这样的功能中进行AI
化,以实现整个AI ISP
的最佳效果。
在爱芯的整个ISP
中,有一个专门为了ISP
设计的NPU
,这个NPU
和传统其他芯片中的NPU
并不完全一样,除了强调计算单元之外,还有Pre-Process
、Post-Process
和一个更大的Shared Memory
,以及一些针对AI ISP
的流式处理和CV
的处理操作,可以使其算力在AI
的图像处理中能够有更好的提升。
参考文章:AI视觉芯片干货分享:深度讲解AI ISP的技术原理([https://zhuanlan.zhihu.com/p/467137601](AI视觉芯片干货分享:深度讲解AI ISP的技术原理))
结束语
持续充电中,博客内容也在不断更新补充中,如有错误,欢迎来私戳小编哦!共同进步,感谢Thanks♪(・ω・)ノ