/* Make match lists symmetric */ void BaseApp::MakeMatchListsSymmetric() { unsigned int num_images = GetNumImages(); std::vector<MatchIndex> matches; for (unsigned int i = 0; i < num_images; i++) { MatchAdjList::const_iterator iter; for (iter = m_matches.Begin(i); iter != m_matches.End(i); iter++) { // unsigned int i = iter->first; unsigned int j = iter->m_index; // iter->second; if (j <= i) continue; assert(ImagesMatch(i, j)); // MatchIndex idx = *iter; MatchIndex idx = GetMatchIndex(i, j); MatchIndex idx_rev = GetMatchIndex(j, i); // int num_matches = (int) m_match_lists[idx].size(); const std::vector<KeypointMatch> &list = iter->m_match_list; unsigned int num_matches = list.size(); // m_match_lists[idx_rev].clear(); m_matches.SetMatch(idx_rev); m_matches.ClearMatch(idx_rev); for (unsigned int k = 0; k < num_matches; k++) { KeypointMatch m1, m2; m1 = list[k]; m2.m_idx1 = m1.m_idx2; m2.m_idx2 = m1.m_idx1; // m_match_lists[idx_rev].push_back(m2); m_matches.AddMatch(idx_rev, m2); } matches.push_back(idx); } } unsigned int num_matches = matches.size(); for (unsigned int i = 0; i < num_matches; i++) { unsigned int img1 = matches[i].first; unsigned int img2 = matches[i].second; SetMatch(img2, img1); } matches.clear(); }
/* Compute epipolar geometry between all matching images */ void BundlerApp::ComputeEpipolarGeometry(bool removeBadMatches, int new_image_start) { unsigned int num_images = GetNumImages(); m_transforms.clear(); std::vector<MatchIndex> remove; for (unsigned int i = 0; i < num_images; i++) { MatchAdjList::iterator iter; for (iter = m_matches.Begin(i); iter != m_matches.End(i); iter++) { unsigned int j = iter->m_index; // first; assert(ImagesMatch(i, j)); MatchIndex idx = GetMatchIndex(i, j); MatchIndex idx_rev = GetMatchIndex(j, i); bool connect12 = ComputeEpipolarGeometry(i, j, removeBadMatches); if (!connect12) { if (removeBadMatches) { // RemoveMatch(i, j); // RemoveMatch(j, i); remove.push_back(idx); remove.push_back(idx_rev); // m_match_lists[idx].clear(); // m_match_lists.erase(idx); m_transforms.erase(idx); m_transforms.erase(idx_rev); } } else { matrix_transpose(3, 3, m_transforms[idx].m_fmatrix, m_transforms[idx_rev].m_fmatrix); } } } int num_removed = (int) remove.size(); for (int i = 0; i < num_removed; i++) { int img1 = remove[i].first; int img2 = remove[i].second; // RemoveMatch(img1, img2); m_matches.RemoveMatch(GetMatchIndex(img1, img2)); } }
void BaseApp::WriteMatchTable(const char *append) { int num_images = GetNumImages(); char buf[256]; sprintf(buf, "nmatches%s.txt", append); FILE *f0 = fopen(buf, "w"); sprintf(buf, "matches%s.txt", append); FILE *f1 = fopen(buf, "w"); if (f0 == NULL || f1 == NULL) { printf("[WriteMatchTable] " "Error opening files for writing.\n"); return; } fprintf(f0, "%d\n", num_images); for (int i = 0; i < num_images; i++) { for (int j = 0; j < num_images; j++) { if (i >= j) { fprintf(f0, "0 "); fprintf(f1, "\n"); } else { if (ImagesMatch(i, j)) { MatchIndex idx = GetMatchIndex(i, j); std::vector<KeypointMatch> &list = m_matches.GetMatchList(idx); unsigned int num_matches = list.size(); fprintf(f0, "%d ", num_matches); for (unsigned int k = 0; k < num_matches; k++) { KeypointMatch m = list[k]; fprintf(f1, "%d %d ", m.m_idx1, m.m_idx2); } fprintf(f1, "\n"); } else { fprintf(f0, "0 "); } } } fprintf(f0, "\n"); } fclose(f0); fclose(f1); }
void BundlerApp::ComputeGeometricConstraints(bool overwrite, int new_image_start) { int num_images = GetNumImages(); /* Read information from files if they exist */ const char *filename = "constraints.txt"; if (!overwrite && FileExists(filename)) { ReadGeometricConstraints(filename); return; } else { LoadMatches(); if (num_images < 40000) WriteMatchTable(".prune"); if (!m_skip_fmatrix || !m_skip_homographies || m_keypoint_border_width > 0 || m_keypoint_border_bottom > 0) LoadKeys(false); if (m_keypoint_border_width > 0) { for (int i = 0; i < num_images; i++) { for (int j = i+1; j < num_images; j++) { if (!ImagesMatch(i, j)) continue; RemoveMatchesNearBorder(i, j, m_keypoint_border_width); } } } if (m_keypoint_border_bottom > 0) { for (int i = 0; i < num_images; i++) { for (int j = i+1; j < num_images; j++) { if (!ImagesMatch(i, j)) continue; RemoveMatchesNearBottom(i, j, m_keypoint_border_bottom); } } } if (!m_skip_fmatrix) { ComputeEpipolarGeometry(true, new_image_start); } if (!m_skip_homographies) { ComputeTransforms(false, new_image_start); } MakeMatchListsSymmetric(); if (num_images < 40000) WriteMatchTable(".ransac"); // RemoveAllMatches(); ComputeTracks(new_image_start); // ClearMatches(); RemoveAllMatches(); // SetMatchesFromTracks(); #if 1 /* Set match flags */ int num_tracks = (int) m_track_data.size(); for (int i = 0; i < num_tracks; i++) { TrackData &track = m_track_data[i]; int num_views = (int) track.m_views.size(); for (int j = 0; j < num_views; j++) { int img1 = track.m_views[j].first; assert(img1 >= 0 && img1 < num_images); for (int k = j+1; k < num_views; k++) { int img2 = track.m_views[k].first; assert(img2 >= 0 && img2 < num_images); SetMatch(img1, img2); SetMatch(img2, img1); } } } #endif WriteGeometricConstraints(filename); if (num_images < 40000) WriteMatchTable(".corresp"); } }
/* Compute rigid transforms between all matching images */ void BundlerApp::ComputeTransforms(bool removeBadMatches, int new_image_start) { unsigned int num_images = GetNumImages(); m_transforms.clear(); for (unsigned int i = 0; i < num_images; i++) { MatchAdjList::iterator iter; for (iter = m_matches.Begin(i); iter != m_matches.End(i); iter++) { unsigned int j = iter->m_index; assert(ImagesMatch(i, j)); MatchIndex idx = GetMatchIndex(i, j); MatchIndex idx_rev = GetMatchIndex(j, i); m_transforms[idx] = TransformInfo(); m_transforms[idx_rev] = TransformInfo(); bool connect12 = ComputeTransform(i, j, removeBadMatches); if (!connect12) { if (removeBadMatches) { // RemoveMatch(i, j); // RemoveMatch(j, i); // m_match_lists[idx].clear(); m_matches.RemoveMatch(idx); m_matches.RemoveMatch(idx_rev); // m_match_lists.erase(idx); m_transforms.erase(idx); m_transforms.erase(idx_rev); } } else { matrix_invert(3, m_transforms[idx].m_H, m_transforms[idx_rev].m_H); } } } /* Print the inlier ratios */ FILE *f = fopen("pairwise_scores.txt", "w"); for (unsigned int i = 0; i < num_images; i++) { MatchAdjList::iterator iter; for (iter = m_matches.Begin(i); iter != m_matches.End(i); iter++) { unsigned int j = iter->m_index; // first; assert(ImagesMatch(i, j)); // MatchIndex idx = *iter; MatchIndex idx = GetMatchIndex(i, j); fprintf(f, "%d %d %0.5f\n", i, j, m_transforms[idx].m_inlier_ratio); } } fclose(f); }