refactored features2d and sample on matching to many images

This commit is contained in:
Maria Dimashova
2010-11-22 18:27:08 +00:00
parent cf0d9da643
commit e406dfee44
13 changed files with 1619 additions and 1025 deletions

View File

@@ -71,11 +71,23 @@ Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPo
/****************************************************************************************\
* DescriptorMatcher *
\****************************************************************************************/
void DescriptorMatcher::DescriptorCollection::set( const vector<Mat>& descCollection )
DescriptorMatcher::DescriptorCollection::DescriptorCollection()
{}
DescriptorMatcher::DescriptorCollection::DescriptorCollection( const DescriptorCollection& collection )
{
mergedDescriptors = collection.mergedDescriptors.clone();
copy( collection.startIdxs.begin(), collection.startIdxs.begin(), startIdxs.begin() );
}
DescriptorMatcher::DescriptorCollection::~DescriptorCollection()
{}
void DescriptorMatcher::DescriptorCollection::set( const vector<Mat>& descriptors )
{
clear();
size_t imageCount = descCollection.size();
size_t imageCount = descriptors.size();
CV_Assert( imageCount > 0 );
startIdxs.resize( imageCount );
@@ -86,35 +98,35 @@ void DescriptorMatcher::DescriptorCollection::set( const vector<Mat>& descCollec
for( size_t i = 1; i < imageCount; i++ )
{
int s = 0;
if( !descCollection[i-1].empty() )
if( !descriptors[i-1].empty() )
{
dim = descCollection[i-1].cols;
type = descCollection[i-1].type();
s = descCollection[i-1].rows;
dim = descriptors[i-1].cols;
type = descriptors[i-1].type();
s = descriptors[i-1].rows;
}
startIdxs[i] = startIdxs[i-1] + s;
}
if( imageCount == 1 )
{
if( descCollection[0].empty() ) return;
if( descriptors[0].empty() ) return;
dim = descCollection[0].cols;
type = descCollection[0].type();
dim = descriptors[0].cols;
type = descriptors[0].type();
}
assert( dim > 0 );
int count = startIdxs[imageCount-1] + descCollection[imageCount-1].rows;
int count = startIdxs[imageCount-1] + descriptors[imageCount-1].rows;
if( count > 0 )
{
dmatrix.create( count, dim, type );
mergedDescriptors.create( count, dim, type );
for( size_t i = 0; i < imageCount; i++ )
{
if( !descCollection[i].empty() )
if( !descriptors[i].empty() )
{
CV_Assert( descCollection[i].cols == dim && descCollection[i].type() == type );
Mat m = dmatrix.rowRange( startIdxs[i], startIdxs[i] + descCollection[i].rows );
descCollection[i].copyTo(m);
CV_Assert( descriptors[i].cols == dim && descriptors[i].type() == type );
Mat m = mergedDescriptors.rowRange( startIdxs[i], startIdxs[i] + descriptors[i].rows );
descriptors[i].copyTo(m);
}
}
}
@@ -123,7 +135,7 @@ void DescriptorMatcher::DescriptorCollection::set( const vector<Mat>& descCollec
void DescriptorMatcher::DescriptorCollection::clear()
{
startIdxs.clear();
dmatrix.release();
mergedDescriptors.release();
}
const Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int imgIdx, int localDescIdx ) const
@@ -135,10 +147,15 @@ const Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int imgIdx, in
return getDescriptor( globalIdx );
}
const Mat& DescriptorMatcher::DescriptorCollection::getDescriptors() const
{
return mergedDescriptors;
}
const Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int globalDescIdx ) const
{
CV_Assert( globalDescIdx < size() );
return dmatrix.row( globalDescIdx );
return mergedDescriptors.row( globalDescIdx );
}
void DescriptorMatcher::DescriptorCollection::getLocalIdx( int globalDescIdx, int& imgIdx, int& localDescIdx ) const
@@ -157,6 +174,11 @@ void DescriptorMatcher::DescriptorCollection::getLocalIdx( int globalDescIdx, in
localDescIdx = globalDescIdx - startIdxs[imgIdx];
}
int DescriptorMatcher::DescriptorCollection::size() const
{
return mergedDescriptors.rows;
}
/*
* DescriptorMatcher
*/
@@ -172,9 +194,17 @@ void convertMatches( const vector<vector<DMatch> >& knnMatches, vector<DMatch>&
}
}
void DescriptorMatcher::add( const vector<Mat>& descCollection )
DescriptorMatcher::~DescriptorMatcher()
{}
void DescriptorMatcher::add( const vector<Mat>& descriptors )
{
trainDescCollection.insert( trainDescCollection.end(), descCollection.begin(), descCollection.end() );
trainDescCollection.insert( trainDescCollection.end(), descriptors.begin(), descriptors.end() );
}
const vector<Mat>& DescriptorMatcher::getTrainDescriptors() const
{
return trainDescCollection;
}
void DescriptorMatcher::clear()
@@ -182,67 +212,134 @@ void DescriptorMatcher::clear()
trainDescCollection.clear();
}
void DescriptorMatcher::match( const Mat& queryDescs, const Mat& trainDescs, vector<DMatch>& matches, const Mat& mask ) const
bool DescriptorMatcher::empty() const
{
Ptr<DescriptorMatcher> tempMatcher = cloneWithoutData();
tempMatcher->add( vector<Mat>(1, trainDescs) );
tempMatcher->match( queryDescs, matches, vector<Mat>(1, mask) );
return trainDescCollection.size() == 0;
}
void DescriptorMatcher::knnMatch( const Mat& queryDescs, const Mat& trainDescs, vector<vector<DMatch> >& matches, int knn,
void DescriptorMatcher::train()
{}
void DescriptorMatcher::match( const Mat& queryDescriptors, const Mat& trainDescriptors, vector<DMatch>& matches, const Mat& mask ) const
{
Ptr<DescriptorMatcher> tempMatcher = clone(true);
tempMatcher->add( vector<Mat>(1, trainDescriptors) );
tempMatcher->match( queryDescriptors, matches, vector<Mat>(1, mask) );
}
void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, vector<vector<DMatch> >& matches, int knn,
const Mat& mask, bool compactResult ) const
{
Ptr<DescriptorMatcher> tempMatcher = cloneWithoutData();
tempMatcher->add( vector<Mat>(1, trainDescs) );
tempMatcher->knnMatch( queryDescs, matches, knn, vector<Mat>(1, mask), compactResult );
Ptr<DescriptorMatcher> tempMatcher = clone(true);
tempMatcher->add( vector<Mat>(1, trainDescriptors) );
tempMatcher->knnMatch( queryDescriptors, matches, knn, vector<Mat>(1, mask), compactResult );
}
void DescriptorMatcher::radiusMatch( const Mat& queryDescs, const Mat& trainDescs, vector<vector<DMatch> >& matches, float maxDistance,
void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, const Mat& trainDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
const Mat& mask, bool compactResult ) const
{
Ptr<DescriptorMatcher> tempMatcher = cloneWithoutData();
tempMatcher->add( vector<Mat>(1, trainDescs) );
tempMatcher->radiusMatch( queryDescs, matches, maxDistance, vector<Mat>(1, mask), compactResult );
Ptr<DescriptorMatcher> tempMatcher = clone(true);
tempMatcher->add( vector<Mat>(1, trainDescriptors) );
tempMatcher->radiusMatch( queryDescriptors, matches, maxDistance, vector<Mat>(1, mask), compactResult );
}
void DescriptorMatcher::match( const Mat& queryDescs, vector<DMatch>& matches, const vector<Mat>& masks )
void DescriptorMatcher::match( const Mat& queryDescriptors, vector<DMatch>& matches, const vector<Mat>& masks )
{
vector<vector<DMatch> > knnMatches;
knnMatch( queryDescs, knnMatches, 1, masks, true /*compactResult*/ );
knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ );
convertMatches( knnMatches, matches );
}
void DescriptorMatcher::knnMatch( const Mat& queryDescs, vector<vector<DMatch> >& matches, int knn,
void DescriptorMatcher::checkMasks( const vector<Mat>& masks, int queryDescriptorsCount ) const
{
if( isMaskSupported() && !masks.empty() )
{
// Check masks
size_t imageCount = trainDescCollection.size();
CV_Assert( masks.size() == imageCount );
for( size_t i = 0; i < imageCount; i++ )
{
if( !masks[i].empty() && !trainDescCollection[i].empty() )
{
CV_Assert( masks[i].rows == queryDescriptorsCount &&
masks[i].cols == trainDescCollection[i].rows &&
masks[i].type() == CV_8UC1 );
}
}
}
}
void DescriptorMatcher::knnMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& masks, bool compactResult )
{
matches.empty();
if( empty() || queryDescriptors.empty() )
return;
CV_Assert( knn > 0 );
checkMasks( masks, queryDescriptors.rows );
train();
knnMatchImpl( queryDescs, matches, knn, masks, compactResult );
knnMatchImpl( queryDescriptors, matches, knn, masks, compactResult );
}
void DescriptorMatcher::radiusMatch( const Mat& queryDescs, vector<vector<DMatch> >& matches, float maxDistance,
void DescriptorMatcher::radiusMatch( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
const vector<Mat>& masks, bool compactResult )
{
matches.empty();
if( empty() || queryDescriptors.empty() )
return;
CV_Assert( maxDistance > std::numeric_limits<float>::epsilon() );
checkMasks( masks, queryDescriptors.rows );
train();
radiusMatchImpl( queryDescs, matches, maxDistance, masks, compactResult );
radiusMatchImpl( queryDescriptors, matches, maxDistance, masks, compactResult );
}
void DescriptorMatcher::read( const FileNode& )
{}
void DescriptorMatcher::write( FileStorage& ) const
{}
bool DescriptorMatcher::isPossibleMatch( const Mat& mask, int queryIdx, int trainIdx )
{
return mask.empty() || mask.at<uchar>(queryIdx, trainIdx);
}
bool DescriptorMatcher::isMaskedOut( const vector<Mat>& masks, int queryIdx )
{
size_t outCount = 0;
for( size_t i = 0; i < masks.size(); i++ )
{
if( !masks[i].empty() && (countNonZero(masks[i].row(queryIdx)) == 0) )
outCount++;
}
return !masks.empty() && outCount == masks.size() ;
}
template<>
void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& masks, bool compactResult )
void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& masks, bool compactResult )
{
#ifndef HAVE_EIGEN2
bfKnnMatchImpl( *this, queryDescs, matches, knn, masks, compactResult );
commonKnnMatchImpl( *this, queryDescriptors, matches, knn, masks, compactResult );
#else
CV_Assert( queryDescs.type() == CV_32FC1 || queryDescs.empty() );
CV_Assert( queryDescriptors.type() == CV_32FC1 || queryDescriptors.empty() );
CV_Assert( masks.empty() || masks.size() == trainDescCollection.size() );
matches.reserve(queryDescs.rows);
matches.reserve(queryDescriptors.rows);
size_t imgCount = trainDescCollection.size();
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> e_query_t;
vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > e_trainCollection(trainDescCollection.size());
vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > e_trainNorms2(trainDescCollection.size());
cv2eigen( queryDescs.t(), e_query_t);
cv2eigen( queryDescriptors.t(), e_query_t);
for( size_t i = 0; i < trainDescCollection.size(); i++ )
{
cv2eigen( trainDescCollection[i], e_trainCollection[i] );
@@ -251,7 +348,7 @@ void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<
vector<Eigen::Matrix<float, Eigen::Dynamic, 1> > e_allDists( imgCount ); // distances between one query descriptor and all train descriptors
for( int qIdx = 0; qIdx < queryDescs.rows; qIdx++ )
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{
if( maskedOut( masks, qIdx ) )
{
@@ -265,10 +362,10 @@ void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<
for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
{
CV_Assert( masks.empty() || masks[iIdx].empty() ||
( masks[iIdx].rows == queryDescs.rows && masks[iIdx].cols == trainDescCollection[iIdx].rows &&
( masks[iIdx].rows == queryDescriptors.rows && masks[iIdx].cols == trainDescCollection[iIdx].rows &&
masks[iIdx].type() == CV_8UC1 ) );
CV_Assert( trainDescCollection[iIdx].type() == CV_32FC1 || trainDescCollection[iIdx].empty() );
CV_Assert( queryDescs.cols == trainDescCollection[iIdx].cols );
CV_Assert( queryDescriptors.cols == trainDescCollection[iIdx].cols );
e_allDists[iIdx] = e_trainCollection[iIdx] *e_query_t.col(qIdx);
e_allDists[iIdx] -= e_trainNorms2[iIdx];
@@ -315,22 +412,22 @@ void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<
}
template<>
void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescs, vector<vector<DMatch> >& matches, float maxDistance,
void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
const vector<Mat>& masks, bool compactResult )
{
#ifndef HAVE_EIGEN2
bfRadiusMatchImpl( *this, queryDescs, matches, maxDistance, masks, compactResult );
commonRadiusMatchImpl( *this, queryDescriptors, matches, maxDistance, masks, compactResult );
#else
CV_Assert( queryDescs.type() == CV_32FC1 || queryDescs.empty() );
CV_Assert( queryDescriptors.type() == CV_32FC1 || queryDescriptors.empty() );
CV_Assert( masks.empty() || masks.size() == trainDescCollection.size() );
matches.reserve(queryDescs.rows);
matches.reserve(queryDescriptors.rows);
size_t imgCount = trainDescCollection.size();
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> e_query_t;
vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > e_trainCollection(trainDescCollection.size());
vector<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> > e_trainNorms2(trainDescCollection.size());
cv2eigen( queryDescs.t(), e_query_t);
cv2eigen( queryDescriptors.t(), e_query_t);
for( size_t i = 0; i < trainDescCollection.size(); i++ )
{
cv2eigen( trainDescCollection[i], e_trainCollection[i] );
@@ -339,7 +436,7 @@ void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescs, vect
vector<Eigen::Matrix<float, Eigen::Dynamic, 1> > e_allDists( imgCount ); // distances between one query descriptor and all train descriptors
for( int qIdx = 0; qIdx < queryDescs.rows; qIdx++ )
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{
if( maskedOut( masks, qIdx ) )
{
@@ -353,10 +450,10 @@ void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescs, vect
for( size_t iIdx = 0; iIdx < imgCount; iIdx++ )
{
CV_Assert( masks.empty() || masks[iIdx].empty() ||
( masks[iIdx].rows == queryDescs.rows && masks[iIdx].cols == trainDescCollection[iIdx].rows &&
( masks[iIdx].rows == queryDescriptors.rows && masks[iIdx].cols == trainDescCollection[iIdx].rows &&
masks[iIdx].type() == CV_8UC1 ) );
CV_Assert( trainDescCollection[iIdx].type() == CV_32FC1 || trainDescCollection[iIdx].empty() );
CV_Assert( queryDescs.cols == trainDescCollection[iIdx].cols );
CV_Assert( queryDescriptors.cols == trainDescCollection[iIdx].cols );
e_allDists[iIdx] = e_trainCollection[iIdx] *e_query_t.col(qIdx);
e_allDists[iIdx] -= e_trainNorms2[iIdx];
@@ -393,12 +490,12 @@ FlannBasedMatcher::FlannBasedMatcher( const Ptr<flann::IndexParams>& _indexParam
CV_Assert( !_searchParams.empty() );
}
void FlannBasedMatcher::add( const vector<Mat>& descCollection )
void FlannBasedMatcher::add( const vector<Mat>& descriptors )
{
DescriptorMatcher::add( descCollection );
for( size_t i = 0; i < descCollection.size(); i++ )
DescriptorMatcher::add( descriptors );
for( size_t i = 0; i < descriptors.size(); i++ )
{
addedDescCount += descCollection[i].rows;
addedDescCount += descriptors[i].rows;
}
}
@@ -421,6 +518,27 @@ void FlannBasedMatcher::train()
}
}
bool FlannBasedMatcher::isMaskSupported() const
{
return false;
}
Ptr<DescriptorMatcher> FlannBasedMatcher::clone( bool emptyTrainData ) const
{
FlannBasedMatcher* matcher = new FlannBasedMatcher(indexParams, searchParams);
if( !emptyTrainData )
{
CV_Error( CV_StsNotImplemented, "deep clone functionality is not implemented, because "
"Flann::Index has not copy constructor or clone method ");
//matcher->flannIndex;
matcher->addedDescCount = addedDescCount;
matcher->mergedDescriptors = DescriptorCollection( mergedDescriptors );
transform( trainDescCollection.begin(), trainDescCollection.end(),
matcher->trainDescCollection.begin(), clone_op );
}
return matcher;
}
void FlannBasedMatcher::convertToDMatches( const DescriptorCollection& collection, const Mat& indices, const Mat& dists,
vector<vector<DMatch> >& matches )
{
@@ -440,28 +558,28 @@ void FlannBasedMatcher::convertToDMatches( const DescriptorCollection& collectio
}
}
void FlannBasedMatcher::knnMatchImpl( const Mat& queryDescs, vector<vector<DMatch> >& matches, int knn,
void FlannBasedMatcher::knnMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& /*masks*/, bool /*compactResult*/ )
{
Mat indices( queryDescs.rows, knn, CV_32SC1 );
Mat dists( queryDescs.rows, knn, CV_32FC1);
flannIndex->knnSearch( queryDescs, indices, dists, knn, *searchParams );
Mat indices( queryDescriptors.rows, knn, CV_32SC1 );
Mat dists( queryDescriptors.rows, knn, CV_32FC1);
flannIndex->knnSearch( queryDescriptors, indices, dists, knn, *searchParams );
convertToDMatches( mergedDescriptors, indices, dists, matches );
}
void FlannBasedMatcher::radiusMatchImpl( const Mat& queryDescs, vector<vector<DMatch> >& matches, float maxDistance,
void FlannBasedMatcher::radiusMatchImpl( const Mat& queryDescriptors, vector<vector<DMatch> >& matches, float maxDistance,
const vector<Mat>& /*masks*/, bool /*compactResult*/ )
{
const int count = mergedDescriptors.size(); // TODO do count as param?
Mat indices( queryDescs.rows, count, CV_32SC1, Scalar::all(-1) );
Mat dists( queryDescs.rows, count, CV_32FC1, Scalar::all(-1) );
for( int qIdx = 0; qIdx < queryDescs.rows; qIdx++ )
Mat indices( queryDescriptors.rows, count, CV_32SC1, Scalar::all(-1) );
Mat dists( queryDescriptors.rows, count, CV_32FC1, Scalar::all(-1) );
for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
{
Mat queryDescsRow = queryDescs.row(qIdx);
Mat queryDescriptorsRow = queryDescriptors.row(qIdx);
Mat indicesRow = indices.row(qIdx);
Mat distsRow = dists.row(qIdx);
flannIndex->radiusSearch( queryDescsRow, indicesRow, distsRow, maxDistance*maxDistance, *searchParams );
flannIndex->radiusSearch( queryDescriptorsRow, indicesRow, distsRow, maxDistance*maxDistance, *searchParams );
}
convertToDMatches( mergedDescriptors, indices, dists, matches );
@@ -507,6 +625,22 @@ Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherT
/*
* KeyPointCollection
*/
GenericDescriptorMatcher::KeyPointCollection::KeyPointCollection() : pointCount(0)
{}
GenericDescriptorMatcher::KeyPointCollection::KeyPointCollection( const KeyPointCollection& collection )
{
pointCount = collection.pointCount;
transform( collection.images.begin(), collection.images.end(), images.begin(), clone_op );
keypoints.resize( collection.keypoints.size() );
for( size_t i = 0; i < keypoints.size(); i++ )
copy( collection.keypoints[i].begin(), collection.keypoints[i].end(), keypoints[i].begin() );
copy( collection.startIndices.begin(), collection.startIndices.end(), startIndices.begin() );
}
void GenericDescriptorMatcher::KeyPointCollection::add( const vector<Mat>& _images,
const vector<vector<KeyPoint> >& _points )
{
@@ -514,9 +648,9 @@ void GenericDescriptorMatcher::KeyPointCollection::add( const vector<Mat>& _imag
CV_Assert( _images.size() == _points.size() );
images.insert( images.end(), _images.begin(), _images.end() );
points.insert( points.end(), _points.begin(), _points.end() );
keypoints.insert( keypoints.end(), _points.begin(), _points.end() );
for( size_t i = 0; i < _points.size(); i++ )
size += _points[i].size();
pointCount += _points[i].size();
size_t prevSize = startIndices.size(), addSize = _images.size();
startIndices.resize( prevSize + addSize );
@@ -524,37 +658,58 @@ void GenericDescriptorMatcher::KeyPointCollection::add( const vector<Mat>& _imag
if( prevSize == 0 )
startIndices[prevSize] = 0; //first
else
startIndices[prevSize] = startIndices[prevSize-1] + points[prevSize-1].size();
startIndices[prevSize] = startIndices[prevSize-1] + keypoints[prevSize-1].size();
for( size_t i = prevSize + 1; i < prevSize + addSize; i++ )
{
startIndices[i] = startIndices[i - 1] + points[i - 1].size();
startIndices[i] = startIndices[i - 1] + keypoints[i - 1].size();
}
}
void GenericDescriptorMatcher::KeyPointCollection::clear()
{
points.clear();
keypoints.clear();
}
size_t GenericDescriptorMatcher::KeyPointCollection::keypointCount() const
{
return pointCount;
}
size_t GenericDescriptorMatcher::KeyPointCollection::imageCount() const
{
return images.size();
}
const vector<vector<KeyPoint> >& GenericDescriptorMatcher::KeyPointCollection::getKeypoints() const
{
return keypoints;
}
const vector<KeyPoint>& GenericDescriptorMatcher::KeyPointCollection::getKeypoints( int imgIdx ) const
{
CV_Assert( imgIdx < (int)imageCount() );
return keypoints[imgIdx];
}
const KeyPoint& GenericDescriptorMatcher::KeyPointCollection::getKeyPoint( int imgIdx, int localPointIdx ) const
{
CV_Assert( imgIdx < (int)images.size() );
CV_Assert( localPointIdx < (int)points[imgIdx].size() );
return points[imgIdx][localPointIdx];
CV_Assert( localPointIdx < (int)keypoints[imgIdx].size() );
return keypoints[imgIdx][localPointIdx];
}
const KeyPoint& GenericDescriptorMatcher::KeyPointCollection::getKeyPoint( int globalPointIdx ) const
{
int imgIdx, localPointIdx;
getLocalIdx( globalPointIdx, imgIdx, localPointIdx );
return points[imgIdx][localPointIdx];
return keypoints[imgIdx][localPointIdx];
}
void GenericDescriptorMatcher::KeyPointCollection::getLocalIdx( int globalPointIdx, int& imgIdx, int& localPointIdx ) const
{
imgIdx = -1;
CV_Assert( globalPointIdx < (int)pointCount() );
CV_Assert( globalPointIdx < (int)keypointCount() );
for( size_t i = 1; i < startIndices.size(); i++ )
{
if( globalPointIdx < startIndices[i] )
@@ -567,20 +722,50 @@ void GenericDescriptorMatcher::KeyPointCollection::getLocalIdx( int globalPointI
localPointIdx = globalPointIdx - startIndices[imgIdx];
}
const vector<Mat>& GenericDescriptorMatcher::KeyPointCollection::getImages() const
{
return images;
}
const Mat& GenericDescriptorMatcher::KeyPointCollection::getImage( int imgIdx ) const
{
CV_Assert( imgIdx < (int)imageCount() );
return images[imgIdx];
}
/*
* GenericDescriptorMatcher
*/
GenericDescriptorMatcher::GenericDescriptorMatcher()
{}
GenericDescriptorMatcher::~GenericDescriptorMatcher()
{}
void GenericDescriptorMatcher::add( const vector<Mat>& imgCollection,
vector<vector<KeyPoint> >& pointCollection )
{
trainPointCollection.add( imgCollection, pointCollection );
}
const vector<Mat>& GenericDescriptorMatcher::getTrainImages() const
{
return trainPointCollection.getImages();
}
const vector<vector<KeyPoint> >& GenericDescriptorMatcher::getTrainKeypoints() const
{
return trainPointCollection.getKeypoints();
}
void GenericDescriptorMatcher::clear()
{
trainPointCollection.clear();
}
void GenericDescriptorMatcher::train()
{}
void GenericDescriptorMatcher::classify( const Mat& queryImage, vector<KeyPoint>& queryPoints,
const Mat& trainImage, vector<KeyPoint>& trainPoints ) const
{
@@ -606,7 +791,7 @@ void GenericDescriptorMatcher::match( const Mat& queryImg, vector<KeyPoint>& que
const Mat& trainImg, vector<KeyPoint>& trainPoints,
vector<DMatch>& matches, const Mat& mask ) const
{
Ptr<GenericDescriptorMatcher> tempMatcher = createEmptyMatcherCopy();
Ptr<GenericDescriptorMatcher> tempMatcher = clone( true );
vector<vector<KeyPoint> > vecTrainPoints(1, trainPoints);
tempMatcher->add( vector<Mat>(1, trainImg), vecTrainPoints );
tempMatcher->match( queryImg, queryPoints, matches, vector<Mat>(1, mask) );
@@ -617,7 +802,7 @@ void GenericDescriptorMatcher::knnMatch( const Mat& queryImg, vector<KeyPoint>&
const Mat& trainImg, vector<KeyPoint>& trainPoints,
vector<vector<DMatch> >& matches, int knn, const Mat& mask, bool compactResult ) const
{
Ptr<GenericDescriptorMatcher> tempMatcher = createEmptyMatcherCopy();
Ptr<GenericDescriptorMatcher> tempMatcher = clone( true );
vector<vector<KeyPoint> > vecTrainPoints(1, trainPoints);
tempMatcher->add( vector<Mat>(1, trainImg), vecTrainPoints );
tempMatcher->knnMatch( queryImg, queryPoints, matches, knn, vector<Mat>(1, mask), compactResult );
@@ -629,7 +814,7 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImg, vector<KeyPoint
vector<vector<DMatch> >& matches, float maxDistance,
const Mat& mask, bool compactResult ) const
{
Ptr<GenericDescriptorMatcher> tempMatcher = createEmptyMatcherCopy();
Ptr<GenericDescriptorMatcher> tempMatcher = clone( true );
vector<vector<KeyPoint> > vecTrainPoints(1, trainPoints);
tempMatcher->add( vector<Mat>(1, trainImg), vecTrainPoints );
tempMatcher->radiusMatch( queryImg, queryPoints, matches, maxDistance, vector<Mat>(1, mask), compactResult );
@@ -660,9 +845,25 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImg, vector<KeyPoint
radiusMatchImpl( queryImg, queryPoints, matches, maxDistance, masks, compactResult );
}
void GenericDescriptorMatcher::read( const FileNode& )
{}
void GenericDescriptorMatcher::write( FileStorage& ) const
{}
/****************************************************************************************\
* OneWayDescriptorMatcher *
\****************************************************************************************/
OneWayDescriptorMatcher::Params::Params( int _poseCount, Size _patchSize, string _pcaFilename,
string _trainPath, string _trainImagesList,
float _minScale, float _maxScale, float _stepScale ) :
poseCount(_poseCount), patchSize(_patchSize), pcaFilename(_pcaFilename),
trainPath(_trainPath), trainImagesList(_trainImagesList),
minScale(_minScale), maxScale(_maxScale), stepScale(_stepScale)
{}
OneWayDescriptorMatcher::OneWayDescriptorMatcher( const Params& _params)
{
initialize(_params);
@@ -691,13 +892,13 @@ void OneWayDescriptorMatcher::clear()
void OneWayDescriptorMatcher::train()
{
if( base.empty() || prevTrainCount < (int)trainPointCollection.pointCount() )
if( base.empty() || prevTrainCount < (int)trainPointCollection.keypointCount() )
{
base = new OneWayDescriptorObject( params.patchSize, params.poseCount, params.pcaFilename,
params.trainPath, params.trainImagesList, params.minScale, params.maxScale, params.stepScale );
base->Allocate( trainPointCollection.pointCount() );
prevTrainCount = trainPointCollection.pointCount();
base->Allocate( trainPointCollection.keypointCount() );
prevTrainCount = trainPointCollection.keypointCount();
const vector<vector<KeyPoint> >& points = trainPointCollection.getKeypoints();
int count = 0;
@@ -714,6 +915,11 @@ void OneWayDescriptorMatcher::train()
}
}
bool OneWayDescriptorMatcher::isMaskSupported()
{
return false;
}
void OneWayDescriptorMatcher::knnMatchImpl( const Mat& queryImg, vector<KeyPoint>& queryPoints,
vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& /*masks*/, bool /*compactResult*/ )
@@ -763,6 +969,23 @@ void OneWayDescriptorMatcher::write( FileStorage& fs ) const
base->Write (fs);
}
Ptr<GenericDescriptorMatcher> OneWayDescriptorMatcher::clone( bool emptyTrainData ) const
{
OneWayDescriptorMatcher* matcher = new OneWayDescriptorMatcher( params );
if( !emptyTrainData )
{
CV_Error( CV_StsNotImplemented, "deep clone dunctionality is not implemented, because "
"OneWayDescriptorBase has not copy constructor or clone method ");
//matcher->base;
matcher->params = params;
matcher->prevTrainCount = prevTrainCount;
matcher->trainPointCollection = trainPointCollection;
}
return matcher;
}
/****************************************************************************************\
* FernDescriptorMatcher *
\****************************************************************************************/
@@ -805,7 +1028,7 @@ void FernDescriptorMatcher::clear()
void FernDescriptorMatcher::train()
{
if( classifier.empty() || prevTrainCount < (int)trainPointCollection.pointCount() )
if( classifier.empty() || prevTrainCount < (int)trainPointCollection.keypointCount() )
{
assert( params.filename.empty() );
@@ -819,6 +1042,11 @@ void FernDescriptorMatcher::train()
}
}
bool FernDescriptorMatcher::isMaskSupported()
{
return false;
}
void FernDescriptorMatcher::calcBestProbAndMatchIdx( const Mat& image, const Point2f& pt,
float& bestProb, int& bestMatchIdx, vector<float>& signature )
{
@@ -921,16 +1149,42 @@ void FernDescriptorMatcher::write( FileStorage& fs ) const
// classifier->write(fs);
}
Ptr<GenericDescriptorMatcher> FernDescriptorMatcher::clone( bool emptyTrainData ) const
{
FernDescriptorMatcher* matcher = new FernDescriptorMatcher( params );
if( !emptyTrainData )
{
CV_Error( CV_StsNotImplemented, "deep clone dunctionality is not implemented, because "
"FernClassifier has not copy constructor or clone method ");
//matcher->classifier;
matcher->params = params;
matcher->prevTrainCount = prevTrainCount;
matcher->trainPointCollection = trainPointCollection;
}
return matcher;
}
/****************************************************************************************\
* VectorDescriptorMatcher *
* VectorDescriptorMatcher *
\****************************************************************************************/
VectorDescriptorMatcher::VectorDescriptorMatcher( const Ptr<DescriptorExtractor>& _extractor,
const Ptr<DescriptorMatcher>& _matcher )
: extractor( _extractor ), matcher( _matcher )
{
CV_Assert( !extractor.empty() && !matcher.empty() );
}
VectorDescriptorMatcher::~VectorDescriptorMatcher()
{}
void VectorDescriptorMatcher::add( const vector<Mat>& imgCollection,
vector<vector<KeyPoint> >& pointCollection )
{
vector<Mat> descCollection;
extractor->compute( imgCollection, pointCollection, descCollection );
vector<Mat> descriptors;
extractor->compute( imgCollection, pointCollection, descriptors );
matcher->add( descCollection );
matcher->add( descriptors );
trainPointCollection.add( imgCollection, pointCollection );
}
@@ -947,28 +1201,33 @@ void VectorDescriptorMatcher::train()
matcher->train();
}
bool VectorDescriptorMatcher::isMaskSupported()
{
return matcher->isMaskSupported();
}
void VectorDescriptorMatcher::knnMatchImpl( const Mat& queryImg, vector<KeyPoint>& queryPoints,
vector<vector<DMatch> >& matches, int knn,
const vector<Mat>& masks, bool compactResult )
{
Mat queryDescs;
extractor->compute( queryImg, queryPoints, queryDescs );
matcher->knnMatch( queryDescs, matches, knn, masks, compactResult );
Mat queryDescriptors;
extractor->compute( queryImg, queryPoints, queryDescriptors );
matcher->knnMatch( queryDescriptors, matches, knn, masks, compactResult );
}
void VectorDescriptorMatcher::radiusMatchImpl( const Mat& queryImg, vector<KeyPoint>& queryPoints,
vector<vector<DMatch> >& matches, float maxDistance,
const vector<Mat>& masks, bool compactResult )
{
Mat queryDescs;
extractor->compute( queryImg, queryPoints, queryDescs );
matcher->radiusMatch( queryDescs, matches, maxDistance, masks, compactResult );
Mat queryDescriptors;
extractor->compute( queryImg, queryPoints, queryDescriptors );
matcher->radiusMatch( queryDescriptors, matches, maxDistance, masks, compactResult );
}
void VectorDescriptorMatcher::read( const FileNode& fn )
{
GenericDescriptorMatcher::read(fn);
extractor->read (fn);
extractor->read(fn);
}
void VectorDescriptorMatcher::write (FileStorage& fs) const
@@ -977,6 +1236,12 @@ void VectorDescriptorMatcher::write (FileStorage& fs) const
extractor->write (fs);
}
Ptr<GenericDescriptorMatcher> VectorDescriptorMatcher::clone( bool emptyTrainData ) const
{
// TODO clone extractor
return new VectorDescriptorMatcher( extractor, matcher->clone(emptyTrainData) );
}
/*
* Factory function for GenericDescriptorMatch creating
*/