相机噪声模型、光子转移曲线与张正友标定:计算成像基础三件套

📅 发布时间:2026/10/14 19:42:23
相机噪声模型、光子转移曲线与张正友标定:计算成像基础三件套
1. 从一张脏图说起为什么你的相机需要被体检如果你拍过暗光照片或者用工业相机做过测量一定遇到过这种情况画面里明明应该是纯黑的区域放大一看全是密密麻麻的彩色噪点拍标定板的时候角点检测总是飘重投影误差怎么都压不下去。很多人第一反应是相机不行或者算法有问题但真相往往更朴素——你根本不了解手里这台相机的噪声特性也没认真做过标定。这一讲要聊的三件事是计算成像里最基础、也最容易被跳过的基本功相机噪声模型、光子转移曲线、张正友标定。它们分别回答三个问题相机的噪声从哪来、有多少、怎么量化相机的响应是不是线性的、增益和读出噪声到底多大相机的内参和外参怎么算出来、算得准不准这套东西适合谁做机器视觉的工程师、搞计算摄影的研究生、玩深度相机和双目视觉的开发者甚至只是想让自己的星空摄影噪点少一点的爱好者都能用得上。我见过太多项目算法调了几个月没进展最后发现是标定没做对、噪声模型拍脑袋设的。把这三块啃下来你会发现后面很多玄学问题突然就有了物理依据。下面我按噪声从哪来→怎么测→怎么标定的顺序把原理、实操、踩坑经验一次讲透。文中涉及的具体参数和步骤一部分来自公开的经典方法比如EMVA 1288标准、张正友的原文一部分是我自己在实际项目里反复验证过的做法会明确区分开。2. 相机噪声模型把脏拆成可量化的几块2.1 噪声不是一种而是一串很多人把噪声当成一个笼统的杂讯但在物理层面CMOS/CCD传感器输出的每一个像素值都是若干独立随机过程叠加的结果。要建模就得先拆解。最核心的几类噪声光子散粒噪声Shot Noise光子到达传感器是个泊松过程这是物理规律决定的无法消除。它的方差等于信号本身的均值所以信号越强绝对噪声越大但信噪比反而越高。读出噪声Read Noise包括复位噪声、源跟随器噪声、量化噪声等与信号强度无关是加性噪声。暗光下它是主要矛盾。暗电流噪声Dark Current Noise热激发产生的电子随温度和曝光时间增长长曝光时明显。固定模式噪声FPN每个像素的响应略有差异表现为空间上的固定花纹可以通过校准扣除。量化噪声ADC位数有限带来的误差通常远小于前几项。关键结论在正常曝光下光子散粒噪声占主导且服从泊松分布在极暗条件下读出噪声占主导近似高斯分布。这就是为什么标题里专门点出泊松噪声——它是理解相机噪声的起点。2.2 泊松噪声为什么它和信号绑定泊松分布描述的是单位时间内随机事件发生次数。光子打到像素上就是这样一个过程平均来N个光子实际来多少个是随机的方差也是N。这意味着什么假设一个像素平均接收到10000个电子那么标准差是100相对噪声1%如果只接收到100个电子标准差是10相对噪声10%。信号越弱相对噪声越夸张这就是暗光画质差的根本原因跟相机好不好关系没那么大。在建模时我们通常把光子数转换成电子数再经过增益转换成DNDigital Number数字值。设增益为g单位e-/DN则信号均值DNS N/g散粒噪声方差DN²σ_shot² N/g² S/g注意这个关系散粒噪声的方差与信号均值成正比比例系数是1/g。这条直线就是后面光子转移曲线的理论依据。2.3 完整噪声模型与信噪比公式把各项加起来一个像素的DN值可以写成DN g·(N_photon N_dark) N_read N_quant对应的方差σ²_total g²·(N_photon N_dark) σ²_read σ²_quant在忽略暗电流和量化噪声的简化模型下σ² g·S σ²_read这个式子极其重要它说明总方差对信号均值作图是一条直线斜率是增益g截距是读出噪声方差σ²_read。这就是光子转移曲线Photon Transfer Curve, PTC的数学基础。信噪比SNR S/σ在散粒噪声主导区SNR ≈ √(S/g)也就是信号越强信噪比越高但提升速度是平方根关系——想信噪比翻倍曝光要翻四倍。这个反直觉的结论是很多曝光策略的底层逻辑。2.4 噪声模型在算法里的实际用途别以为这只是理论。噪声模型直接决定了去噪算法的参数BM3D、非局部均值这些算法噪声标准差是必填参数填错了要么糊要么没效果。图像融合的权重多帧降噪时每帧的权重应该按噪声方差倒数来分配。HDR合成的可信度暗帧噪声大合成时权重就该低。仿真数据生成训练神经网络需要加噪加什么噪、加多少全靠这个模型。我做过一个项目客户抱怨去噪后细节全丢。一查他们把所有帧的噪声当成同一个常数实际上暗帧噪声是亮帧的好几倍权重一刀切暗部自然被过度平滑。改成按方差加权后效果立竿见影。3. 光子转移曲线给相机做一次体检3.1 PTC到底测什么光子转移曲线PTC是EMVA 1288标准里的核心工具它通过分析方差-均值关系一次性把增益g和读出噪声σ_read两个关键参数测出来。原理就是上一节那个公式σ² g·S σ²_read。我们只要采集一组不同曝光下的平场图像对每个亮度水平计算均值和方差然后做线性拟合斜率的倒数相关量就是增益截距开根号就是读出噪声。为什么叫光子转移因为它描述的是光子转换成电子、再转换成DN这个转移过程的统计特性。名字听着玄本质就是一次线性回归。3.2 采集数据平场、多曝光、别饱和实操步骤这是我自己常用的流程和标准略有简化但足够用准备均匀光源积分球最好没有的话用均匀背光板、毛玻璃加稳定光源也行。关键是画面亮度要均匀不能有渐变或纹理。盖住镜头或对均匀面确保没有场景结构只有平场。固定增益和温度整个采集过程相机参数不能变温度尽量稳定暗电流会漂。改变曝光时间从最短开始逐步增加覆盖从接近全黑到接近饱和的整个范围。建议至少15-20个曝光档每档拍20-50帧。避免饱和一旦像素值接近满阱比如12bit的4095散粒噪声统计就失真了这些点必须剔除。注意每档曝光拍多帧是为了估计该亮度下的时间噪声方差。单帧算不出方差这是新手最容易犯的错。3.3 计算与拟合一步步来拿到数据后对每档曝光的N帧逐像素计算均值和方差再对全图取平均或取中心区域避开暗角和坏点。得到一系列S_i, σ²_i数据点。剔除饱和点和明显离群点。对 σ² g·S σ²_read 做线性最小二乘拟合。拟合出来的斜率k增益g 1/k单位e-/DN截距b读出噪声σ_read √b单位DN乘以g就是e-。这里有个细节如果相机内部已经做了黑电平扣除截距可能接近0甚至为负这时候读出噪声要用别的方法比如暗帧标准差交叉验证。3.4 一个真实案例的数据解读我之前测过一台工业相机12bit输出拟合结果参数拟合值物理含义斜率k0.42 DN²/DN每DN信号贡献0.42 DN²方差增益g2.38 e-/DN每个DN对应约2.4个电子截距b18.6 DN²读出噪声方差读出噪声σ_read4.31 DN ≈ 10.3 e-暗光噪声水平满阱约4095 DN ≈ 9700 e-饱和容量解读这台相机增益偏高2.38 e-/DN意味着动态范围被压缩但暗光灵敏度好。读出噪声10 e-属于中等水平。如果做暗光成像满阱只有9700 e-很容易饱和需要控制曝光。这些数字不是摆设。比如你要做光子计数级别的成像读出噪声10 e-就太高了得换sCMOS如果只是普通机器视觉这个水平完全够用。3.5 PTC实操中的坑光源不稳如果光源本身有闪烁方差会被高估拟合斜率偏大增益算错。用直流光源或者多帧平均掉闪烁。暗角没处理镜头暗角会让边缘亮度低全图平均会引入额外方差。建议只取中心1/4区域。坏点污染热像素、死像素会严重拉高方差。先做坏点检测和剔除。温度漂移长时间采集暗电流变化低曝光档的数据会漂。控制环境温度或缩短采集时间。只测一个增益很多相机有多个增益档每个档的g和σ_read都不同要分别测。我见过有人拿低增益的参数去配高增益的图像去噪参数全错。4. 张正友标定从棋盘格到内参矩阵4.1 为什么是张正友相机标定方法很多但张正友标定法Zhangs Method几乎是工业界的默认选择。原因很简单只需要一块打印的棋盘格拍十几张不同角度的照片就能同时解出内参和畸变系数精度还很高。相比需要精密三维标定物的方法成本低到可以忽略。它的核心思想是棋盘格平面上的角点在世界坐标系里是已知的比如Z0平面上的规则网格通过单应性矩阵Homography把平面点映射到图像点再利用旋转矩阵的正交约束解出内参。4.2 内参矩阵长什么样相机内参矩阵KK [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]fx, fy焦距以像素为单位通常接近相等差异来自像素非正方形。cx, cy主点坐标理论上接近图像中心实际会有偏移。畸变系数通常用径向切向模型5参数k1, k2, p1, p2, k3。径向畸变让直线变弯桶形/枕形切向畸变来自镜头和传感器不平行。4.3 标定实操从拍板到出结果准备阶段棋盘格打印精度要高贴在硬板上保证平整。格子数建议内角点7x9或9x11太小约束不够太大检测慢。尺寸让棋盘格在画面里占1/3到2/3太小角点定位不准太大容易出画。光照均匀避免反光和阴影角点对比度要高。采集阶段拍15-25张覆盖画面各个区域中心、四角、边缘。角度多样正对、倾斜、旋转倾斜角度建议20-45度。每张都要完整清晰角点检测要稳。计算阶段以OpenCV为例import cv2 import numpy as np # 棋盘格内角点数 pattern_size (9, 6) objp np.zeros((pattern_size[0]*pattern_size[1], 3), np.float32) objp[:, :2] np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) objpoints [] # 3D点 imgpoints [] # 2D点 images [...] # 图像列表 for fname in images: img cv2.imread(fname) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners cv2.findChessboardCorners(gray, pattern_size, None) if ret: corners2 cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) objpoints.append(objp) imgpoints.append(corners2) ret, K, dist, rvecs, tvecs cv2.calibrateCamera( objpoints, imgpoints, gray.shape[::-1], None, None) print(内参矩阵:\n, K) print(畸变系数:, dist.ravel())评估阶段重投影误差Reprojection Error把3D点用解出的参数投影回图像和检测到的角点比算均方误差。好的标定应该在0.1-0.3像素以内超过0.5就要检查。看误差分布如果误差集中在某些图或某些区域说明那些图质量差或角度覆盖不均。4.4 标定中的经验与坑棋盘格不平打印纸翘边是重投影误差大的头号原因。贴在玻璃或铝板上。角点检测失败光照不均、模糊、格子太小都会导致。用cornerSubPix做亚像素精化能显著提升精度。角度太单一全是正对拍摄标定会退化畸变系数解不准。一定要有倾斜。张数不是越多越好20张高质量图胜过50张糊图。质量优先。主点漂移cx, cy有时会解到很奇怪的位置如果和图像中心差太多检查是否有系统性误差。畸变模型选择普通镜头5参数够用鱼眼要用专门的鱼眼模型fisheye别硬套。4.5 双目与RGB-D标定多一层外参单目标定只解决内参。双目相机还要标外参两个相机之间的旋转和平移RGB-D比如D435i还要标深度和彩色的对齐。双目标定用stereoCalibrate输入两个相机的内参和对应角点输出R、T。关键是两个相机要同时看到棋盘格且棋盘格要在两者共同视野里。D435i这类相机出厂有内参但实际使用中建议自己重标因为温度、装配都会让参数漂移。ROS里有camera_calibration包可以交互式标定适合快速上手。提示双目标定后一定要做极线校正stereoRectify检查校正后的图像行对齐。如果行对不齐说明外参有问题视差计算会全错。5. 三者的联动噪声、标定与成像质量5.1 噪声模型如何影响标定精度标定依赖角点检测而角点检测在噪声大的图像上会飘。如果你知道相机的读出噪声和增益就能预估角点定位的理论精度进而判断标定结果是否可信。举个例子读出噪声10 e-增益2.4 e-/DN那么噪声约4 DN。角点亚像素定位精度大致和噪声成正比噪声越大重投影误差下限越高。如果实测重投影误差远大于理论下限说明是标定流程有问题不是噪声的锅。5.2 标定参数如何反哺噪声测量反过来做PTC时如果知道畸变系数可以先做畸变校正让平场更均匀减少暗角带来的方差污染。这是一个正向循环标定越准噪声测量越干净噪声模型越准标定评估越可靠。5.3 一个完整的相机表征流程我在项目里通常这么做先做张正友标定拿到内参和畸变评估重投影误差。用畸变校正后的图像做PTC测增益和读出噪声。用噪声参数指导后续去噪、融合、HDR算法。定期复测因为相机参数会随温度和时间漂移。这套流程走下来相机的脾气就摸清了后面所有算法都有了物理依据不再是拍脑袋调参。6. 常见问题速查与避坑清单6.1 噪声与PTC常见问题问题现象可能原因排查与解决拟合斜率异常大光源闪烁、坏点污染换直流光源剔除坏点截距为负黑电平已扣除用暗帧标准差交叉验证读出噪声低曝光档数据离散读出噪声主导样本不足增加帧数多帧平均高曝光档偏离直线饱和剔除接近满阱的点不同增益结果矛盾增益档混淆每个增益档单独测6.2 标定常见问题问题现象可能原因排查与解决重投影误差大棋盘格不平、模糊换硬板重新对焦畸变系数离谱角度单一增加倾斜和旋转角度主点偏移大系统性误差检查图像是否有裁剪双目行不对齐外参错误重新采集同步图像角点检测失败光照/对比度差改善照明调整检测参数6.3 几条压箱底的经验标定板别用A4纸直接打纸张会翘误差直接翻倍。花几十块贴个铝板省下的是几天的调试时间。PTC别只测一次相机温度变化10度暗电流可能翻倍。重要项目要建温度-噪声曲线。重投影误差不是唯一指标还要看误差的空间分布。均匀分布的小误差比集中在某区域的大误差更可信。标定后一定要验证用标定参数去测一个已知尺寸的物体看测量值对不对。这是最实在的检验。别迷信出厂参数D435i、RealSense这类相机出厂内参是平均值个体差异不小自己标一遍更放心。7. 写在最后的一点个人体会这套东西我前后折腾了好几年最大的感受是计算成像里很多高级问题根子都在这些基础环节。你把噪声模型搞对了去噪、超分、HDR的效果会突然上一个台阶你把标定做扎实了双目深度、三维重建的精度会稳定得让你惊讶。我见过太多人一上来就调神经网络结果输入数据本身带着没标定、没建模的系统误差网络再强也救不回来。反过来基础打牢了哪怕用最朴素的算法结果也拿得出手。如果你刚开始接触建议先拿手边的相机做一遍PTC再标一次棋盘格把这两个流程跑通。跑通之后你对相机这个东西的理解会完全不一样。后面再聊具体的去噪、融合、深度估计你就能听懂每一步背后的物理意义而不是只会调包。这套流程后续还能扩展比如加入多光谱相机的通道间标定、加入卷帘快门的时间标定、把噪声模型做到光子级用于单光子成像。路很长但每一步都踩在实处。