From 03ac2aef0e6d30c638d2476c7e79abecb64ba06d Mon Sep 17 00:00:00 2001
From: rayonnant14 <smolpolina199906@icloud.com>
Date: Mon, 22 Jun 2020 12:51:51 +0300
Subject: [PATCH] added new stages

---
 modules/vslam/orb_slam.cpp | 1254 ++++++++++++++++++++++--------------
 1 file changed, 774 insertions(+), 480 deletions(-)

diff --git a/modules/vslam/orb_slam.cpp b/modules/vslam/orb_slam.cpp
index b056dc6ab..bf713bf79 100644
--- a/modules/vslam/orb_slam.cpp
+++ b/modules/vslam/orb_slam.cpp
@@ -1,552 +1,846 @@
 #include <opencv2/opencv.hpp>
-#include <opencv2/objdetect.hpp>
-#include <opencv2/imgcodecs.hpp>
-#include <opencv2/highgui/highgui.hpp>
 #include <opencv2/imgproc/imgproc.hpp>
 #include <iostream>
-#include <opencv2/videoio.hpp>
 #include <opencv2/core.hpp>
-#include <stdlib.h>
+#include <opencv2/calib3d/calib3d.hpp>
 #include <stdio.h>
-#include <ctime>
-#include <opencv2/core/utility.hpp>
 #include <opencv2/sfm.hpp>
 #include <opencv2/viz.hpp>
+#include <opencv2/stitching/detail/motion_estimators.hpp>
+#include <opencv2/stitching/detail/camera.hpp>
 
 using namespace cv;
-using namespace std;
 #include<vector>
-#include <string>
 
