SfM两视图三维点云重建--【VS2015+OpenCV3.4+PCL1.8】

本文介绍了使用SfM进行两视图三维点云重建的步骤,包括特征点提取、匹配、对极几何约束、三维变换关系恢复和三角化法。通过VS2015、OpenCV3.4和PCL1.8实现,展示了从图像到三维点云的转换过程。注意,选择相邻图片以确保足够特征点匹配,以及正确处理本质矩阵的分解和归一化方法对重建结果的影响。
摘要由CSDN通过智能技术生成
概述

视觉三维重建,是指使用相机采集的图片、根据相关知识推导目标物体三维信息的过程。这里借鉴《视觉SLAM14讲》中的分类方法,将视觉三维重建分为基于特征点和非提取特征点的重建。本文旨在使用基于特征点的重建方法完成相邻两张图片间的三维重建。

步骤

基于特征点的视觉三维重建方法主要包括如下流程:

  1. 提取单张图片特征点;
  2. 多张图片间特征点的匹配;
  3. 利用对极几何约束,使用SfM恢复两相机间的三维变换关系;
  4. 使用三角量测法(或称三角化法),重构二维图像对应点的三维点信息。

按照我的理解,上述流程可以概括为如下两部分:求解相机内外参、三维重建。

  • 求解相机内外参:
    提取特征点并进行匹配只是为了组成匹配对,以方便计算基本矩阵F/本质矩阵E(对极几何约束),而计算出矩阵E或F后,即可进行SVD分解得到两相机间的三维变换关系(旋转矩阵R、平移矩阵t)。至此,是为求解相机内外参的过程。当然,也可以使用相机标定的方式获取相机内外参数,但多张重建会比较繁琐。
  • 三维重建
    在已知两图片间变换矩阵的情况下,就可以使用三角化进行三维重建了。重建后的三维点是以第一张图片对应的相机坐标系为世界坐标系。

这里只是进行简单的介绍,并不涉及复杂的原理,有兴趣的可参考14讲中的内容,网上也有许多优秀博文可供参考。

代码

环境:Win10+VS2015+OpenCV3.4+PCL1.8

#include <iostream>
#include <opencv2/opencv.hpp>

#include <opencv2/features2d/features2d.hpp> 
#include <opencv2/xfeatures2d/nonfree.hpp>

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>

using namespace std;
using namespace cv;
using namespace pcl;
using namespace cv::xfeatures2d;

// ratio & symmetry test
void ratioTest(vector<vector<DMatch>> &matches, vector<DMatch> &goodMatches);
void symmetryTest(const vector<DMatch>& matches1, const vector<DMatch>& matches2, vector<DMatch>& symMatches);

// 从匹配对中提取特征点
void fillPoints(vector<DMatch> goodMatches, vector<KeyPoint> keypoints1, vector<KeyPoint> keypoints2, vector<Point2f>& points1, vector<Point2f>& points2);

// 三维重建
void reconstruct(Mat& K, Mat& fundamentalMatrix, vector<Point2f>& points1, vector<Point2f>& points2, vector<Point3f>& points3D, Mat_<double>& R, Mat_<double>& t);

// 获取关键点RGB
void getPointColor(vector<Point2f> points1, Mat BaseImageLeft, vector<Vec3b>& colors);

int main(int argc, char* argv[])
{
   
	// PCL可视化
	PointCloud<PointXYZRGB>::Ptr cloud(new PointCloud<PointXYZRGB>);
	boost::shared_ptr<visualization::PCLVisualizer> viewer(new visualization::PCLVisualizer("3D viewer")); // 实例化PCLVisualizer对象,窗口命名为3D viewer

	Mat K;			// 内参数矩阵
	Matx34d P, P1;  // 两图片的相机坐标

	// 1.读入图片
	Mat BaseImageLeft = imread(".\\images\\004.png", -1);
	Mat BaseImageRight = imread(".\\images\\006.png", -1);
	if (BaseImageLeft.empty() || BaseImageRight.empty())
	{
   
		cout << "ERROR! NO IMAGE LOADED!" << endl;
		return -1;
	}
	cout << "processing..." << endl;
	// 2.SIFT提取特征点
	Ptr<Feature2D> detector = xfeatures2d::SIFT::create(0, 3, 0.04, 10);

	vector<KeyPoint> keypoints_1, keypoints_2; // 关键点
	Mat descriptors_1, descriptors_2;		   // 描述符

	detector->detectAndCompute(BaseImageLeft, noArray(), keypoints_1, descriptors_1);
	detector->detectAndCompute(BaseImageRight, noArray(), keypoints_2, descriptors_2);

	// 3.Flann匹配特征点
	vector<vector<DMatch>> matches1, matches2;
	vector<DMatch> goodMatches1, goodMatches2, goodMatches, outMatches;

	FlannBasedMatcher matcher;
	
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值