光学基础:镜头的光学特性、渐晕效应与色彩偏移原理
做图像处理这些年,我越来越觉得:不懂光学,ISP 调得再好也是空中楼阁。你想想看,传感器前面那个镜头,才是决定图像质量的第一个关卡。今天我们就来聊聊镜头的光学特性,以及它带来的两个经典问题——渐晕和色彩偏移。
镜头的光学特性
镜头不是完美的。它由多组透镜组成,目的是把光线汇聚到传感器上。但在这个过程中,有几个物理限制是绕不开的。
1. 光圈与进光量
光圈控制进光量,这个大家都懂。但有个细节:光圈越大(F 值越小),边缘光线入射角度越大,渐晕和色彩偏移就越明显。我在项目中遇到过一款手机镜头,F1.6 大光圈,拍出来的照片四角发暗、偏紫,后来不得不把光圈缩到 F2.0 才勉强压住。
2. 焦距与视场角
焦距越短,视场角越大,边缘光线入射角也越大。广角镜头是渐晕和色彩偏移的重灾区。超广角镜头(比如 12mm 等效焦距)的边缘入射角能到 30° 以上,这时候传感器上的微透镜都开始「吃不到」光线了。
3. 镜头镀膜与透过率
不同波长的光在镜头镀膜上的透过率不一样。一般来说,蓝光透过率最低,红光最高。这就导致了色彩偏移——镜头中心到边缘,色温会发生变化。
渐晕效应(Vignetting)
说白了,渐晕就是照片四角比中心暗。原因很简单:边缘光线走的路更长,被镜头遮挡了一部分。
渐晕的三种类型
| 类型 | 成因 | 特点 |
|---|---|---|
| 光学渐晕 | 镜头镜筒遮挡边缘光线 | 与光圈大小相关,大光圈更明显 |
| 自然渐晕 | 余弦四次方定律 | 与入射角相关,广角镜头更严重 |
| 像素渐晕 | 传感器微透镜效率下降 | 与像素位置相关,边缘像素更暗 |
我刚开始做 ISP 时,以为渐晕只是亮度问题,用个简单的增益补偿就行。后来发现,渐晕还伴随着色彩偏移——四角不仅暗,还偏色。这时候只做亮度补偿是不够的。
渐晕的数学模型
理想情况下,渐晕可以用一个径向衰减函数来描述:
# 渐晕补偿模型
def vignetting_correction(image, center, coefficients):
"""
image: 输入图像
center: 光轴中心坐标 (cx, cy)
coefficients: 多项式系数 [a0, a1, a2, ...]
"""
h, w = image.shape[:2]
cx, cy = center
result = image.copy()
for y in range(h):
for x in range(w):
# 计算径向距离
r = np.sqrt((x - cx)**2 + (y - cy)**2)
# 计算增益
gain = 1.0
for i, coeff in enumerate(coefficients):
gain += coeff * (r ** (i+1))
# 应用增益
result[y, x] = np.clip(image[y, x] * gain, 0, 255)
return result
这个模型虽然简单,但实际项目中够用了。我一般用 4 阶多项式,系数通过标定板拟合得到。
色彩偏移原理
色彩偏移,也叫 Color Shading。它和渐晕是「孪生兄弟」。渐晕是亮度问题,色彩偏移是颜色问题。两者都源于镜头的光学特性。
为什么会有色彩偏移?
原因有两个:
- 镜头镀膜的波长依赖性: 不同波长的光在镜头中的折射率不同。蓝光折射率大,红光折射率小。边缘光线经过更多透镜,蓝光被「甩」得更远。
- 传感器微透镜的入射角敏感性: 微透镜对不同角度入射光的收集效率不同。大角度入射时,蓝光通道的收集效率下降最快。
我记得有一次,客户反馈某款手机拍出来的照片,四角偏紫红色。我一看就知道是色彩偏移。中心色温 5000K,四角色温能偏到 4500K 以下。这就是典型的「红蓝通道增益不匹配」。
色彩偏移的两种模式
| 模式 | 表现 | 成因 |
|---|---|---|
| Luma Shading | 四角偏暗,色温不变 | 主要是自然渐晕 |
| Color Shading | 四角色温偏移 | 镀膜 + 微透镜共同作用 |
实际项目中,两者往往混合出现。我习惯先做 Luma Shading 补偿,再做 Color Shading 补偿。顺序不能乱——先调亮度,再调颜色。
色彩偏移的补偿思路
补偿色彩偏移,本质上是对 R、G、B 三个通道分别做渐晕补偿,但补偿系数不同。比如:
# 色彩偏移补偿
def color_shading_correction(image, center, r_gain, b_gain):
"""
r_gain, b_gain: 与位置相关的增益矩阵
"""
# 分离通道
r, g, b = cv2.split(image)
# 分别补偿
r_corrected = r * r_gain
b_corrected = b * b_gain
# G 通道通常不做补偿,或者做少量补偿
# 合并
result = cv2.merge([r_corrected, g, b_corrected])
return result
这里有个坑:R 和 B 的增益矩阵不能独立标定。我试过分别标定,结果补偿后 G 通道反而偏了。后来改用联合标定——同时拍摄灰卡,同时拟合 R、G、B 三个通道的增益。
知识结构总览
下面这张图,是我自己总结的镜头阴影与色彩偏移的知识框架。每次做项目前,我都会对照着梳理一遍。
实战中的避坑指南
做镜头阴影校正这些年,我踩过不少坑。挑几个典型的说说:
- 标定板要均匀: 我曾经用一块不均匀的灰板标定,结果补偿后图像出现「环形伪影」。后来改用积分球光源,问题才解决。
- 温度影响: 镜头镀膜对温度敏感。冬天和夏天的标定结果不一样。我建议在常温下标定,然后做温度补偿。
- 不要过度补偿: 四角增益太大,噪声会被放大。我一般限制最大增益 1.5 倍,超过的部分用平滑过渡。
- 注意镜头模组公差: 同一批镜头,每颗的光学特性都有差异。量产时最好每颗单独标定,或者至少抽检。
好了,光学基础就聊到这儿。记住一句话:镜头阴影和色彩偏移是物理限制,我们只能补偿,不能消除。理解了这个,后面的校正算法才能用得得心应手。