diff --git a/README.md b/README.md index b714d23..a437b0c 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ If you use the covisibility-based matching method for your research, please cite 3.Run the following script to automatically reconstruction: ``` -python3 ./scripts/auto_reconstruction.py --workspace_path ${workspace_path}$ +python3 ./scripts/run_test_data.py --workspace_path ${workspace_path}$ ``` Refer to [tutorial.md](docs/en/tutorial.md) for more details. diff --git a/README_CN.md b/README_CN.md index 4df1c3d..ac3ec15 100644 --- a/README_CN.md +++ b/README_CN.md @@ -55,7 +55,7 @@ XRSfM 是一个开源的运动恢复结构代码仓库,它是[OpenXRLab](https 3.运行以下脚本进行重建: ``` -python3 ./scripts/auto_reconstruction.py --workspace_path ${workspace_path}$ +python3 ./scripts/run_test_data.py --workspace_path ${workspace_path}$ ``` 更多细节请查看[tutorial.md](docs/zh/tutorial.md) diff --git a/docs/en/tutorial.md b/docs/en/tutorial.md index 8b1fbf4..7393b10 100644 --- a/docs/en/tutorial.md +++ b/docs/en/tutorial.md @@ -126,5 +126,5 @@ workspace ``` Then run the following command line to reconstruct ``` -python3 ./scripts/auto_reconstruction.py --workspace_path ${workspace_path}$ --estimate_scale +python3 ./scripts/run_test_data.py --workspace_path ${workspace_path}$ --estimate_scale ``` diff --git a/docs/zh/tutorial.md b/docs/zh/tutorial.md index b3e0284..7af3206 100644 --- a/docs/zh/tutorial.md +++ b/docs/zh/tutorial.md @@ -130,5 +130,5 @@ workspace ``` 然后通过以下脚本达到相同的效果。 ``` -python3 ./scripts/auto_reconstruction.py --workspace_path ${workspace_path}$ --estimate_scale +python3 ./scripts/run_test_data.py --workspace_path ${workspace_path}$ --estimate_scale ``` diff --git a/scripts/auto_reconstruction.py b/scripts/run_test_data.py similarity index 76% rename from scripts/auto_reconstruction.py rename to scripts/run_test_data.py index bd3a0ec..71ace51 100644 --- a/scripts/auto_reconstruction.py +++ b/scripts/run_test_data.py @@ -6,13 +6,24 @@ def get_opts(): parser = ArgumentParser() parser.add_argument('--workspace_path', type=str, required=True, help='workspace_path') - # parser.add_argument('--start_from_ios_binary',action='store_true', - # help='estimate_scale') parser.add_argument('--estimate_scale', action='store_true', help='estimate_scale') + # parser.add_argument('--start_from_ios_binary',action='store_true', + # help='estimate_scale') return parser.parse_args() +def change_camera_txt_format(data_path): + with open(data_path+'/camera.txt', 'r') as file: + line = file.readline() + + space_index1 = line.find(' ') + space_index2 = line.find(' ', space_index1 + 1) + + with open(data_path+'/camera_colmap.txt', 'w') as file: + file.write(f'0 RADIAL 1440 1920 {line[space_index2+1:]}') + + if __name__ == '__main__': args = get_opts() @@ -22,7 +33,7 @@ def get_opts(): data_path = data_path+'/' images_path = data_path+'images/' - camera_path = data_path+'camera.txt' + camera_path = data_path+'camera_colmap.txt' retrieval_path = data_path+'retrieval.txt' output_path = data_path @@ -30,10 +41,13 @@ def get_opts(): # if(args.start_from_ios_binary): # ios_file = data_path+'Data.txt' # os.system('./bin/unpack_collect_data '+ios_file+' '+data_path) + change_camera_txt_format(data_path) + os.system('./bin/run_matching ' + images_path + ' ' + retrieval_path + ' sequential ' + output_path) os.system('./bin/run_reconstruction ' + output_path + ' ' + camera_path + ' ' + output_path) + if (args.estimate_scale): output_refined_path = data_path+'refined/' if not os.path.exists(output_refined_path): diff --git a/src/base/camera.hpp b/src/base/camera.hpp index fb31ab1..eb74d90 100644 --- a/src/base/camera.hpp +++ b/src/base/camera.hpp @@ -10,6 +10,24 @@ namespace xrsfm { class Camera { public: Camera() {} + Camera(int _id, std::string mode_name, int w, int h) { + id_ = _id; + width_ = w; + height_ = h; + if (mode_name == "SIMPLE_PINHOLE") { + model_id_ = 0; + } else if (mode_name == "PINHOLE") { + model_id_ = 1; + } else if (mode_name == "SIMPLE_RADIAL") { + model_id_ = 2; + } else if (mode_name == "RADIAL") { + model_id_ = 3; + } else if (mode_name == "OPENCV") { + model_id_ = 4; + } + params_.resize(camera_model_param_size(model_id_)); + is_valid = true; + } Camera(int _id, int _model_id) { id_ = _id; model_id_ = _model_id; @@ -26,6 +44,7 @@ class Camera { uint32_t id_ = -1; uint32_t model_id_ = -1; + int width_, height_; std::vector params_; bool is_valid; diff --git a/src/base/camera_model.hpp b/src/base/camera_model.hpp index 825822e..0f06959 100644 --- a/src/base/camera_model.hpp +++ b/src/base/camera_model.hpp @@ -219,17 +219,6 @@ struct OpenCVCameraModel { #endif -inline int camera_model_param_size(int model_id) { -#define CAMERA_MODEL_CASE(CameraModel) \ - if (model_id == CameraModel::kModelId) \ - return CameraModel::kNumParams; - - CAMERA_MODEL_CASES -#undef CAMERA_MODEL_CASE - assert(false); - return -1; -} - inline int index_fx(int model_id) { #define CAMERA_MODEL_CASE(CameraModel) \ if (model_id == CameraModel::kModelId) \ @@ -285,5 +274,16 @@ inline int index_distort(int model_id) { return -1; }; +inline int camera_model_param_size(int model_id) { +#define CAMERA_MODEL_CASE(CameraModel) \ + if (model_id == CameraModel::kModelId) \ + return CameraModel::kNumParams; + + CAMERA_MODEL_CASES +#undef CAMERA_MODEL_CASE + assert(false); + return -1; +} + } // namespace xrsfm #endif diff --git a/src/base/map.h b/src/base/map.h index 421bdec..834de60 100644 --- a/src/base/map.h +++ b/src/base/map.h @@ -115,9 +115,6 @@ class CorrespondenceGraph { class Map { public: - std::vector images_; // for debug - - // std::vector cameras_; std::vector tracks_; std::vector frames_; std::vector frame_pairs_; diff --git a/src/feature/feature_extraction.cc b/src/feature/feature_extraction.cc index 6cac8da..4e5d91c 100644 --- a/src/feature/feature_extraction.cc +++ b/src/feature/feature_extraction.cc @@ -14,7 +14,6 @@ #include "optim/loransac.h" #include "optim/ransac.h" #include "sift_extractor.h" -#include "utility/io_ecim.hpp" #include "utility/timer.h" namespace xrsfm { @@ -38,7 +37,8 @@ void FeatureExtract(const std::string &image_dir_path, for (int i = 0; i < frames.size(); i++) { Frame &frame = frames[i]; frame.keypoints_.clear(); - const cv::Mat image = cv::imread(image_dir_path + frame.name); + const cv::Mat image = cv::imread(image_dir_path + frame.name, + cv::IMREAD_IGNORE_ORIENTATION); if (image.rows == 0) { std::cout << "Can't read " << image_dir_path + frame.name << std::endl; diff --git a/src/feature/feature_processing.cc b/src/feature/feature_processing.cc index 061a86f..687b443 100644 --- a/src/feature/feature_processing.cc +++ b/src/feature/feature_processing.cc @@ -16,7 +16,6 @@ #include "optim/loransac.h" #include "optim/ransac.h" #include "sift_extractor.h" -#include "utility/io_ecim.hpp" #include "utility/timer.h" #include "match_expansion.h" diff --git a/src/geometry/error_corrector.h b/src/geometry/error_corrector.h index 774f217..9e2105a 100644 --- a/src/geometry/error_corrector.h +++ b/src/geometry/error_corrector.h @@ -12,21 +12,11 @@ inline double ToDeg(double theta) { return theta * 180 / M_PI; } class ErrorDetector { public: - Init(std::string image_dir, bool debug) { - debug_ = debug; - image_dir_ = image_dir; - }; - bool CheckAllRelativePose(Map &map, int frame_id, std::set &bad_matched_frame_ids); bool IsGoodRelativePose(const Map &map, const FramePair &fp, std::vector &inlier_mask); - void IsGoodRelativePose_Debug(Map &map, FramePair &fp, - const std::vector &inlier_mask); - // void StoreRelativePose(Map &map, int frame_id, std::ofstream &file); - bool debug_; - // ViewerThread *viewerTh_; std::string image_dir_; }; diff --git a/src/geometry/error_detector.cc b/src/geometry/error_detector.cc index e10da27..d54e6cb 100644 --- a/src/geometry/error_detector.cc +++ b/src/geometry/error_detector.cc @@ -100,29 +100,6 @@ bool ErrorDetector::IsGoodRelativePose(const Map &map, const FramePair &fp, return true; } -void ErrorDetector::IsGoodRelativePose_Debug( - Map &map, FramePair &fp, const std::vector &inlier_mask) { - auto &frame1 = map.frames_[fp.id1]; - auto &frame2 = map.frames_[fp.id2]; - cv::Mat image1 = cv::imread(image_dir_ + frame1.name); - cv::Mat image2 = cv::imread(image_dir_ + frame2.name); - if (image1.empty() || image2.empty()) { - printf("%s\n", (image_dir_ + frame1.name).c_str()); - } else { - // DrawFeatureMatches(image1, image2, frame1.points, frame2.points, - // fp.matches, inlier_mask); - // DrawFeatureMatches1(image1, frame1.points, frame2.points, fp.matches, - // inlier_mask); - } - // frame1.flag_for_view = frame2.flag_for_view = true; - // viewer_->Draw(map, true); - // frame1.flag_for_view = frame2.flag_for_view = false; - frame1.flag_for_view = frame2.flag_for_view = true; - // viewerTh_->update_map(map); - frame1.flag_for_view = frame2.flag_for_view = false; - cv::waitKey(); -} - bool ErrorDetector::CheckAllRelativePose(Map &map, int frame_id, std::set &bad_matched_frame_ids) { bad_matched_frame_ids.clear(); @@ -170,7 +147,6 @@ bool ErrorDetector::CheckAllRelativePose(Map &map, int frame_id, } else { int bad_neighbor_id = fp.id1 == frame_id ? fp.id2 : fp.id1; bad_matched_frame_ids.insert(bad_neighbor_id); - // if (debug_) IsGoodRelativePose_Debug(map, fp, inlier_mask); } } } @@ -182,21 +158,4 @@ bool ErrorDetector::CheckAllRelativePose(Map &map, int frame_id, return true; } -// void ErrorDetector::StoreRelativePose(Map &map, int frame_id, -// std::ofstream &file) { -// for (const auto id : map.frameid2framepairids_[frame_id]) { -// auto &fp = map.frame_pairs_[id]; -// const auto &frame1 = map.frames_[fp.id1]; -// const auto &frame2 = map.frames_[fp.id2]; -// if (frame1.registered && frame2.registered && frame1.is_keyframe && -// frame2.is_keyframe) { -// file << id << std::endl; -// file << frame1.Tcw.q.coeffs().transpose() << " " -// << frame1.Tcw.t.transpose() << std::endl; -// file << frame2.Tcw.q.coeffs().transpose() << " " -// << frame2.Tcw.t.transpose() << std::endl; -// } -// } -// file << "-1" << std::endl; -// } } // namespace xrsfm diff --git a/src/optimization/ba_solver.cc b/src/optimization/ba_solver.cc index 4d81883..0af2f56 100644 --- a/src/optimization/ba_solver.cc +++ b/src/optimization/ba_solver.cc @@ -672,7 +672,6 @@ void BASolver::KGBA(Map &map, const std::vector fix_key_frame_ids, ceres::Solve(solver_options, &problem, &summary); // std::cout << summary.BriefReport() << "\n"; PrintSolverSummary(summary); - map.Camera(0).log(); printf("kf: %d/%d\n", num_kf, num_rf); UpdateByRefFrame(map); diff --git a/src/run_matching.cc b/src/run_matching.cc index ecca6e5..86494ef 100644 --- a/src/run_matching.cc +++ b/src/run_matching.cc @@ -12,8 +12,16 @@ using namespace xrsfm; -void GetFeatures(const std::string &images_path, const std::string &ftr_path, - std::vector &frames) { +void GetFeatures(const std::string &images_path, + const std::vector &image_names, + const std::string &ftr_path, std::vector &frames) { + const int num_image = image_names.size(); + frames.resize(num_image); + for (int i = 0; i < num_image; ++i) { + frames[i].id = i; + frames[i].name = image_names[i]; + } + std::ifstream ftr_bin(ftr_path); if (ftr_bin.good()) { ReadFeatures(ftr_path, frames); @@ -33,7 +41,8 @@ void GetImageSizeVec(const std::string &images_path, LoadImageSize(path, image_size); } else { for (const auto &image_name : image_names) { - const cv::Mat image = cv::imread(images_path + image_name); + const cv::Mat image = cv::imread(images_path + image_name, + cv::IMREAD_IGNORE_ORIENTATION); image_size.push_back(ImageSize(image.cols, image.rows)); } SaveImageSize(path, image_size); @@ -173,27 +182,25 @@ int main(int argc, const char *argv[]) { const std::string fp_init_path = output_path + "fp_init.bin"; const std::string fp_path = output_path + "fp.bin"; - // 1.read imagesstd::filesystem + // 1.read images if (!std::experimental::filesystem::exists(images_path)) { std::cout << "image path not exists :" << images_path << "\n"; exit(-1); } std::vector image_names; LoadImageNames(images_path, image_names); - std::vector image_size_vec; - GetImageSizeVec(images_path, image_names, size_path, image_size_vec); std::map name2id; const int num_image = image_names.size(); - std::vector frames(num_image); for (int i = 0; i < num_image; ++i) { - frames[i].id = i; - frames[i].name = image_names[i]; name2id[image_names[i]] = i; } std::cout << "Load Image Info Done.\n"; // 2.feature extraction - GetFeatures(images_path, ftr_path, frames); + std::vector frames; + std::vector image_size_vec; + GetFeatures(images_path, image_names, ftr_path, frames); + GetImageSizeVec(images_path, image_names, size_path, image_size_vec); std::cout << "Extract Features Done.\n"; // 5.image matching diff --git a/src/run_reconstruction.cc b/src/run_reconstruction.cc index dc6c571..7c582ec 100644 --- a/src/run_reconstruction.cc +++ b/src/run_reconstruction.cc @@ -18,10 +18,12 @@ void PreProcess(const std::string dir_path, const std::string camera_path, std::cout << "ReadFramePairs\n"; // set cameras & image name - Camera seq = ReadCameraIOSRecord(camera_path); + std::map cameras = ReadCamerasText(camera_path); + CHECK_EQ(cameras.size(), 1); + const int camera_id = cameras.begin()->first; for (auto &frame : frames) { - frame.camera_id = seq.id_; + frame.camera_id = camera_id; } // convert keypoint to points(for reconstruction) @@ -36,7 +38,7 @@ void PreProcess(const std::string dir_path, const std::string camera_path, } } - map.camera_map_[seq.id_] = seq; + map.camera_map_ = cameras; map.frames_ = frames; map.frame_pairs_ = frame_pairs; diff --git a/src/tag/tag_extract.hpp b/src/tag/tag_extract.hpp index bedd9c1..818da4b 100644 --- a/src/tag/tag_extract.hpp +++ b/src/tag/tag_extract.hpp @@ -26,7 +26,6 @@ extern "C" { #include "optimization/cost_factor_ceres.h" #include "utility/io_ecim.hpp" #include "utility/timer.h" -// #include "utility/viewer.h" namespace xrsfm { @@ -48,7 +47,7 @@ tag_extract(std::string image_dir) { for (auto &image_name : image_vec) { std::string img_path = image_dir + image_name; cv::Mat frame, gray; - frame = cv::imread(img_path.c_str()); + frame = cv::imread(img_path.c_str(), cv::IMREAD_IGNORE_ORIENTATION); cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); image_u8_t im = {.width = gray.cols, .height = gray.rows, @@ -90,7 +89,7 @@ tag_extract(const std::string &image_dir, for (auto &image_name : image_vec) { std::string img_path = image_dir + image_name; cv::Mat frame, gray; - frame = cv::imread(img_path.c_str()); + frame = cv::imread(img_path.c_str(), cv::IMREAD_IGNORE_ORIENTATION); cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); image_u8_t im = {.width = gray.cols, .height = gray.rows, diff --git a/src/utility/io_ecim.cc b/src/utility/io_ecim.cc index be83d27..77e6377 100644 --- a/src/utility/io_ecim.cc +++ b/src/utility/io_ecim.cc @@ -225,6 +225,10 @@ void WritePoints3DBinary(const std::string &path, } void WriteColMapDataBinary(const std::string &output_path, const Map &map) { + namespace fs = std::experimental::filesystem; + if (!fs::is_directory(output_path)) { + fs::create_directories(output_path); + } WriteCamerasBinary(output_path + "cameras.bin", map.camera_map_); WriteImagesBinary(output_path + "images.bin", map.frames_); WritePoints3DBinary(output_path + "points3D.bin", map.tracks_); diff --git a/src/utility/io_ecim.hpp b/src/utility/io_ecim.hpp index f4e863b..ee6af52 100644 --- a/src/utility/io_ecim.hpp +++ b/src/utility/io_ecim.hpp @@ -19,23 +19,33 @@ namespace xrsfm { -inline Camera ReadCameraIOSRecord(const std::string &file_name) { - Camera cam(0, 2); +inline std::map ReadCamerasText(const std::string &path) { + std::map cameras; + + std::ifstream file(path); + CHECK(file.is_open()) << path; - std::ifstream file(file_name, std::ios::out); std::string line; + std::string item; + while (std::getline(file, line)) { - if (line[0] == '#') + if (line.empty() || line[0] == '#') { continue; - std::string image_name, model_name; + } + std::stringstream ss(line); - ss >> image_name >> model_name; - ss >> cam.params_[0] >> cam.params_[0] >> cam.params_[1] >> - cam.params_[2] >> cam.params_[3]; - break; - } + int camera_id, width, height; + std::string model_name; + ss >> camera_id >> model_name >> width >> height; + Camera camera(camera_id, model_name, width, height); - return cam; + for (int i = 0; i < camera.params_.size(); ++i) { + ss >> camera.params_[i]; + } + cameras.emplace(camera_id, camera); + } + file.close(); + return cameras; } inline void ReadCameraInfo(const std::string &file_name, diff --git a/src/utility/view.cc b/src/utility/view.cc index 86e3acf..3166172 100644 --- a/src/utility/view.cc +++ b/src/utility/view.cc @@ -22,8 +22,10 @@ void DrawMatchesColmap(const std::string dir_path, const FramePair &fp, const Map &map) { auto &f1 = map.frames_[fp.id1]; auto &f2 = map.frames_[fp.id2]; - cv::Mat image1 = cv::imread(dir_path + f1.name); - cv::Mat image2 = cv::imread(dir_path + f2.name); + cv::Mat image1 = + cv::imread(dir_path + f1.name, cv::IMREAD_IGNORE_ORIENTATION); + cv::Mat image2 = + cv::imread(dir_path + f2.name, cv::IMREAD_IGNORE_ORIENTATION); DrawFeatureMatches(image1, image2, f1.points, f2.points, fp.matches); cv::waitKey(); }