-struct map_points
-{
-	vector<Point3d> position_3d;
-	vector<vector<Vec3b> > colors;
-};
 
 class OrbSLAM
 {
 public:
-	OrbSLAM(Mat calib_mat_, Mat dist_coeffs_);
-	OrbSLAM();
-	void alignImages(Mat& im1);
-	vector<KeyPoint> gridFeatureDetect(Mat& img, Mat& descriptors, int grid);
-	void getMatcheBF(Mat& descriptor1, Mat& descriptor2, vector<DMatch>& matches);
-	void getMatcheKNN(Mat& descriptor1, Mat& descriptor2, vector<DMatch>& matches);
-	double computeScore(Mat &M, vector<Point2f>& points1, vector<Point2f>& points2, const double T_M);
-	bool reconstract(Mat& H, vector<Point2f>& points1,
-		vector<Point2f>& points2);
-	bool doMapInitialization(vector<Point2f>& points1, vector<Point2f>& points2);
-	bool doTracking();
-	void getImage(Mat &img)
-	{
-		frames.push_back(img);
-		alignImages(frames.back());
-	};
-	void setCamera();
-	void updateCovisibilityGraph();
+    OrbSLAM(Mat calib_mat_, Mat dist_coeffs_);
+    OrbSLAM();
+    void loadImage(Mat &img)
+    {
+        frames.push_back(img);
+        alignImages(frames.back());
+        if(frames.size() > 1)
+            updateCovisibilityGraph();
+    };
 protected:
-	vector<Mat> gray_frames;
-	vector<Mat> frames;
-	vector<vector<KeyPoint> > keypoints;
-	vector<Mat> descriptors;
-
-	vector<vector<int> > covisibility_graph;
-	vector<vector<Point3f> > cur_points3d;
-	vector<vector<Point2f> > cur_points2d;
-	vector<vector<Vec3b>>  colors;
-	vector<Affine3d> cam_pose;
-	Mat calib_mat;
-	Mat dist_coeffs;
-	Matx33d new_calib;
-	int grid = 1;
+    void alignImages(Mat& im1);
+    std::vector<KeyPoint> gridFeatureDetect(Mat& img, Mat& descriptors, int grid);
+    std::vector<KeyPoint> featureDetectInit(Mat& img, Mat& descriptor);
+    void getMatcheInit(Mat& descriptor1, Mat& descriptor2, std::vector<DMatch>& matches);
+    void getMatcheBF(Mat& descriptor1, Mat& descriptor2, std::vector<DMatch>& matches);
+    void getMatcheKNN(Mat& descriptor1, Mat& descriptor2, std::vector<DMatch>& matches);
+    double computeScore(Mat &M, std::vector<Point2f>& points1, std::vector<Point2f>& points2,
+                        const double T_M, size_t num_iter);
+    bool reconstract(std::vector<Point2f>& points1, std::vector<Point2f>& points2,
+                     std::vector<Mat>& rotations, std::vector<Mat>& translations);
+    std::vector<std::vector<Mat> > getRotationsAndTranslationsFundamental(Mat& F, std::vector<Point2f>& points1,
+                                                                          std::vector<Point2f>& points2);
+    std::vector<std::vector<Mat> > getRotationsAndTranslationsHomography(Mat& F, std::vector<Point2f>& points1,
+                                                                         std::vector<Point2f>& points2);
+    bool doMapInitialization(std::vector<Point2f>& points1, std::vector<Point2f>& points2);
+    bool doTracking(Mat r_matrix, Mat t_matrix);
+    int motionChooseSolution(std::vector<Point2f>& points1, std::vector<Point2f>& points2,
+                             std::vector<Mat>& rotations, std::vector<Mat>& translations);
+    void performBA_(Mat rotation, Mat translation);
+    void setCamera();
+    void updateCovisibilityGraph();
+    Mat performBA(Mat rotation, Mat translation);
+    std::vector<Mat> gray_frames;
+    std::vector<Mat> frames;
+    std::vector<std::vector<KeyPoint> > keypoints;
+    std::vector<Mat> descriptors;
+    std::vector<detail::MatchesInfo> features_matches;
+    std::vector<detail::ImageFeatures> features_images;
+
+    std::vector<std::vector<size_t> > covisibility_graph;
+private:
+    std::vector<std::vector<Point3f> > cur_points3d;
+    std::vector<std::vector<Point2f> > cur_points2d;
+    std::vector<std::vector<Vec3b> >  colors;
+    std::vector<Affine3d> cam_pose;
+    Mat calib_mat;
+    Mat dist_coeffs;
+    Matx33d new_calib;
+    int grid = 5;
+    std::vector<Mat> homographies;
+    std::vector<std::vector<uchar> > homographies_mask;
+    std::vector<detail::MatchesInfo> pairwise_matches;
+    bool match_two_image = false;
 };
 
 OrbSLAM::OrbSLAM()
 {
-	covisibility_graph.resize(covisibility_graph.size() + 1);
-	for (int i = 0; i < covisibility_graph.size(); i++)
-	{
-		covisibility_graph[i].resize(covisibility_graph.size());
-	}
-	covisibility_graph[covisibility_graph.size() - 1][covisibility_graph.size() - 1] = 0;
-	setCamera();
+    covisibility_graph.resize(covisibility_graph.size() + 1);
+    for (int i = 0; i < covisibility_graph.size(); i++)
+    {
+        covisibility_graph[i].resize(covisibility_graph.size());
+    }
+    covisibility_graph[covisibility_graph.size() - 1][covisibility_graph.size() - 1] = 0;
+    setCamera();
 };
 
 OrbSLAM::OrbSLAM(Mat calib_mat_, Mat dist_coeffs_)
 {
-	/*
-	covisibility_graph.resize(1);
-	for(int i = 0; i < 1; i++)
-		covisibility_graph[i].resize(1);
-	covisibility_graph[0][0] = 0;
-	*/
-	calib_mat = calib_mat_;
-	dist_coeffs = dist_coeffs_;
-	new_calib = Matx33d(calib_mat);
-	covisibility_graph.resize(covisibility_graph.size() + 1);
-	for (int i = 0; i < covisibility_graph.size(); i++)
-	{
-		covisibility_graph[i].resize(covisibility_graph.size());
-	}
-	covisibility_graph[covisibility_graph.size() - 1][covisibility_graph.size() - 1] = 0;
+    calib_mat = calib_mat_;
+    dist_coeffs = dist_coeffs_;
+    new_calib = Matx33d(calib_mat);
+    covisibility_graph.resize(covisibility_graph.size() + 1);
+    for (int i = 0; i < covisibility_graph.size(); i++)
+    {
+        covisibility_graph[i].resize(covisibility_graph.size());
+    }
+    covisibility_graph[covisibility_graph.size() - 1][covisibility_graph.size() - 1] = 0;
 };
 
 //for logi 1080p HD C920
 void OrbSLAM::setCamera()
 {
-	Mat calib_mat_(3, 3, CV_64FC1);
-	Mat dist_coeffs_ = Mat::zeros(5, 1, CV_64FC1);
-	/*
-	calib_mat_.at<double>(0, 0) = 987;
-	calib_mat_.at<double>(0, 1) = 0.0;
-	calib_mat_.at<double>(0, 2) = 630;
-	calib_mat_.at<double>(1, 0) = 0.0;
-	calib_mat_.at<double>(1, 1) = 987;
-	calib_mat_.at<double>(1, 2) = 357;
-	calib_mat_.at<double>(2, 0) = 0.0;
-	calib_mat_.at<double>(2, 1) = 0.0;
-	calib_mat_.at<double>(2, 2) = 1.0;
-	*/
-	calib_mat_.at<double>(0, 0) = 612.03;
-	calib_mat_.at<double>(0, 1) = 0.0;
-	calib_mat_.at<double>(0, 2) = 320.15;
-	calib_mat_.at<double>(1, 0) = 0.0;
-	calib_mat_.at<double>(1, 1) = 661.6614;
-	calib_mat_.at<double>(1, 2) = 117.5195;
-	calib_mat_.at<double>(2, 0) = 0.0;
-	calib_mat_.at<double>(2, 1) = 0.0;
-	calib_mat_.at<double>(2, 2) = 1.0;
-	calib_mat = calib_mat_;
-
-	dist_coeffs_.at<double>(0, 0) = -0.128224;
-	dist_coeffs_.at<double>(1, 0) = 0.023572;
-	dist_coeffs_.at<double>(2, 0) = -0.0596;
-	dist_coeffs_.at<double>(3, 0) = 0.040301;
-	dist_coeffs_.at<double>(4, 0) = 0.0;
-	dist_coeffs = dist_coeffs_;
-	new_calib = Matx33d(612.03, 0.0, 320.15, 0.0, 661.6614, 117.5195, 0.0, 0.0, 1.0);
+    Mat calib_mat_(3, 3, CV_64FC1);
+    Mat dist_coeffs_ = Mat::zeros(5, 1, CV_64FC1);
+    /*
+    calib_mat_.at<double>(0, 0) = 987;
+    calib_mat_.at<double>(0, 1) = 0.0;
+    calib_mat_.at<double>(0, 2) = 630;
+    calib_mat_.at<double>(1, 0) = 0.0;
+    calib_mat_.at<double>(1, 1) = 987;
+    calib_mat_.at<double>(1, 2) = 357;
+    calib_mat_.at<double>(2, 0) = 0.0;
+    calib_mat_.at<double>(2, 1) = 0.0;
+    calib_mat_.at<double>(2, 2) = 1.0;
+    */
+    calib_mat_.at<double>(0, 0) = 612.03;
+    calib_mat_.at<double>(0, 1) = 0.0;
+    calib_mat_.at<double>(0, 2) = 320.15;
+    calib_mat_.at<double>(1, 0) = 0.0;
+    calib_mat_.at<double>(1, 1) = 661.6614;
+    calib_mat_.at<double>(1, 2) = 117.5195;
+    calib_mat_.at<double>(2, 0) = 0.0;
+    calib_mat_.at<double>(2, 1) = 0.0;
+    calib_mat_.at<double>(2, 2) = 1.0;
+    calib_mat = calib_mat_;
+
+    dist_coeffs_.at<double>(0, 0) = -0.128224;
+    dist_coeffs_.at<double>(1, 0) = 0.023572;
+    dist_coeffs_.at<double>(2, 0) = -0.0596;
+    dist_coeffs_.at<double>(3, 0) = 0.040301;
+    dist_coeffs_.at<double>(4, 0) = 0.0;
+    dist_coeffs = dist_coeffs_;
+    new_calib = Matx33d(612.03, 0.0, 320.15, 0.0, 661.6614, 117.5195, 0.0, 0.0, 1.0);
 }
 
 void OrbSLAM::updateCovisibilityGraph()
 {
-	covisibility_graph.resize(covisibility_graph.size() + 1);
-	for (int i = 0; i < covisibility_graph.size(); i++)
-	{
-		covisibility_graph[i].resize(covisibility_graph.size());
-	}
-	covisibility_graph[covisibility_graph.size() - 1][covisibility_graph.size() - 1] = 0;
-	colors.resize(colors.size() + 1);
-	cur_points2d.resize(cur_points2d.size() + 1);
-	vector<Point2f> points1, points2;
-	for (size_t i = 0; i < covisibility_graph.size() - 1; i++)
-	{
-		int j = covisibility_graph.size() - 1;
-
-		cout << "graph ver :" << i << " " << j << endl;
-
-		vector<DMatch> matches;
-		getMatcheBF(descriptors[i], descriptors[j], matches);
-		covisibility_graph[i][j] = matches.size();
-		//draw matches
-		Mat imMatches;
-		//drawMatches(frames[i], keypoints[i], frames[j], keypoints[j], matches, imMatches);
-		//imshow("matches", imMatches);
-		//waitKey();
-
-		vector<KeyPoint> tmp_keypoints_i;
-		vector<KeyPoint> tmp_keypoints_j;
-		Mat tmp_descriptors_i(Size(0, 32), CV_8U);
-		Mat tmp_descriptors_j(Size(0, 32), CV_8U);
-		vector<size_t> ind_keypoints_i;
-		vector<size_t> ind_keypoints_j;
-		
-		for (size_t n = 0; n < matches.size(); n++)
-		{
-			points1.push_back(keypoints[i][matches[n].queryIdx].pt);
-			points2.push_back(keypoints[j][matches[n].trainIdx].pt);
-			colors[colors.size() - 1].push_back(viz::Color(frames[j].at<Vec3b>(points2.back())));
-			ind_keypoints_i.push_back(matches[n].queryIdx);
-			ind_keypoints_j.push_back(matches[n].trainIdx);
-		}
-		//sort(ind_keypoints_i.begin(), ind_keypoints_i.end());
-		//sort(ind_keypoints_j.begin(), ind_keypoints_j.end());
-		for (size_t n = 0; n < keypoints[i].size(); n++)
-		{
-			for (size_t m = 0; m < ind_keypoints_i.size(); m++)
-			{
-				if (ind_keypoints_i[m] == n)
-				{
-					tmp_keypoints_i.push_back(keypoints[i][n]);
-					tmp_descriptors_i.push_back(descriptors[i].row(n));
-					break;
-				}
-			}
-		}
-		for (size_t n = 0; n < keypoints[j].size(); n++)
-		{
-			for (size_t m = 0; m < ind_keypoints_j.size(); m++)
-			{
-				if (ind_keypoints_j[m] == n)
-				{
-					tmp_keypoints_j.push_back(keypoints[j][n]);
-					tmp_descriptors_j.push_back(descriptors[j].row(n));
-					break;
-				}
-			}
-		}
-		descriptors[i].resize(tmp_descriptors_i.rows);
-		descriptors[j].resize(tmp_descriptors_j.rows);
-		descriptors[i] = tmp_descriptors_i;
-		descriptors[j] = tmp_descriptors_j;
-		keypoints[i] = tmp_keypoints_i;
-		keypoints[j] = tmp_keypoints_j;
-		
-
-
-	}
-	
-	cur_points2d[cur_points2d.size() - 1].insert(cur_points2d[cur_points2d.size() - 1].end(),
-		points2.cbegin(),
-		points2.cend());
-	if (points1.size() != 0)
-		doMapInitialization(points1, points2);
-
+    covisibility_graph.resize(covisibility_graph.size() + 1);
+    for (int i = 0; i < covisibility_graph.size(); i++)
+    {
+        covisibility_graph[i].resize(covisibility_graph.size());
+    }
+    covisibility_graph[covisibility_graph.size() - 1][covisibility_graph.size() - 1] = 0;
+    colors.resize(colors.size() + 1);
+    cur_points2d.resize(cur_points2d.size() + 1);
+    std::vector<Point2f> points1, points2;
+    std::vector<std::vector<KeyPoint> > tmp_keypoints = keypoints;
+    std::vector<Mat> tmp_descriptors = descriptors;
+    std::cout << "sizes: " << cur_points2d.size() << " " << colors.size() << std::endl;
+    int count_matches = 0;
+    for (int k = 0; k < 1; k++)
+    {
+        int i = covisibility_graph.size() - 2;
+        size_t j = covisibility_graph.size() - 1;
+
+        std::cout << "graph ver :" << i << " " << j << std::endl;
+        if ((j - i) == 1)
+        {
+            match_two_image = true;
+        }
+        else
+            match_two_image = false;
+        if ((descriptors[i].cols == 0) || (descriptors[j].cols == 0))
+            continue;
+        std::vector<DMatch> matches;
+        if(match_two_image)
+            //getMatcheBF(descriptors[i], descriptors[j], matches);
+            getMatcheInit(descriptors[i], descriptors[j], matches);
+        else
+            getMatcheBF(descriptors[i], descriptors[j], matches);
+
+        covisibility_graph[i][j] += matches.size();
+        count_matches += matches.size();
+        //draw matches
+        //Mat imMatches;
+        //drawMatches(frames[i], keypoints[i], frames[j], keypoints[j], matches, imMatches);
+        //imshow("matches", imMatches);
+        //waitKey();
+
+        std::vector<KeyPoint> tmp_keypoints_i;
+        std::vector<KeyPoint> tmp_keypoints_j;
+        Mat tmp_descriptors_i(Size(0, 32), CV_8U);
+        Mat tmp_descriptors_j(Size(0, 32), CV_8U);
+        std::vector<size_t> ind_keypoints_i;
+        std::vector<size_t> ind_keypoints_j;
+
+        for (size_t n = 0; n < matches.size(); n++)
+        {
+            points1.push_back(keypoints[i][matches[n].queryIdx].pt);
+            points2.push_back(keypoints[j][matches[n].trainIdx].pt);
+            colors.back().push_back(viz::Color(frames[j].at<Vec3b>(points2.back())));
+            ind_keypoints_i.push_back(matches[n].queryIdx);
+            ind_keypoints_j.push_back(matches[n].trainIdx);
+        }
+
+        //sort(ind_keypoints_i.begin(), ind_keypoints_i.end());
+        //sort(ind_keypoints_j.begin(), ind_keypoints_j.end());
+        for (size_t n = 0; n < keypoints[i].size(); n++)
+        {
+            for (size_t m = 0; m < ind_keypoints_i.size(); m++)
+            {
+                if (ind_keypoints_i[m] == n)
+                {
+                    tmp_keypoints_i.push_back(keypoints[i][n]);
+                    tmp_descriptors_i.push_back(descriptors[i].row(n));
+                    break;
+                }
+            }
+        }
+        for (size_t n = 0; n < keypoints[j].size(); n++)
+        {
+            for (size_t m = 0; m < ind_keypoints_j.size(); m++)
+            {
+                if (ind_keypoints_j[m] == n)
+                {
+                    tmp_keypoints_j.push_back(keypoints[j][n]);
+                    tmp_descriptors_j.push_back(descriptors[j].row(n));
+                    break;
+                }
+            }
+        }
+        /*
+        descriptors[i].resize(tmp_descriptors_i.rows);
+        descriptors[j].resize(tmp_descriptors_j.rows);
+        descriptors[i] = tmp_descriptors_i;
+        descriptors[j] = tmp_descriptors_j;
+        keypoints[i] = tmp_keypoints_i;
+        keypoints[j] = tmp_keypoints_j;
+        */
+
+
+    }
+
+    cur_points2d[cur_points2d.size() - 1].insert(cur_points2d[cur_points2d.size() - 1].end(),
+                                                 points2.cbegin(),
+                                                 points2.cend());
+    std::cout << "sizes: " << cur_points2d.size() << " " << colors.size() << std::endl;
+    if (points1.size() != 0)
+    {
+        bool res = doMapInitialization(points1, points2);
+        if (!res)
+        {
+
+            keypoints = tmp_keypoints;
+            descriptors = tmp_descriptors;
+
+        }
+    }
+    else
+    {
+        colors.resize(colors.size() - 1);
+        cur_points2d.resize(cur_points2d.size() - 1);
+    }
 }
 
