modified features2d interface; added algorithmic test for DescriptorMatcher; added sample on matching to many images

This commit is contained in:
Maria Dimashova
2010-10-29 08:44:42 +00:00
parent 0d3809d0b1
commit 69e329c9fd
16 changed files with 1786 additions and 920 deletions

View File

@@ -108,11 +108,11 @@ void BOWImgDescriptorExtractor::setVocabulary( const Mat& _vocabulary )
{
dmatcher->clear();
vocabulary = _vocabulary;
dmatcher->add( vocabulary );
dmatcher->add( vector<Mat>(1, vocabulary) );
}
void BOWImgDescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints, Mat& imgDescriptor,
vector<vector<int> >* pointIdxsOfClusters ) const
vector<vector<int> >* pointIdxsOfClusters )
{
imgDescriptor.release();
@@ -140,8 +140,8 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& key
float *dptr = (float*)imgDescriptor.data;
for( size_t i = 0; i < matches.size(); i++ )
{
int queryIdx = matches[i].indexQuery;
int trainIdx = matches[i].indexTrain; // cluster index
int queryIdx = matches[i].queryIdx;
int trainIdx = matches[i].trainIdx; // cluster index
CV_Assert( queryIdx == (int)i );
dptr[trainIdx] = dptr[trainIdx] + 1.f;

View File

@@ -67,6 +67,13 @@ struct RoiPredicate
float minX, minY, maxX, maxY;
};
void DescriptorExtractor::compute( const vector<Mat>& imageCollection, vector<vector<KeyPoint> >& pointCollection, vector<Mat>& descCollection ) const
{
descCollection.resize( imageCollection.size() );
for( size_t i = 0; i < imageCollection.size(); i++ )
compute( imageCollection[i], pointCollection[i], descCollection[i] );
}
void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
Size imageSize, int borderPixels )
{

View File

@@ -61,6 +61,13 @@ struct MaskPredicate
const Mat& mask;
};
void FeatureDetector::detect(const vector<Mat>& imageCollection, vector<vector<KeyPoint> >& pointCollection, const vector<Mat>& masks ) const
{
pointCollection.resize( imageCollection.size() );
for( size_t i = 0; i < imageCollection.size(); i++ )
detect( imageCollection[i], pointCollection[i], masks.empty() ? Mat() : masks[i] );
}
void FeatureDetector::removeInvalidPoints( const Mat& mask, vector<KeyPoint>& keypoints )
{
if( mask.empty() )
@@ -88,7 +95,7 @@ void FastFeatureDetector::write (FileStorage& fs) const
fs << "nonmaxSuppression" << nonmaxSuppression;
}
void FastFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints) const
void FastFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
@@ -126,8 +133,7 @@ void GoodFeaturesToTrackDetector::write (FileStorage& fs) const
fs << "k" << k;
}
void GoodFeaturesToTrackDetector::detectImpl( const Mat& image, const Mat& mask,
vector<KeyPoint>& keypoints ) const
void GoodFeaturesToTrackDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
@@ -192,7 +198,7 @@ void MserFeatureDetector::write (FileStorage& fs) const
}
void MserFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const
void MserFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
vector<vector<Point> > msers;
@@ -246,7 +252,7 @@ void StarFeatureDetector::write (FileStorage& fs) const
fs << "suppressNonmaxSize" << star.suppressNonmaxSize;
}
void StarFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints) const
void StarFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
@@ -291,8 +297,7 @@ void SiftFeatureDetector::write (FileStorage& fs) const
}
void SiftFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
vector<KeyPoint>& keypoints) const
void SiftFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
@@ -325,8 +330,7 @@ void SurfFeatureDetector::write (FileStorage& fs) const
fs << "octaveLayers" << surf.nOctaveLayers;
}
void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
vector<KeyPoint>& keypoints) const
void SurfFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
@@ -337,7 +341,7 @@ void SurfFeatureDetector::detectImpl( const Mat& image, const Mat& mask,
/*
* DenseFeatureDetector
*/
void DenseFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const
void DenseFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
keypoints.clear();
@@ -388,8 +392,7 @@ void keepStrongest( int N, vector<KeyPoint>& keypoints )
}
}
void GridAdaptedFeatureDetector::detectImpl( const Mat &image, const Mat &mask,
vector<KeyPoint> &keypoints ) const
void GridAdaptedFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
keypoints.clear();
keypoints.reserve(maxTotalKeypoints);
@@ -428,7 +431,7 @@ PyramidAdaptedFeatureDetector::PyramidAdaptedFeatureDetector( const Ptr<FeatureD
: detector(_detector), levels(_levels)
{}
void PyramidAdaptedFeatureDetector::detectImpl( const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints ) const
void PyramidAdaptedFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat src = image;
for( int l = 0, multiplier = 1; l <= levels; ++l, multiplier *= 2 )

View File

@@ -165,33 +165,6 @@ static inline void _drawMatch( Mat& outImg, Mat& outImg1, Mat& outImg2 ,
color, 1, CV_AA, draw_shift_bits );
}
void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2,const vector<KeyPoint>& keypoints2,
const vector<int>& matches1to2, Mat& outImg,
const Scalar& matchColor, const Scalar& singlePointColor,
const vector<char>& matchesMask, int flags )
{
if( matches1to2.size() != keypoints1.size() )
CV_Error( CV_StsBadSize, "matches1to2 must have the same size as keypoints1" );
if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() )
CV_Error( CV_StsBadSize, "matchesMask must have the same size as matches1to2" );
Mat outImg1, outImg2;
_prepareImgAndDrawKeypoints( img1, keypoints1, img2, keypoints2,
outImg, outImg1, outImg2, singlePointColor, flags );
// draw matches
for( size_t i1 = 0; i1 < keypoints1.size(); i1++ )
{
int i2 = matches1to2[i1];
if( (matchesMask.empty() || matchesMask[i1] ) && i2 >= 0 )
{
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags );
}
}
}
void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
const Mat& img2, const vector<KeyPoint>& keypoints2,
const vector<DMatch>& matches1to2, Mat& outImg,
@@ -208,8 +181,8 @@ void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
// draw matches
for( size_t m = 0; m < matches1to2.size(); m++ )
{
int i1 = matches1to2[m].indexQuery;
int i2 = matches1to2[m].indexTrain;
int i1 = matches1to2[m].queryIdx;
int i2 = matches1to2[m].trainIdx;
if( matchesMask.empty() || matchesMask[m] )
{
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
@@ -236,8 +209,8 @@ void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
{
for( size_t j = 0; j < matches1to2[i].size(); j++ )
{
int i1 = matches1to2[i][j].indexQuery;
int i2 = matches1to2[i][j].indexTrain;
int i1 = matches1to2[i][j].queryIdx;
int i2 = matches1to2[i][j].trainIdx;
if( matchesMask.empty() || matchesMask[i][j] )
{
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];

View File

@@ -517,10 +517,10 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
vector<KeyPoint>& keypoints1, vector<KeyPoint>& keypoints2,
vector<vector<DMatch> >* _matches1to2, vector<vector<uchar> >* _correctMatches1to2Mask,
vector<Point2f>& recallPrecisionCurve,
const Ptr<GenericDescriptorMatch>& _dmatch )
const Ptr<GenericDescriptorMatcher>& _dmatcher )
{
Ptr<GenericDescriptorMatch> dmatch = _dmatch;
dmatch->clear();
Ptr<GenericDescriptorMatcher> dmatcher = _dmatcher;
dmatcher->clear();
vector<vector<DMatch> > *matches1to2, buf1;
matches1to2 = _matches1to2 != 0 ? _matches1to2 : &buf1;
@@ -531,7 +531,7 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
if( keypoints1.empty() )
CV_Error( CV_StsBadArg, "keypoints1 must be no empty" );
if( matches1to2->empty() && dmatch.empty() )
if( matches1to2->empty() && dmatcher.empty() )
CV_Error( CV_StsBadArg, "dmatch must be no empty when matches1to2 is empty" );
bool computeKeypoints2ByPrj = keypoints2.empty();
@@ -543,10 +543,8 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
if( matches1to2->empty() || computeKeypoints2ByPrj )
{
dmatch->clear();
dmatch->add( img2, keypoints2 );
// TODO: use more sophisticated strategy to choose threshold
dmatch->match( img1, keypoints1, *matches1to2, std::numeric_limits<float>::max() );
dmatcher->clear();
dmatcher->radiusMatch( img1, keypoints1, img2, keypoints2, *matches1to2, std::numeric_limits<float>::max() );
}
float repeatability;
int correspCount;
@@ -559,8 +557,8 @@ void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, con
(*correctMatches1to2Mask)[i].resize((*matches1to2)[i].size());
for( size_t j = 0;j < (*matches1to2)[i].size(); j++ )
{
int indexQuery = (*matches1to2)[i][j].indexQuery;
int indexTrain = (*matches1to2)[i][j].indexTrain;
int indexQuery = (*matches1to2)[i][j].queryIdx;
int indexTrain = (*matches1to2)[i][j].trainIdx;
(*correctMatches1to2Mask)[i][j] = thresholdedOverlapMask.at<uchar>( indexQuery, indexTrain );
}
}

File diff suppressed because it is too large Load Diff