投影矩阵的使用

 opencv3.0中有一个函数 triangulatePoints 可以用两个投影矩阵和匹配点来得到 3D点

现在就用这个函数来重建,相当于一个简易的 pmvs。

 先写一个流程:


1。在visualize下读入两个图(已经崎变校正过的)

2。检测特征点(可以任何一种,后面用AKAZE)

3。匹配

(1)粗配--match_features_knn

(2)一致性过滤--Gms_Match

(3)极线约束过滤--RANSAC

4。在txt下读入两个投影矩阵
5。生成3D点(匹配点和投影矩阵)
6。保存到文件(ply格式)


头文件

#include "Header.h" 
#include "gms_matcher.h" //这两个可以在这下载:https://github.com/JiawangBian/GMS-Feature-Matcher
#include<fstream> //保存文件用
opencv.hpp和其它的一些已经在Header.h中了,如果不用gms的话自行添加

主函数

int main()
{

	//总目录
	string path="C:/2345downloads/bundler-v0.4-source/examples/kermit/k0.nvm.cmvs/00/";//(自行修改)
	//在visualize下读入两个图
	string name1=path + "visualize/00000000.jpg";
	string name2=path + "visualize/00000001.jpg";
	std::cout <<"正在读入图:"<< name1 << '\n';
	Mat img1 = imread(name1);//data/nn_left.jpgdata/0000.jpg
	std::cout <<"正在读入图:"<< name2 << '\n';
	Mat img2 = imread(name2);//data/nn_right.jpgdata/0001.jpg

	//匹配
	vector<KeyPoint> kp1,kp2;
	vector<DMatch> matches;
	meMatch2(img1, img2,kp1,kp2,matches);

	//txt下读入两个投影矩阵
	name1=path + "txt/00000000.txt";
	name2=path + "txt/00000001.txt";

	// 两个相机的投影矩阵K.[R T],triangulatePoints只支持float型
	Mat project1 = Mat::zeros (3, 4, CV_32FC1);
	Mat project2 = Mat::zeros (3, 4, CV_32FC1);
	readProject(name1,name2,project1,project2);

	//匹配点生成3D点
	vector<Point2f> points1, points2;
	get_match_points (kp1, kp2, matches, points1, points2);

	//获得匹配点颜色
	vector<Vec3b> colors;
	get_match_colors(img1,points1,colors);

	//由生成3D点
	vector<Point3f> structure;
	reconstruct ( project1, project2, points1,points2,structure);

	//保存到文件中
	//save_structure1 ("out1.xyz", structure);//保存为 xyz 格式

	save_structure2 ("out2.ply", structure,colors);//保存到 ply 格式


	return 0;
}


匹配

//在img1,img2 中检测特征点,然后匹配,除去误匹配
//结果保存到kp1,kp2, matches_gms 中
void meMatch2(Mat &img1, Mat &img2,vector<KeyPoint> &kp1,vector<KeyPoint> &kp2,vector<DMatch> &matches_hao)
{
	Mat d1, d2;

	cout << "正在检测特征点:... " << endl;

	//AKAZE
	Ptr<AKAZE> akaze = AKAZE::create();  
	akaze->detectAndCompute(img1, noArray(), kp1, d1);  
	akaze->detectAndCompute(img2, noArray(), kp2, d2);  
	cout << "当前图1特征点: " << d1.rows << "个" << endl;
	cout << "当前图2特征点: " << d2.rows << "个" << endl;

	cout << "正在粗略匹配:knn " << endl;

	//knn匹配
	match_features_knn(d1, d2, matches_hao);
	cout << "粗略匹配点有:"<<matches_hao.size () << endl;
	// 画匹配
	Mat show = DrawInlier(img1, img2, kp1, kp2, matches_hao, 1);
	imshow("show", show);
	imwrite("show1.jpg",show);
	waitKey();

	// 一致性过滤器
	Gms_Match(img1, img2,kp1,kp2,matches_hao);
	// 画匹配
	show = DrawInlier(img1, img2, kp1, kp2, matches_hao, 1);
	imshow("show", show);
	imwrite("show2.jpg",show);
	waitKey();

	//利用极线约束(基础矩阵)剔除误匹配点
	cout << "正在利用基础矩阵剔除误匹配点" << endl;

	Mat Fundamental;
	refineMatchesWithFundamental(kp1,kp2,matches_hao,Fundamental); 

	cout << "共有好的 " << matches_hao.size () << " 个匹配点." << endl;
	// 画匹配
	show = DrawInlier(img1, img2, kp1, kp2, matches_hao, 1);
	imshow("show", show);
	imwrite("show3.jpg",show);

	waitKey();
}

初匹图


直接RANSAC图


由于这里可能还有失匹点,所以中间加入gms


这样可能点少了点,但都是正确的了。

建三维点

/*重建出三维点,并将其保存在structure中。*/
void reconstruct (
	Mat project1,
	Mat project2,
	vector<Point2f> points1,
	vector<Point2f> points2,
	vector<Point3f>& structure
)
{
	Mat structure_matrix;
	triangulatePoints (project1, project2, points1, points2, structure_matrix); // 三角重建
	//projMatr1– 3x4 第一个相机的投影矩阵.
	//projMatr2– 3x4 第二个相机的投影矩阵.
	//projPoints1– 2xN 第一幅图像的特征点矩阵.
	//projPoints2– 2xN第二幅图像的特征点矩阵.
	//points4D– 4xN 在齐次坐标系之中重构的向量

	structure.reserve (structure_matrix.cols); // 不能用resize
	for (int i = 0; i < structure_matrix.cols; i++)
	{
		Mat_<float> coordinate = structure_matrix.col (i);
		coordinate /= coordinate (3);//齐次坐标,需要除以最后一个元素才是真正的坐标值
		structure.push_back (Point3f (coordinate (0), coordinate (1), coordinate (2)));
	}
}

保存到文件(ply)

/********************************************************************************************************
参数:
filename 文件名; 
structure 重建出的三维点;
colors 点颜色
功能:
将重建出的3D点保存在.ply文件中。
*********************************************************************************************************/

void save_structure2 (char* filename,vector<Point3f>& structure,vector<Vec3b>& colors)
{
	ofstream fout (filename);
	fout <<"ply\n" ;
	fout <<"format ascii 1.0\n" ;

	int pointNumber = structure.size ();
	fout <<"element vertex " <<pointNumber<< endl;
	fout <<"property float x\n" ;
	fout <<"property float y\n" ;
	fout <<"property float z\n" ;
	fout <<"property uchar red\n" ;
	fout <<"property uchar green\n" ;
	fout <<"property uchar blue\n" ;
	fout <<"end_header\n" ;

	for (int i = 0; i < pointNumber; i++)
	{
		fout << structure[i].x << ' ' << structure[i].y << ' ' << structure[i].z <<  ' ' << (int)colors[i][2] << ' ' << (int)colors[i][1] << ' ' << (int)colors[i][0] << endl;

	}
	fout.close ();

}
由于篇幅太长,后面继续.......

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值