-bool OrbSLAM::doMapInitialization(vector<Point2f>& points1, vector<Point2f>& points2)
+bool OrbSLAM::doMapInitialization(std::vector<Point2f>& points1, std::vector<Point2f>& points2)
 {
-	//vector<Point2f> points1, points2;
-	//alignImages(frames.back());
-	cout << points1.size() << " " << points2.size() << endl;
-
-	Mat h = findHomography(points1, points2, RANSAC, 5.99);
-	Mat f(3, 3, CV_64FC1);
-	f = findFundamentalMat(points1, points2, FM_RANSAC, 3.84);
-	double score_f = computeScore(f, points1, points2, 3.84);
-	double score_h = computeScore(h, points1, points2, 5.99);
-	double R_h = score_h / (score_h + score_f);
-	//vector<Point3d> points3d;
-	if (R_h > 0.45)
-	{
-		return reconstract(h, points1, points2);
-	}
-	else
-	{
-		cout << "not implemented\n";
-		// REWORK!!!!!!
-		return reconstract(h, points1, points2);
-	}
-	return true;
+    std::cout << points1.size() << " " << points2.size() << std::endl;
+    std::vector<uchar> mask;
+    Mat h = findHomography(points1, points2, mask, RANSAC, 5.99);
+    if (h.empty())
+    {
+        colors.resize(colors.size() - 1);
+        cur_points2d.resize(cur_points2d.size() - 1);
+        return false;
+    }
+
+    Mat f(3, 3, CV_64FC1);
+    f = findFundamentalMat(points1, points2, FM_RANSAC, 3.84);
+    if (f.empty())
+    {
+        colors.resize(colors.size() - 1);
+        cur_points2d.resize(cur_points2d.size() - 1);
+        return false;
+    }
+    std::cout << f << std::endl;
+    double score_f = computeScore(f, points1, points2, 3.84, 8);
+    double score_h = computeScore(h, points1, points2, 5.99, 4);
+    double R_h = score_h / (score_h + score_f);
+
+    if (R_h > 0.45)
+    {
+        std::vector<std::vector<Mat> >sol = getRotationsAndTranslationsHomography(h, points1, points2);
+        if (sol.size() != 2)
+            return false;
+        std::vector<Mat> rotations = sol[0];
+        std::vector<Mat> translations = sol[1];
+        return reconstract(points1, points2, rotations, translations);
+    }
+    else
+
+    {
+        std::vector<std::vector<Mat> >sol = getRotationsAndTranslationsFundamental(f, points1, points2);
+        if (sol.size() != 2)
+            return false;
+        std::vector<Mat> rotations = sol[0];
+        std::vector<Mat> translations = sol[1];
+        return reconstract(points1, points2, rotations, translations);
+    }
+    return true;
 
 }
 
-void OrbSLAM::getMatcheKNN(Mat& descriptor1, Mat& descriptor2, vector<DMatch>& matches)
+void OrbSLAM::getMatcheKNN(Mat& descriptor1, Mat& descriptor2, std::vector<DMatch>& matches)
 {
-	cv::Ptr<cv::DescriptorMatcher> matcher = cv::makePtr<cv::FlannBasedMatcher>(cv::makePtr<cv::flann::LshIndexParams>(12, 20, 2));
-	std::vector< std::vector<DMatch> > knn_matches;
-	matcher->knnMatch(descriptor1, descriptor2, knn_matches, 2);
-	const float ratio_thresh = 0.6f;
-	for (size_t i = 0; i < knn_matches.size(); i++)
-	{
-		if (knn_matches[i].size() >= 2)
-		{
-			if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance)
-			{
-				matches.push_back(knn_matches[i][0]);
-			}
-		}
-	}
+    cv::Ptr<cv::DescriptorMatcher> matcher = cv::makePtr<cv::FlannBasedMatcher>(cv::makePtr<cv::flann::LshIndexParams>(12, 20, 2));
+    std::vector< std::vector<DMatch> > knn_matches;
+    matcher->knnMatch(descriptor1, descriptor2, knn_matches, 2);
+    const float ratio_thresh = 0.6f;
+    for (size_t i = 0; i < knn_matches.size(); i++)
+    {
+        if (knn_matches[i].size() >= 2)
+        {
+            if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance)
+            {
+                matches.push_back(knn_matches[i][0]);
+            }
+        }
+    }
 }
 
-void OrbSLAM::getMatcheBF(Mat& descriptor1, Mat& descriptor2, vector<DMatch>& matches)
+void OrbSLAM::getMatcheBF(Mat& descriptor1, Mat& descriptor2, std::vector<DMatch>& matches)
 {
-	float good_match_percent = 0.08f;
-	Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
-	matcher->match(descriptor1, descriptor2, matches, Mat());
-	std::sort(matches.begin(), matches.end(),
-		[](DMatch a, DMatch b) { return a.distance > b.distance; });
-	const int numGoodMatches = matches.size() * good_match_percent;
-	matches.erase(matches.begin() + numGoodMatches, matches.end());
+
+    float good_match_percent = 0.08f;
+    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
+    matcher->match(descriptor1, descriptor2, matches, Mat());
+    std::sort(matches.begin(), matches.end(),
+              [](DMatch a, DMatch b) { return a.distance > b.distance; });
+    const int numGoodMatches = matches.size() * good_match_percent;
+    matches.erase(matches.begin() + numGoodMatches, matches.end());
+
+}
+void OrbSLAM::getMatcheInit(Mat& descriptor1, Mat& descriptor2, std::vector<DMatch>& matches)
+{
+    Ptr<detail::FeaturesMatcher> matcher;
+
+    matcher = makePtr<detail::BestOf2NearestMatcher>(1, 0.1);
+
+    std::vector<detail::ImageFeatures> features;
+    features.push_back(features_images[frames.size() - 2]);
+    features.push_back(features_images[frames.size() - 1]);
+    features[0].img_idx = 0;
+    features[1].img_idx = 1;
+    (*matcher)(features, features_matches);
+    matcher->collectGarbage();
+    matches = features_matches[1].matches;
+    std::cout << matches.size();
 
 }
 
 void OrbSLAM::alignImages(Mat& im1)
 {
-	Mat new_gray_frame;
-	cvtColor(im1, new_gray_frame, cv::COLOR_BGR2GRAY);
-	gray_frames.push_back(new_gray_frame);
-	//keypoints.resize(keypoints.size() + 1);
-	descriptors.resize(descriptors.size() + 1);
-	//colors.resize(colors.size() + 1)
-	cvtColor(im1, gray_frames.back(), cv::COLOR_BGR2GRAY);
-	vector<KeyPoint> new_keypoints = gridFeatureDetect(gray_frames.back(), descriptors.back(), grid);
-
-	keypoints.push_back(new_keypoints);
-	cout << "keypoints size " << keypoints.size() << endl;
-	//getMatcheBF(descriptors1, descriptors2, matches.back());
-
-	//draw matches
-	//Mat imMatches;
-	//drawMatches(im1, keypoints1, im2, keypoints2, matches, imMatches);
-	//imshow("matches", imMatches);
-	//waitKey();
-	//for( size_t i = 0; i < matches.back().size(); i++ )
-	//{
-	//    points1.push_back( keypoints1[ matches[i].queryIdx ].pt );
-	//    points2.push_back( keypoints2[ matches[i].trainIdx ].pt );
-	//    colors.push_back(viz::Color(im1.at<Vec3b>(points1[i])));
-	//}
+    Mat new_gray_frame;
+    cvtColor(im1, new_gray_frame, cv::COLOR_BGR2GRAY);
+    gray_frames.push_back(new_gray_frame);
+    //keypoints.resize(keypoints.size() + 1);
+    descriptors.resize(descriptors.size() + 1);
+    //colors.resize(colors.size() + 1)
+    cvtColor(im1, gray_frames.back(), cv::COLOR_BGR2GRAY);
+    std::vector<KeyPoint> new_keypoints;
+    //if (frames.size() > 2)
+    //new_keypoints = gridFeatureDetect(gray_frames.back(), descriptors.back(), grid);
+    //else
+    new_keypoints = featureDetectInit(gray_frames.back(), descriptors.back());
+    //new_keypoints = gridFeatureDetect(gray_frames.back(), descriptors.back(), grid);
+    std::cout << "keypoints size " << new_keypoints.size() << std::endl;
+    keypoints.push_back(new_keypoints);
+    std::cout << "keypoints size " << keypoints.size() << std::endl;
+}
 
+std::vector<KeyPoint> OrbSLAM::featureDetectInit(Mat& img, Mat& descriptor)
+{
+    Ptr<Feature2D> finder;
+    finder = ORB::create(2000);
+    detail::ImageFeatures features;
+
+    computeImageFeatures(finder, img, features);
+    features.img_idx = frames.size();
+    descriptor = features.descriptors.getMat(ACCESS_RW).clone();
+    Mat im;
+    std::vector<KeyPoint> keypoints_ = features.keypoints;
+    //drawKeypoints(frames.back(), keypoints_, im, Scalar(100, 200, 0));
+    //imshow("a", im);
+    //waitKey();
+    std::cout << keypoints_.size() << std::endl;
+    std::cout << descriptor.size() << std::endl;
+    features_images.push_back(features);
+    return keypoints_;
 }
