void runTest(const flann::Index<L2_Simple<float> >& index, SearchParams params)
    {
        start_timer("Searching Radius (single core)...");
        params.cores = 1;
        int single_neighbor_count = index.radiusSearch(query_, indices_single_, dists_single_, radius_, params);
        printf("done (%g seconds)\n", stop_timer());

        start_timer("Searching Radius (multi core)...");
        params.cores = 0;
        int multi_neighbor_count = index.radiusSearch(query_, indices_multi_, dists_multi_, radius_, params);
        printf("done (%g seconds)\n", stop_timer());

        EXPECT_EQ(single_neighbor_count, multi_neighbor_count);

        printf("Checking results...\n");
        float precision = compute_precision(indices_single_, indices_multi_);
        EXPECT_GE(precision, 0.99);
        printf("Precision: %g\n", precision);
    }
Beispiel #2
0
  //! Find the nearest neighbors in the descriptor space using FLANN.
  void append_nearest_neighbors(
    size_t i1,
    const Set<OERegion, RealDescriptor>& keys1,
    const Set<OERegion, RealDescriptor>& keys2,
    vector<Match>& matches,
    const flann::Matrix<float>& /*data2*/,
    flann::Index<flann::L2<float>>& tree2,
    float squared_ratio_thres,
    Match::Direction dir,
    bool self_matching, const KeyProximity& is_redundant, // self-matching
    vector<int>& vec_indices,
    vector<float>& vec_dists,
    size_t num_max_neighbors) // internal storage parameters
  {
    // Prepare the query matrix
    flann::Matrix<float> query{
      const_cast<float *>(&(keys1.descriptors.matrix()(0, i1))),
      1, keys1.descriptors.dimension()
    };

    // Prepare the indices and distances.
    flann::Matrix<int> indices{ &vec_indices[0], 1, num_max_neighbors };
    flann::Matrix<float> dists{ &vec_dists[0], 1, num_max_neighbors };

    // Create search parameters.
    flann::SearchParams search_params;

    // N.B.: We should not be in the boundary case in practice, in which case the
    // ambiguity score does not really make sense.
    //
    // Boundary case 1.
    if (keys2.size() == 0)
      return;
    // Boundary case 2.
    if (keys2.size() == 1 && !self_matching)
    {
      auto m = Match{
        &keys1.features[i1], &keys2.features[0], 1.f, dir, int(i1), 0
      };
      m.rank() = 1;

      if(dir == Match::Direction::TargetToSource)
      {
        swap(m.x_pointer(), m.y_pointer());
        swap(m.x_index(), m.y_index());
      }

      if (m.score() < squared_ratio_thres)
        matches.push_back(m);
      return;
    }
    // Boundary case 3.
    if (keys2.size() == 2 && self_matching)
    {
      tree2.knnSearch(query, indices, dists, 2, search_params);

      const auto i2 = indices[0][1]; // The first index can't be indices[0][0], which is i1.
      auto m = Match{
        &keys1.features[i1], &keys2.features[i2], 1.f, dir,
        int(i1), i2
      };
      m.rank() = 1;

      if(dir == Match::Direction::TargetToSource)
      {
        swap(m.x_pointer(), m.y_pointer());
        swap(m.x_index(), m.y_index());
      }

      if (m.score() < squared_ratio_thres)
        matches.push_back(m);

      return;
    }


    // Now treat the generic case.
    //
    // Search the nearest neighbor.
    tree2.knnSearch(query, indices, dists, 3, search_params);

    // This is to avoid the source key matches with himself in case of intra
    // image matching.
    const auto top1_index = self_matching ? 1 : 0;
    auto top1_score = dists[0][top1_index + 1] > 0.f ?
      dists[0][top1_index] / dists[0][top1_index + 1] : 0.f;
    auto K = 1;

    // Determine the number of nearest neighbors.
    if (squared_ratio_thres > 1.f)
    {
      // Performs an adaptive radius search.
      const auto radius = dists[0][top1_index] * squared_ratio_thres;
      K = tree2.radiusSearch(query, indices, dists, radius, search_params);
    }

    // Retrieve the right key points.
    for (int rank = top1_index; rank < K; ++rank)
    {
      auto score = 0.f;
      if (rank == top1_index)
        score = top1_score;
      else if (dists[0][top1_index])
        score = dists[0][rank] / dists[0][top1_index];

      // We still need this check as FLANN can still return wrong neighbors.
      if (score > squared_ratio_thres)
        break;

      auto i2 = indices[0][rank];

      // Ignore the match if keys1 == keys2.
      if (self_matching && is_redundant(keys1.features[i1], keys2.features[i2]))
        continue;

      Match m(&keys1.features[i1], &keys2.features[i2], score, dir, i1, i2);
      m.rank() = top1_index == 0 ? rank+1 : rank;
      if(dir == Match::Direction::TargetToSource)
      {
        swap(m.x_pointer(), m.y_pointer());
        swap(m.x_index(), m.y_index());
      }

      matches.push_back(m);
    }
  }