2025-04-23
真 3D 要求能够给出任意两个点的 metric distance(度量距离).
而显然深度图中给出的信息(一个点的 pixel 坐标以及 depth)单位对不上,所以无法得知 metric distance.
Depth Sensors 不是无限远的. 有一个最近 & 最远的距离(near plane & far plane). 可以测量到的空间为一个棱台. 所以比如人脸检测的时候不能靠太近.
Depth Sensor 要四个东西. RGB & IR Projector & 2 IR Receiver. (IR:红外)
最简单的用两个 RGB 即可得到 Stereo Sensor. 即用两个水平的相机,找到同一个点在两个相机分别的位置. 设在两张纸上的 pixel 坐标,一个在 \(u\) 一个在 \(u'\),视差为 \(u-u'\). 两个相机相隔 \(B\),则 \(u-u'=\frac{Bf}{z}\).
我们先让两张图片处于同一水品. 然后对同一水平线做 line search. 然后找同一个点的方法是做特征提取,然后每个 Pixel 的特征两张图做点积. 点积最大的意味着对应.
图中有若干部分是左眼看得见而右眼看不见的. 可能是因为在边缘,也可能因为是被挡住了.
一个较大的问题是对应关系很难找. 比如纹理缺失的墙就根本对应不起来,重复的东西也对应不起来. 并且如果有镜子的话,左右两眼看到的同一个点对应的是不同的东西(画一画就能明白),因为我们看到的是镜子反射出的别的东西,所以就无法建立两张图图片中的正确的 correspondance. 并且透明的物体也有类似的问题,因为光的折射.
所以这个方法只能做一个 diffuse surface(漫反射表面)的工作,而做不了镜面(specular)和透明(transparent);点是两个眼睛都能看到的 texture 缺失或者过于.
结构光:发射红外射线,形成红外光斑,来打上 texture. 不能在户外使用,因为会有别的红外干扰(太阳光).
之前直接做的是 Passive Stereo. 而主动发射红外光线的 Active Stereo 解决了 textureless 的问题,但是却还是无法解决镜面和透明的问题.
黑色会吸收光,所以会导致 Missing Value. 而透明的可能不会有什么 Missing Value 但是会导致很多塌陷(相当于折射之后透过去了). 反光肯定也还是测不标准的.
激光雷达:获得 Ray Depth. 但是还是无法很好地处理透明和镜面.
这是一个很难办的问题. 接下来还是先假定这些没遇到上述问题比较好.
Voxels:Volumetric Pixels
清晰度很小的时候就已经量级很大了. 比如 \(32^3\) 所需存储量已经大于了 \(256^2\).
离散带来的几何偏差很大,刻画能力和精细度很差.
但是好处是确实够简单. 比如可以应用一个 3D 的 CNN. 不过参数量也很巨大.
Mesh,Point Cloud 和 Implicit representation(\(F(x)=0\))都可以给出表面信息.
Mesh:对表面的一个分段线性(Piecewise Linear)的近似,用一个简单的线性平面来近似每一个局部.
Triangle Mesh 表面近似成很多个三角形拼凑起来. Quad Mesh 则可以用四边形平面,但由于一些拓扑的问题会导致有奇点所以不常用. 最多用的就是三角面片.
实际上我们可以用一个 Graph 来表示. 每个三角形的顶点用一个 Vertex \(V\subset R^3\) 表示,然后三角形的边就形成了 Edge \(\subset V\times V\),然后三个 Vertex 可以组成一个 Face \(\subset V\times V\times V\). 所以一个 Mesh 可以用 Vertex 集合,Edge 集合,Face 集合三个来一起表征.
下面探讨几何属性,略去材质,颜色等属性.
数据存储方法:OBJ Format,存每个 Vertex 的坐标,和每个 Triangle 由哪几个 Vertex 组成. 每个 Triangle 的点按照逆时针列出(符合右手定则). 如果在此基础上,钦定字典序最小,那么就能唯一确定了. 如果转向错了的话,法向量就反了,会导致渲染出错,或者法向量作为 feature 的时候出错.
Geodesic Distance:表面上两个点的最短距离. 算这个东西一个很 Naive 且不准确的做法是直接计算最短路. 存在一点更好且更快的近似算法.
Point Cloud:只保留 \(V\). 是 Irregular 且 Orderless 的. 很轻量级.
点云本质是一个 Point Set. 点的顺序无意义. 在同等的存储量上,Point Cloud 的集合刻画最好.
点云是在 Surface 这个二维流形中的采样. 对于同一个 Surface,可以有很多不同的采样方式.
均匀采样:即任取一个面积,除以总面积之后,点数比约等于面积比.我们第一步需要得到一个 Mesh. 然后再去从 Mesh 上把点云采下来. 假如有 \(M\) 个三角形,我们按三角形的面积作为权,每次以这个为权随机选一个三角形,然后再在三角形中随机采点. 如何在三角形中随机采点?考虑镜像扩充成一个平行四边形,然后在平行四边形的坐标中采点,然后再镜像回三角形.
但是这种纯随机还是会有很多不令人满意的地方. 因为随机,只是期望正确,所以有的地方稀疏有的地方密集.
Farthest Point Sampling:使得任两个 Sample 的点的距离之和最大. 这样显然会导致分布的很均匀,但这是个 NP Hard 问题. 考虑做点贪心近似.
首先做 \(N\) 更大的 Uniform Sampling,然后再在这些点中去找尽量的 FPS 子集. 考虑一个贪心:先找一个随机的点,然后再找一个点使得到那个点距离最大,然后再找一个点使得到这两个点距离和最大... 这样找 \(K\) 个点,得到 \(O(NK)\) 的贪心算法. 这个就更加 Evenly Distributed 了,并且更少丢掉一些 local 信息.
而实际上我们也不一定要用 Mesh 去做. 我们也可以直接从深度图中得到 \(H\times W\) 个点,然后再 FPS.
如何比较两个点云呢?
Chamfer Distance:对于点云 \(A\) 的每个点,找其在 \(B\) 中的最近邻,距离和加起来. 对于 \(B\) 同理. 两个距离和加起来得到 Chamfer Distance.
Earth Mover's Distance:找 \(A,B\) 的最小二分图匹配 \(\phi\). 令 \(d_{EMD}(A,B)\) 为最小权匹配的距离和.
EMD 对于每个区域的密度很敏感,而 CD 则好一些.
3D Deep Learning
直接把 \(3n\) 长度的 vector 喂给 MLP 很糟糕. 因为点云无关顺序,但是 vector 换个顺序输出就会变很大.
如果只是 sorting,那么删一个点增一个点,变化也太大了,很糟糕.
PointNet:先对每个 \((x,y,z)\) 通过 MLP 变成长 \(c\) 向量(\(n\times 3\to n\times c\)),然后再 MLP 变成长 \(d\) 向量. 然后再对每个维取一个对称函数 \(g\) (比如 max pool)得到一个 \(c\) 维向量 \(z\)(\(n\times d\to 1\times d\)),然后再 MLP 做 classification.
如果我们要做 Segmentation,那么就直接暴力将 \(z\) 拼接在每个点的长 \(c\) 向量之后得到 \(n\times(d+c)\) 然后直接还原.
PointNet 对加删点非常鲁棒. 因为只有那个维度的 Max 被删掉才会导致发生变化.
PointNet 的局限性在于并没有局部信息. 只有单点信息和全局信息. 比如所有点都 \(+1\) 那么就变化剧烈.
如何提取局部特征,做有层级的特征提取呢?
考虑选一个点 \(c\),考虑其半径为 \(r\) 的领域,用其关于 \(c\) 的相对坐标,再 append 上 \(c\) 的绝对坐标,去做 Point Net. 将最后得到的向量放在 \(c\) 处. 于是点数变少,通道数增加,完成了 Down Sampling.
如何做 Up Sampling 呢?我们先对于每个被删去的点,找到在保留的点中的三近邻,然后做线性插值 得到其信息. 然后再结合其 Skip Link 得到的 Feature,Concatenate 之后再对每个单点做 Pointnet 得到新的 Feature.