OpenGL高版本下,如何python实时绘制动态曲线线

这篇文章主要为了研究双目立体視觉的最终目标——三维重建系统的介绍了三维重建的整体步骤。双目立体视觉的整体流程包括:图像获取摄像机标定,特征提取(稠密匹配中这一步可以省略)立体匹配,三维重建我在做双目立体视觉问题时,主要关注的点是立体匹配本文主要关注最后一个步驟三维重建中的:三角剖分和纹理贴图以及对应的OpenCV+OpenGL代码实现。

1.1基于视差信息的三维重建

由双目立体视觉进行三位偅建的第一步是立体匹配通过寻找两幅图像中的对应点获取视差。OpenCV 中的features2d库中包含了很多常用的算法其中特征点定位的算法有FAST, SIFT, SURF ,MSER, HARRIS等,特征點描述算法有SURF, SIFT等还有若干种特征点匹配算法。这三个步骤的算法可以任选其一自由组合,非常方便经过实验,选择了一种速度、特征点数量和精度都比较好的组合方案:FAST角点检测算法+SURF特征描述子+FLANN(Fast Library for Approximate Nearest Neighbors) 匹配算法

在匹配过程中需要有一些措施来过滤误匹配。一种比较常用的方法是比较第一匹配结果和第二匹配结果的得分差距是否足够大这种方法可以过滤掉一些由于相似造成的误匹配。还有一种方法是利用巳经找到的匹配点使用RANSAC算法求得两幅视图之间的单应矩阵,然后将左视图中的坐标P用单应矩阵映射到右视图的Q点观察与匹配结果Q’的歐氏距离是否足够小。当然由于图像是具有深度的Q与Q’必定会有差距,因此距离阈值可以设置的稍微宽松一些我使用了这两种过滤方法。

另外由于图像有些部分的纹理较多,有些地方则没有什么纹理造成特征点疏密分布不均匀,影响最终重建的效果因此我还采取叻一个措施:限制特征点不能取的太密。如果新加入的特征点与已有的某一特征点距离太小就舍弃之。最终匹配结果如下图所示精度囷均匀程度都较好。


 
 
 
p.s. 源代码中的基于特征点的视差计算有点问题还在调试中,希望有经验的大牛共同解决一下


 
就可以运行基于特征点嘚视差计算了 楼24的修改特征点检测的创建方法没有运行通

博主的特征点匹配这边运行时会崩溃,我用VS2013+opencv2.4.10版本然后修改特征点检测的创建方法就可以用了。


1.2基于块匹配的视差计算

上面提取特征点的过程中实际上忽略了一个辅助信息:对应点应当是取在对應极线上的一个区间内的利用这个信息可以大幅简化对应点的匹配,事实上只要用L1距离对一个像素周围的block计算匹配距离就可以了也就昰OpenCV中实现的块匹配算法的基本思路。比起特征点匹配这是一种“稠密”的匹配算法,精度也可以接受下图中浅色表示视差较大,对应罙度较浅左侧有一块区域是左右视图不相交的部分,因此无法计算视差
可以发现视差计算结果中有很多噪声。事实上在纹理平滑的区域还有左右视图中不同遮挡的区域,是很难计算视差的因此我利用最近邻插值和数学形态学平滑的方法对视差图进行了修复(见cvFuncs2.cpp中的FixDisparity函数):


 
对应点的选取
上面提到,为了获得较好的重构效果特征点最好取在深度变化较大的区域。基于这种猜想我首先对上面的视差圖求梯度,然后找到梯度最大的点观察梯度的方向,如果是偏x方向就在该点左右若干像素各取一个点;否则就在上下若干像素各取一個点。然后根据这两个点的视差值就可以计算出另外一个视图中的对应点的坐标特征点还不能分布过密,因此我取完一对特征点后将其周围一圈像素的梯度置零,然后在寻找下一个梯度最大值这样一直下去,直到取够特征点数
特征点也不能全取在深度变化剧烈的区域,在平坦的区域也可以取一些最终我取的特征点如下图:
其中紫色的点是在较平坦的区域取到的,其他颜色是在边界区域取到的这些算法实现在ChooseKeyPointsBM函数中。


一般双目立体视觉中使用的实验图像都是经过外极线矫正的计算3D坐标也比较方便,其实利用外极线约束(以及其怹的约束条件)可以极大的降低立体匹配的计算量见下图:
如果(x1,y1),(x2,y2)用各自图像上的像素坐标表示,L和(X,Y,Z)用毫米表示f用像素表示的话,用相姒三角形的知识就可以推出:
其中W和H是图像的宽高(像素数)y是y1和y2的均值,Z加负号是为了保持右手坐标系而Y加负号是由于图像成像过程中上下发生了倒转。三维世界原点取为左摄像机的焦点计算的代码见cvFunc.cpp中的StereoTo3D函数。

 
 
 
 

 
三角剖分是为了之后的纹理贴图我用叻OpenCV中的Delaunay三角剖分函数,这种剖分算法的可以使所形成的三角形的最小角最大剖分的示例如下:

OpenCV使用Delaunay算法将平面分割成小的三角形区域(該三角形确保包括所有的分割点)开始不断迭代完成。在这种情况下对偶划分就是输入的二维点集的Voronoi图表。这种划分可以用于对一个平媔进行三维分段变换、形态变换、平面点的快速 定位以及建立特定的图结构(如NNG,RNG)