-vector<KeyPoint> OrbSLAM::gridFeatureDetect(Mat& img, Mat& descriptor, int grid)
+std::vector<KeyPoint> OrbSLAM::gridFeatureDetect(Mat& img, Mat& descriptor, int grid)
 {
-	vector<KeyPoint> keypoints_;
-	int step_c = img.cols / grid;
-
-	int step_r = img.rows / grid;
-
-	int max_threshold = 500;
-	int step_threshold = 8;
-	int max_features = 4000;
-	max_features = max_features / grid;
-	vector<Mat> masks;
-	for (int i = 0; i < img.cols; i += step_c)
-	{
-		for (int j = 0; j < img.rows; j += step_r)
-		{
-			Mat mask = Mat::zeros(img.size(), CV_8UC1);
-			rectangle(mask, Point(i, j), Point(i + step_c, j + step_r), Scalar(255), -1);
-			masks.push_back(mask);
-		}
-	}
-
-	for (size_t i = 0; i < masks.size(); i++)
-	{
-		Ptr<ORB> orb = ORB::create(max_features);
-		orb->setScoreType(ORB::FAST_SCORE);
-		for (int threshold = 20; threshold < max_threshold; threshold += step_threshold)
-		{
-			vector<KeyPoint> keypoints_temp;
-			Mat descriptors_temp;
-			orb->setFastThreshold(threshold);
-			orb->detectAndCompute(img, masks[i], keypoints_temp, descriptors_temp);
-			if (keypoints_temp.size() >= 5)
-			{
-				std::copy(begin(keypoints_temp), end(keypoints_temp), std::back_inserter(keypoints_));
-				descriptor.push_back(descriptors_temp);
-				break;
-			}
-		}
-	}
-	return keypoints_;
+    std::vector<KeyPoint> keypoints_;
+    int step_c = img.cols / grid;
+
+    int step_r = img.rows / grid;
+
+    int max_threshold = 500;
+    int step_threshold = 20;
+    int max_features = 2000;
+    max_features = max_features / grid;
+    std::vector<Mat> masks;
+    for (int i = 0; i < img.cols; i += step_c)
+    {
+        for (int j = 0; j < img.rows; j += step_r)
+        {
+            Mat mask = Mat::zeros(img.size(), CV_8UC1);
+            rectangle(mask, Point(i, j), Point(i + step_c, j + step_r), Scalar(255), -1);
+            masks.push_back(mask);
+        }
+    }
+
+    for (size_t i = 0; i < masks.size(); i++)
+    {
+        //imshow("a", masks[i]);
+        //waitKey();
+
+        //orb->setScoreType(ORB::FAST_SCORE);
+        for (int threshold = 20; threshold < max_threshold; threshold += step_threshold)
+        {
+            Ptr<ORB> orb = ORB::create(max_features);
+            std::vector<KeyPoint> keypoints_temp;
+            Mat descriptors_temp;
+            orb->setFastThreshold(threshold);
+            //orb->setEdgeThreshold(threshold);
+            orb->detectAndCompute(img, masks[i], keypoints_temp, descriptors_temp);
+            if (keypoints_temp.size() >= max_features)
+            {
+                std::copy(begin(keypoints_temp), end(keypoints_temp), std::back_inserter(keypoints_));
+                descriptor.push_back(descriptors_temp);
+                break;
+            }
+
+        }
+    }
+    Mat im;
+    drawKeypoints(frames.back(), keypoints_, im, Scalar(100, 200, 0));
+    imshow("a", im);
+    waitKey();
+    return keypoints_;
 }
 
 //S = summ(p_M(d^2(m1, M^(-1) * m2) + p_M(d^2(m2, M * m1))))
 //p_M(d^2) = 5.99 - d^2 if d^2 < 5.99
 //else p_M(d^2) = 0
-double OrbSLAM::computeScore(Mat &M, vector<Point2f>& points1, vector<Point2f>& points2, const double T_M)
+double OrbSLAM::computeScore(Mat &M, std::vector<Point2f>& points1, std::vector<Point2f>& points2, const double T_M, size_t num_iter)
 {
-	Mat M_inv = M.inv();
-	Mat m2(3, points2.size(), CV_64FC1);
-	for (int i = 0; i < points2.size(); i++)
-	{
-		m2.at<double>(0, i) = points2[i].x;
-		m2.at<double>(1, i) = points2[i].y;
-		m2.at<double>(2, i) = 1;
-	}
-	Mat M_inv_m2_mat = M_inv * m2;
-	vector<Point2f> M_inv_m2;
-	vector<double> dist1;
-	for (int i = 0; i < points1.size(); i++)
-	{
-		M_inv_m2.push_back(Point2f(M_inv_m2_mat.at<double>(0, i) / M_inv_m2_mat.at<double>(2, i),
-			M_inv_m2_mat.at<double>(1, i) / M_inv_m2_mat.at<double>(2, i)));
-		dist1.push_back((M_inv_m2[i].x - points1[i].x) * (M_inv_m2[i].x - points1[i].x) +
-			(M_inv_m2[i].y - points1[i].y) * (M_inv_m2[i].y - points1[i].y));
-	}
-	//TODO use convertPointsToHomogeneous() and convertPointsFromHomogeneous()
-	Mat m1(3, points1.size(), CV_64FC1);
-	for (int i = 0; i < points1.size(); i++)
-	{
-		m1.at<double>(0, i) = points1[i].x;
-		m1.at<double>(1, i) = points1[i].y;
-		m1.at<double>(2, i) = 0;
-	}
-	Mat M_m1_mat = M * m1;
-	vector<Point2f> M_m1;
-	vector<double> dist2;
-	double S_M = 0;
-	for (int i = 0; i < points2.size(); i++)
-	{
-		M_m1.push_back(Point2f(M_m1_mat.at<double>(0, i) / M_m1_mat.at<double>(2, i),
-			M_m1_mat.at<double>(1, i) / M_m1_mat.at<double>(2, i)));
-		dist2.push_back((M_m1[i].x - points2[i].x) * (M_m1[i].x - points2[i].x) +
-			(M_m1[i].y - points2[i].y) * (M_m1[i].y - points2[i].y));
-	}
-	double T_H = 5.99;
-	for (int i = 0; i < dist1.size(); i++)
-	{
-		if (dist1[i] < T_M)
-			S_M += T_H - dist1[i];
-		if (dist2[i] < T_M)
-			S_M += T_H - dist2[i];
-	}
-	cout << "S_M = " << S_M << endl;
-	return S_M;
+    Mat M_inv = M.inv();
+    Mat m2(3, num_iter, CV_64FC1);
+    if (points2.size() < num_iter)
+        num_iter = points2.size();
+    for (int i = 0; i < num_iter; i++)
+    {
+        m2.at<double>(0, i) = points2[i].x;
+        m2.at<double>(1, i) = points2[i].y;
+        m2.at<double>(2, i) = 1;
+    }
+    Mat M_inv_m2_mat = M_inv * m2;
+    std::vector<Point2f> M_inv_m2;
+    std::vector<double> dist1;
+    for (int i = 0; i < num_iter; i++)
+    {
+        M_inv_m2.push_back(Point2f(M_inv_m2_mat.at<double>(0, i) / M_inv_m2_mat.at<double>(2, i),
+                                   M_inv_m2_mat.at<double>(1, i) / M_inv_m2_mat.at<double>(2, i)));
+        dist1.push_back((M_inv_m2[i].x - points1[i].x) * (M_inv_m2[i].x - points1[i].x) +
+                        (M_inv_m2[i].y - points1[i].y) * (M_inv_m2[i].y - points1[i].y));
+    }
+    //TODO: use convertPointsToHomogeneous() and convertPointsFromHomogeneous()
+    Mat m1(3, num_iter, CV_64FC1);
+    for (int i = 0; i < num_iter; i++)
+    {
+        m1.at<double>(0, i) = points1[i].x;
+        m1.at<double>(1, i) = points1[i].y;
+        m1.at<double>(2, i) = 0;
+    }
+    Mat M_m1_mat = M * m1;
+    std::vector<Point2f> M_m1;
+    std::vector<double> dist2;
+    double S_M = 0;
+    for (int i = 0; i < num_iter; i++)
+    {
+        M_m1.push_back(Point2f(M_m1_mat.at<double>(0, i) / M_m1_mat.at<double>(2, i),
+                               M_m1_mat.at<double>(1, i) / M_m1_mat.at<double>(2, i)));
+        dist2.push_back((M_m1[i].x - points2[i].x) * (M_m1[i].x - points2[i].x) +
+                        (M_m1[i].y - points2[i].y) * (M_m1[i].y - points2[i].y));
+    }
+    double T_H = 5.99;
+    for (int i = 0; i < num_iter; i++)
+    {
+        if (dist1[i] < T_M)
+            S_M += T_H - dist1[i];
+        if (dist2[i] < T_M)
+            S_M += T_H - dist2[i];
+    }
+    std::cout << "S_M = " << S_M << std::endl;
+    return S_M;
 }
 
