[e976b6]: src / hugin_base / algorithms / control_points / KDTreeKeypointMatcher.cpp  Maximize  Restore  History

Download this file

144 lines (118 with data), 4.2 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* @file KDTreeKeypointMatcher.cpp
* gsoc2008_feature_matching
*
* This class is a generic k-d tree wrapper
*
* @author Onur Kucuktunc <onurcc@gmail.com>
*/
#include "KDTreeKeypointMatcher.h"
/**
* create KDTree from the feature descriptors stored in the panorama.
*
* @param pano Panorama from which the keypoints are taken.
*/
void KDTreeKeypointMatcher::create(const PanoramaData & pano)
{
UIntSet imgs;
// for each image in panorama
for (int im=0; im < pano.getNrOfImages(); im++)
imgs.insert(im);
// call the create function with all images
create(pano, &imgs);
}
/**
* create KDTree from the feature descriptors stored in the panorama.
*
* @param pano Panorama from which the keypoints are taken.
* @param images Only use keypoints from the specified images.
*/
void KDTreeKeypointMatcher::create(const PanoramaData & pano, const UIntSet & imgs)
{
int nKeypoints=0;
int dim=0;
// first, count how many descriptors we have, and the dimension of the space
for (UIntSet::const_iterator it=imgs.begin(); it != imgs.end(); ++it) {
const std::vector<Keypoint> & keypoints = pano.getImage(*it).getKeypoints();
nKeypoints += keypoints.size();
if (keypoints.size() > 0)
dim = keypoints[0].descriptor.size();
}
assert(dim > 0);
// prepare a big list of points, and insert all points
if (m_allPoints) delete[] m_allPoints;
m_allPoints = new ANNpoint[nKeypoints];
ANNpointArray pointsPtr = m_allPoints;
// for all images
for (UIntSet::iterator it=imgs.begin(); it != imgs.end(); ++it) {
// get all keypoints in this image
const std::vector<Keypoint> & keypoints = pano.getImage(*it).getKeypoints();
// iterate over the keypoints
int j=0;
for (vector<Keypoint>::const_iterator itkey=keypoints.begin();
itkey != keypoints.end(); ++itkey)
{
// create an ImageKeypoint
ImageKeypoint ik(*it, j, *itkey);
// add to m_keypoints list
m_keypoints.push_back(ik);
// add as an ANNpoint
ANNpoint *pt = const_cast<float *>(&(*(key.descriptor.begin())));
*pointsPtr = pt;
pointsPtr++;
j++;
}
}
// options: match distance.
// create KDTree
m_KDTree = new ANNkd_tree (m_allPoints, // the data points
nKeypoints, // number of points
dim); // dimension of space
}
// match a single keypoint
// TODO: kNN search instead of priority search
// TODO: modify the decision part
ImageKeypoint KDTreeKeypointMatcher::match(const Keypoint & key, unsigned int imageOfKeypoint)
{
int nKeypoints = m_keypoints.size();
int searchDepth = std::max(200, hugin_utils::roundi(log(nKeypoints)/log(1000)*130));
DEBUG_DEBUG("search depth: " << searchDepth);
annMaxPtsVisit(searchDepth);
// perform nearest neighbor matching
ANNcoord * acord = const_cast<float *>(&(*(key.descriptor.begin())));
m_KDTree->annkPriSearch(acord,
m_k, // number of near neighbors
m_nnIdx, // nearest neighbors (returned)
m_dists, // distance (returned)
0.0); // error bound
// keep the list of rejected images
UIntSet rejectedImages;
// iterate over nearest neighbor search results
for (int i=0; i < m_k-1; i++)
{
// skip if this keypoint is in the same image
if (m_keypoints[m_nnIdx[i]].imageNr == imageOfKeypoint)
continue;
// skip if we have already rejected this image
if (set_contains(rejectedImages, m_keypoints[m_nnIdx[i]].imageNr))
continue;
// check for nearest neighbors using 0.6 rule
float dist1 = eucdist(key, m_keypoints[m_nnIdx[i]].keypoint);
float dist2 = eucdist(key, m_keypoints[m_nnIdx[i+1]].keypoint);
if (dist1/dist2 < 0.6)
{
return m_keypoints[m_nnIdx[i]];
}
else if (m_keypoints[m_nnIdx[i]].imageNr == m_keypoints[m_nnIdx[i+1]].imageNr) {
rejectedImages.insert(m_keypoints[m_nnIdx[i]].imageNr);
}
}
// All matches are bad. Need to check more nearest neighbours.
// Be conservative and report no matches
return NULL;
}
int KDTreeKeypointMatcher::getKeypointIdxOfMatch(unsigned int matchNr) const
{
assert(matchNr < m_k);
return (m_nnIdx[matchNr]);
}

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks