Пример #1
0
object search(ANNkd_tree& kdtree, object q, int k, double eps, bool priority = false)
{
    BOOST_ASSERT(k <= kdtree.nPoints() && kdtree.theDim() == len(q));
    ANNpointManaged annq(kdtree.theDim());
    for (int c = 0; c < kdtree.theDim(); ++c)
        annq.pt[c] = extract<ANNcoord>(q[c]);

    npy_intp dims[] = { k};
    PyObject *pydists = PyArray_SimpleNew(1,dims, sizeof(ANNdist)==8 ? PyArray_DOUBLE : PyArray_FLOAT);
    BOOST_ASSERT(!!pydists);
    PyObject *pyidx = PyArray_SimpleNew(1,dims, PyArray_INT);
    if( !pyidx )
        Py_DECREF(pydists);
    BOOST_ASSERT(!!pyidx);
    ANNdist* pdists = (ANNdist*)PyArray_DATA(pydists);
    ANNidx* pidx = (ANNidx*)PyArray_DATA(pyidx);

    std::vector<ANNidx> nn_idx(k);
    std::vector<ANNdist> dists(k);

    if (priority)
        kdtree.annkPriSearch(annq.pt, k, pidx, pdists, eps);
    else
        kdtree.annkSearch(annq.pt, k, pidx, pdists, eps);
    return boost::python::make_tuple(static_cast<numeric::array>(handle<>(pyidx)), static_cast<numeric::array>(handle<>(pydists)));
}
Пример #2
0
object search_array(ANNkd_tree& kdtree, object qarray, int k, double eps, bool priority = false)
{
    BOOST_ASSERT(k <= kdtree.nPoints());
    int N = len(qarray);
    if( N == 0 )
        return boost::python::make_tuple(numeric::array(boost::python::list()).astype("i4"),numeric::array(boost::python::list()));

    BOOST_ASSERT(len(qarray[0])==kdtree.theDim());
    ANNpointManaged annq(kdtree.theDim());
    npy_intp dims[] = { N,k};
    PyObject *pydists = PyArray_SimpleNew(2,dims, sizeof(ANNdist)==8 ? PyArray_DOUBLE : PyArray_FLOAT);
    BOOST_ASSERT(!!pydists);
    PyObject *pyidx = PyArray_SimpleNew(2,dims, PyArray_INT);
    if( !pyidx ) {
        Py_DECREF(pydists);
    }
    BOOST_ASSERT(!!pyidx);
    ANNdist* pdists = (ANNdist*)PyArray_DATA(pydists);
    ANNidx* pidx = (ANNidx*)PyArray_DATA(pyidx);

    std::vector<ANNdist> dists(k);
    std::vector<ANNidx> nn_idx(k);
    for(int i = 0; i < N; ++i) {
        object q = qarray[i];
        for (int c = 0; c < kdtree.theDim(); ++c)
            annq.pt[c] = extract<ANNcoord>(q[c]);
        if (priority)
            kdtree.annkPriSearch(annq.pt, k, &nn_idx[0], &dists[0], eps);
        else
            kdtree.annkSearch(annq.pt, k, &nn_idx[0], &dists[0], eps);

        std::copy(nn_idx.begin(),nn_idx.end(),pidx);
        pidx += k;
        std::copy(dists.begin(),dists.end(),pdists);
        pdists += k;
    }

