/* 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. }
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 matches from files */ void BaseApp::LoadMatches() { if (m_matches_loaded) return; /* we already loaded the matches */ if (m_match_table != NULL) { LoadMatchTable(m_match_table); } else if (m_match_index_dir != NULL) { LoadMatchIndexes(m_match_index_dir); } else { printf("[LoadMatches] Loading matches\n"); int num_images = GetNumImages(); FILE *f = fopen("match-index.txt", "r"); if (f == NULL) { /* Try all pairs */ for (int i = 0; i < num_images; i++) { for (int j = i+1; j < num_images; j++) { ReadMatchFile(i, j); } } } else { printf("[LoadMatches] Reading matches from 'match-index.txt'\n"); fflush(stdout); /* Set all matches to false */ // ClearMatches(); RemoveAllMatches(); char buf[256]; unsigned int count = 0; while (fgets(buf, 256, f)) { int i1, i2; sscanf(buf, "%d %d\n", &i1, &i2); ReadMatchFile(i1, i2); count++; } printf("[LoadMatches] Read %d match files\n", count); fflush(stdout); fclose(f); } } // WriteMatchTableDrew(".init"); PruneDoubleMatches(); m_matches_loaded = true; }
/* Load a list of image names from a file. Appears to also populate some of the meta-info about where to get key files from/dump them to. */ void BaseApp::LoadImageNamesFromFile(FILE *f) { // m_image_names.clear(); m_image_data.clear(); char buf[256]; int idx = 0; while (fgets(buf, 256, f)) { ImageData data; data.InitFromString(buf, m_image_directory, m_fisheye); // Try to find a keypoint file in key directory, or in current directory. if (strcmp(m_key_directory, ".") != 0) { char key_buf[256]; data.GetBaseName(key_buf); char key_path[512]; sprintf(key_path, "%s/%s.key", m_key_directory, key_buf); data.m_key_name = strdup(key_path); } else { // FIXME: I think this causes a memory leak // TODO: Assumes that filename related to data.m_name. char key_buf[256]; strcpy(key_buf, data.m_name); int len = strlen(key_buf); key_buf[len - 3] = 'k'; key_buf[len - 2] = 'e'; key_buf[len - 1] = 'y'; data.m_key_name = strdup(key_buf); } m_image_data.push_back(data); idx++; } // Create an empty match table m_matches = MatchTable(GetNumImages()); RemoveAllMatches(); m_matches_computed = true; m_num_original_images = GetNumImages(); if (m_use_intrinsics) ReadIntrinsicsFile(); }
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); }
/* 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"); }
/* Load a list of image names from a file */ void BaseApp::LoadImageNamesFromFile(FILE *f) { // m_image_names.clear(); m_image_data.clear(); char buf[256]; int idx = 0; while (fgets(buf, 256, f)) { ImageData data; data.InitFromString(buf, m_image_directory, m_fisheye); /* Try to find a keypoint file */ if (strcmp(m_key_directory, ".") != 0) { char key_buf[256]; data.GetBaseName(key_buf); char key_path[512]; sprintf(key_path, "%s/%s.key", m_key_directory, key_buf); data.m_key_name = strdup(key_path); } else { /* FIXME: I think this causes a memory leak */ char key_buf[256]; strcpy(key_buf, data.m_name); int len = strlen(key_buf); key_buf[len - 3] = 'k'; key_buf[len - 2] = 'e'; key_buf[len - 1] = 'y'; // char key_path[512]; // sprintf(key_path, "%s/%s", m_key_directory, key_buf); data.m_key_name = strdup(key_buf); } // printf("Keyname: %s\n", data.m_key_name); #if 0 if (log != NULL) { log->AppendText(" "); log->AppendText(buf); log->AppendText("\n"); } #endif #if 0 /* Eat the newline */ if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0; /* Split the buffer into tokens */ std::string str(buf); std::vector<std::string> toks; Tokenize(str, toks, " "); #if 0 wxStringTokenizer t(str, wxT(" ")); while (t.HasMoreTokens()) { wxString tok = t.GetNextToken(); toks.push_back(tok); } #endif #if 0 if (log != NULL) { log->AppendText(" "); log->AppendText(buf); log->AppendText("\n"); } #endif int num_toks = (int) toks.size(); bool fisheye = m_fisheye; // false; if (num_toks >= 2) { fisheye = (atoi(toks[1].c_str()) == 1); } bool has_init_focal = false; double init_focal = 0.0; if (num_toks >= 3) { has_init_focal = true; init_focal = atof(toks[2].c_str()); } ImageData data; // m_imgs.push_back(img); // printf("Adding image %s\n", toks[0].c_str()); char buf[512]; sprintf(buf, "%s/%s", m_image_directory, toks[0].c_str()); data.m_name = strdup(buf); data.m_img = NULL; data.m_thumb = NULL; data.m_thumb8 = NULL; data.m_wximage = NULL; data.m_image_loaded = false; data.m_keys_loaded = false; data.m_fisheye = fisheye; data.m_has_init_focal = has_init_focal; data.m_init_focal = init_focal; data.m_camera.m_adjusted = false; data.m_texture_index = -1; #endif m_image_data.push_back(data); idx++; // wxSafeYield(); } // Create the match table m_matches = MatchTable(GetNumImages()); // ClearMatches(); RemoveAllMatches(); m_matches_computed = true; m_num_original_images = GetNumImages(); if (m_use_intrinsics) ReadIntrinsicsFile(); }
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 matches from files. Looks to see if there is a file that specifies which images should be matchedd. There are different options: a match table file, a match file directory, and a default matches text file plus associated key point match files. */ void BaseApp::LoadMatches() { if (m_matches_loaded) // Are matches already loaded? return; if (m_match_table != NULL) // Is there a filename specified? { LoadMatchTable(m_match_table); } else if (m_match_index_dir != NULL) // Or maybe a directory? { LoadMatchIndexes(m_match_index_dir); } else // Otherwise, go to default file(s). { #ifdef _DEBUG_ printf("[LoadMatches] Loading matches\n"); #endif int num_images = GetNumImages(); FILE *f = fopen("match-index.txt", "r"); // Try this file. if (f == NULL) // If not, try individual files. { /* Try all pairs */ for (int i = 0; i < num_images; i++) for (int j = i+1; j < num_images; j++) ReadMatchFile(i, j); } else // If so, the read it. { #ifdef _DEBUG_ printf("[LoadMatches] Reading matches from 'match-index.txt'\n"); fflush(stdout); #endif /* Clear all matches/match table. */ RemoveAllMatches(); char buf[256]; unsigned int count = 0; while (fgets(buf, 256, f)) { int i1, i2; sscanf(buf, "%d %d\n", &i1, &i2); // Read image pair (to load). ReadMatchFile(i1, i2); // Load match info from file. count++; } #ifdef _DEBUG_ printf("[LoadMatches] Read %d match files\n", count); fflush(stdout); #endif _DEBUG_ fclose(f); } } PruneDoubleMatches(); m_matches_loaded = true; }
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"); } }