-bool OrbSLAM::reconstract(Mat& H, vector<Point2f>& points1, vector<Point2f>& points2)
+int OrbSLAM::motionChooseSolution(std::vector<Point2f>& points1, std::vector<Point2f>& points2,
+                                  std::vector<Mat>& rotations, std::vector<Mat>& translations)
 {
-	vector<Mat> rotations, translations, normals;
-	int solutions = decomposeHomographyMat(H, calib_mat, rotations, translations, normals);
-	cout << "solution " << solutions << endl;
-	if (solutions == 0)
-	{
-		cur_points2d.resize(cur_points2d.size() - 1);
-		colors.resize(colors.size() - 1);
-		return false;
-	}
-	vector<int> possible_solution;
-	filterHomographyDecompByVisibleRefpoints(rotations, normals, points1, points2, possible_solution);
-
-	//cout << "possible solution " << possible_solution.size() << endl;
-	if (possible_solution.size() == 0)
-	{
-		cur_points2d.resize(cur_points2d.size() - 1);
-		return false;
-	}
-	vector<vector<Point3f> > possible_3d_points(possible_solution.size());
-	vector<float> reprojection_error(possible_solution.size());
-	for (int m = 0; m < possible_solution.size(); m++)
-	{
-		Mat projection1, projection2;
-		Mat id_mat = Mat::eye(rotations[m].size(), CV_64FC1);
-		Mat z = Mat::zeros(translations[m].size(), CV_64FC1);
-
-		cv::sfm::projectionFromKRt(calib_mat, id_mat, z, projection1);
-		cv::sfm::projectionFromKRt(calib_mat, rotations[possible_solution[m]], translations[possible_solution[m]], projection2);
-		cv::Mat points1Mat(2, points1.size(), CV_64FC1);
-		cv::Mat points2Mat(2, points1.size(), CV_64FC1);
-
-
-		for (int i = 0; i < points1.size(); i++)
-		{
-			cv::Point2f myPoint1 = points1.at(i);
-			cv::Point2f myPoint2 = points2.at(i);
-			points1Mat.at<double>(0, i) = myPoint1.x;
-			points1Mat.at<double>(1, i) = myPoint1.y;
-			points2Mat.at<double>(0, i) = myPoint2.x;
-			points2Mat.at<double>(1, i) = myPoint2.y;
-		}
-
-		vector<Mat> points2d;
-		points2d.push_back(points1Mat);
-		points2d.push_back(points2Mat);
-
-		vector<Mat> projections;
-		projections.push_back(projection1);
-		projections.push_back(projection2);
-
-		Mat points3d_mat(3, 1, CV_64FC1);
-		Mat Rs;
-		Mat Ts;
-		cv::sfm::triangulatePoints(points2d, projections, points3d_mat);
-
-
-		for (int i = 0; i < points3d_mat.cols; i++)
-		{
-			possible_3d_points[m].push_back(Point3f(points3d_mat.at<double>(0, i),
-				points3d_mat.at<double>(1, i),
-				points3d_mat.at<double>(2, i)));
-		}
-
-		vector<Point2f> new_points;
-		projectPoints(possible_3d_points[m], rotations[possible_solution[m]], translations[possible_solution[m]], calib_mat, dist_coeffs, new_points);
-		sort(new_points.begin(), new_points.end(),
-			[](Point2f& a, Point2f& b) {return sqrt(a.x * a.x + a.y * a.y) <
-			sqrt(b.x * b.x + b.y * b.y);    });
-		sort(cur_points2d.back().begin(), cur_points2d.back().end(),
-			[](Point2f& a, Point2f& b) {return sqrt(a.x * a.x + a.y * a.y) <
-			sqrt(b.x * b.x + b.y * b.y);    });
-
-		reprojection_error[m] = 0;
-		for (int i = 0; i < new_points.size(); i++)
-			reprojection_error[m] += sqrt(((new_points[i].x - cur_points2d.back()[i].x) * (new_points[i].x - cur_points2d.back()[i].x)) +
-			((new_points[i].y - cur_points2d.back()[i].y) * (new_points[i].y - cur_points2d.back()[i].y)));
-		cout << reprojection_error[m] << endl;
-	}
-	cout << "possible solution: " << reprojection_error.size() << endl;
-	size_t ind_min_reprojection_err = 0;
-	float min = numeric_limits<float>::max();
-	for (size_t i = 0; i < reprojection_error.size(); i++)
-	{
-		if (reprojection_error[i] < min)
-		{
-			min = reprojection_error[i];
-			ind_min_reprojection_err = i;
-		}
-	}
-	cur_points3d.resize(cur_points3d.size() + 1);
-	cur_points3d[cur_points3d.size() - 1] = possible_3d_points[ind_min_reprojection_err];
-	doTracking();
-	return true;
+    std::vector<int> count_solution(rotations.size());
+    std::vector<std::vector<Point2f>> points_2d(rotations.size());
+    std::vector<std::vector<Point3f>> points_3d(rotations.size());
+
+    Mat projection1, id_mat, z;
+
+    id_mat = Mat::eye(rotations[0].size(), CV_64FC1);
+    z = Mat::zeros(translations[0].size(), CV_64FC1);
+
+    cv::sfm::projectionFromKRt(calib_mat, id_mat, z, projection1);
+    for (size_t i = 0; i < rotations.size(); i++)
+    {
+        count_solution[i] = 0;
+        Mat projection2;
+        cv::sfm::projectionFromKRt(calib_mat, rotations[i], translations[i], projection2);
+        std::cout << "rotation " << rotations[i] << std::endl;
+        cv::Mat points1Mat(2, points1.size(), CV_64FC1);
+        cv::Mat points2Mat(2, points1.size(), CV_64FC1);
+        //TODO: use reshape()
+
+        for (int j = 0; j < points1.size(); j++)
+        {
+            cv::Point2f myPoint1 = points1.at(j);
+            cv::Point2f myPoint2 = points2.at(j);
+            points1Mat.at<double>(0, j) = myPoint1.x;
+            points1Mat.at<double>(1, j) = myPoint1.y;
+            points2Mat.at<double>(0, j) = myPoint2.x;
+            points2Mat.at<double>(1, j) = myPoint2.y;
+        }
+
+        std::vector<Mat> points2d;
+        points2d.push_back(points1Mat);
+        points2d.push_back(points2Mat);
+
+        std::vector<Mat> projections;
+        projections.push_back(projection1);
+        projections.push_back(projection2);
+
+        Mat points3d_mat(3, 1, CV_64FC1);
+        Mat Rs;
+        Mat Ts;
+        cv::sfm::triangulatePoints(points2d, projections, points3d_mat);
+        std::vector<Affine3d> cam_pose;
+
+        cam_pose.push_back(Affine3d(rotations[i], translations[i]));
+        cam_pose.push_back(Affine3d(id_mat, z));
+        std::vector<Point3d> all_points;
+        for (size_t k = 0; k < points3d_mat.cols; k++)
+        {
+            all_points.push_back(Point3d(points3d_mat.at<double>(0, k),
+                                         points3d_mat.at<double>(1, k),
+                                         points3d_mat.at<double>(2, k)));
+        }
+        /*
+        viz::Viz3d window;
+
+
+        viz::WCloud cloud_wid(all_points, viz::Color::green());
+        cloud_wid.setRenderingProperty(cv::viz::POINT_SIZE, 2);
+        window.showWidget("cameras_frames_and_lines", viz::WTrajectory(cam_pose, viz::WTrajectory::BOTH, 0.1, viz::Color::red()));
+        window.showWidget("cameras_frustums", viz::WTrajectoryFrustums(cam_pose, Matx33d(calib_mat), 0.1, viz::Color::red()));
+        //window.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
+        window.showWidget("points", cloud_wid);
+        window.setViewerPose(cam_pose.back());
+        window.spin();
+        */
+        for (size_t k = 0; k < points3d_mat.cols; k++)
+        {
+            Mat X(3, 1, CV_64FC1);
+            X.at<double>(0, 0) = points3d_mat.at<double>(0, k);
+            X.at<double>(1, 0) = points3d_mat.at<double>(1, k);
+            X.at<double>(2, 0) = points3d_mat.at<double>(2, k);
+            double d1 = sfm::depth(id_mat, z, X);
+            double d2 = sfm::depth(rotations[i], translations[i], X);
+
+            // Test if point is front to the two cameras.
+            if (d1 > 0 && d2 > 0)
+            {
+                count_solution[i]++;
+                points_2d[i].push_back(points2[k]);
+                points_3d[i].push_back(Point3f(X.at<double>(0, 0),
+                                               X.at<double>(1, 0),
+                                               X.at<double>(2, 0)));
+            }
+        }
+    }
+    int ind_max, prev_max;
+    if (count_solution[0] > count_solution[1])
+    {
+        ind_max = 0;
+        prev_max = 1;
+    }
+    else
+    {
+        ind_max = 1;
+        prev_max = 0;
+    }
+    std::cout << "num: " << count_solution[0] << std::endl;
+    std::cout << "num: " << count_solution[1] << std::endl;
+    for (size_t i = 2; i < count_solution.size(); i++)
+    {
+        std::cout << "num: " << count_solution[i] << std::endl;
+        if (count_solution[i] >= count_solution[ind_max])
+        {
+            prev_max = ind_max;
+            ind_max = i;
+        }
+        else if (count_solution[i] >= count_solution[prev_max])
+            prev_max = i;
+
+    }
+    ind_max = prev_max;
+    std::cout << "num: " << count_solution[ind_max] << std::endl;
+    if (count_solution[ind_max] < 7)
+        return -1;
+    //ind_max = 0;
+    cur_points2d.back() = points_2d[ind_max];
+    cur_points3d.resize(cur_points3d.size() + 1);
+    cur_points3d.back() = points_3d[ind_max];
+    return ind_max;
 }
 
