void BaseApp::LoadMatchTable(const char *filename) { if (m_matches_loaded) return; /* we already loaded the matches */ printf("[LoadMatchTable] Loading matches\n"); /* Set all matches to false */ // ClearMatches(); RemoveAllMatches(); FILE *f = fopen(filename, "r"); if (f == NULL) { printf("[LoadMatchTable] Error opening file %s for reading\n", filename); exit(1); } char buf[256]; while (fgets(buf, 256, f)) { /* Read the images */ int i1, i2; sscanf(buf, "%d %d\n", &i1, &i2); SetMatch(i1, i2); // SetMatch(i2, i1); // m_matches[i1 * num_images + i2] = true; // m_matches[i2 * num_images + i1] = true; /* Read the number of matches */ int nMatches; fscanf(f, "%d\n", &nMatches); /* Read the matches */ std::vector<KeypointMatch> matches; for (int i = 0; i < nMatches; i++) { int k1, k2; fscanf(f, "%d %d\n", &k1, &k2); #ifdef KEY_LIMIT if (k1 > KEY_LIMIT || k2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ KeypointMatch m; m.m_idx1 = k1; m.m_idx2 = k2; matches.push_back(m); } MatchIndex idx = GetMatchIndex(i1, i2); // m_match_lists[idx] = matches; m_matches.GetMatchList(idx) = matches; } fclose(f); }
/* Load the match table from file. This table contains the set of pairwise matches across two images. The matches are specified by the key point indices. The table location/slot specifies which pair of images are being queried. The filename is passed as an argument. If it doesn't exist, then the program will quit. */ void BaseApp::LoadMatchTable(const char *filename) { if (m_matches_loaded) // Are matches already loaded? return; #ifdef _DEBUG_ printf("[LoadMatchTable] Loading matches\n"); #endif // Clear all matches / empty the table. RemoveAllMatches(); // Open the file, make sure OK. If not able to open, exit program. FILE *f = fopen(filename, "r"); if (f == NULL) { printf("[LoadMatchTable] Error opening file %s for reading\n", filename); exit(1); } // Read the matching keypoint indices. char buf[256]; while (fgets(buf, 256, f)) { // Read images indices describing which pairwise matching being loaded. int i1, i2; sscanf(buf, "%d %d\n", &i1, &i2); SetMatch(i1, i2); // SetMatch(i2, i1); // Read the number of matches int nMatches; fscanf(f, "%d\n", &nMatches); // Read the matching indices and populate match table. std::vector<KeypointMatch> matches; for (int i = 0; i < nMatches; i++) { int k1, k2; fscanf(f, "%d %d\n", &k1, &k2); #ifdef KEY_LIMIT if (k1 > KEY_LIMIT || k2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ KeypointMatch m; m.m_idx1 = k1; m.m_idx2 = k2; matches.push_back(m); } MatchIndex idx = GetMatchIndex(i1, i2); m_matches.GetMatchList(idx) = matches; } fclose(f); // Done loading table, close shop. }
/* 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(); }
void BaseApp::ReadMatchFile(int i, int j) { /* Read matches from a file */ char buf[256]; sprintf(buf, "%s/match-%03d-%03d.txt", m_match_directory, i, j); if (FileExists(buf)) { FILE *f = fopen(buf, "r"); /* Read the number of matches */ int num_matches; fscanf(f, "%d", &num_matches); if (num_matches < MIN_MATCHES) { // RemoveMatch(i, j); // RemoveMatch(j, i); fclose(f); return; } SetMatch(i, j); // SetMatch(j, i); std::vector<KeypointMatch> matches; for (int k = 0; k < num_matches; k++) { int idx1, idx2; fscanf(f, "%d %d", &idx1, &idx2); #ifdef KEY_LIMIT if (idx1 > KEY_LIMIT || idx2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ KeypointMatch m; m.m_idx1 = idx1; m.m_idx2 = idx2; matches.push_back(m); } MatchIndex idx = GetMatchIndex(i, j); // m_match_lists[idx] = matches; m_matches.GetMatchList(idx) = matches; fclose(f); } else { // RemoveMatch(i, j); // RemoveMatch(j, i); } }
void BaseApp::SetMatchesFromTracks() { /* Clear all matches */ // ClearMatches(); RemoveAllMatches(); int num_tracks = (int) m_track_data.size(); int num_tracks_used = 0; for (int i = 0; i < num_tracks; i++) { TrackData &t = m_track_data[i]; int num_views = (int) t.m_views.size(); if (num_views < m_min_track_views) continue; /* Not enough observations */ if (num_views > m_max_track_views) continue; /* Too many observations */ for (int j = 0; j < num_views; j++) { for (int k = 0; k < num_views; k++) { if (j == k) continue; int v1 = t.m_views[j].first; int v2 = t.m_views[k].first; int k1 = t.m_views[j].second; int k2 = t.m_views[k].second; MatchIndex idx = GetMatchIndex(v1, v2); // m_matches[idx] = true; SetMatch(v1, v2); // m_match_lists[idx].push_back(KeypointMatch(k1,k2)); m_matches.GetMatchList(idx).push_back(KeypointMatch(k1, k2)); } } num_tracks_used++; } LOGI("[BaseApp::SetMatchesFromTracks] Used %d tracks\n", num_tracks_used); }
/* Read from file containing key point matches. The matches are added to the list of matches/MatchTable. The filename is determined by the two images whose matches should be loaded. If the file doesn't exist, then no matched were found between the two images. The file is presumed to be called match-XXX-YYY.txt and should be found in the match directory. */ void BaseApp::ReadMatchFile(int i, int j) { char buf[256]; sprintf(buf, "%s/match-%03d-%03d.txt", m_match_directory, i, j); if (FileExists(buf)) { FILE *f = fopen(buf, "r"); // Read the number of matches. int num_matches; fscanf(f, "%d", &num_matches); // If less than minimum allowed, don't bother, move on. if (num_matches < MIN_MATCHES) { fclose(f); return; } SetMatch(i, j); std::vector<KeypointMatch> matches; for (int k = 0; k < num_matches; k++) { int idx1, idx2; fscanf(f, "%d %d", &idx1, &idx2); #ifdef KEY_LIMIT if (idx1 > KEY_LIMIT || idx2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ KeypointMatch m; m.m_idx1 = idx1; m.m_idx2 = idx2; matches.push_back(m); } MatchIndex idx = GetMatchIndex(i, j); m_matches.GetMatchList(idx) = matches; fclose(f); } }
/* Use the bundle-adjusted points to create a new set of matches */ void BaseApp::SetMatchesFromPoints(int threshold) { LOGI("[BaseApp::SetMatchesFromPoints] Setting up matches...\n"); /* Clear all matches */ // ClearMatches(); RemoveAllMatches(); int num_points = (int) m_point_data.size(); for (int i = 0; i < num_points; i++) { int num_views = (int) m_point_data[i].m_views.size(); if (num_views < threshold) continue; for (int j = 0; j < num_views; j++) { for (int k = 0; k < num_views; k++) { if (j == k) continue; ImageKey view1 = m_point_data[i].m_views[j]; ImageKey view2 = m_point_data[i].m_views[k]; int v1 = view1.first; int v2 = view2.first; int k1 = view1.second; int k2 = view2.second; KeypointMatch m; m.m_idx1 = k1; m.m_idx2 = k2; // m_matches[v1 * num_images + v2] = true; SetMatch(v1, v2); MatchIndex idx = GetMatchIndex(v1, v2); // m_match_lists[idx].push_back(m); m_matches.AddMatch(idx, m); } } } LOGI("[BaseApp::SetMatchesFromPoints] Done!\n"); }
void BaseApp::LoadMatchIndexes(const char *index_dir) { int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { char buf[256]; sprintf(buf, "%s/match-%03d.txt", index_dir, i); FILE *f = fopen(buf, "r"); if (f == NULL) continue; printf("[LoadMatchIndexes] Loading matches for image %d... ", i); int num_matched_images = 0; int index; while(fgets(buf, 256, f) != NULL) { sscanf(buf, "%d\n", &index); int num_matches; fscanf(f, "%d\n", &num_matches); std::vector<KeypointMatch> matches; for (int k = 0; k < num_matches-1; k++) {//-1 is a temp hack int idx1, idx2; fscanf(f, "%d %d\n", &idx1, &idx2); #ifdef KEY_LIMIT if (idx1 > KEY_LIMIT || idx2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ KeypointMatch m; m.m_idx1 = idx1; m.m_idx2 = idx2; matches.push_back(m); } if (num_matches < MIN_MATCHES || index >= num_images) { if (index >= num_images) printf("[LoadMatchIndexes] image index %d > num_images\n", index); // RemoveMatch(i, index); matches.clear(); } else { SetMatch(i, index); MatchIndex idx = GetMatchIndex(i, index); // m_match_lists[idx] = matches; m_matches.GetMatchList(idx) = matches; num_matched_images++; } } printf("%d match files loaded.\n", num_matched_images); fflush(stdout); fclose(f); } }
void BaseApp::ReadMatchTable(const char *append) { int num_images = GetNumImages(); unsigned long int num_matches_total = 0; char buf[256]; sprintf(buf, "nmatches%s.txt", append); FILE *f0 = fopen(buf, "r"); sprintf(buf, "matches%s.txt", append); FILE *f1 = fopen(buf, "r"); if (f0 == NULL || f1 == NULL) { printf("[ReadMatchTable] " "Error opening files for reading.\n"); return; } int num_images_check; fscanf(f0, "%d\n", &num_images_check); assert(num_images == num_images_check); RemoveAllMatches(); for (int i = 0; i < num_images; i++) { for (int j = 0; j < num_images; j++) { MatchIndex idx = GetMatchIndex(i, j); int num_matches; fscanf(f0, "%d", &num_matches); if (num_matches > 0) { // m_match_lists[idx].clear(); SetMatch(i, j); std::vector<KeypointMatch> &list = m_matches.GetMatchList(idx); // m_matches.ClearMatch(idx); for (int k = 0; k < num_matches; k++) { KeypointMatch m; int idx1, idx2; fscanf(f1, "%d %d", &(idx1), &(idx2)); #ifdef KEY_LIMIT if (idx1 > KEY_LIMIT || idx2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ m.m_idx1 = idx1; m.m_idx2 = idx2; // m_match_lists[idx].push_back(m); list.push_back(m); } num_matches_total += num_matches; } } } printf("[ReadMatchTable] Read %lu matches in total\n", num_matches_total); fclose(f0); fclose(f1); }
/* Load the keypoint indices for the matched points. For each image, there is a specific file with this information. Loop through all images and load the data from the corresponding file. Populate the match table. TODO: Correct to that it is LoadMatchIndices. */ void BaseApp::LoadMatchIndexes(const char *index_dir) { int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) // For each image, try to load file ... { char buf[256]; sprintf(buf, "%s/match-%03d.txt", index_dir, i); FILE *f = fopen(buf, "r"); if (f == NULL) continue; #ifdef _DEBUG_ printf("[LoadMatchIndexes] Loading matches for image %d... ", i); #endif int num_matched_images = 0; int index; while(fgets(buf, 256, f) != NULL) // If file has data, then process it ... { sscanf(buf, "%d\n", &index); int num_matches; fscanf(f, "%d\n", &num_matches); std::vector<KeypointMatch> matches; for (int k = 0; k < (num_matches-1); k++) //-1 is a temp hack { int idx1, idx2; fscanf(f, "%d %d\n", &idx1, &idx2); #ifdef KEY_LIMIT if (idx1 > KEY_LIMIT || idx2 > KEY_LIMIT) continue; #endif /* KEY_LIMIT */ KeypointMatch m; m.m_idx1 = idx1; m.m_idx2 = idx2; matches.push_back(m); } if (num_matches < MIN_MATCHES || index >= num_images) // Bum matches. { matches.clear(); // Clear out whatever was loaded. if (index >= num_images) // Kick out a warning message. printf("[LoadMatchIndexes] image index %d > num_images\n", index); } else // Good matches. { SetMatch(i, index); // Add to table. MatchIndex idx = GetMatchIndex(i, index); m_matches.GetMatchList(idx) = matches; num_matched_images++; // Keep count. } } #ifdef _DEBUG_ printf("%d match files loaded.\n", num_matched_images); fflush(stdout); #endif fclose(f); } }
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"); } }