diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 70fe4094b0..a00fbc4976 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -117,6 +117,10 @@ public: * Remove duplicated keypoints. */ static void removeDuplicated( std::vector& keypoints ); + /* + * Remove duplicated keypoints and sort the remaining keypoints + */ + static void removeDuplicatedSorted( std::vector& keypoints ); /* * Retain the specified number of the best keypoints (according to the response) diff --git a/modules/features2d/src/keypoint.cpp b/modules/features2d/src/keypoint.cpp index 0cf7ae0571..a2bb511d36 100644 --- a/modules/features2d/src/keypoint.cpp +++ b/modules/features2d/src/keypoint.cpp @@ -221,4 +221,44 @@ void KeyPointsFilter::removeDuplicated( std::vector& keypoints ) keypoints.resize(j); } +struct KeyPoint12_LessThan +{ + bool operator()(const KeyPoint &kp1, const KeyPoint &kp2) const + { + if( kp1.pt.x != kp2.pt.x ) + return kp1.pt.x < kp2.pt.x; + if( kp1.pt.y != kp2.pt.y ) + return kp1.pt.y < kp2.pt.y; + if( kp1.size != kp2.size ) + return kp1.size > kp2.size; + if( kp1.angle != kp2.angle ) + return kp1.angle < kp2.angle; + if( kp1.response != kp2.response ) + return kp1.response > kp2.response; + if( kp1.octave != kp2.octave ) + return kp1.octave > kp2.octave; + return kp1.class_id > kp2.class_id; + } +}; + +void KeyPointsFilter::removeDuplicatedSorted( std::vector& keypoints ) +{ + int i, j, n = (int)keypoints.size(); + + if (n < 2) return; + + std::sort(keypoints.begin(), keypoints.end(), KeyPoint12_LessThan()); + + for( i = 0, j = 1; j < n; ++j ) + { + const KeyPoint& kp1 = keypoints[i]; + const KeyPoint& kp2 = keypoints[j]; + if( kp1.pt.x != kp2.pt.x || kp1.pt.y != kp2.pt.y || + kp1.size != kp2.size || kp1.angle != kp2.angle ) { + keypoints[++i] = keypoints[j]; + } + } + keypoints.resize(i + 1); +} + }