-bool OrbSLAM::doTracking()
+bool OrbSLAM::reconstract(std::vector<Point2f>& points1, std::vector<Point2f>& points2,
+                          std::vector<Mat>& rotations, std::vector<Mat>& translations)
 {
-	cout << "in tracking";
-	Mat rvec(Mat::zeros(3, 1, CV_64FC1));       // output rotation vector
-	Mat tvec(Mat::zeros(3, 1, CV_64FC1));       // output translation vector
-	Mat _R_matrix(Mat::zeros(3, 1, CV_64FC1)); // rotation matrix
-	Mat _t_matrix(Mat::zeros(3, 1, CV_64FC1)); // translation matrix
-
-
-
-	int iterationsCount = 500;        // number of Ransac iterations.
-	float reprojectionError = 5.0;    // maximum allowed distance to consider it an inlier.
-	float confidence = 0.95;          // RANSAC successful confidence.
-	bool useExtrinsicGuess = false;
-
-	int flags = 0;
-	Mat inliers(Mat::zeros(1, 1, CV_64FC1));
-	cout << "3d and 2d sizes:" << cur_points3d.back().size() << " " << cur_points2d.back().size() << endl;
-	solvePnPRansac(cur_points3d.back(), cur_points2d.back(), calib_mat, dist_coeffs, rvec, tvec,
-		useExtrinsicGuess, iterationsCount, reprojectionError);
-
-
+    int solution_ind = motionChooseSolution(points1, points2, rotations, translations);
+
+
+    if (solution_ind == -1)
+    {
+        cur_points2d.resize(cur_points2d.size() - 1);
+        colors.resize(colors.size() - 1);
+        return false;
+    }
+
+    if (match_two_image)
+    {
+        Mat r = performBA(rotations[solution_ind], translations[solution_ind]);
+        Mat t;
+
+        //translations[solution_ind].at<double>(0, 0) *= -1;
+        //translations[solution_ind].at<double>(1, 0) *= -1;
+        //translations[solution_ind].at<double>(2, 0) *= -1;
+        doTracking(r, translations[solution_ind]);
+        //
+        //std::cout << new_rotation << std::endl;
+        //doTracking(rotations[solution_ind], translations[solution_ind]);
+        return true;
+
+    }
+    else
+        doTracking(rotations[solution_ind], translations[solution_ind]);
+    return true;
+}
 
-	Rodrigues(rvec, _R_matrix);                   // converts Rotation Vector to Matrix
-	_t_matrix = tvec;                            // set translation matrix
+std::vector<std::vector<Mat> > OrbSLAM::getRotationsAndTranslationsHomography(Mat& H, std::vector<Point2f>& points1,
+                                                                              std::vector<Point2f>& points2)
+{
+    std::vector<Mat> rotations, translations, normals;
+    int solutions = decomposeHomographyMat(H, calib_mat, rotations, translations, normals);
+
+    std::cout << "solution " << solutions << std::endl;
+    if (solutions == 0)
+    {
+        cur_points2d.resize(cur_points2d.size() - 1);
+        colors.resize(colors.size() - 1);
+        return std::vector<std::vector<Mat> >();
+    }
+    std::cout << normals[0] << std::endl;
+    std::vector<std::vector<Mat> >rotate_and_transl(2);
+    rotate_and_transl[0] = rotations;
+    rotate_and_transl[1] = translations;
+    return rotate_and_transl;
+}
 
-	cam_pose.push_back(Affine3d(_R_matrix, _t_matrix));
-	
+std::vector<std::vector<Mat> > OrbSLAM::getRotationsAndTranslationsFundamental(Mat& F, std::vector<Point2f>& points1,
+                                                                               std::vector<Point2f>& points2)
+{
+    Mat E = (F.t().mul(calib_mat)).mul(F);
+
+    std::vector<Mat> rotations(2);
+    Mat translations;
+
+    //sfm::motionFromEssential(E, rotations, translations);
+    decomposeEssentialMat(E, rotations[0], rotations[1], translations);
+    std::vector<std::vector<Mat> > rotate_and_transl(2);
+    rotate_and_transl[0].push_back(rotations[0]);
+    rotate_and_transl[0].push_back(rotations[0]);
+    rotate_and_transl[0].push_back(rotations[1]);
+    rotate_and_transl[0].push_back(rotations[1]);
+    Mat neg_translation(3, 1, CV_64FC1);
+    neg_translation.at<double>(0, 0) = - translations.at<double>(0, 0);
+    neg_translation.at<double>(1, 0) = -translations.at<double>(1, 0);
+    neg_translation.at<double>(2, 0) = -translations.at<double>(2, 0);
+    rotate_and_transl[1].push_back(translations);
+    rotate_and_transl[1].push_back(neg_translation);
+    rotate_and_transl[1].push_back(translations);
+    rotate_and_transl[1].push_back(neg_translation);
+    return rotate_and_transl;
 
-	vector<Point3d> all_points;
-	vector<Vec3b> all_colors;
+}
 
