一、相关3D扫描技术分析
1. 散斑结构光技术分析
I. 散斑空间不变性
考虑在不同距离下的,通平面上的散斑间距\(d_{P_1P_2}=D\times[tan(\alpha+\theta)-tan(\alpha)]=kD\),其中 \(\theta\) 为光斑光束发散间隔角为常亮,同时 \(\alpha\) 作为发射角度也为常量,因此在同一平面深度上,散斑的间距随着间距 \(D\) 线性变化。
由于成像过程如上图所示,对于特定的距离有对应的成像放大率,根据相似三角形定理:\(\frac{h}{h'}=\frac{D}{f}\),根据上述公式可以计算 \(d_{P_1P_2}\)间距在成像平面上间距为:
故此散斑间距在不同深度的同一平面上的间距不变(距离的表现形式为散斑的整体平移,基线与散斑平面平行),由于散斑的大小尺寸在深度方向上自身变化较小,故此在不同的成像平面上,散斑的尺寸变化也较小,这是散斑光源的基本特征模型。
虽然深度越大,散斑之间的距离越大,但是距离越大,成像透镜对其缩小的倍数也越大,相互抵消,从而导致散斑之间的距离在成像面上的成像与深度无关。同理,可以证明,散斑的大小也不会随着深度的变化而在成像面上发生变化。所以散斑间的距离,斑点大小以及散斑分布模式在不同深度的反射面上成像是基本相同的。散斑图中物体深度发生变化时,只有物体上的散斑图整体移动,所以我们可以使用匹配的方法将物体散斑图与参考散斑图进行匹配。
左右图分别是在不同距离下拍摄的平面散斑图,可以很容易看出,散斑整体发生了偏移,与上面的理论分析一致。
总体来看,散斑结构光算法与双目算法非常类似,其核心都在于匹配。
上述的所有推导,都是基于理想平行双目系统,实际环境中,不会存在这样的理想系统,那么我们如何仿照双目算法的处理方式,对散斑结构光系统进行矫正。
核心还是在于标定,我们需要对散斑发射装置(譬如投影仪)和相机进行位置关系标定,通过标定出来的系统参数,同样可以对散斑结构光系统做极线矫正,这点对于实际散斑结构光相机非常重要。
另外,散斑结构光系统对于散斑模式是有随机性要求的。随机性需求的核心是为了解决匹配过程中的误匹配问题,所以这种随机只要求在搜索范围内随机即可,3D结构光都是采用VCSEL随机点阵的散斑发射器+DOE复制的方案,来减少无匹配发生的概率。
二、三维重建算法
1. 重建算法基本过程
基于立体视觉的三维重建算法是利用两个或多个相机从不同角度拍摄目标物体,通过计算物体在不同相机中的位置和角度,进而还原出物体的三维结构。常用的算法包括立体匹配算法、三维重建算法和多视图几何算法等。
I. 立体匹配算法
立体匹配算法是基于两幅立体图像之间的像素点的对应关系,通过计算像素点的视差(disparity)来获取深度信息。常用的立体匹配算法包括基于区域的匹配算法、基于能量优化的匹配算法和基于机器学习的匹配算法等。
<text color:#666>sda
a. SGM立体匹配算法
SGM(semi-global matching) 是一种用于计算双目视觉中视差的半全局匹配算法。在 OpenCV
中的实现为 semi-global block matching(SGBM)。
SGBM 的思路是:通过选取每个像素点的 \(Disparity\) ,组成一个 \(Disparity Map\),设置一个和 \(Disparity map\) 相关的全局能量函数,使这个能量函数最小化,以达到求解每个像素最优 \(Disparity\) 的目的。
本小结梳理了 SGM 算法的各步骤的实现细节,帮助快速理解算法中每一步到底在做什么。已知,左右两张矫正过的双目相机图片:\(IMG_{left}, IMG_{right}\) 。
-
Step1. 图像前处理,Census变换 🚀🚀🚀
\(IMG_{left}, IMG_{right}\) 按 \(5\times 5\) 窗口,\(stride=1\) 滑动,得到各自 Census 变换的二维矩阵。其中,原图像的左右各补 \(pad=2\) ,维持滑动之后二维数组宽高不变。
census 变换是指,窗口所有数据依次和其中心点数据相比,大于为1,小于等于为0,窗口按照左右,上下的顺序,组成一个 \(5*5=25\) 长度的二进制序列,即为该窗口的 census 变换数。汉明距离是指,两个二进制数 异或操作 ,即不同的 bit 对应个数。
census变换与汉明距离示意图:
⭐ Notice: 如果是散斑图像,只需要对散斑位置进行深度视差计算就可以完成了(速度效率更高,精度有所下降,无法达到像素级精度),而对于普通的双目成像无结构光的场景,需要对整幅图像进行像素的处理。 -
Step2. 代价计算 🚀🚀🚀
以左图为标准,计算右图和左图同样坐标位置的census值的汉明(hamming)距离。设置视差范围d,得到一个h,w,d的三维矩阵cost。
视差范围d在第三维,这样对应:逐行遍历,假设P的二维坐标为(x,y),点P的d_range代价计算为:


- Step3. 代价聚合 🚀🚀🚀
如果没有代价聚合,得到的视差图有很多噪声,所以,分别计算每个像素不同角度的代价值,然后加权综合考虑,会得到很大的优化。经典聚合策略有:4路径聚合,8路径聚合,16路径聚合。
下图左边是按不同方向聚合的示意图,右图是以左→右聚合为例,像素P在d视差上的代价计算示意图。
这一步需要根据选择几路径,来更新每个路径的代价矩阵。
左右的话,P-r就是同一行的前一个像素,或者同一行的后一个像素
上下的话,P-r就是同一列的上一行像素,或者同一列的下一行像素
p1,p2是超参数; C(p,d)表示p像素,d视差的代价.
如果是4路径聚合的话,就是左右,右左,上下,下上的四个路径的代价矩阵对应坐标位置值相加,就是最终聚合的代价矩阵。
- Step4. 视差计算 🚀🚀🚀
采用WTA(Winner Takes All)赢家通吃算法。就是每个像素位置在所有视差范围内找到一个代价值最小值,其所在的index就是该像素的最终视差,是一个二维矩阵。
- Step4. 视差优化 🚀🚀🚀
-
优化目的:
- 提高精度:
前面的视差计算步骤中,我们选择最小代价值对应的视差值,它是一个整数值(整数值我们才能有离散化的视差空间W H D ),即整像素级精度,而实际应用中整像素精度基本无法满足需求,必须优化到子像素精度才有意义。 - 剔除错误
即剔除错误的视差值,比如a像素本应和b像素是同名点,而结果却是a像素和c像素是同名点,这就是错误的视差值。造成错误匹配的原因有遮挡、弱纹理等,所谓错误是永恒的,完美是不存在的。 - 弱纹理区优化
弱纹理区域是所有立体匹配都会面对的难题,极端情况下,一块白墙,怎么找同名点?SGM提出的是一种基于图像分割+平面拟合的处理弱纹理的方法。 - 填补空洞
剔除错误匹配后,被剔除的像素会造成无效值空洞,如何填补使视差图更加完整也是优化所研究的内容。
- 提高精度:
-
优化手段
- 子像素拟合
为了提高精度,确定到亚像素的情况下,SGM算法在像素位置确定上使用了抛物线 \(ax^2+bx+c=y\) 拟合算法,通过三个(三个未知量\(a,b,c\)) Disparity 点确定抛物线最低点,从而获得精确的亚像素位置,使用最后的亚像素位置作为深度视差输出。
\[D_L(\vec{p})=argmin_dS(\vec{p},d)\\D^{sub}_{Lp}=D_{Lp}+\frac{S(p,D_{Lp}-1)-S(p,D_{Lp}+1)}{2S(p,D_{Lp}-1)-4S(p,D_{Lp})-2S(p,D_{Lp}+1)} \]- 一致性检查
一致性检查也能够在一定程度上一直存在的孔洞,使数据更加的真实有效。
\[D_R(p)=argmin_dS(p+[d,0]^T,d). \]- 唯一性约束
唯一性约束的含义是:最优视差的代价值应该是所有候选视差中唯一的最小代价,换句话说它的代价值比其他视差的代价值足够小,这样它才能在众多候选视差中脱颖而出。如果有另外一个视差的代价值和它一样,那么它就不再是最好的那一个了,而是最好的两个之一,而我们不能接受有两个最好,只能忍痛舍弃它。
其实,这里面蕴含的另一层含义是:视差估计的可靠性!如果两个最小的代价值相差很小,比如一个是30,一个是31,因为视差估计是带有噪声影响的,所以其实不能肯定的说是30最好还是31最好,可能31才是正确的那个视差,因为两个值相差太小了,可能是由于一些轻微的噪声导致实际上最优的那个视差的代价值却是次最小的。所以就干脆把这种让人头疼的选择题给PASS掉,遇到这种情况直接给它一个NO!
用程序来处理时,我们会计算最小代价和次最小代价的相对差值,如果差值小于阈值,那就表明最小的两个代价值相差不明显,就给这个像素赋一个无效视差。 - 剔除小连通区
学过图像处理的同学对连通区应该并不陌生,它是图像处理中很常见的一个名词,它的含义是通过4-邻域或8-邻域连通在一起的像素集合,在SGM中,这一步用来剔除连通在一起的小块错误匹配像素,像这样的:
首先这些像素是一致性检查的漏网之鱼,看上去和周围的像素极不协调,而且连通成一定大小的块,所以中值滤波这类窗口类滤波算法也搞不定,只能通过区域跟踪,把它们跟踪成块,然后判断块的大小是否小于一定的阈值,如果是则剔除,即把整块都置为无效视差。思路不复杂,就是一个区域跟踪算法。 - 中值滤波
中值滤波在立体匹配中使用的还挺广泛的,作为一个平滑算法,它主要是用来剔除视差图中的一些孤立的离群外点,同时还能起到填补小洞的作用。
- 子像素拟合
-
- Reference
II. 三维重建算法
三维重建算法是利用立体匹配算法得到的视差信息,通过三角测量等方法计算出三维点的坐标。常用的三维重建算法包括直接线性变换(DLT)算法、最小二乘法(LS)算法和非线性优化算法等。
III. 多视图几何算法
多视图几何算法是基于多个相机拍摄的图像数据,通过几何关系和投影变换计算出三维点的坐标。常用的多视图几何算法包括三角测量算法、基于光束法的算法和基于最小二乘法的算法等。
2. 重建算法GPU加速方法
🌻 针对单/双目散斑形式的 GPU 加速算法的思考?
由于使用DOE散斑衍射器件投射的图案形式不随平面空间位置的变化而变化,因此其基本三维重建方式为:
- 在标准平面使用标准平板平面采集DOE散斑结构光模式图 \(I_{ori}\) 。
- 对该模式图进行散斑位置信息提取以及对应散斑点位置 \(Dot_{pos}\) 的特征信息 \(Dot_{feature}\) 进行提取,完成了设备的初始化标定操作。
- 对任意三维结构进行投影图像 \(I_{obj}\) 采集,准备重建该三维立体对象。
- 在 GPU 上针对步骤二中提前提取到的散斑为单位处理线程,对当前线程负责的散斑点进行匹配操作,操作流程如下:
- 以 \(I_{ori}\) 中的散斑点位置 \(Dot_{pos}\) 作为 \(I_{obj}\) 图像中的像素搜索起点 \(O_{search}\)
- 在 \(O_{search}\) 起点的设备测量范围对应的像素变化范围内 \(±Rg\) 进行同行 ROW 搜索
- 使用特征信息 \(Dot_{feature}\) 进行对应光斑位置的匹配操作,直到查询到对应的散斑点为止
- 计算该散斑点对应的三角结构下的空间位置点云 \(PointCloud\)
- 将所有线程计算完成的点云组织完成输出,即为所需要的点云深度数据 \(I_{depth}\)
三、相关论文阅读参考
A. 反光问题设计
- 《A Polarized Structured Light Method for the 3D Measurement of High-Reflective Surfaces》
- 文章主要使用了偏振相机 大恒 MER2-503-36U3M POL 用来做图像采集工作,DLP投影仪发出的光也为偏振光,其偏正方向与相机像素偏振极化方向为105°,从而每类像素采集到的光强度计算为:\(I_{\alpha}=I_0\times cos^2\alpha\),其中 \(\alpha=105°\);这样在单次图像采集过程中即可得到四张不同曝光亮度条件的数据,从而完成强反光物体的拍摄。
- 文章考虑到不同曝光位置像素还原过程中的位置偏移,通过将所有数据都归一化 \([R|t]\) 旋转平移到第一像素位置上,从而避免了重建点云的重影偏移问题。
- 图像采集基本原理:
- 文章中不同极化像素获取图像的融合流程:
- 《High dynamic range 3D shape measurement based on crosstalk characteristics of a color camera》
B. 基于网格线的3D重建技术
- 《A GRID-POINT DETECTION METHOD BASED ON U-NET FOR A STRUCTURED LIGHT SYSTEM》
-
文中使用了交叉网格线的投影方式对三维对象进行提取识别,同时在识别特征点的过程中,使用了U-Net的卷积神经网络框架,通过将采集到的网格图像分割为\(64\times 64\) 大小的图像方块作为训练集和测试集,其中的训练集通过提取标准骨架图像作为图像标签进行损失函数训练,设置了合理的训练框架和最终识别评价函数,完成对识别精度的提升。(未提及处理速度)
-
文章对最终识别特征点的误差评估办法使用了 MAE(Mean Absolute Error) 方法:\(MAE=\frac{\sum^N_{t=1}|C_t-C_d|}{N}\),最终的平均误差为 \(0.27Pixel\),最大偏差\(2Pixel\) .
-
图像采集基本原理:
-
文章中不同极化像素获取图像的融合流程:
C. 三维重建&视觉纹理贴图技术
- 《A System for Capturing Textured 3D Shapes based on One-shot Grid Pattern with Multi-band Camera and Infrared Projector》
- 文中使用了交叉网格线的投影方式对三维对象进行提取识别,同时在识别特征点的过程中,识别方式使用了普通的图像处理技术,文章关键点着重于如何保证在生成的三维重建实体上增加物体实际的表面纹理,为了保证采集的实际纹理图像和三维重建点之间不存在Mapping的偏差,文章使用了棱镜的方案完成了在同一点采集图像的方案,文章通过多光谱波段的编码分离信息实现了3D信息和普通光照下的图像同步采集。
- 图像采集基本原理:
- 文章贴图效果如下:
D. 三维重建技术概览 ⭐⭐⭐
- 《High-speed 3D shape measurement with structured light methods A review》 ⭐⭐
- 文中分别对目前3D城乡的技术进行了介绍,对比了双目成像和结构光的优劣势,然后重点介绍了主动式的结构光3D图像获取方案,其中包括了散斑结构光方案,BinaryCode二进制条纹方案,GrayCode格雷码条纹方案,PhaseShift相移方案(通过FFT傅里叶变换取得,帧率可达300Hz),同时介绍了Defocus的虚焦方案,实现了条纹的虚化过程,从而大大提升了重建精度。
- 解算过程的极线理论:
极线理论的重点在于大大降低了3D重建过程中的匹配计算量,大大提升了设备重建数据的实时性,将2D平面匹配过程降低到1D:原始过程的匹配为在左侧相机中采集到的某一点需要在右侧相机中匹配查询到与之匹配的某一点,匹配完成后根据三角解算原理计算出实际的物理空间位置\(p\);而极线存在的目的可以看出,空间上任意一点在左侧像平面成像的点与\(o^lo^r\)直线共同确认了一张空间平面,而此平面就能够与右侧像平面产生唯一交线\(L^r\),而对应的匹配点只需要在这个一维的空间直线\(L^r\)上查询即可,从而大大降低了实际的计算量,提升系统实时性。 - 系统搭建图
- 系统优劣对比:⭐
- Speckle Projector散斑投影:
- 优势:
- 容易理解,3D结构光的计算很直接地基于三角理论.
- 容易实施,由于只需要一组静态图像,因此仅仅需要一个普通的数字视频投影技术,激光散斑投影,或者狭缝的衍射投影等。
- 方便小型化,因为静态模式能够非常容易的被便携式设备所识别,因此很利于小型化。
- 劣势:
- 空间分辨率低,由于投影的散斑点需要能够非常好滴被像素点分开识别,因此有大量的像素点是浪费的,将会远低于图像CMOS的像素分辨率。
- 对于噪声较为敏感,由于采集过程中的固定模式容易被环境等因素影响,容易造成误检测。
- 测量精度低,很难达到像素级别的分辨率。
- 优势:
- Binary Code二进制条纹:
- 优势:
- 二进制编码是简单的,体现在其编解码算法上。
- 检测速度是很快的,由于其解算算法的简单特性。
- 系统速度很快是由于其带宽仅仅是1-bit binary模式的切换过程,信息量是较小的。
- 系统的鲁棒性较好,尽管只有两个编码需要被识别。
- 劣势:
- 系统的整体分辨率需要考虑到DMD投影端和CMOS成像端两侧同时决定的系统精度。
- 优势:
- Speckle Projector散斑投影:
-
《High-Capacity Spatial Structured Light for Robust and Accurate Reconstruction》
-
《Optimization of Stereo Vision Depth Estimation using Edge-Based Disparity Map》 - 基于边缘匹配的视差提取算法
- 文章首先介绍了一些传统的匹配算法,同时介绍了3D重建的基本流程,流程图如下所示,同时对双目立体成像的相机标定矫正、双目匹配面矫正,以及三角测量原理及其公式进行了相关推导,接着对三种匹配算法进行了初步的介绍,重点介绍了基于边缘特征的匹配算法,其流程图如下所示:
- 几种算法的基本介绍
- Block Matching (BM) 块匹配算法: 此算法将左边的图像分割为相同大小区域的块,将分割之后的区域块与右图进行匹配找到对应合适的位置区域,其代价评估算法可以使用 Sum of Absolute Diffrence(SAD) 或者 Sum of Square Difference (SSD) 和 Normalized Cross Correlation (NCC),这种传统的方法容易受到光照变化、视角变化、颜色变化等情况的影响。
- Semi-Global Matching (SGM):一种基于互信息理论的像素级匹配方法,参考其他文献吧,这里不赘述。
- Edge-Based Disparity Map:一种将传统SAD代价算法与边缘检测算法结合在一起的匹配方法,有效提高块匹配过程中的可靠性,边缘作为一种重要的形貌特征,能够有效地减少不必要的区域像素点的运算参与,从而提高效率;形态学操作能够有效扩展目标的边缘像素,本文中使用了 Canny 边缘检测算法,具体的实施流程见上右图。
- 运行结果图下:(BM - SGBM - EdgeBasedBM)
🌻 总结: 文章虽然提出了一种新的匹配算法,在时间效率上有较好的优势,但是通过观察看的出其重建的深度图存在很多的空洞,这和原始场景的纹理丰富程度相关,所以对于稠密重建,可能还是SGM算法更有优势。
E. 基于DOE的静态散斑结构光3D重建技术 ⭐⭐⭐
- 《Single-Shot Structured Light Sensor for 3D Dense and Dynamic Reconstruction》 ⭐⭐
- 文中主要介绍了其构建的双目的DOE散斑结构光系统,首先系统确定了散斑光源的设计参数,第二部分介绍了系统矫正、立体视觉矫正、极线矫正等,文章重点介绍了其散斑的匹配算法SGM,最终的实验结果表明了 \(Accurate:0.4m@0.5mm-30FPS\).
- 系统搭建方案图:
- 散斑DOE结构光设计要求:散斑的目的在于提高物体表面的纹理特征,以此为判断基准,通过分析可知散斑的间隔应该等于散斑光源的BAR(Brightness Attenuation Range)大小,从而保证了在提升纹理特征的条件下保证了每个光斑都能够有效地被区分开来。 🚀🚀
- 散斑纹理特征等级评估如下:
通过对图像的灰度通道下的梯度分布特征来决定,在特定窗口内的梯度越大表示其变化越剧烈,相反越平坦的光滑的表面就会表现出纹理特征越少,梯度对应越小,对于每一个像素点的梯度计算公式如下:
其中 \(\Delta I(u,v)\) 表示了像素点 \((u,v)^T\) 位置处的梯度,而 \(G_u,G_v\) 代表了在图像 \(u,v\) 方向上的梯度,为了将两个方向上的梯度都考虑进来,则实际计算的梯度为:\(G(u,v)=||\Delta I(u,v)||=\sqrt{G_u^2+G_v^2}\),由于单个像素点的梯度值较大不能够表面该区域的纹理特征是丰富的,因此需要确定在一个窗口区域范围内的平均梯度值来作为该点的纹理特征判定条件,故此可得:
其中\(k(i,j)\) 为全为一的均值矩阵。接着对计算的结果使用阈值方式确定纹理特征丰富的点位置,其中应该选取的 \(\delta>4\),从而保证梯度特征大于16的就作为纹理特征丰富点,反之亦然。
最终的计算结果如下图所示:

- 系统的矫正流程
系统矫正主要是考虑到当前系统的成像平面法向量存在夹角,上下错位等问题,从而导致系统所构造的极线并不平行于图像像素的ROW行方向,从而导致匹配容易发生错误;故此文章通过两个方向的旋转(1.同心旋转矩阵 2.垂直于基线旋转矩阵)完成了图像平面的矫正工作,同时根据畸变参数重新定位了图像的中心位置,从而确定了像素偏移向量 \(\vec m_0\)
- SGM匹配算法优化
Reference:
F. 基于GPU加速的SGM算法 ⭐⭐
- 《Embedded real-time stereo estimation via Semi-Global Matching on the GPU》 ⭐⭐
- 本文主要介绍了SGM算法的基本原理和不同计算平台的实时性能对比,重点介绍了使用更加灵活且方便的GPU进行实际的算法加速实现(FPGA、ASIC的实现难度更大,且不灵活),接着文章介绍了整个SGM算法在GPU上进行部署的基本流程,并从整体上考虑了GPU加速算法的实现过程中的基本瓶颈限制(内存带宽)和GPU系统架构下的编程方式(ThreadId),接着文章对SGM算法中的两个步骤(互信息计算 & 聚合计算 & 视差计算)进行了深入的分析和GPU实现的伪代码编写,最后作者通过调用CUDA编程的特殊指令对相关并行化代码进行了优化,进一步提高了系统的运行效率;如下图所示为GPU处理SGM算法的基本流程:
- 深度视差算法实现深度检测的理论原理:
- \(f\) 为相机的焦距;
- \(T\) 为基线上,两光心质点之间的间距;
- \(d\) 为通过 SGM 算法提取的到的深度像素视差;
- 这里通过本篇文章,能够在一定程度上推算出实际的SGM算法的计算量如下(算力评估可能存在误差,由于内存带宽等细节参数未考虑):
- 测试平台 Nvidia Tegra X1 参数: \(1TFLOPS\)
- 测试结果:\(42FPS-640\times 480Pixel-128Disparity-4PathDir\)
- 对于单点像素的 SGM 计算量为:\(OPS_{Pixel}=1TFLOPS*\frac{1}{framerate}*\frac{1}{W\times H}=77504 OPS\)
- 测试平台 Nvidia GTX 280 参数: \(622GFLOPS\)
- 测试结果:\(53FPS-512\times 383Pixel\)
- 对于单点像素的 SGM 计算量为:\(OPS_{Pixel}=622GFLOPS*\frac{1}{framerate}*\frac{1}{W\times H}=59847 OPS\)
- 测试平台 Nvidia Tesla C2050 参数: \(1TFLOPS\)
- 测试结果:\(27FPS-1024\times 768Pixel-128Disparity\)
- 对于单点像素的 SGM 计算量为:\(OPS_{Pixel}=1TFLOPS*\frac{1}{framerate}*\frac{1}{W\times H}=47095 OPS\)
- 测试平台 Nvidia Tegra X1 参数: \(1TFLOPS\)
- 《Mutual Information based Semi-Global Stereo Matching on the GPU》 ⭐⭐
- H老爷子在本文中主要介绍了如何使用GPU进行SGM双目视觉匹配算法的部署,文中提出了可以使用OpenGL和CUDA两种方式对GPU、进行编程,而老爷子在本文中采用的OpenGL的方式进行编程(理由是可以用在老点的GPU设备上...),文中表达了SGM算法的时间复杂度为:\(O(width\times height \times disparityrange)\),同时对比了SGM算法与局部匹配算法(速度较快精度很低)和全局匹配算法(速度很低精度较高)的优劣,并且SGM算法非常适合于使用GPU来部署。
- Semi-Global Matching Algorithm:
- Pixelwise Matching Costs using Mutual Information: 像素互信息匹配代价计算
\[MI_{I_L,I_R}=H_{I_L}+H_{I_R}-H_{I_L,I_R}\\C(p,d)=mi_{I_L,I_R}(L(\vec{p}),R(\vec{p}-[d,0]^T)) \]- Aggregation of Pixelwise Matching Costs: 聚合互信息代价,相当于滤波的过程,确保互信息误差的提取是准确的.
这里需要注意的是,\(P_2\) 惩罚是和左右匹配图之间的像素亮度有关系的,其原因在于由于在场景突变的情况下,存在前后位置突变的像素点,而这种像素点在成像相机上展现的结果即为像素亮度的差异 (由于距离不同,前后深度差较大的像素点的光辐照度在Sensor上的呈现差异导致的)
\[E(D)=\sum_p{(C(\vec{p},D_p)+\sum_{q\in N_p}{P_1T[|D_p-D_q|=1]}+\sum_{q\in N_p}{P_2T[|D_p-D-q|>1]})}\\P_1=Constant. \ is\ a\ constant\\P_2=\frac{P'_2}{|I_{bp}-I_{bp-r}|}.\ P'_2=Constant \]- Disparity Selection: 视差选择(赢家通吃算法),在选择最小视差的过程中,除了确定最小视差的对比以外还需要确定对应该视差下的像素点索引,而赢家通吃算法完成的功能在于,通过比较所有视差范围 \(d\) 当中的代价值,选择代价最小的点即可。但是为了提高精度,确定到亚像素的情况下,SGM算法在像素位置确定上使用了抛物线 \(ax^2+bx+c=y\) 拟合算法,通过三个(三个未知量\(a,b,c\)) Disparity 点确定抛物线最低点,从而获得精确的亚像素位置,使用最后的亚像素位置作为深度视差输出。
\[D_L(\vec{p})=argmin_dS(\vec{p},d)\\D^{sub}_{Lp}=D_{Lp}+\frac{S(p,D_{Lp}-1)-S(p,D_{Lp}+1)}{2S(p,D_{Lp}-1)-4S(p,D_{Lp})-2S(p,D_{Lp}+1)} \]- Post Filtering and Consistency Checking: 孔洞点滤波和一致性检查,滤波算法的目的在于将深度视差图中存在孔洞点消除的功能,从而确保该区域内平滑,而一致性检查也能够在一定程度上一直存在的孔洞,使数据更加的真实有效。
\[D_R(p)=argmin_dS(p+[d,0]^T,d). \] - 文章最后对比了不同平台下的处理速度,如下所示:
- 《MGM: A Significantly More Global Matching for Stereovision》
G. 使用一维线传感器进行三维重建
- 《Dual Structured Light 3D using a 1D Sensor》
-
本文主要介绍了一套全新的三维重建技术方案,其基本原理为:使用DMD的空间光调制器实现三维物体的虚线扫描过程,同时采用目镜+柱面透镜实现对2D平面的垂直方向上的压缩,从而保证光束汇聚在1D-Sensor上,从而确定不同位置的点光斑在像平面上偏移的程度,从而完成单条线上的3D重建,通过DMD芯片的空间光调制,再次确认了另外一条虚线扫描位置上的3D深度,最终完成整个区域的重建过程,系统的基本原理如下:
-
使用1D传感器的目的在于:
- 一维传感器的价格远低于2D传感器,对于有大量烟雾、灰尘的环境,SWIR传感器能够更好地
- 一维传感器的SNR信噪比能够做的更好
- 一维传感器的成像速度也是足够快的
-
光路参数设计过程,如下所示可以看到在柱面棱镜的垂直X方向上,不同场景位置处的物理点呈现在线传感器不同的像素位置上,而在柱面棱镜的水平方向上,不同场景位置出的物理点呈现在线传感器同一列的像素区域内,从而降低了传感器的2D需求,如下图所示:
-
基本光学参数计算如下,其中 \(D\) 为物镜的数值孔径,\(H\) 为线阵传感器的像素高度:
\[\frac{1}{u_c}+\frac{1}{u-u_c}=\frac{1}{f_c} : focusing \ aperture\ plane\ onto\ image\ plane\\ \frac{D}{H}=\frac{u-u_c}{u_c} : magnification \ constraints \] -
系统的时间分辨率:系统的时间分辨率主要取决于1D传感器的性能,与投影仪DMD器件的性能无关(因为DMD的性能很高),而线阵传感器的性能主要取决于ADC的转换性能,而整个采集过程需要转化的像素点总数为:\(N(pixel)\times N(pixel) *N(Depth)=N^3\)
-
整体系统实物图及其光路仿真:
四、实验工具
1. 结构光图像生成器:
光绘(Glare)一款自由开源的数字散斑图像生成和评价软件。该软件具有散斑图生成、变形图生成、散斑质量评价和散斑图案推荐等功能:可以生成椭圆、多边形和高斯散斑;可以渲染平移、拉伸/压缩、旋转、正弦、高斯和剪切带等变形模式的变形图;可以计算散斑占空比、散斑尺寸、系统误差和随机误差等关键散斑质量评价参数;可以根据工况生成矢量格式的推荐散斑图案。该软件不仅可用于数字图像相关的学术研究和工程应用,也可服务于实验力学的教学工作,具有广阔的应用前景。 下载
2. 算法性能评估网站
五、代码实现(C++分析)
1. SGM代码的Python实现
2. SGM代码的C++实现
🌻 上述代码在Linux平台上进行测试
- 代码工程
LinuxEditionCode - 编写 CMakeLists.txt
cmake_minimum_required(VERSION 2.8) project (SGMDemonstrationPro) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED TRUE) find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) # add the OpenCV headfile. include_directories(./) set(SRC_LIST ./main.cpp ./SemiGlobalMatching.cpp ./sgm_util.cpp ./stdafx) add_executable(main ${SRC_LIST}) target_link_libraries(main ${OpenCV_LIBS})
- 测试结果
运行代码:./main ../../Data/cone/im2.png ../../Data/cone/im6.png 0 64
Loading Views...Done! w = 450, h = 375, d = [0,64] SGM Initializing... SGM Initializing Done! Timing : 0.060000 s SGM Matching... computing cost! timing : 0.428000 s cost aggregating! timing : 1.811000 s computing disparities! timing : 0.115000 s postprocessing! timing : 0.256000 s SGM Matching...Done! Timing : 2.612000 s
3. SGM Opencv
🌻 基于Opencv&PCL的深度点云重建
- 算法步骤:
- 读取左右两目图像与相机内参
- 基于OpenCV库对左右两目图像进行匹配,并生成视差矩阵
- 基于视差矩阵计算每一个像素点的深度,再通过相机模型计算每一个像素点对应的三维坐标
- 将每一个像素所对应的三维坐标添加到PCL点云中
- 通过OpenCV和PCL库中的可视化模块分别显示视差图和三维点云
- 代码编程:
#include <iostream> #include <opencv2/opencv.hpp> #include <pcl/point_types.h> #include <pcl/visualization/cloud_viewer.h> using namespace std; int main(int argc, char **argv) { // 双目相机参数 double fx = 718.856, fy = 718.856, cx = 607.1928, cy = 185.2157; double b = 0.573; // 读取左右两目图像并计算视差 cv::Mat left = cv::imread("../data/left.png"); cv::Mat right = cv::imread("../data/right.png"); cv::Ptr<cv::StereoSGBM> sgbm = cv::StereoSGBM::create( 0, 96, 9, 8 * 9 * 9, 32 * 9 * 9, 1, 63, 10, 100, 32); cv::Mat disparity_sgbm, disparity; sgbm->compute(left, right, disparity_sgbm); disparity_sgbm.convertTo(disparity, CV_32F, 1.0 / 16.0f); // 定义点云使用的格式:这里用的是XYZRGB pcl::PointCloud<pcl::PointXYZRGB>::Ptr road_cloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 根据视差和相机模型计算每一个点的三维坐标, 并添加到PCL点云中 for (int v = 0; v < left.rows; v++) for (int u = 0; u < left.cols; u++) { if (disparity.at<float>(v, u) <= 0.0 || disparity.at<float>(v, u) >= 96.0) continue; double depth = fx * b / (disparity.at<float>(v, u)); pcl::PointXYZRGB p; p.x = depth * (u - cx) / fx; p.y = depth * (v - cy) / fy; p.z = depth; p.b = left.at<cv::Vec3b>(v, u)[0]; p.g = left.at<cv::Vec3b>(v, u)[1]; p.r = left.at<cv::Vec3b>(v, u)[2]; road_cloud->points.push_back(p); } //可视化视差图 cv::imshow("disparity", disparity / 96.0); cv::waitKey(0); //可视化三维点云 road_cloud->height = 1; road_cloud->width = road_cloud->points.size(); pcl::visualization::CloudViewer viewer("Cloud Viewer"); viewer.showCloud(road_cloud); while(!viewer.wasStopped()){} return 0; }
- 编译上述代码:
CMakeLists.txt
# cmake版本及工程名 cmake_minimum_required( VERSION 2.8 ) project( stereo2pcd ) # 设置opencv库 find_package( OpenCV REQUIRED ) include_directories( ${OpenCV_INCLUDE_DIRS} ) # 设置pcl库 find_package( PCL REQUIRED) include_directories( ${PCL_INCLUDE_DIRS} ) # 编译与链接 add_executable( stereoVision stereoVision.cpp ) target_link_libraries( stereoVision ${OpenCV_LIBS} ${PCL_LIBRARIES} )
- 运行结果:
4. SGM MATLAB
Reference
- SLStudio -- Real Time Structured Light : 《Open-Source Framework for Real-Time Structured Light》
- 所有论文合集