Skip to content
Snippets Groups Projects
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();
	        }
	    }
	}
}