-	for(int i = 0; i < cur_points3d.size(); i++)
-		for(int j = 0; j < cur_points3d[i].size(); j++)
-		{
-			all_points.push_back(cur_points3d[i][j]);
-			all_colors.push_back(colors[i][j]);
-		}
-	cout << "start visualization" << endl;
-	viz::Viz3d window;
-	//viz::WCameraPosition cpw(0.25); // Coordinate axes
+Mat OrbSLAM::performBA(Mat rotation, Mat translation)
+{
+    std::cout << "In BA\n";
+    std::cout << rotation << std::endl;
+    std::vector<detail::CameraParams> cameras;
+    std::vector<Mat> rotations;
+    if (cam_pose.size() > 0)
+        rotations.push_back(Mat(cam_pose.back().rotation()));
+    else
+        rotations.push_back(rotation);
+    rotations.push_back(rotation);
+    for (size_t i = 0; i < 2; i++)
+    {
+        detail::CameraParams cam;
+        rotations[i].convertTo(rotations[i], CV_32F);
+        cam.R = rotations[i];
+        cam.t = (Mat_<double>(3, 1) << 0, 0, 0);
+        //cam.t = translation;
+        cam.ppx = calib_mat.at<double>(0, 2);
+        cam.ppy = calib_mat.at<double>(1, 2);
+        cam.focal = calib_mat.at<double>(0, 0);
+        cam.aspect = calib_mat.at<double>(1, 1) / calib_mat.at<double>(0, 0);
+
+        cameras.push_back(cam);
+    }
+
+    Ptr<detail::BundleAdjusterBase> adjuster;
+    adjuster = makePtr<detail::BundleAdjusterReproj>();
+    adjuster->setConfThresh(0.01);
+    /*
+    Mat_<uchar> refine_mask = Mat::zeros(3, 3, CV_8U);
+    refine_mask(0, 0) = 1;
+    refine_mask(0, 1) = 1;
+    refine_mask(0, 2) = 1;
+    refine_mask(1, 1) = 1;
+    refine_mask(1, 2) = 1;
+    adjuster->setRefinementMask(refine_mask);
+    */
+    std::vector<detail::ImageFeatures> features;
+    features.push_back(features_images[frames.size() - 2]);
+    features.push_back(features_images[frames.size() - 1]);
+    features[0].img_idx = 0;
+    features[1].img_idx = 1;
+    if (!(*adjuster)(features, features_matches, cameras))
+        std::cout << "Camera parameters adjusting failed." << std::endl;
+    std::cout << calib_mat.at<double>(0, 2) << " "
+              << calib_mat.at<double>(1, 2) << " "
+              << calib_mat.at<double>(0, 0) << " "
+              << calib_mat.at<double>(1, 1) / calib_mat.at<double>(0, 0) << std::endl;
+    std::cout << cameras[1].ppx << " "
+              << cameras[1].ppy << " "
+              << cameras[1].focal << " "
+              << cameras[1].aspect << std::endl;
+
+    features_matches.clear();
+    if (frames.size() == 3)
+    {
+        calib_mat.at<double>(0, 2) = cameras[1].ppx;
+        calib_mat.at<double>(1, 2) = cameras[1].ppy;
+        calib_mat.at<double>(0, 0) = cameras[1].focal;
+        calib_mat.at<double>(1, 1) = cameras[1].aspect * cameras[1].focal;
+    }
+
+    return cameras[1].R;
+}
+bool OrbSLAM::doTracking(Mat r_matrix, Mat t_matrix)
+{
 
-	//viz::WCameraPosition cpw_frustum(new_calib, 0.3, viz::Color::yellow());
-	//window.showWidget("coordinate", viz::WCoordinateSystem());
+    std::cout << "in tracking\n";
+    r_matrix.convertTo(r_matrix, CV_64F);
+    std::cout << r_matrix.type() << std::endl;
+    if (!match_two_image)
+    {
+        Mat rvec(Mat::zeros(3, 1, CV_64FC1));       // output rotation vector
+        Mat tvec(Mat::zeros(3, 1, CV_64FC1));       // output translation vector
+        Mat _R_matrix(Mat::zeros(3, 1, CV_64FC1)); // rotation matrix
+        Mat _t_matrix(Mat::zeros(3, 1, CV_64FC1)); // translation matrix
+
+
+
+        int iterationsCount = 500;        // number of Ransac iterations.
+        float reprojectionError = 5.0;    // maximum allowed distance to consider it an inlier.
+        double confidence = 0.95;          // RANSAC successful confidence.
+        bool useExtrinsicGuess = false;
+
+        int flags = 0;
+        Mat inliers(Mat::zeros(1, 1, CV_64FC1));
+        std::cout << "3d and 2d sizes:" << cur_points3d.back().size() << " "
+                  << cur_points2d.back().size() << std::endl;
+        size_t cur_ind = cur_points3d.size() - 1;
+        try
+        {
+            solvePnPRansac(cur_points3d[cur_ind], cur_points2d[cur_ind], calib_mat, dist_coeffs, rvec, tvec,
+                           useExtrinsicGuess, iterationsCount, reprojectionError, confidence, inliers);
+        }
+        catch (cv::Exception& e)
+        {
+            const char* err_msg = e.what();
+            std::cout << "exception caught: " << err_msg << std::endl;
+            cur_points2d.resize(cur_points2d.size() - 1);
+            cur_points3d.resize(cur_points3d.size() - 1);
+            colors.resize(colors.size() - 1);
+            return false;
+        }
+        std::cout << inliers.size() << std::endl;
+
+        Rodrigues(rvec, _R_matrix);                   // converts Rotation Vector to Matrix
+        _t_matrix = tvec;                            // set translation matrix
+
+        cam_pose.push_back(Affine3d(_R_matrix, _t_matrix));
+    }
+    else
+        cam_pose.push_back(Affine3d(r_matrix, t_matrix));
+    std::cout << "translation : " << cam_pose.back().translation() << std::endl;
+    //cam_pose.push_back(Affine3d(r_matrix, t_matrix));
+    std::vector<Point3d> all_points;
+    std::vector<Vec3b> all_colors;
+    for (int i = 0; i < cur_points3d.size(); i++)
+    {
+        for (int j = 0; j < cur_points3d[i].size(); j++)
+        {
+            all_points.push_back(cur_points3d[i][j]);
+            all_colors.push_back(colors[i][j]);
+        }
+
+    }
+    std::cout << "start visualization" << std::endl;
+    viz::Viz3d window;
+    //viz::WCameraPosition cpw(0.25); // Coordinate axes
+
+    //viz::WCameraPosition cpw_frustum(new_calib, 0.3, viz::Color::yellow());
+    //window.showWidget("coordinate", viz::WCoordinateSystem());
 //    window.showWidget("CPW", cpw, cam_pose);
 //used for visualization
 
-	viz::WCloud cloud_wid(all_points, all_colors);
-	cloud_wid.setRenderingProperty( cv::viz::POINT_SIZE, 5 );
-	window.showWidget("cameras_frames_and_lines", viz::WTrajectory(cam_pose, viz::WTrajectory::BOTH, 0.1, viz::Color::green()));
-	window.showWidget("cameras_frustums", viz::WTrajectoryFrustums(cam_pose, Matx33d(calib_mat), 0.1, viz::Color::yellow()));
-	//window.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
-	window.showWidget("points", cloud_wid);
-	window.setViewerPose(cam_pose.back());
-	window.spin();
-	return true;
+    viz::WCloud cloud_wid(all_points, all_colors);
+    cloud_wid.setRenderingProperty( cv::viz::POINT_SIZE, 2 );
+    window.showWidget("cameras_frames_and_lines", viz::WTrajectory(cam_pose, viz::WTrajectory::BOTH, 0.1, viz::Color::green()));
+    window.showWidget("cameras_frustums", viz::WTrajectoryFrustums(cam_pose, Matx33d(calib_mat), 0.1, viz::Color::green()));
+    //window.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose);
+    window.showWidget("points", cloud_wid);
+    window.setViewerPose(cam_pose.back());
+    window.spin();
+    return true;
 }
\ No newline at end of file