DSO之光度标定

之前一直没看DSO1,前阵子对应光度模型的论文和代码研究了一下,做了简单的总结。

1. 相机光度模型(Photometric Model)

在光度标定的论文2中,作者给出光度模型如下:

(1) I ( x ) = G ( t V ( x ) B ( x ) )

这里的 G 为相机的响应函数(response function), V 为(归一化的)渐晕函数(vignette), B 是辐照度图像(irradiance image), I 是我们从相机获取的图像。在论文中,使用的是非参数化(non-parametric)的求解方式,也就是说我们不是求出函数的表达式,而是得到一个映射表。

2. 相机响应函数标定(Response Calibration)

在标定相机响应函数的时候,作者是将相机固定,逐渐变换相机曝光时间,对一个静止的场景进行采集。也就是说,在这个过程中,相机的辐照度图像 B 是不变的。由于相机的渐晕是相机固有的属性,在标定相机响应函数的时候,把相机的光度模型转换成:

(2) I ( x ) = G ( t B ( x ) )

这里 B ( x ) := V ( x ) B ( x ) 。在求响应函数的时候,为了方便起见,作者求的是响应函数的反函数: U := G 1 ,给定一个图像 I i ,其对应的曝光时间为 t i ,假设在 U ( I ( x ) ) 上有一个零均值的高斯噪声,则模型有如下形式:

(3) U ( I i ( x ) ) = t i B ( x ) + n i , n i N ( 0 , σ i 2 )

扫描二维码关注公众号,回复: 100802 查看本文章

通过最大似然估计,我们近似给出如下最小二乘的形式:

(4) E ( U , B ) = i x Ω ( U ( I i ( x ) ) t i B ( x ) ) 2

第一个求和是对所有(不同曝光时间的)图像,第二个求和是对图像平面上所有的像素点。对上式最小化,通过轮流最小化求解 U B 得到:

(5.1) U ( k ) = arg min U ( k ) E ( U , B ) = Ω k t i B ( x ) | Ω k | (5.2) B ( x ) = arg min B ( x ) E ( U , B ) = i t i U ( I i ( x ) ) i t i 2

先看 U ( k ) 的求解,由于论文中使用的是非参数方式, U ( k ) 对应于一个大小为256的表格(一维数组),对于固定的 k 值, U ( k ) 也是常量。因此在求 U ( k ) 时,相当于对 ( 4 ) 式子中的一个变量求偏导,并令式子为 0

(6) i x Ω ( U ( k ) t i B ( x ) ) = i x Ω U ( k ) i x Ω t i B ( x ) = x Ω k U ( k ) x Ω k t i B ( x ) = 0

这里的 Ω := { x | I i ( x ) = k } ,是对于第 i 帧图像的所有像素值为 k 的像素点的集合,而这里的 Ω k := { i , x | I i ( x ) = k } 是在所有图像中,像素值等于 k 的像素点的集合。从而我们可以解出 ( 5.1 ) 式。对应代码:

            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]);
            }

对于 B ( x ) 同理,由于是只对某一位置像素点求,因此可以把每一个 B ( x ) 分开,求得其对应的最优。转换得到

(7) E ( U , B ) = x Ω i ( U ( I i ( x ) ) t i B ( x ) ) 2 E ( U , B , x )

则分别对每一个 B ( x ) 求偏导,也就是对 E ( U , B , x ) 中的 B ( x ) 求偏导,可得:

(8) 2 i t i ( U ( I i ( x ) ) t i B ( x ) ) = 2 i t i U ( I i ( x ) ) 2 i t i 2 B ( x )

整理之后就可以得到式 ( 5.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;
            }

在求响应函数的时候,对像素值为 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.05 ms逐渐提升到 20 ms,采集1000张图像,覆盖120种不同曝光时间,以保证响应函数计算的准确。

3.渐晕标定(Vignette Calibration)

同样,对渐晕标定也使用非参数化的形式,使用一个渐晕映射表 V : Ω [ 0 , 1 ] 。标定过程是对这一块白墙进行图像的采集,假设白墙是理想的朗伯反射面(Lambertian Suface),也就是指在固定照明下,从任意视角上观察都有相同亮度的平面。

论文中,作者通过AR Marker获取相机相对平面的位姿。定义从3D空间到图像平面的映射 π : P Ω 。同样假设在 U ( I i ( π i ( x ) ) ) 上有高斯白噪声,通过最大似然,得到如下的误差方程:

(9) E ( C , V ) = i , x p ( t i V ( [ π i ( x ) ] ) C ( x ) U ( I i ( π i ( x ) ) ) ) 2

这里的 C : P R 是平面上的点到相机的辐射度(irradiance),是未知的。论文中把平面表示为正方区域,且分成 1000 × 1000 个离散点。这里的 [ ] 表示距离最近的离散坐标。

通过交替最小化 C V ,给出:

(10.1) C ( x ) = arg min C ( x ) E ( C , V ) = i t i V ( [ π i ( x ) ] ) U ( I i ( π i ( x ) ) ) i ( t i V ( [ π i ( x ) ] ) ) 2 (10.2) V ( x ) = arg min V ( x ) E ( C , V ) = i t i C ( x ) U ( I i ( π i ( x ) ) ) i ( t i C ( x ) ) 2

实际代码中的操作,其实把光度模型写作:
(11) 1 t i U ( I i ( π i ( x ) ) ) = V ( [ π i ( x ) ] ) C ( x )

也就定义为作用了渐晕效果后的辐射度图像。实际上,在求 C V 的时候,如果使用恒定的曝光时间,则直接可以去掉曝光时间 t i 的影响,这里本身就存在一个不确定的尺度因子,由于 U 是归一化在区间 [ 0 , 255 ] 中,V的值域在 [ 0 , 1 ] 。在曝光恒定的条件下,只要给的曝光时间和真实曝光时间差别不要太大,都是可以的,实际上只会影响辐射度图像 C 的值域范围,不影响我们标定的渐晕 V 的结果。如果直接不管 t i (令其为1),则相当于辐射度图像的值域和得到的图像亮度范围基本是一致的。

去除曝光时间的影响, ( 10 ) 可以转化为:

(12.1) C ( x ) = arg min C ( x ) E ( C , V ) = i V ( [ π i ( x ) ] ) U ( I i ( π i ( x ) ) ) i ( V ( [ π i ( x ) ] ) ) 2 (12.2) V ( x ) = arg min V ( x ) E ( C , V ) = i C ( x ) U ( I i ( π i ( x ) ) ) i ( C ( x ) ) 2

这里 U ( I i ( π i ( x ) ) ) = 1 t i U ( I i ( π i ( x ) ) )

和相机响应函数标定一样,这里是稠密的打表的形式,因此,需要尽可能多的数据,才可以较好地恢复出渐晕的映射表。和响应函数相似,这里对应代码就不贴出了。

猜你喜欢

转载自blog.csdn.net/kokerf/article/details/80170257
DSO