-
Angel Santamaria-Navarro authoredAngel Santamaria-Navarro authored
feature_matcher.cpp 6.47 KiB
#include "feature_matcher.h"
CFeature_Matcher::CFeature_Matcher(const std::string& _type, const std::string& _match_out_type, const CMatcher_Params& _params)
{
setAllTypes();
is_init_ = init(_type, _params);
if (!is_init_)
{
std::cerr << "[Feature Matcher]: Something went wrong during initialization! Feature Matcher not initialized."
<< std::endl;
}
}
CFeature_Matcher::CFeature_Matcher(void)
{
setAllTypes();
}
CFeature_Matcher::~CFeature_Matcher(void)
{
}
void CFeature_Matcher::setAllTypes(void)
{
// Define all types
std::vector<std::string> types;
types += "FlannBased", "BruteForce", "BruteForce-L1", "BruteForce-Hamming", "BruteForce-Hamming(2)";
types_.set(types);
type_ = "BruteForce"; // Default value
// Define all match output variants
std::vector<std::string> out_types;
out_types += "Match", "knnMatch", "radiusMatch";
match_search_types_.set(out_types);
match_search_type_ = "knnMatch"; // Default value
}
std::vector<std::string> CFeature_Matcher::listSearchTypes(void)
{
return match_search_types_.list();
}
void CFeature_Matcher::getSearchType(int& _type)
{
_type = match_search_types_(match_search_type_);
}
void CFeature_Matcher::getSearchType(std::string& _type)
{
_type = match_search_type_;
}
bool CFeature_Matcher::setSearchType(const std::string& _type, const CMatcher_Params& _params)
{
// TODO: Set parameters for each matcher type
for (unsigned int ii = 0; ii < match_search_types_.size(); ++ii)
{
if (_type.compare(match_search_types_(ii))==0)
{
match_search_type_ = _type;
match_search_params_ = _params;
return true;
}
}
std::cerr << "[Feature Matcher]: matcher output type " << _type << " doesn't exist !" << std::endl;
return false;
}
bool CFeature_Matcher::init(const std::string& _type, const CMatcher_Params& _params)
{
if (is_init_)
{
std::cerr
<< "[CFeature_Matcher::init]: Matcher already initialized."
<< std::endl;
return false;
}
std::cout << _type << std::endl;
// TODO: Set parameters for each matcher type
if (_type.compare(types_(0))==0)
{
feature_matcher_ = cv::DescriptorMatcher::create(_type);
type_ = types_(0);
}
else if (_type.compare(types_(1))==0)
{
feature_matcher_ = cv::DescriptorMatcher::create(_type);
type_ = types_(1);
}
else if (_type.compare(types_(2))==0)
{
feature_matcher_ = cv::DescriptorMatcher::create(_type);
type_ = types_(2);
}
else if (_type.compare(types_(3))==0)
{
feature_matcher_ = cv::DescriptorMatcher::create(_type);
type_ = types_(3);
}
else if (_type.compare(types_(4))==0)
{
feature_matcher_ = cv::DescriptorMatcher::create(_type);
type_ = types_(4);
}
else
{
std::cerr << "[Feature Matcher]: mathcer_type " << _type << " doesn't exist !" << std::endl;
return false;
}
is_init_ = true;
return true;
}
// TODO: Match features and process matches (e.g. https://github.com/kipr/opencv/blob/master/samples/cpp/detector_descriptor_matcher_evaluation.cpp)
void CFeature_Matcher::match(const cv::Mat& _desc1, const cv::Mat& _desc2, std::vector<cv::DMatch>& matches)
{
std::cout << __LINE__ << std::endl;
if (!is_init_)
std::cerr << "[CFeature_Matcher::match]: Matcher non initialized." << std::endl;
if (match_search_type_.compare(match_search_types_(0))==0)
{
clock_t tStart = clock();
// TODO: use parameters related with the search type (match_search_params_)
std::cout << __LINE__ << " " << _desc1.size() << " " << _desc2.size() << std::endl;
if (!_desc1.empty() && !_desc2.empty())
feature_matcher_->match( _desc1, _desc2, matches);
comp_time_ = (double)(clock() - tStart) / CLOCKS_PER_SEC;
}
else
std::cerr << "[CFeature_Matcher::match]: The selected matcher output is different than your object." << std::endl;
}
// TODO: Match features and process matches (e.g. https://github.com/kipr/opencv/blob/master/samples/cpp/detector_descriptor_matcher_evaluation.cpp)
void CFeature_Matcher::match(const cv::Mat& _desc1, const cv::Mat& _desc2, std::vector< std::vector<cv::DMatch> >& matches)
{
if (!is_init_)
std::cerr << "[CFeature_Matcher::match]: Matcher non initialized." << std::endl;
if (match_search_type_.compare(match_search_types_(1))==0)// knn match
{
clock_t tStart = clock();
// TODO: use parameters related with the search type (match_search_params_)
if (!_desc1.empty() && !_desc2.empty())
feature_matcher_->knnMatch(_desc1, _desc2, matches, 2);
comp_time_ = (double)(clock() - tStart) / CLOCKS_PER_SEC;
}
else if (match_search_type_.compare(match_search_types_(2))==0) // radius match
{
clock_t tStart = clock();
// TODO: use parameters related with the search type (match_search_params_)
if (!_desc1.empty() && !_desc2.empty())
feature_matcher_->radiusMatch(_desc1, _desc2, matches, 2);
comp_time_ = (double)(clock() - tStart) / CLOCKS_PER_SEC;
}
else
std::cerr << "[CFeature_Matcher::match]: The selected matcher output is different than your object." << std::endl;
}
void CFeature_Matcher::filterMatches(const KeyPointVector& _kpts1,const KeyPointVector& _kpts2, const std::vector< std::vector<cv::DMatch> >& _dirty, const int& _img_width, const int& _img_height, std::vector<cv::DMatch>& _filtered_matches, KeyPointVector& _filtered_kpts)
{
//only 25% of maximum of possible distance
double tresholdDist = 0.25 * sqrt(double(_img_height*_img_height + _img_width*_img_width));
std::vector< cv::DMatch > good_matches2;
_filtered_matches.reserve(_dirty.size());
for (size_t ii = 0; ii < _dirty.size(); ++ii)
{
for (unsigned int jj = 0; jj < _dirty[ii].size(); jj++)
{
cv::Point2f from = _kpts1[_dirty[ii][jj].queryIdx].pt;
cv::Point2f to = _kpts2[_dirty[ii][jj].trainIdx].pt;
//calculate local distance for each possible match
double dist = std::sqrt((from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y));
//save as best match if local distance is in specified area and on same height
if (dist < tresholdDist && std::abs(from.y-to.y)<5)
{
_filtered_matches.push_back(_dirty[ii][jj]);
cv::KeyPoint kpt = cv::KeyPoint(to,1);
_filtered_kpts.push_back(kpt);
jj = _dirty[ii].size();
}
}
}
}