Path: blob/master/modules/features2d/src/keypoint.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2008, Willow Garage Inc., all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#include "precomp.hpp"4243namespace cv44{4546struct KeypointResponseGreaterThanThreshold47{48KeypointResponseGreaterThanThreshold(float _value) :49value(_value)50{51}52inline bool operator()(const KeyPoint& kpt) const53{54return kpt.response >= value;55}56float value;57};5859struct KeypointResponseGreater60{61inline bool operator()(const KeyPoint& kp1, const KeyPoint& kp2) const62{63return kp1.response > kp2.response;64}65};6667// takes keypoints and culls them by the response68void KeyPointsFilter::retainBest(std::vector<KeyPoint>& keypoints, int n_points)69{70//this is only necessary if the keypoints size is greater than the number of desired points.71if( n_points >= 0 && keypoints.size() > (size_t)n_points )72{73if (n_points==0)74{75keypoints.clear();76return;77}78//first use nth element to partition the keypoints into the best and worst.79std::nth_element(keypoints.begin(), keypoints.begin() + n_points, keypoints.end(), KeypointResponseGreater());80//this is the boundary response, and in the case of FAST may be ambiguous81float ambiguous_response = keypoints[n_points - 1].response;82//use std::partition to grab all of the keypoints with the boundary response.83std::vector<KeyPoint>::const_iterator new_end =84std::partition(keypoints.begin() + n_points, keypoints.end(),85KeypointResponseGreaterThanThreshold(ambiguous_response));86//resize the keypoints, given this new end point. nth_element and partition reordered the points inplace87keypoints.resize(new_end - keypoints.begin());88}89}9091struct RoiPredicate92{93RoiPredicate( const Rect& _r ) : r(_r)94{}9596bool operator()( const KeyPoint& keyPt ) const97{98return !r.contains( keyPt.pt );99}100101Rect r;102};103104void KeyPointsFilter::runByImageBorder( std::vector<KeyPoint>& keypoints, Size imageSize, int borderSize )105{106if( borderSize > 0)107{108if (imageSize.height <= borderSize * 2 || imageSize.width <= borderSize * 2)109keypoints.clear();110else111keypoints.erase( std::remove_if(keypoints.begin(), keypoints.end(),112RoiPredicate(Rect(Point(borderSize, borderSize),113Point(imageSize.width - borderSize, imageSize.height - borderSize)))),114keypoints.end() );115}116}117118struct SizePredicate119{120SizePredicate( float _minSize, float _maxSize ) : minSize(_minSize), maxSize(_maxSize)121{}122123bool operator()( const KeyPoint& keyPt ) const124{125float size = keyPt.size;126return (size < minSize) || (size > maxSize);127}128129float minSize, maxSize;130};131132void KeyPointsFilter::runByKeypointSize( std::vector<KeyPoint>& keypoints, float minSize, float maxSize )133{134CV_Assert( minSize >= 0 );135CV_Assert( maxSize >= 0);136CV_Assert( minSize <= maxSize );137138keypoints.erase( std::remove_if(keypoints.begin(), keypoints.end(), SizePredicate(minSize, maxSize)),139keypoints.end() );140}141142class MaskPredicate143{144public:145MaskPredicate( const Mat& _mask ) : mask(_mask) {}146bool operator() (const KeyPoint& key_pt) const147{148return mask.at<uchar>( (int)(key_pt.pt.y + 0.5f), (int)(key_pt.pt.x + 0.5f) ) == 0;149}150151private:152const Mat mask;153MaskPredicate& operator=(const MaskPredicate&);154};155156void KeyPointsFilter::runByPixelsMask( std::vector<KeyPoint>& keypoints, const Mat& mask )157{158CV_INSTRUMENT_REGION();159160if( mask.empty() )161return;162163keypoints.erase(std::remove_if(keypoints.begin(), keypoints.end(), MaskPredicate(mask)), keypoints.end());164}165166struct KeyPoint_LessThan167{168KeyPoint_LessThan(const std::vector<KeyPoint>& _kp) : kp(&_kp) {}169bool operator()(int i, int j) const170{171const KeyPoint& kp1 = (*kp)[i];172const KeyPoint& kp2 = (*kp)[j];173if( kp1.pt.x != kp2.pt.x )174return kp1.pt.x < kp2.pt.x;175if( kp1.pt.y != kp2.pt.y )176return kp1.pt.y < kp2.pt.y;177if( kp1.size != kp2.size )178return kp1.size > kp2.size;179if( kp1.angle != kp2.angle )180return kp1.angle < kp2.angle;181if( kp1.response != kp2.response )182return kp1.response > kp2.response;183if( kp1.octave != kp2.octave )184return kp1.octave > kp2.octave;185if( kp1.class_id != kp2.class_id )186return kp1.class_id > kp2.class_id;187188return i < j;189}190const std::vector<KeyPoint>* kp;191};192193void KeyPointsFilter::removeDuplicated( std::vector<KeyPoint>& keypoints )194{195int i, j, n = (int)keypoints.size();196std::vector<int> kpidx(n);197std::vector<uchar> mask(n, (uchar)1);198199for( i = 0; i < n; i++ )200kpidx[i] = i;201std::sort(kpidx.begin(), kpidx.end(), KeyPoint_LessThan(keypoints));202for( i = 1, j = 0; i < n; i++ )203{204KeyPoint& kp1 = keypoints[kpidx[i]];205KeyPoint& kp2 = keypoints[kpidx[j]];206if( kp1.pt.x != kp2.pt.x || kp1.pt.y != kp2.pt.y ||207kp1.size != kp2.size || kp1.angle != kp2.angle )208j = i;209else210mask[kpidx[i]] = 0;211}212213for( i = j = 0; i < n; i++ )214{215if( mask[i] )216{217if( i != j )218keypoints[j] = keypoints[i];219j++;220}221}222keypoints.resize(j);223}224225struct KeyPoint12_LessThan226{227bool operator()(const KeyPoint &kp1, const KeyPoint &kp2) const228{229if( kp1.pt.x != kp2.pt.x )230return kp1.pt.x < kp2.pt.x;231if( kp1.pt.y != kp2.pt.y )232return kp1.pt.y < kp2.pt.y;233if( kp1.size != kp2.size )234return kp1.size > kp2.size;235if( kp1.angle != kp2.angle )236return kp1.angle < kp2.angle;237if( kp1.response != kp2.response )238return kp1.response > kp2.response;239if( kp1.octave != kp2.octave )240return kp1.octave > kp2.octave;241return kp1.class_id > kp2.class_id;242}243};244245void KeyPointsFilter::removeDuplicatedSorted( std::vector<KeyPoint>& keypoints )246{247int i, j, n = (int)keypoints.size();248249if (n < 2) return;250251std::sort(keypoints.begin(), keypoints.end(), KeyPoint12_LessThan());252253for( i = 0, j = 1; j < n; ++j )254{255const KeyPoint& kp1 = keypoints[i];256const KeyPoint& kp2 = keypoints[j];257if( kp1.pt.x != kp2.pt.x || kp1.pt.y != kp2.pt.y ||258kp1.size != kp2.size || kp1.angle != kp2.angle ) {259keypoints[++i] = keypoints[j];260}261}262keypoints.resize(i + 1);263}264265}266267268