2、摄像头成像原理:小孔成像模型、透镜与畸变、感光元件与色彩滤波阵列
各位同学,今天我们聊聊摄像头成像的底层逻辑。说白了,你手里那个小小的摄像头,它怎么把现实世界的光线变成一张数字图片?这背后有三个核心环节:小孔成像模型、透镜与畸变、感光元件与色彩滤波阵列。我做了这么多年车载视觉,每次标定出问题,十有八九都是对这几个基础概念理解不到位。咱们一个一个来拆解。
2.1 小孔成像模型:最朴素的相机
先说说最理想的情况——小孔成像。你想想看,一个密闭的盒子,前面戳一个小孔,光线穿过小孔,在后面的感光面上形成一个倒立的像。这就是相机最原始的原理。
数学上怎么描述?很简单,一个相似三角形的关系:
// 小孔成像的几何关系
// 物体高度 H,物体到小孔距离 Z
// 像高度 h,像到小孔距离 f(焦距)
// 关系:h / f = H / Z
// 写成坐标形式:
// 世界点 (X, Y, Z) 映射到像平面 (x, y)
x = f * (X / Z)
y = f * (Y / Z)
嗯,这里要注意,这个模型是理想化的。它假设小孔无限小,光线严格直线传播。但在实际项目中,小孔太小了进光量不够,图像太暗;小孔太大了又模糊。所以,我们得用透镜。
核心要点:小孔成像模型是所有相机模型的数学基础。车载摄像头标定中,我们通常用这个模型来建立世界坐标到像素坐标的映射关系。我习惯把它叫做「理想相机」,后面所有的畸变校正,都是在这个理想模型上做修正。
2.2 透镜与畸变:理想很丰满,现实很骨感
为了获得足够亮的图像,我们给摄像头装上了透镜。透镜能汇聚光线,让更多光进入感光元件。但代价是什么?畸变。
我在项目中遇到过最头疼的事:一辆车的环视系统,四个摄像头拼接出来的画面总是对不齐。查了半天,发现是其中一个摄像头的畸变参数没标对。你想想看,透镜的物理形状决定了它不可能完美成像。
常见的畸变有两种:
- 径向畸变:光线经过透镜边缘时弯曲得更厉害。说白了,就是画面中间正常,越往边缘越「鼓」或者越「瘪」。鱼眼镜头就是典型的径向畸变。
- 切向畸变:透镜和感光元件不平行,装歪了。这个在车载摄像头的量产装配中比较常见。
数学上怎么校正?我们用多项式模型来描述畸变:
// 径向畸变模型(Brown-Conrady 模型)
// (x, y) 是理想坐标,(x_distorted, y_distorted) 是实际畸变坐标
// r^2 = x^2 + y^2
x_distorted = x * (1 + k1*r^2 + k2*r^4 + k3*r^6) + [2*p1*x*y + p2*(r^2 + 2*x^2)]
y_distorted = y * (1 + k1*r^2 + k2*r^4 + k3*r^6) + [p1*(r^2 + 2*y^2) + 2*p2*x*y]
// 其中 k1, k2, k3 是径向畸变系数
// p1, p2 是切向畸变系数
避坑指南:我曾经在标定一个广角摄像头时,只用了 k1 和 k2 两个参数,结果边缘校正效果很差。后来发现,对于视场角超过 120° 的镜头,必须加上 k3 甚至更高阶项。否则,你校正出来的图像在边缘会有明显的「波浪」效应。
2.3 感光元件与色彩滤波阵列:从光到电
好了,光线经过透镜,在感光元件上成像了。但感光元件只能感知光的强度,它分不清颜色。怎么办?
这就引出了色彩滤波阵列(CFA),最常见的就是 Bayer 阵列。我刚开始做图像处理时,一直没搞明白为什么 raw 图是「绿油油」的。后来才明白,Bayer 阵列里绿色像素占了 50%,红色和蓝色各占 25%。为什么?因为人眼对绿色最敏感。
| Bayer 模式 | 像素排列 | 特点 |
|---|---|---|
| RGGB | 第一行:R G R G... 第二行:G B G B... |
最常用,绿色信息丰富 |
| BGGR | 第一行:B G B G... 第二行:G R G R... |
部分 Sony 传感器使用 |
| RGBW | 加入白色像素 | 低光照下表现更好 |
感光元件输出的原始数据叫 raw 图。每个像素只有一个颜色通道的值。要得到完整的彩色图像,需要做去马赛克(Demosaicing)处理——也就是用周围像素的信息,插值出缺失的颜色。
个人经验:我建议你在做车载摄像头调试时,一定要先看 raw 图。很多 ISP(图像信号处理器)的自动白平衡、自动曝光算法会「美化」图像,掩盖掉传感器本身的噪声和坏点。直接看 raw 图,你能发现最真实的问题。比如,某个像素一直偏亮,那可能就是坏点,需要在标定前先做坏点校正。
2.4 从世界坐标到像素坐标:完整的映射链
把上面三个环节串起来,就是摄像头成像的完整流程:
- 世界坐标系:现实中的三维点 (X, Y, Z)
- 相机坐标系:通过外参(旋转 R、平移 t)变换到相机坐标系
- 归一化平面:通过小孔成像模型,投影到归一化平面 (x, y)
- 畸变校正:加上透镜畸变,得到实际像点 (x', y')
- 像素坐标系:通过内参(焦距 fx, fy,主点 cx, cy)映射到像素坐标 (u, v)
// 完整的投影过程(伪代码)
function projectPoint(X, Y, Z, R, t, K, distCoeffs):
// 1. 世界坐标 -> 相机坐标
[Xc, Yc, Zc] = R * [X, Y, Z] + t
// 2. 归一化平面
x = Xc / Zc
y = Yc / Zc
// 3. 畸变校正
r2 = x*x + y*y
x_dist = x * (1 + k1*r2 + k2*r2*r2 + k3*r2*r2*r2) + 2*p1*x*y + p2*(r2 + 2*x*x)
y_dist = y * (1 + k1*r2 + k2*r2*r2 + k3*r2*r2*r2) + p1*(r2 + 2*y*y) + 2*p2*x*y
// 4. 像素坐标
u = fx * x_dist + cx
v = fy * y_dist + cy
return (u, v)
嗯,这个流程你看着可能有点复杂。但实际做标定时,OpenCV 的 calibrateCamera() 函数已经帮我们封装好了。你只需要提供棋盘格角点的世界坐标和像素坐标,它就能解算出内参、外参和畸变系数。
总结一下:摄像头成像原理,说白了就是「光路 + 电路」的配合。小孔模型是数学基础,透镜带来了畸变这个「副产品」,感光元件和 CFA 完成了光电转换。搞懂了这些,你再去调摄像头标定、做图像校正,心里就有底了。下一章,我们聊聊具体的标定方法和实战技巧。
公众号:蓝海资料掘金营,微信deep3321