    return boost::python::make_tuple(static_cast<numeric::array>(handle<>(pyidx)), static_cast<numeric::array>(handle<>(pydists)));
}
Пример #3
0
int FeatureMatcher::match() {
  matches.clear();
  /// For all groups of points clustered based on their epipolar lines
  /// Read clusterPointsFast() to see implementation details

  for(int i=0; i < pointGroups.size(); i++) {  
    int qPtSize = pointGroups[i].size();

    /// Get corresponding epipolar line for this group of pts
    int idx = groupEpiLineIdx[i];
    int groupIdx = pointToLineGroupIdx[idx];

    /// Get features close to the epipolar line and construct a Kd-tree 
    /// of its descriptors

    vector<int> probMatches;
    ANNkd_tree* tree = constructSearchTree(idx, probMatches);

    /// Limit the nodes to visit in this tree as max(20% of candidates,20)
    int PtsToVisit = (float)(probMatches.size())/20;
    PtsToVisit = PtsToVisit > 20 ? PtsToVisit : 20;
    annMaxPtsVisit(PtsToVisit);

    if(tree == NULL) {
      continue;
    }

    /// For each points within a cluster, find the closest two points
    /// from the candidate set (probMatches) using Kd-tree in descriptor
    /// space and perform ratio-test
    for(int j=0; j < pointGroups[i].size(); j++) {
      vector<ANNidx> nn_idx(2);
      vector<ANNdist> dists(2);

      vector<ANNidx> nn_idx1(2);
      vector<ANNdist> dists1(2);

      int qPtIdx = pointGroups[i][j];
      unsigned char* currQuery = srcKey + 128*qPtIdx;
      tree->annkPriSearch(currQuery, 2, nn_idx.data(), dists.data(), 0.0);


      /// Perform ratio-test between closest two points
      /// Discard the match if ratio is above a threshold
      float bestDist = (float)(dists[0]);
      float secondBestDist = (float)(dists[1]);
      float distRatio1 = sqrt(bestDist/secondBestDist);

      if(distRatio1 > 0.6) {
        continue;
      }

      int matchingPt = probMatches[(int)nn_idx[0]];

      /// Perform epipolar verification
      double x2[] = {refKeysInfo[matchingPt].x,
        refKeysInfo[matchingPt].y, 1.0};
      double line[3];
      geometry::ComputeEpipolarLine(x2,fMatrix.data(),line,true); 

      double x1[] = {srcKeysInfo[qPtIdx].x,
        srcKeysInfo[qPtIdx].y, 1.0};
      float epiDist2 = 
        geometry::ComputeDistanceFromLine( x1, line);
      if(epiDist2 >= 4.0) {
        continue;
      }
      matches.push_back(make_pair(qPtIdx, matchingPt));

    }

    /// Free memory.
    annDeallocPts(tree->pts);
    delete tree;
  }

  int matchCount = (int)(matches.size());
  return matchCount;
}
Пример #4
0
int FeatureMatcher::globalMatch(int h, bool twoWaySearch) {
  /// Clear previously computed matches if any
  matches.clear();

  /// Find number of h% matches
  int numTopRefPts = (int)(numRefPts*h/100);  
  int numTopSrcPts = (int)(numSrcPts*h/100);  

  /// Allocate point structures for Kd-tree based search
  ANNpointArray keyPts = annAllocPts( numTopRefPts, 128);
  ANNpointArray qKeyPts = annAllocPts( numTopSrcPts, 128);

  /// Copy descriptors to allocated point structures
  for(int i=0; i < numTopRefPts; i++) 
    memcpy(keyPts[i], refKey+128*i, sizeof(unsigned char)*128);

  for(int i=0; i < numTopSrcPts; i++) 
    memcpy(qKeyPts[i], srcKey+128*i, sizeof(unsigned char)*128);

  /// Create trees for source and target descriptors
  ANNkd_tree* tree = new ANNkd_tree(keyPts, numTopRefPts, 128, 16);
  ANNkd_tree* qTree = new ANNkd_tree(qKeyPts, numTopSrcPts, 128, 16);

  /// Number of nodes to visit in Kd-tree (standard practice)
  /// Limit this number to the lesser 500 or TotalPoints/20
  /// If the 20% points are too less, limit it at least to 50
  int PtsToVisit = numTopRefPts > numTopSrcPts ? numTopRefPts : numTopSrcPts;

  PtsToVisit = ceil((float)PtsToVisit/(float)20) < 
    500 ? ceil((float)PtsToVisit/(float)20) : 500;

  if(PtsToVisit < 50) PtsToVisit = 50;

  annMaxPtsVisit(PtsToVisit);
  //printf("\nPts To Visit : %d", PtsToVisit);

  /// For each of the selected source features
  for(int i=0; i < numTopSrcPts; i++) {

    vector<ANNidx> indices(2);
    vector<ANNdist> dists(2);

    /// Search for two closest points in the reference tree
    unsigned char* qKey = srcKey + 128*i;
    tree->annkPriSearch(qKey, 2, indices.data(), dists.data(), 0.0);

    /// Compute best distance to second best distance ratio
    float bestDist = (float)(dists[0]);
    float secondBestDist = (float)(dists[1]);

    float distRatio = sqrt(bestDist/secondBestDist);

 //   printf("\nSrc Point %d, best dist %f, second best %f, ratio %f, 1st %d, 2nd %d",
 //       i, bestDist, secondBestDist, distRatio, (int)indices[0], (int)indices[1]);

 
    /// If the ratio is larger than threshold, match is not considered
    if(distRatio > 0.6) {
      continue;
    }

    /// If the ratio is below the threshold, the closest point is the match
    int matchingPt = (int)indices[0];
    int secondMatch = (int)indices[1];
    indices.clear();
    dists.clear();

    /// If two way search is enabled, verify that 
    //  the query point is the best match for the
    //  matching point and also satisfies ratio test
    if(twoWaySearch) {

      unsigned char* qKey1 = refKey + 128*matchingPt;
      qTree->annkPriSearch(qKey1, 2, indices.data(), dists.data(), 0.0);

      float bestDist1 = (float)(dists[0]);
      float secondBestDist1 = (float)(dists[1]);

      float distRatio1 = sqrt(bestDist1/secondBestDist1);

      if((int)(indices[0]) != i) {
        continue;
      }

      if(distRatio1 > 0.6) {
        continue;
      }
    }

//    printf("\nSrc Point %d, 1st %d, 2nd %d",
//        i, matchingPt, secondMatch);
    /// Add the pairs to matches list
    matches.push_back(make_pair(i, matchingPt)); 
  }

  /// Deallocate Point Structures
  annDeallocPts(keyPts);
  annDeallocPts(qKeyPts);

  /// Delete Kd-tree
  delete tree;
  delete qTree;
  return (int)matches.size();
}