Skip to content

Instantly share code, notes, and snippets.

@cashiwamochi
Last active September 11, 2017 16:34
Show Gist options
  • Save cashiwamochi/912c0a10f9f7655800cc125bff82c6df to your computer and use it in GitHub Desktop.
Save cashiwamochi/912c0a10f9f7655800cc125bff82c6df to your computer and use it in GitHub Desktop.
This function is used to do feature points matching based on epipolar-line search. It does also ratio-cross-check-test.
#include <iostream>
#include <vector>
#include <cmath>
#include <opencv2/opencv.hpp>
using namespace std;
template <typename T>
static float distancePointLine(const cv::Point_<T> point, const cv::Vec<T,3>& line)
{
//http://www.hasper.info/opencv-draw-epipolar-lines/
// a little changed
return fabsf(line(0)*point.x + line(1)*point.y + line(2))
/ sqrt(line(0)*line(0)+line(1)*line(1));
}
vector< cv::DMatch > epipolar_match
(
const cv::Mat& F,
const cv::Mat& image1,
const cv::Mat& desc1,
const vector<cv::KeyPoint>& kpts1,
const cv::Mat& image2,
const cv::Mat& desc2,
const vector<cv::KeyPoint>& kpts2
)
{
vector<cv::DMatch> epipolar_match12_vec;
vector<cv::Point2f> kpts1_pt_vec, kpts2_pt_vec;
for(int i = 0; i < kpts1.size(); i++)
kpts1_pt_vec.push_back(kpts1[i].pt);
for(int i = 0; i < kpts2.size(); i++)
kpts2_pt_vec.push_back(kpts2[i].pt);
vector<cv::Vec3f> epipolar_lines_on_img1, epipolar_lines_on_img2;
cv::computeCorrespondEpilines(kpts1_pt_vec , 1, F, epipolar_lines_on_img2);
cv::computeCorrespondEpilines(kpts2_pt_vec , 2, F, epipolar_lines_on_img1);
assert(kpts1_pt_vec.size() == epipolar_lines_on_img2.size() and
kpts2_pt_vec.size() == epipolar_lines_on_img1.size());
// epipolar feature points matching
const float inlier_distance = 3.f;
const double inlier_ratio = 0.8;
vector<cv::DMatch> match_1to2;
for(int i = 0; i < kpts1.size(); i++) {
double best_distance_score = 10000000000000;
double second_best_distance_score = 1000000000000;
cv::DMatch m;
for(int j = 0; j < kpts2.size(); j++) {
if(distancePointLine(kpts2[j].pt, epipolar_lines_on_img2[i]) < inlier_distance) {
double dist = cv::norm(desc1.row(i), desc2.row(j), cv::NORM_L2, cv::noArray());
if(dist < best_distance_score) {
best_distance_score = dist;
m = cv::DMatch(i, j, (float)dist);
}
else if(dist < second_best_distance_score) {
second_best_distance_score = dist;
}
}
}
if(best_distance_score / second_best_distance_score < inlier_ratio) {
match_1to2.push_back(m);
}
else {
match_1to2.push_back(cv::DMatch(-1, -1, -114514.f));
}
}
vector<cv::DMatch> match_2to1;
for(int i = 0; i < kpts2.size(); i++) {
double best_distance_score = 10000000000000;
double second_best_distance_score = 1000000000000;
cv::DMatch m;
for(int j = 0; j < kpts1.size(); j++) {
if(distancePointLine(kpts1[j].pt, epipolar_lines_on_img1[i]) < inlier_distance) {
double dist = cv::norm(desc2.row(i), desc1.row(j), cv::NORM_L2, cv::noArray());
if(dist < best_distance_score) {
best_distance_score = dist;
m = cv::DMatch(i, j, (float)dist);
}
else if(dist < second_best_distance_score) {
second_best_distance_score = dist;
}
}
}
if(best_distance_score / second_best_distance_score < inlier_ratio) {
match_2to1.push_back(m);
}
else {
match_2to1.push_back(cv::DMatch(-1, -1, -114514.f));
}
}
// cross check
for(int i = 0; i < match_1to2.size(); i++) {
if( match_1to2[i].queryIdx != -1
and
match_1to2[i].trainIdx != -1
and
match_1to2[i].queryIdx == match_2to1[match_1to2[i].trainIdx].trainIdx )
{
epipolar_match12_vec.push_back(match_1to2[i]);
}
}
if(true) {
cv::Mat im;
cv::drawMatches(image1.clone(), kpts1, image2.clone(), kpts2, epipolar_match12_vec, im);
// cv::imshow("epipolar_match", im);
// cv::waitKey(0);
cv::imwrite("epipolar_match.png", im);
}
return epipolar_match12_vec;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment