本文只求尽量全面的简介和科普常见的相机模型、畸变模型、光度模型,虽然我想拒绝公式~~
目录
1.2.4 Unified Projection Model
1.3.1 相机响应函数标定(Response Calibration)
1.1 相机模型
相机模型通常分为omnidirectional 广角相机、Pinhole 针孔相机,据大佬说,小于90度使用Pinhole,大于90度使用MEI模型。要注意畸变矫正之后的相机内参会变化。
1.2 畸变模型
1.2.1 radtan畸变模型
即普通相机畸变通常包括径向畸变和切向畸变
1)径向畸变表式沿半径方向的偏移量, 径向畸变的形成原因是镜头制造工艺不完美,使得镜头形状存在缺陷, 通常又分为桶性畸变和枕形畸变,如图
2)在相机的组装过程中由于不能使透镜严格和成像平面平行会引入切向畸变,切向畸变又分为薄透镜畸变和离心畸变等,薄透镜畸变则是因为透镜存在一定的细微倾斜造成的;离心畸变的形成原因是镜头是由多个透镜组合而成的,而各个透镜的光轴不在同一条中心线上,如图
1.2.2 鱼眼畸变模型 Equidistant
鱼眼镜头的畸变模型有很多种:
其中使用最多的是Equidistant模型,opencv中的fisheye::calibrate就是用的该畸变模型. 也叫作kannala-brandt模型.
1.2.3 FOV畸变模型
1.2.4 Unified Projection Model
在鱼眼相机中通常会看到Unified Projection Model或者MEI model, 其实就是Omnidirectional相机模型+radtan畸变模型. 前面提到了Omnidirectional模型涵盖了Pinhole模型, 所以MEI model可以表示鱼眼和非鱼眼相机.
1.3 光度模型
物体一点反射光量为辐射(radiance),通常假设物体时郎伯面(漫反射);感光器件单位时间在x位置接收的能量叫辐照(Irradiance),辐照和辐射是相对应的,而且相机会存在渐晕(辐照衰减)V(x),建模成0和1之间的数
传感器在曝光时间ti内对辐照进行积分,假设期间辐照恒定,则建模为,cmos将积分辐照值输出为图像强度,通常为非线性相应函数G,一般为0-255,则最终光度模型为: ;其中I 是我们从相机获取的图像。在论文中,使用的是非参数化(non-parametric)的求解方式,也就是说我们不是求出函数的表达式,而是得到一个映射表。
所谓光度矫正就是去除响应函数和渐晕影响:
1.3.1 相机响应函数标定(Response Calibration)
假如拍摄一个亮度非常均匀的物体,图像中心和边缘的亮度值并不一致。如果这些因素都没有影响,那么从scene radiance到sensor irradiance的转化是线性的自动曝光模式下,如图:
不同场景曝光时间并不一样,会导致同一物体在不同场景下的灰度值产生差异,输入的曝光量和输出的亮度值之间的关系称为响应函数(response function)。响应函数一般来说是非线性的,甚至包含人为调整的成分,比如伽马校正、白平衡、色调、饱和度等。为图像进行伽马编码的目的是用来对人类视觉的特性进行补偿,从而根据人类对光线或者黑白的感知,最大化地利用表示黑白的数据位或带宽。人眼对暗部比较敏感,因此一般选择提高暗部的分辨率。这些因素会非线性地修正曝光量,因此作者希望通过光度标定来补偿它们的影响。
具体而言,在固定场景下,相机在不同曝光时间下,重复拍照得到一系列图像。由于场景不变,B在不同图像中是一样的,图像亮度值的差异来源于曝光时间和响应函数。因此,作者构建了一个能量误差函数,用迭代的方法求解,其中待求解变量为B和U。每步迭代中,先用估计的U求解B,然后用更新的B求解U。
在标定相机响应函数的时候,作者是将相机固定,逐渐变换相机曝光时间,对一个静止的场景进行采集。也就是说,在这个过程中,相机的辐照度图像B是不变的。由于相机的渐晕是相机固有的属性,在标定相机响应函数的时候,把相机的光度模型转换成:
用函数V来表示光学模块的影响。V是光学模块的固有属性,作者用一个权重矩阵(和图像一样大)来表示其对每个像元的影响,用t来表示曝光时间。相机有开启自动曝光时,每一帧的t都不相同,用函数G来表示响应函数,其值域是离散的(比如0~255)。G是传感器的固有属性
假设存在零均值高斯噪音,令响应函数的反函数:, ,给定图像Ii ,其对应的曝光时间为ti,则有
通过最大似然估计(寻找一个参数使得似然函数取到最大值),我们近似给出如下最小二乘的形式:
(1)
第一个求和是对所有(不同曝光时间的)图像,第二个求和是对图像平面上所有的像素点。对上(1)式最小化,通过轮流最小化求解U和B′得到 :
(2)
(3)
先看U(k)的求解,由于论文中使用的是非参数方式,U(k)对应于一个大小为256的表格(一维数组),对于固定的k值,U(k)也是常量。因此在求U(k)时,相当于将(1)展开然后关于U(k)求偏导,并令式子为0,得:
其中: ,是对于第i帧图像的所有像素值为k的像素点的集合;是在所有图像中,像素值等于k的像素点的集合,得到公式(2),对应代码如下:
for(int i=0;i<n;i++)
for(int k=0;k<w*h;k++)
{
//if(dataVec[i][k]==255) continue;
E[k] += dataVec[i][k];
En[k] ++;
}
for(int k=0;k<w*h;k++) E[k] = E[k]/En[k];
/*........*/
for(int it=0;it<nits;it++)
{
if(optG)
{
// optimize log inverse response function.
double* GSum = new double[256];
double* GNum = new double[256];
memset(GSum,0,256*sizeof(double));
memset(GNum,0,256*sizeof(double));
for(int i=0;i<n;i++)
{
for(int k=0;k<w*h;k++)
{
int b = dataVec[i][k];
if(b == 255) continue;
GNum[b]++;
GSum[b]+= E[k] * exposureVec[i];
}
}
for(int i=0;i<256;i++)
{
G[i] = GSum[i] / GNum[i];
if(!std::isfinite(G[i]) && i > 1) G[i] = G[i-1] + (G[i-1]-G[i-2]);
}
delete[] GSum;
delete[] GNum;
printf("optG RMSE = %f! \t", rmse(G, E, exposureVec, dataVec, w*h )[0]);
char buf[1000]; snprintf(buf, 1000, "photoCalibResult/G-%d.png", it+1);
plotG(G, buf);
}
对于B′(x)同理,由于是只对某一位置像素点求,因此可以把每一个B′(x)分开,求得其对应的最优。(1)式转换得到
关于B′(x)求导得整理后得到式3)
if(optE)
{
// optimize scene irradiance function.
double* ESum = new double[w*h];
double* ENum = new double[w*h];
memset(ESum,0,w*h*sizeof(double));
memset(ENum,0,w*h*sizeof(double));
for(int i=0;i<n;i++)
{
for(int k=0;k<w*h;k++)
{
int b = dataVec[i][k];
if(b == 255) continue;
ENum[k] += exposureVec[i]*exposureVec[i];
ESum[k] += (G[b]) * exposureVec[i];
}
}
for(int i=0;i<w*h;i++)
{
E[i] = ESum[i] / ENum[i];
if(E[i] < 0) E[i] = 0;
}
delete[] ENum;
delete[] ESum;
printf("OptE RMSE = %f! \t", rmse(G, E, exposureVec, dataVec, w*h )[0]);
char buf[1000]; snprintf(buf, 1000, "photoCalibResult/E-%d", it+1);
plotE(E,w,h, buf);
}
在求响应函数的时候,对像素值为255的点都是认为过曝光的,因此都剔除了。则U(255)就没法正常计算得到,因此论文中通过使用相邻的函数值推断得到。并且为了除去尺度的多义性,令U(255)=255,并把U(k)其他值按照该尺度进行缩放。对应代码:
// rescale such that maximum response is 255 (fairly arbitrary choice).
double rescaleFactor=255.0 / G[255];
for(int i=0;i<w*h;i++)
{
E[i] *= rescaleFactor;
if(i<256) G[i] *= rescaleFactor;
}
由于论文使用的是打表(非参数化)的形式,因此在计算(5.1)的时候,我们需要保证每一个U(k)都应该可以计算,也就是说采集的图像上的像素值要尽可能覆盖0∼255的所有范围。实际操作的时候,作者是从曝光时间从0.05ms逐渐提升到20ms,采集1000张图像,覆盖120种不同曝光时间,以保证响应函数计算的准确。
参考:
A Photometrically Calibrated Benchmark For Monocular Visual Odometry