之前一直没看DSO1,前阵子对应光度模型的论文和代码研究了一下,做了简单的总结。
1. 相机光度模型(Photometric Model)
在光度标定的论文2中,作者给出光度模型如下:
这里的 为相机的响应函数(response function), 为(归一化的)渐晕函数(vignette), 是辐照度图像(irradiance image), 是我们从相机获取的图像。在论文中,使用的是非参数化(non-parametric)的求解方式,也就是说我们不是求出函数的表达式,而是得到一个映射表。
2. 相机响应函数标定(Response Calibration)
在标定相机响应函数的时候,作者是将相机固定,逐渐变换相机曝光时间,对一个静止的场景进行采集。也就是说,在这个过程中,相机的辐照度图像 是不变的。由于相机的渐晕是相机固有的属性,在标定相机响应函数的时候,把相机的光度模型转换成:
这里 。在求响应函数的时候,为了方便起见,作者求的是响应函数的反函数: ,给定一个图像 ,其对应的曝光时间为 ,假设在 上有一个零均值的高斯噪声,则模型有如下形式:
![](/qrcode.jpg)
通过最大似然估计,我们近似给出如下最小二乘的形式:
第一个求和是对所有(不同曝光时间的)图像,第二个求和是对图像平面上所有的像素点。对上式最小化,通过轮流最小化求解 和 得到:
先看
的求解,由于论文中使用的是非参数方式,
对应于一个大小为256的表格(一维数组),对于固定的
值,
也是常量。因此在求
时,相当于对
式子中的一个变量求偏导,并令式子为
:
这里的 ,是对于第 帧图像的所有像素值为 的像素点的集合,而这里的 是在所有图像中,像素值等于 的像素点的集合。从而我们可以解出 式。对应代码:
for(int i=0;i<n;i++)//! 遍历 i (图像)
{
for(int k=0;k<w*h;k++)//! 遍历 x (像素点)
{
int b = dataVec[i][k];
if(b == 255) continue;
GNum[b]++;//! 所有像素值为b的像素点个数|omega_k|
GSum[b]+= E[k] * exposureVec[i];//! 累计的ti*B'(x)
}
}
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]);
}
对于 同理,由于是只对某一位置像素点求,因此可以把每一个 分开,求得其对应的最优。转换得到
则分别对每一个 求偏导,也就是对 中的 求偏导,可得:
整理之后就可以得到式 。对应的代码为:
for(int i=0;i<n;i++)//! 遍历 i (图像)
{
for(int k=0;k<w*h;k++)//! 遍历 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;
}
在求响应函数的时候,对像素值为 的点都是认为过曝光的,因此都剔除了。则 就没法正常计算得到,因此论文中通过使用相邻的函数值推断得到。并且为了除去尺度的多义性,令 ,并把 其他值按照该尺度进行缩放。对应代码:
// 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;
}
由于论文使用的是打表(非参数化)的形式,因此在计算 的时候,我们需要保证每一个 都应该可以计算,也就是说采集的图像上的像素值要尽可能覆盖 的所有范围。实际操作的时候,作者是从曝光时间从 ms逐渐提升到 ms,采集1000张图像,覆盖120种不同曝光时间,以保证响应函数计算的准确。
3.渐晕标定(Vignette Calibration)
同样,对渐晕标定也使用非参数化的形式,使用一个渐晕映射表 。标定过程是对这一块白墙进行图像的采集,假设白墙是理想的朗伯反射面(Lambertian Suface),也就是指在固定照明下,从任意视角上观察都有相同亮度的平面。
论文中,作者通过AR Marker获取相机相对平面的位姿。定义从3D空间到图像平面的映射
。同样假设在
上有高斯白噪声,通过最大似然,得到如下的误差方程:
这里的 是平面上的点到相机的辐射度(irradiance),是未知的。论文中把平面表示为正方区域,且分成 个离散点。这里的 表示距离最近的离散坐标。
通过交替最小化
和
,给出:
实际代码中的操作,其实把光度模型写作:
也就定义为作用了渐晕效果后的辐射度图像。实际上,在求 和 的时候,如果使用恒定的曝光时间,则直接可以去掉曝光时间 的影响,这里本身就存在一个不确定的尺度因子,由于 是归一化在区间 中,V的值域在 。在曝光恒定的条件下,只要给的曝光时间和真实曝光时间差别不要太大,都是可以的,实际上只会影响辐射度图像 的值域范围,不影响我们标定的渐晕 的结果。如果直接不管 (令其为1),则相当于辐射度图像的值域和得到的图像亮度范围基本是一致的。
去除曝光时间的影响, 可以转化为:
这里 。
和相机响应函数标定一样,这里是稠密的打表的形式,因此,需要尽可能多的数据,才可以较好地恢复出渐晕的映射表。和响应函数相似,这里对应代码就不贴出了。