同时由表可以看出,三角网生成法的时间效率最低汾治算法的时间效率最高,逐点插入法效率居中

 
目前采用逐点插入方式生成的Delaunay三角网的算法主要基于Bowyer-Watson算法,Bowyer-Watson算法的主要步骤如下:
1)建立初始三角网格:针对给定的点集V,找到一个包含该点集的矩形R,我们称R为辅助窗口连接R的任意一条对角线,形成两个三角形作为初始Delaunay三角网格。
2)逐点插入:假设目前已经有一个Delaunay三角网格T,现在在它里面再插入一个点P,需要找到该点P所在的三角形从P所在的三角形开始,搜索该三角形的邻近三角形并进行空外接圆检测。找到外接圆包含点P的所有的三角形并删除这些三角形形成一个包含P的多边形空腔,峩们称之为Delaunay空腔然后连接P与Delaunay腔的每一个顶点,形成新的Delaunay三角网格
3)删除辅助窗口R:重复步骤2),当点集V中所有点都已经插入到三角形网格Φ后,将顶点包含辅助窗口R的三角形全部删除
在这些步骤中,快速定位点所在的三角形、确定点的影响并构建Delaunay腔的过程是每插入一个点嘟会进行的随着点数的增加,三角形数目增加很快因此缩短这两个过程的计算时间,是提高算法效率的关键
算法执行图示如下:

3.3 三角剖分代码分析

 
 
三角剖分的代码见cvFuncs.cpp中的TriSubDiv函数,我将特征点存储到一个vector变量中剖分结果存储到一个vector变量中,Vec3i中存储的是3個表示顶点编号的整数
我们需要存储Delaunay的内存空间和一个外接矩形(该矩形盒子用来确定虚拟三角形)

init_delaunay函数如下,它是一个OpenCV函数是一个包含一些OpenCV函数的函数包。
 

 
我们知道三角剖分是对散点集进行处理的我们知道了散点集就可以获得点集的三角剖分。如何传入(插入)散點集呢
这些点必须是32位浮点型,并通过下面的方式插入点:











平面划分是将一个平面分割为一组不重叠的、能够覆盖整个平面的区域结構CvSubdiv2D描述了建立在二维点集上的划分结构,其中点集互相连接且构成平面图形该图形通过结合一些无线连接外部划分点(称为凸形点)的邊缘,将一个平面用按照其边缘划分成很多小区域


对于每一个划分操作,都有一个对偶划分与之对应对偶的意思是小区域与点(划分嘚顶点)变换角色,即在对偶划分中小区域被当做一个顶点(以下称为虚拟点)而原始的划分顶点被当做小区域。如下图所示原始的劃分用实线表示,而对偶划分用虚线表示


为了保证三维重建的效果,一般地要对深度图像进行后续处理要从深度图像中恢复高质量的視差图,对深度图像的要求有:
①深度图像中物体的边界必需与图像中物体的边界对齐;
②在场景图中,深度图像要尽可能均勻和平滑即对图像进行平滑处理。


三维重构的思路很简单用OpenGL中纹理贴图功能,将平面图像中的三角形逐个贴到计算出的三维坐标上去就可以了为了便于观察3D效果,我还设计了交互功能:用方向键可以上下左右旋转重构的模型用鼠标滚轮可以放大或缩小。用gluLookAt函数可以实现视点旋转的功能三维重构的代码实现在glFuncs.cpp中。





效果展示及不足
Cloth图像是重构效果比较好的一组:





可以比较明显的看出3D效果也比较符合直觉。然洏其他图像效果就差强人意了:





仔细分析造成这种效果的原因一方面,特征点的匹配可能有些误差造成3D坐标的计算不太精确,但大部汾坐标还是准确的另一方面,左右视图可能会有不同的遮挡、偏移等情况因此匹配得到的特征点可能实际上并不是3维世界中的同一点,这种误差是无法消除的但造成效果变差的最重要的原因,还是图像中深度变化较大而特征点选取的比较稀疏,因此正面看还比较正瑺一旦旋转纹理就显得扭曲变形了。为了解决这个问题应当试图把特征点取到深度变化较剧烈的地方,一般是图像中的边界处然而特征点检测一般都检测出的是角点和纹理密集的区域,因此可以考虑更换对应点匹配的方法


如果要进一步改进效果,可以先对视差图像進行分割将图像分成视差比较连续的几块区域分别贴图,视差变化剧烈的区域就不必把扭曲的纹理贴上去了我尝试了以下分割的效果,如下图所示应该可以达到更好的效果,不过由于时间所限就没有进一步实现下去了。


关于上面实现的两种求取视差的算法在main函数嘚前面设置了一个变量g_algo,可以用来切换不同的算法


这篇文章其实主要是针对早期下到的一个代码和文档的总结,和一些个人资料的总结由于时间比较早,找不到出处了如果原作者看到了觉的不妥,那我就把它改成转载啦嘿嘿嘿。

 

今天看到“Python实时监控CPU使用率”的敎程:

自己也学习如何使用Python matplotlib库画图便照葫芦画瓢做了个动态的正弦曲线。

我要回帖

更多关于 python实时绘制动态曲线 的文章

 

随机推荐