/* 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(); }
/* Read the ignore file */ void BaseApp::ReadIgnoreFile() { if (m_ignore_file == NULL) return; FILE *f = fopen(m_ignore_file, "r"); if (f == NULL) { printf("[ReadIgnoreFile] Error opening file %s " "for reading\n", m_ignore_file); return; } char buf[256]; int num_images = GetNumImages(); while (fgets(buf, 255, f)) { int img = atoi(buf); if (img < 0 || img >= num_images) { printf("[ReadIgnoreFile] " "Error: image %d out of range\n", img); continue; } printf("[ReadIgnoreFile] Ignoring image %d\n", img); m_image_data[img].m_ignore_in_bundle = true; } fclose(f); fflush(stdout); }
void BaseApp::CreateTracksFromPoints() { m_track_data.clear(); int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { m_image_data[i].m_visible_points.clear(); m_image_data[i].m_visible_keys.clear(); } int num_points = m_point_data.size(); for (int i = 0; i < num_points; i++) { TrackData track; track.m_views = m_point_data[i].m_views; m_track_data.push_back(track); int num_views = (int) m_point_data[i].m_views.size(); for (int j = 0; j < num_views; j++) { int v = m_point_data[i].m_views[j].first; int k = m_point_data[i].m_views[j].second; m_image_data[v].m_visible_points.push_back(i); m_image_data[v].m_visible_keys.push_back(k); } } }
/* Prune points that match to multiple targets */ void BaseApp::PruneDoubleMatches() { unsigned int num_images = GetNumImages(); for (unsigned int i = 0; i < num_images; i++) { MatchAdjList::iterator iter; std::vector<unsigned int> remove; for (iter = m_matches.Begin(i); iter != m_matches.End(i); iter++) { HashSetInt seen; int num_pruned = 0; // MatchIndex idx = *iter; // GetMatchIndex(i, j); std::vector<KeypointMatch> &list = iter->m_match_list; /* Unmark keys */ // int num_matches = (int) m_match_lists[idx].size(); int num_matches = (int) list.size(); for (int k = 0; k < num_matches; k++) { int idx2 = list[k].m_idx2; // if (GetKey(j,idx2).m_extra != -1) { if (seen.find(idx2) != seen.end()) { /* This is a repeat */ // printf("[%d] Pruning repeat %d\n", i, idx2); list.erase(list.begin() + k); num_matches--; k--; num_pruned++; } else { /* Mark this key as matched */ // GetKey(j,idx2).m_extra = k; seen.insert(idx2); } } // unsigned int i = iter->first; // unsigned int j = iter->second; unsigned int j = iter->m_index; // first; printf("[PruneDoubleMatches] Pruned[%d,%d] = %d / %d\n", i, j, num_pruned, num_matches + num_pruned); if (num_matches < m_min_num_feat_matches) { /* Get rid of... */ remove.push_back(iter->m_index); // first); } } for (unsigned int j = 0; j < remove.size(); j++) { int idx2 = remove[j]; m_matches.RemoveMatch(GetMatchIndex(i, idx2)); printf("[PruneDoubleMatches] Removing[%d,%d]\n", i, idx2); } } }
/* Grab the color of each keypoint */ void BaseApp::ReadKeyColors() { int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { m_image_data[i].ReadKeyColors(); } }
/* Clear the current model */ void BaseApp::ClearModel() { int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { m_image_data[i].m_camera.m_adjusted = false; } m_point_data.clear(); }
/* 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(); }
int BaseApp::FindImageWithName(const char *name) { int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { if (strcmp(m_image_data[i].m_name, name) == 0) return i; } return -1; }
/* 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 SkpModel::print_all_counts(){ std::cout << "Definitions: " << GetNumDefinitions() << "\n"; std::cout << "Instances: " << GetNumInstances() << "\n"; std::cout << "Groups: " << GetNumGroups() << "\n"; std::cout << "Faces: " << GetNumFaces() << "\n"; std::cout << "Images: " << GetNumImages() << "\n"; std::cout << "Edges: " << GetNumEdges() << "\n"; std::cout << "Guides: " << GetNumGuides() << "\n"; std::cout << "Curves: " << GetNumCurves() << "\n"; }
/* Read intrinsics */ void BaseApp::ReadIntrinsicsFile() { printf("[ReadIntrinsicsFile] Reading intrinsics...\n"); assert(m_intrinsics_file != NULL); FILE *f = fopen(m_intrinsics_file, "r"); assert(f != NULL); int num_intrinsics = 0; fscanf(f, "%d\n", &num_intrinsics); std::vector<intrinsics_t> Ks; for (int i = 0; i < num_intrinsics; i++) { intrinsics_t I; fscanf(f, "%lf %lf %lf %lf %lf %lf %lf %lf %lf\n", I.K + 0, I.K + 1, I.K + 2, I.K + 3, I.K + 4, I.K + 5, I.K + 6, I.K + 7, I.K + 8); fscanf(f, "%lf %lf %lf %lf %lf\n", I.k + 0, I.k + 1, I.k + 2, I.k + 3, I.k + 4); Ks.push_back(I); } int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { assert(m_image_data[i].m_has_init_focal); double f = m_image_data[i].m_init_focal; double min_dist = DBL_MAX; int best_K = -1; for (int j = 0; j < num_intrinsics; j++) { double f_j = 0.5 * (Ks[j].K[0] + Ks[j].K[4]); double dist = fabs(f_j - f); if (dist < min_dist) { best_K = j; min_dist = dist; } } printf(" image %d has intrinsics %d\n", i, best_K); memcpy(m_image_data[i].m_K, Ks[best_K].K, 9 * sizeof(double)); memcpy(m_image_data[i].m_k, Ks[best_K].k, 5 * sizeof(double)); m_image_data[i].m_known_intrinsics = true; } fclose(f); }
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); }
/* 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; }
/* Get the index of a registered camera */ int BaseApp::GetRegisteredCameraIndex(int cam) { int num_images = GetNumImages(); int count = 0; for (int i = 0; i < num_images; i++) { if (m_image_data[i].m_camera.m_adjusted) { if (count == cam) return i; count++; } } printf("[SifterApp::GetRegisteredCameraIndex] " "Error: ran out of cameras\n"); return -1; }
void BaseApp::ReindexPoints() { int num_images = GetNumImages(); int adjusted = 0; int *reindex = new int[num_images]; m_num_views_orig.clear(); for (int i = 0; i < num_images; i++) { if (m_image_data[i].m_camera.m_adjusted && m_image_data[i].m_licensed) { reindex[i] = adjusted; adjusted++; } } int num_points = m_point_data.size(); for (int i = 0; i < num_points; i++) { int num_views = (int) m_point_data[i].m_views.size(); m_num_views_orig.push_back(num_views); for (int j = 0; j < num_views; j++) { int v = m_point_data[i].m_views[j].first; if (!m_image_data[v].m_camera.m_adjusted || !m_image_data[v].m_licensed) { m_point_data[i].m_views.erase(m_point_data[i].m_views.begin() + j); j--; num_views--; } else { m_point_data[i].m_views[j].first = reindex[v]; } } } delete [] reindex; }
/* Load keys from a file */ void BaseApp::LoadKeys(bool descriptor) { printf("[LoadKeys] Loading keys...\n"); clock_t start = clock(); int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { printf("[LoadKeys] Loading keys from image %d...\n", i); fflush(stdout); m_image_data[i].LoadKeys(descriptor); } clock_t end = clock(); printf("[LoadKeys] Loaded keys in %0.3fs\n", (end - start) / (double) CLOCKS_PER_SEC); }
size_t DDSImage::Read(const char* pData, const size_t dataSize) { // Read in header and decode if (!ReadHeader(pData, surfacedata_)) return -1; if (surfacedata_.mipmapcount==0) surfacedata_.mipmapcount=1; imgdata_.height = surfacedata_.height; imgdata_.width = surfacedata_.width; if(surfacedata_.flags & DDS::DDSD_DEPTH) imgdata_.depth = surfacedata_.depth; else imgdata_.depth = 0; // no depth to these images imgdata_.colourdepth = surfacedata_.pixelformat.RGBBitCount; imgdata_.numMipMaps = surfacedata_.mipmapcount; imgdata_.format = GetTextureFormat(); imgdata_.numImages = GetNumImages(); imgdata_.size = CalculateStoreageSize(); if(0 >= imgdata_.size) return -1; if(-1 == imgdata_.format) return -1; const long headerSize=128; const size_t DDSStructSize = sizeof(DDS::DDSStruct)+4; // proceed with allocating memory and reading the file imgdata_.imgData = new byte[imgdata_.size]; // Read in remaining data memcpy(imgdata_.imgData, pData + headerSize, dataSize-headerSize); return dataSize - headerSize; }
void BaseApp::SetTracksFromPoints() { int num_images = GetNumImages(); int num_points = (int) m_point_data.size(); for (int i = 0; i < num_images; i++) { int num_keys = (int) m_image_data[i].m_keys.size(); for (int j = 0; j < num_keys; j++) { m_image_data[i].m_keys[j].m_track = -1; } } for (int i = 0; i < num_points; i++) { int num_views = (int) m_point_data[i].m_views.size(); for (int j = 0; j < num_views; j++) { ImageKey &k = m_point_data[i].m_views[j]; m_image_data[k.first].m_keys[k.second].m_track = i; } } }
/* Initialize images read from a file without performing bundle * adjustment */ void BaseApp::InitializeImagesFromFile(FILE *f) { char buf[256]; int num_images = GetNumImages(); while (fgets(buf, 256, f)) { ImageData data; data.InitFromString(buf, m_image_directory, false); data.m_licensed = true; printf("[InitializeImagesFromFile] Initializing image %s\n", data.m_name); /* Read the extra data */ int img_idx = (int) m_image_data.size(); if (data.ReadCamera() && data.ReadTracks(img_idx, m_point_data)) { data.ReadMetadata(); data.m_added = true; m_image_data.push_back(data); } } UnscaleCameras(num_images); }
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"); } }
/* 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); } }
/* 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; }
/* Read in information about the "world" from the specified file. */ void BaseApp::ReadBundleFile(char *filename) { #ifdef _DEBUG_ printf("[BaseApp::ReadBundleFile] Reading file...\n"); #endif //--[1] See if file will open ... FILE *f = fopen(filename, "r"); if (f == NULL) { printf("Error opening file %s for reading\n", filename); return; } //--[2] If so, then process the header. Get #images and #points. int num_images, num_points; char first_line[256]; fgets(first_line, 256, f); if (first_line[0] == '#') { double version; sscanf(first_line, "# Bundle file v%lf", &version); m_bundle_version = version; fscanf(f, "%d %d\n", &num_images, &num_points); #ifdef _DEBUG_ printf("[ReadBundleFile] Bundle version: %0.3f\n", version); #endif } else if (first_line[0] == 'v') { double version; sscanf(first_line, "v%lf", &version); m_bundle_version = version; fscanf(f, "%d %d\n", &num_images, &num_points); #ifdef _DEBUG_ printf("[ReadBundleFile] Bundle version: %0.3f\n", version); #endif } else { m_bundle_version = 0.1; sscanf(first_line, "%d %d\n", &num_images, &num_points); } #ifdef _DEBUG_ printf("[BaseApp::ReadBundleFile] Reading %d images and %d points...\n", num_images, num_points); #endif if (num_images != GetNumImages()) // Compare to known info (sanity check). { printf("Error: number of images doesn't match file!\n"); return; } //--[3] Read in camera information. (One camera per image, yeah?) // Camera has focal length, two nonlinear parms, and extrinsic parms. for (int i = 0; i < num_images; i++) { double focal_length; double R[9]; double t[3]; double k[2] = { 0.0, 0.0 }; if (m_bundle_version >= 0.4) { char name[512]; int w, h; fscanf(f, "%s %d %d\n", name, &w, &h); } //--[3.1] Focal length if (m_bundle_version > 0.1) fscanf(f, "%lf %lf %lf\n", &focal_length, k+0, k+1); else fscanf(f, "%lf\n", &focal_length); //--[3.2] Rotation fscanf(f, "%lf %lf %lf\n%lf %lf %lf\n%lf %lf %lf\n", R+0, R+1, R+2, R+3, R+4, R+5, R+6, R+7, R+8); //--[3.3] Translation fscanf(f, "%lf %lf %lf\n", t+0, t+1, t+2); //--[3.4] If data is "sane" then aggregate data into camera info object. if (focal_length <= 100.0 || m_image_data[i].m_ignore_in_bundle) { /* No (or bad) information about this camera */ m_image_data[i].m_camera.m_adjusted = false; } else { CameraInfo cd; cd.m_adjusted = true; cd.m_width = m_image_data[i].GetWidth(); cd.m_height = m_image_data[i].GetHeight(); cd.m_focal = focal_length; cd.m_k[0] = k[0]; cd.m_k[1] = k[1]; memcpy(cd.m_R, R, sizeof(double) * 9); memcpy(cd.m_t, t, sizeof(double) * 3); cd.Finalize(); m_image_data[i].m_camera = cd; } } //--[4] Read in the points of the bundle/world point cloud. m_point_data.clear(); m_point_data.resize(num_points); int num_min_views_points = 0; for (int i = 0; i < num_points; i++) { PointData &pt = m_point_data[i]; //--[4.1] Position fscanf(f, "%lf %lf %lf\n", pt.m_pos + 0, pt.m_pos + 1, pt.m_pos + 2); //--[4.2] Color fscanf(f, "%f %f %f\n", pt.m_color + 0, pt.m_color + 1, pt.m_color + 2); //--[4.3] Visibility info (frame, keypoint index, coord location). int num_visible; fscanf(f, "%d", &num_visible); // How many images have this point? pt.m_num_vis=num_visible; if (num_visible >=3) // If more than three, add as good point. num_min_views_points++; for (int j = 0; j < num_visible; j++) { int view, key; fscanf(f, "%d %d", &view, &key); if (m_image_data[view].m_camera.m_adjusted) { /* Check chirality */ bool val = (m_bundle_version >= 0.3); double proj_test[2]; if (m_image_data[view].m_camera.Project(pt.m_pos, proj_test) == val) { pt.m_views.push_back(ImageKey(view, key)); } else { printf("[BaseApp::ReadBundleFile] " "Excluding view %d from point %d [chirality]\n", view, i); } } if (m_bundle_version >= 0.3) { double x, y; fscanf(f, "%lf %lf", &x, &y); } } // #define CROP_POINT_CLOUD #ifdef CROP_POINT_CLOUD const double x_min = 1.327; const double x_max = 3.556; const double y_min = -1.414; const double y_max = 1.074; const double z_min = -5.502; const double z_max = -3.288; if (pt.m_pos[0] < x_min || pt.m_pos[0] > x_max || pt.m_pos[1] < y_min || pt.m_pos[1] > y_max || pt.m_pos[2] < z_min || pt.m_pos[2] > z_max) pt.m_views.clear(); #endif /* CROP_POINT_CLOUD */ } fclose(f); #ifdef _DEBUG_ printf("[BaseApp::ReadBundleFile] %d / %d points visible to over 2 cameras!\n", num_min_views_points, num_points); #endif }
bool BundlerApp::OnInit() { printf("[OnInit] Running program %s\n", argv[0]); char *imageList; bool load_file = false; if (argc >= 2) { printf("Loading images from file '%s'\n", argv[1]); imageList = argv[1]; load_file = true; } else { PrintUsage(); exit(0); } printf("[BundlerApp::OnInit] Processing options...\n"); ProcessOptions(argc - 1, argv + 1); if (m_use_intrinsics && m_estimate_distortion) { printf("Error: --intrinsics and --estimate_distortion " "are incompatible\n"); exit(1); } if (m_fixed_focal_length && m_estimate_distortion) { printf("Error: --fixed_focal_length and --estimate_distortion " "are currently incompatible\n"); exit(1); } printf("[BundlerApp::OnInit] Loading frame...\n"); printf("[BundlerApp::OnInit] Loading images...\n"); fflush(stdout); if (load_file) { FILE *f = fopen(imageList, "r"); if (f == NULL) { printf("[BundlerApp::OnInit] Error opening file %s for reading\n", imageList); exit(1); } LoadImageNamesFromFile(f); int num_images = GetNumImages(); if (m_fisheye) { double fCx = 0.0, fCy = 0.0, fRad = 0.0, fAngle = 0.0, fFocal = 0.0; ReadFisheyeParameters(m_fisheye_params, fCx, fCy, fRad, fAngle, fFocal); for (int i = 0; i < num_images; i++) { if (m_image_data[i].m_fisheye) { m_image_data[i].m_fCx = fCx; m_image_data[i].m_fCy = fCy; m_image_data[i].m_fRad = fRad; m_image_data[i].m_fAngle = fAngle; m_image_data[i].m_fFocal = fFocal; } } } fclose(f); } if (m_rerun_bundle) { // ReadCameraConstraints(); assert(m_bundle_provided); printf("[BundlerApp::OnInit] Reading bundle file...\n"); ReadBundleFile(m_bundle_file); if (m_bundle_version < 0.3) { printf("[BundlerApp::OnInit] Reflecting scene...\n"); FixReflectionBug(); } ReRunSFM(); exit(0); } if (m_use_constraints) { ReadCameraConstraints(); } if (m_ignore_file != NULL) { printf("[BundlerApp::OnInit] Reading ignore file...\n"); ReadIgnoreFile(); } if (m_ignore_file != NULL) { printf("[BundlerApp::OnInit] Reading ignore file...\n"); ReadIgnoreFile(); } /* Do bundle adjustment (or read from file if provided) */ // ParseCommand("UndistortAll", NULL); if (m_bundle_provided) { printf("[BundlerApp::OnInit] Reading bundle file...\n"); ReadBundleFile(m_bundle_file); if (m_bundle_version < 0.3) { printf("[BundlerApp::OnInit] Reflecting scene...\n"); FixReflectionBug(); } if (m_compress_list) { OutputCompressed(); return 0; } if (m_reposition_scene) { double center[3], R[9], scale; RepositionScene(center, R, scale); OutputCompressed("reposition"); return 0; } if (m_prune_bad_points) { SetupImagePoints(3); RemoveBadImages(24); PruneBadPoints(); OutputCompressed("pruned"); return 0; } if (m_scale_focal != 1.0) { ScaleFocalLengths(m_scale_focal); return 0; } if (m_scale_focal_file != NULL) { ScaleFocalLengths(m_scale_focal_file); return 0; } if (m_rotate_cameras_file != NULL) { RotateCameras(m_rotate_cameras_file); } if (m_track_file != NULL) { CreateTracksFromPoints(); WriteTracks(m_track_file); } if (m_zero_distortion_params) { ZeroDistortionParams(); OutputCompressed("nord"); return 0; } if (m_output_relposes) { double center[3], R[9], scale; RepositionScene(center, R, scale); RepositionScene(center, R, scale); // OutputRelativePoses2D(m_output_relposes_file); OutputRelativePoses3D(m_output_relposes_file); return 0; } if (m_compute_covariance) { ComputeCameraCovariance(); return 0; } #define MIN_POINT_VIEWS 3 // 0 // 2 if (!m_run_bundle) { SetMatchesFromPoints(MIN_POINT_VIEWS); // WriteMatchTableDrew(".final"); printf("[BundlerApp::OnInit] " "Setting up image points and lines...\n"); SetupImagePoints(/*2*/ MIN_POINT_VIEWS); RemoveBadImages(6); if (m_point_constraint_file != NULL) { printf("[BundlerApp::OnInit] Reading point constraints...\n"); m_use_point_constraints = true; ReadPointConstraints(); } printf("[BundlerApp::OnInit] Scaling world...\n"); printf("[BundlerApp::OnInit] Computing camera orientations...\n"); ComputeImageRotations(); double center[3], R[9], scale; RepositionScene(center, R, scale); if (m_rerun_bundle) { ReRunSFM(); } } if (m_add_image_file != NULL) { printf("[BundlerApp::OnInit] Adding additional images...\n"); FILE *f = fopen(m_add_image_file, "r"); if (f == NULL) { printf("[BundlerApp::OnInit] Error opening file %s for " "reading\n", m_add_image_file); } else { BundleImagesFromFile(f); /* Write the output */ OutputCompressed("added"); if (m_bundle_version < 0.3) FixReflectionBug(); // RunSFMWithNewImages(4); fclose(f); } } } if (m_run_bundle) { if (!m_fast_bundle) BundleAdjust(); else BundleAdjustFast(); if (m_bundle_version < 0.3) FixReflectionBug(); exit(0); } return true; }
void BaseApp::ReloadBundleFile(const char *filename) { #ifndef __DEMO__ /* Count the old number of cameras */ int num_images = GetNumImages(); int old_num_cameras = 0; for (int i = 0; i < num_images; i++) { if (m_image_data[i].m_camera.m_adjusted) old_num_cameras++; } /* Save the previous model */ std::vector<PointData> old_points = m_point_data; std::vector<ImageData> old_images = m_image_data; /* Load the new model */ ClearModel(); ReadBundleFile(filename); if (m_bundle_version < 0.3) FixReflectionBug(); /* Count the new number of cameras */ int num_cameras = 0; for (int i = 0; i < num_images; i++) { if (m_image_data[i].m_camera.m_adjusted) num_cameras++; } int old_num_points = old_points.size(); int new_num_points = m_point_data.size(); std::vector<v3_t> points_old_csp, points_new_csp; /* Find point correspondences */ for (int i = 0; i < old_num_points; i++) { for (int j = i - 5; j < i + 5; j++) { if (j < 0 || j >= new_num_points) continue; float *old_col = old_points[i].m_color; float *col = m_point_data[j].m_color; if (old_col[0] == col[0] && old_col[1] == col[1] && old_col[2] == col[2]) { double *old_pos = old_points[i].m_pos; double *pos = m_point_data[i].m_pos; points_old_csp.push_back(v3_new(old_pos[0], old_pos[1], old_pos[2])); points_new_csp.push_back(v3_new(pos[0], pos[1], pos[2])); goto Next; } } Next: ; } int num_csp_points = points_old_csp.size(); int num_points = old_num_cameras + num_csp_points; v3_t *left_points = new v3_t[num_points]; v3_t *right_points = new v3_t[num_points]; int count = 0; for (int i = 0; i < num_images; i++) { if (old_images[i].m_camera.m_adjusted) { double left_pos[3], right_pos[3]; m_image_data[i].m_camera.GetPosition(left_pos); old_images[i].m_camera.GetPosition(right_pos); left_points[count] = v3_new(left_pos[0], left_pos[1], left_pos[2]); right_points[count] = v3_new(right_pos[0], right_pos[1], right_pos[2]); count++; } } for (int i = 0; i < num_csp_points; i++) { left_points[count] = points_new_csp[i]; right_points[count] = points_old_csp[i]; count++; } /* Do the registration */ double T[16]; align_horn_3D(num_points, right_points, left_points, 1, T); /* Transform the world */ memcpy(m_xform, T, 16 * sizeof(double)); TransformWorldReal(); // TransformWorld(); delete [] left_points; delete [] right_points; #endif /* __DEMO__ */ }
/* Read in information about the world */ void BaseApp::ReadBundleFile(const char *filename) { printf("[ReadBundleFile] Reading file...\n"); FILE *f = fopen(filename, "r"); if (f == NULL) { printf("Error opening file %s for reading\n", filename); return; } int num_images, num_points; char first_line[256]; fgets(first_line, 256, f); if (first_line[0] == '#') { double version; sscanf(first_line, "# Bundle file v%lf", &version); m_bundle_version = version; printf("[ReadBundleFile] Bundle version: %0.3f\n", version); fscanf(f, "%d %d\n", &num_images, &num_points); } else if (first_line[0] == 'v') { double version; sscanf(first_line, "v%lf", &version); m_bundle_version = version; printf("[ReadBundleFile] Bundle version: %0.3f\n", version); fscanf(f, "%d %d\n", &num_images, &num_points); } else { m_bundle_version = 0.1; sscanf(first_line, "%d %d\n", &num_images, &num_points); } printf("[ReadBundleFile] Reading %d images and %d points...\n", num_images, num_points); if (num_images != GetNumImages()) { printf("Error: number of images doesn't match file!\n"); return; } /* Read cameras */ for (int i = 0; i < num_images; i++) { double focal_length; double R[9]; double t[3]; double k[2] = { 0.0, 0.0 }; if (m_bundle_version >= 0.4) { char name[512]; int w, h; fscanf(f, "%s %d %d\n", name, &w, &h); } /* Focal length */ if (m_bundle_version > 0.1) { fscanf(f, "%lf %lf %lf\n", &focal_length, k+0, k+1); } else { fscanf(f, "%lf\n", &focal_length); } /* Rotation */ fscanf(f, "%lf %lf %lf\n%lf %lf %lf\n%lf %lf %lf\n", R+0, R+1, R+2, R+3, R+4, R+5, R+6, R+7, R+8); /* Translation */ fscanf(f, "%lf %lf %lf\n", t+0, t+1, t+2); #if 0 if (m_bundle_version < 0.3) { R[2] = -R[2]; R[5] = -R[5]; R[6] = -R[6]; R[7] = -R[7]; t[2] = -t[2]; } #endif if (focal_length <= 100.0 || m_image_data[i].m_ignore_in_bundle) { /* No (or bad) information about this camera */ m_image_data[i].m_camera.m_adjusted = false; } else { CameraInfo cd; cd.m_adjusted = true; cd.m_width = m_image_data[i].GetWidth(); cd.m_height = m_image_data[i].GetHeight(); cd.m_focal = focal_length; cd.m_k[0] = k[0]; cd.m_k[1] = k[1]; memcpy(cd.m_R, R, sizeof(double) * 9); memcpy(cd.m_t, t, sizeof(double) * 3); cd.Finalize(); m_image_data[i].m_camera = cd; } } /* Read points */ m_point_data.clear(); m_point_data.resize(num_points); int num_min_views_points = 0; for (int i = 0; i < num_points; i++) { PointData &pt = m_point_data[i]; /* Position */ fscanf(f, "%lf %lf %lf\n", pt.m_pos + 0, pt.m_pos + 1, pt.m_pos + 2); // if (m_bundle_version < 0.3) // pt.m_pos[2] = -pt.m_pos[2]; /* Color */ fscanf(f, "%f %f %f\n", pt.m_color + 0, pt.m_color + 1, pt.m_color + 2); int num_visible; fscanf(f, "%d", &num_visible); pt.m_num_vis=num_visible; if (num_visible >=3) num_min_views_points++; // pt.m_views.resize(num_visible); for (int j = 0; j < num_visible; j++) { int view, key; fscanf(f, "%d %d", &view, &key); if (!m_image_data[view].m_camera.m_adjusted) { // printf("[ReadBundleFile] " // "Removing view %d from point %d\n", view, i); } else { /* Check cheirality */ bool val = (m_bundle_version >= 0.3); double proj_test[2]; if (m_image_data[view].m_camera. Project(pt.m_pos, proj_test) == val) { pt.m_views.push_back(ImageKey(view, key)); } else { printf("[ReadBundleFile] " "Removing view %d from point %d [cheirality]\n", view, i); // pt.m_views.push_back(ImageKey(view, key)); } } // pt.m_views.push_back(ImageKey(view, key)); if (m_bundle_version >= 0.3) { double x, y; fscanf(f, "%lf %lf", &x, &y); } } // #define CROP_POINT_CLOUD #ifdef CROP_POINT_CLOUD const double x_min = 1.327; const double x_max = 3.556; const double y_min = -1.414; const double y_max = 1.074; const double z_min = -5.502; const double z_max = -3.288; if (pt.m_pos[0] < x_min || pt.m_pos[0] > x_max || pt.m_pos[1] < y_min || pt.m_pos[1] > y_max || pt.m_pos[2] < z_min || pt.m_pos[2] > z_max) { pt.m_views.clear(); } #endif /* CROP_POINT_CLOUD */ } #if 0 /* Read outliers */ int num_outliers; fscanf(f, "%d", &num_outliers); for (int i = 0; i < num_outliers; i++) { ImageKey ik; fscanf(f, "%d %d", &(ik.first), &(ik.second)); m_outliers.push_back(ik); } #endif fclose(f); printf("[ReadBundleFile] %d / %d points visible to more than 2 cameras!\n", num_min_views_points, num_points); }
/* 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::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); } }
/* Coalesce feature descriptors for each feature point */ void BundlerApp::CoalesceFeatureDescriptors() { if (m_features_coalesced) return; int num_points = (int) m_point_data.size(); int *num_observations = new int[num_points]; for (int i = 0; i < num_points; i++) { num_observations[i] = 0; m_point_data[i].m_desc = new float[DESCRIPTOR_LENGTH]; for (int j = 0; j < DESCRIPTOR_LENGTH; j++) m_point_data[i].m_desc[j] = 0.0f; } float *xx = new float[num_points * DESCRIPTOR_LENGTH]; int num_images = GetNumImages(); for (int i = 0; i < num_images; i++) { if (!m_image_data[i].m_camera.m_adjusted) continue; printf("[CoalesceFeatureDescriptors] Adding features from " "image %d\n", i); fflush(stdout); m_image_data[i].LoadKeys(true); for (int j = 0; j < num_points; j++) { int num_views = (int) m_point_data[j].m_views.size(); int key_seen = -1; if (num_views == 0) continue; for (int k = 0; k < num_views; k++) { if (m_point_data[j].m_views[k].first == i) { key_seen = m_point_data[j].m_views[k].second; break; } } if (key_seen >= 0) { KeypointWithDesc &key = GetKeyWithDesc(i, key_seen); for (int k = 0; k < DESCRIPTOR_LENGTH; k++) { float x = (float) key.m_d[k]; m_point_data[j].m_desc[k] += key.m_d[k]; xx[DESCRIPTOR_LENGTH * j + k] += x * x; } num_observations[j]++; } } m_image_data[i].UnloadKeys(); } double *variance = new double[num_points]; for (int i = 0; i < num_points; i++) { if (num_observations[i] != (int) m_point_data[i].m_views.size()) printf("[CoalesceFeatureDescriptors] " "Mismatch in observation count\n"); if (num_observations[i] == 0) continue; for (int j = 0; j < DESCRIPTOR_LENGTH; j++) { m_point_data[i].m_desc[j] /= num_observations[i]; xx[DESCRIPTOR_LENGTH * i + j] /= num_observations[i]; } variance[i] = 0.0; for (int j = 0; j < DESCRIPTOR_LENGTH; j++) { double x = m_point_data[i].m_desc[j]; variance[i] += xx[DESCRIPTOR_LENGTH * i + j] - x * x; } } double median = kth_element(num_points, iround(0.5 * num_points), variance); printf("[CoalesceFeatureDescriptors] Median squared variance: " "%0.3f\n", median); fflush(stdout); delete [] num_observations; delete [] xx; delete [] variance; m_features_coalesced = true; }
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); }