1. 简介
资料来源为:
1)B站多视图几何三维重建视频讲解:https://www.bilibili.com/video/BV1Sj411f73e
2)武汉大学摄影测量与遥感专业博士李迎松的CSDN: https://blog.csdn.net/rs_lys/article/list/1
涉及的内容主要是 sfm, PatchMatch,刚开始看三维重建,可能有错误,欢迎指正。
2. 多视图几何中的三维重建
2.1 流程 :
影像序列采集—> 稀疏重建—>稠密重建—>三角化—>纹理重建
2.2 sfm:
a. 特征点匹配
匹配到的左右视图同名点对作为Bundle Adjustment (BA)优化的真实值,以便找到合适的场景参数[R|T],
使得重投影误差最小。
b. 左右相机相对位姿[R|T]估计
以第一幅影像作为参考影像,计算其余影像相对于第一幅影像的位姿,如果参考影像位姿为R=I(单位向量),
T=0(零向量),重建出来的点云坐标为相对坐标,如果对第一幅影像的位姿进行绝对定向,重建出来的点云坐标
为绝对坐标。
法一:5点解算法或三角测量:
双视图极限约束: ( => => => , )
极限约束将二维平面搜索压缩为一维极线搜索。
F 为右图像到左图像的基础矩阵,图像坐标系。
E= [R|T]= 为本质矩阵,归一化的相机坐标系。
此处不考虑相机内参K,只求解E,E为3x4的矩阵,有三个叫参数和三个平移参数,原本需要6个点求解,通过
降维(具体什么降维没看)只需要5个点即可求解出[R|T]。
法二:BA优化(光束平差法):
目标函数:
Xj :第j个空间点(由左图KRT得到)
xij : i-th view image 上由SIFT确定的Xj实际像素点
过程:随机初始化[R|T],根据初始化的值计算左图像素点在右图上的同名点像素坐标,并计算其与SIFT匹配
得到的实际同名点的像素坐标的误差平方。
c. 稀疏点云重建
单个点云的重建步骤:
有了K(相机标定)和[R|T],即可列出方程组求解:
简化成AX=0的形式,对A进行SVD分解,最小的奇异值所对应的向量即为所求的空间点三维坐标。
影像序列重建方式:
增量式重建:两两视图重建,由于得到的[R|T]总是会有误差,所以五误差会一直向后传递并累计,大场景
重建时 会有场景漂移。而且迭代进行BA很耗时。此外,对初始影像对的选取和影像添加顺
序 敏感。优点是用ransac过滤外点,精度高。
全局式重建:把结构一次性全部计算完,所有影像都和第一张参考影像求相对位姿,误差均匀分布在外极
几何上(平差),这样误差就不会累积了。不需要考虑初始影像选取。仅执行一次BA优
化,效率高,但鲁棒性不 足,相机相对平移对匹配外点敏感;过滤外极几何边可能会丢失
部分图像。
混合式重建:先全局式为[R|T]提供一个初始值,再增量式捆绑调整。没有累积误差。
2 .3 稠密重建(Multi-view system, MVS)
MVS分类:
基于voxel的MVS
基于点对扩散的MVS
基于深度图的MVS
流程:匹配代价构造—>代价累计(传播,聚合)—>深度估计—>深度图优化。
只看了SGM和PatchMatch。
经典PatchMatch算法 梳理:
a. Slanted support windows模型
SGM等方法采用的是(a)视差相等的策略,整幅图所有像素视差相等,且视差值为整数, 如需得到
浮点型视 差,要做一元二次曲线拟合;而PMS采用的是倾斜视窗策略,每个像素的视差都是不同的,更
加贴合地物走势,而 且视差值是浮点型的。
具体的,PMS为每个像素点p(x,y)都初始化一个视差值d(d~(dmin,dmax), 左视图初始化正的视
差值, 右视图初始化负的视差值)和法向量n(n.x, n.y, n.z),并计算过点(x,y,d)且法向量为n的空间
平面方程fp:
fp = ax+by+c, a = -n.x/n.z, b = -n.y/n.z,
c = (n.x * x + n.y * y + n.z * d)/n.z)
根据平面方程计算匹配代价函数,并根据视差传播来调整更新四个值:平面fp,视差d,法向量n以
及代价 cost。
注意:此处的点(x,y,d)是在三维中构建了一个x-y-d坐标系,d是视差,绝不是空间点的z坐标值,
点(x,y,d)代入fp求得fp = d,而周边落在平面fp上的点都满足fp公式,并可以根据公式求出它们
各自对应 的视差。
b. 代价计算
思想:采用局部代价计算方式
像素点p的代价costp: 在以p为中心的窗口Wp内,计算所有像素q的代价并加权求和。加权是为了考
虑那些颜色差异大的地方,这些地方很可能是边界区域,因此允许他们存在较大的匹配代价,颜色差异
越大,他们和中心 点p的权值越小。
for q in Wp:
// 计算q的视差dq
dq = a * qx + b * qy + c
//另一视图同名点坐标为q’ = q-dq,计算二者颜色和梯度不相似性:
col = min (|r-r|+|g-g|+|b-b|, τcol)
grad = min (|grad_x - grad_x| + | grad_y – grad_y|, τgrad)
//计算两个同名点的代价
ρ(q,q’) =(1-α)*col +α* grad
//计算p和q的颜色不相似性col_pq(rgb的L1距离和)
col_pq = min (|r-r|+|g-g|+|b-b|, τcol)
//计算q的权值
w(p.q) = exp(-col_pq/γ)
// 计算q点加权后的匹配代价
costq = w(p.q) *ρ(q,q’) = w(p.q) *ρ(q,q-dq)
// 累加求和
costp += costq
c. 迭代传播
实质是平面的传播,PMS建议迭代3次。
包括:空间传播,视图传播,时序传播,平面优化
思想:
空间传播:邻域像素可能有更合适的平面,检查 p邻域内的像素 q 的平面 fq是否更适合 p ,
即检查 m(p,fq) 视图传播:左右视图同名点应该有相似的平面; 时序传播:相邻帧同一位置的像素应该有相似的平面(适用于移动较慢,位移较小的情况); 平面优化:给视差和法向量添加抖动,看其是否代价更小。 注意:每个像素做完上述所有过程,才可以处理下一个像素。并不是所有像素一起做空间传播再做视图传 播以及后续操作。 d. 后处理 Left-right check: 左右视差图的同名点处,视差值应该互为相反数,因此理论上相加接近于0。实践中,设置 阈值 T=1(1个像素),若: |d(p) + d(p’)|=|d(p) + d(p-dp)| Matches集合中,否则放入misMatches集合中。同时,设置misMatches中点的视差为无效 值。 Fill: 无效值多是由于是背景区域或被前景遮挡而导致视差匹配错误。对于被遮挡或者背景区域,他们离相机 相对较远,视差也相对较小。因此对于无效值,左右各找一个有效视差,取他们的平面为当前无效像素 计算视差,视差小的作 为输出视差。 Weighted median filter:视差填充造成条带,因此进行中值滤波。具体操作是,将Wp中的权值w(p,q)和他 们的视差值dq组成数据对(w(p,q), dq),并按照w(p,q)从小到大排列,当累加 权值首次超 过总权值一 半时,所对应的视差值即为输出视差值。 For (num_iter = 0; num_iter++; num_iter<3){
//第一阶段:空间传播
dir= (num_iter%2==0)? 1,-1;
//传播起点像素坐标,偶数次迭代,从图像左上角->右下角传播;奇数次迭代,从图像右下角->左上角传播
x = (dir == 1)? 0, width-1;
y = (dir == 1)? 0, height-1;
//偶数次迭代,取左侧和上侧像素的平面;奇数次迭代,取右侧和下侧像素的平面
// 左侧/右侧
qx=px-dir;
// 根据q的编号取出平面fq
ind = y *width+qx;
fq = plane(ind);
//以新的平面参数重新计算视察和代价
dp_new = fq(px, py);
costp_new = computeA(fq, px, py);
if (costp