| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef COLMAP_SRC_BASE_RECONSTRUCTION_H_ |
| | #define COLMAP_SRC_BASE_RECONSTRUCTION_H_ |
| |
|
| | #include <tuple> |
| | #include <unordered_map> |
| | #include <unordered_set> |
| | #include <vector> |
| |
|
| | #include <Eigen/Core> |
| |
|
| | #include "base/camera.h" |
| | #include "base/database.h" |
| | #include "base/image.h" |
| | #include "base/point2d.h" |
| | #include "base/point3d.h" |
| | #include "base/similarity_transform.h" |
| | #include "base/track.h" |
| | #include "estimators/similarity_transform.h" |
| | #include "optim/loransac.h" |
| | #include "util/alignment.h" |
| | #include "util/types.h" |
| |
|
| | namespace colmap { |
| |
|
| | struct PlyPoint; |
| | struct RANSACOptions; |
| | class DatabaseCache; |
| | class CorrespondenceGraph; |
| |
|
| | |
| | |
| | |
| | class Reconstruction { |
| | public: |
| | struct ImagePairStat { |
| | |
| | size_t num_tri_corrs = 0; |
| | |
| | size_t num_total_corrs = 0; |
| | }; |
| |
|
| | Reconstruction(); |
| |
|
| | |
| | inline size_t NumCameras() const; |
| | inline size_t NumImages() const; |
| | inline size_t NumRegImages() const; |
| | inline size_t NumPoints3D() const; |
| | inline size_t NumImagePairs() const; |
| |
|
| | |
| | inline const class Camera& Camera(const camera_t camera_id) const; |
| | inline const class Image& Image(const image_t image_id) const; |
| | inline const class Point3D& Point3D(const point3D_t point3D_id) const; |
| | inline const ImagePairStat& ImagePair(const image_pair_t pair_id) const; |
| | inline ImagePairStat& ImagePair(const image_t image_id1, |
| | const image_t image_id2); |
| |
|
| | |
| | inline class Camera& Camera(const camera_t camera_id); |
| | inline class Image& Image(const image_t image_id); |
| | inline class Point3D& Point3D(const point3D_t point3D_id); |
| | inline ImagePairStat& ImagePair(const image_pair_t pair_id); |
| | inline const ImagePairStat& ImagePair(const image_t image_id1, |
| | const image_t image_id2) const; |
| |
|
| | |
| | inline const EIGEN_STL_UMAP(camera_t, class Camera) & Cameras() const; |
| | inline const EIGEN_STL_UMAP(image_t, class Image) & Images() const; |
| | inline const std::vector<image_t>& RegImageIds() const; |
| | inline const EIGEN_STL_UMAP(point3D_t, class Point3D) & Points3D() const; |
| | inline const std::unordered_map<image_pair_t, ImagePairStat>& ImagePairs() |
| | const; |
| |
|
| | |
| | std::unordered_set<point3D_t> Point3DIds() const; |
| |
|
| | |
| | inline bool ExistsCamera(const camera_t camera_id) const; |
| | inline bool ExistsImage(const image_t image_id) const; |
| | inline bool ExistsPoint3D(const point3D_t point3D_id) const; |
| | inline bool ExistsImagePair(const image_pair_t pair_id) const; |
| |
|
| | |
| | void Load(const DatabaseCache& database_cache); |
| |
|
| | |
| | |
| | void SetUp(const CorrespondenceGraph* correspondence_graph); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | void TearDown(); |
| |
|
| | |
| | |
| | void AddCamera(class Camera camera); |
| |
|
| | |
| | void AddImage(class Image image); |
| |
|
| | |
| | point3D_t AddPoint3D( |
| | const Eigen::Vector3d& xyz, Track track, |
| | const Eigen::Vector3ub& color = Eigen::Vector3ub::Zero()); |
| |
|
| | |
| | void AddObservation(const point3D_t point3D_id, const TrackElement& track_el); |
| |
|
| | |
| | |
| | |
| | point3D_t MergePoints3D(const point3D_t point3D_id1, |
| | const point3D_t point3D_id2); |
| |
|
| | |
| | void DeletePoint3D(const point3D_t point3D_id); |
| |
|
| | |
| | |
| | |
| | void DeleteObservation(const image_t image_id, const point2D_t point2D_idx); |
| |
|
| | |
| | void DeleteAllPoints2DAndPoints3D(); |
| |
|
| | |
| | void RegisterImage(const image_t image_id); |
| |
|
| | |
| | void DeRegisterImage(const image_t image_id); |
| |
|
| | |
| | inline bool IsImageRegistered(const image_t image_id) const; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void Normalize(const double extent = 10.0, const double p0 = 0.1, |
| | const double p1 = 0.9, const bool use_images = true); |
| |
|
| | |
| | Eigen::Vector3d ComputeCentroid(const double p0 = 0.1, |
| | const double p1 = 0.9) const; |
| |
|
| | |
| | std::pair<Eigen::Vector3d, Eigen::Vector3d> ComputeBoundingBox( |
| | const double p0 = 0.0, const double p1 = 1.0) const; |
| |
|
| | |
| | void Transform(const SimilarityTransform3& tform); |
| |
|
| | |
| | |
| | |
| | |
| | Reconstruction Crop( |
| | const std::pair<Eigen::Vector3d, Eigen::Vector3d>& bbox) const; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | bool Merge(const Reconstruction& reconstruction, |
| | const double max_reproj_error); |
| |
|
| | |
| | |
| | |
| | template <bool kEstimateScale = true> |
| | bool Align(const std::vector<std::string>& image_names, |
| | const std::vector<Eigen::Vector3d>& locations, |
| | const int min_common_images, |
| | SimilarityTransform3* tform = nullptr); |
| |
|
| | |
| | template <bool kEstimateScale = true> |
| | bool AlignRobust(const std::vector<std::string>& image_names, |
| | const std::vector<Eigen::Vector3d>& locations, |
| | const int min_common_images, |
| | const RANSACOptions& ransac_options, |
| | SimilarityTransform3* tform = nullptr); |
| |
|
| | |
| | const class Image* FindImageWithName(const std::string& name) const; |
| |
|
| | |
| | std::vector<image_t> FindCommonRegImageIds( |
| | const Reconstruction& reconstruction) const; |
| |
|
| | |
| | |
| | void TranscribeImageIdsToDatabase(const Database& database); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | size_t FilterPoints3D(const double max_reproj_error, |
| | const double min_tri_angle, |
| | const std::unordered_set<point3D_t>& point3D_ids); |
| | size_t FilterPoints3DInImages(const double max_reproj_error, |
| | const double min_tri_angle, |
| | const std::unordered_set<image_t>& image_ids); |
| | size_t FilterAllPoints3D(const double max_reproj_error, |
| | const double min_tri_angle); |
| |
|
| | |
| | |
| | |
| | size_t FilterObservationsWithNegativeDepth(); |
| |
|
| | |
| | |
| | |
| | std::vector<image_t> FilterImages(const double min_focal_length_ratio, |
| | const double max_focal_length_ratio, |
| | const double max_extra_param); |
| |
|
| | |
| | size_t ComputeNumObservations() const; |
| | double ComputeMeanTrackLength() const; |
| | double ComputeMeanObservationsPerRegImage() const; |
| | double ComputeMeanReprojectionError() const; |
| |
|
| | |
| | void Read(const std::string& path); |
| | void Write(const std::string& path) const; |
| |
|
| | |
| | void ReadText(const std::string& path); |
| | void ReadBinary(const std::string& path); |
| |
|
| | |
| | void WriteText(const std::string& path) const; |
| | void WriteBinary(const std::string& path) const; |
| |
|
| | |
| | std::vector<PlyPoint> ConvertToPLY() const; |
| |
|
| | |
| | |
| | void ImportPLY(const std::string& path); |
| | void ImportPLY(const std::vector<PlyPoint>& ply_points); |
| |
|
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | bool ExportNVM(const std::string& path, bool skip_distortion = false) const; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | bool ExportCam(const std::string& path, bool skip_distortion = false) const; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | bool ExportRecon3D(const std::string& path, |
| | bool skip_distortion = false) const; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | bool ExportBundler(const std::string& path, const std::string& list_path, |
| | bool skip_distortion = false) const; |
| |
|
| | |
| | void ExportPLY(const std::string& path) const; |
| |
|
| | |
| | void ExportVRML(const std::string& images_path, |
| | const std::string& points3D_path, const double image_scale, |
| | const Eigen::Vector3d& image_rgb) const; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | bool ExtractColorsForImage(const image_t image_id, const std::string& path); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void ExtractColorsForAllImages(const std::string& path); |
| |
|
| | |
| | void CreateImageDirs(const std::string& path) const; |
| |
|
| | private: |
| | size_t FilterPoints3DWithSmallTriangulationAngle( |
| | const double min_tri_angle, |
| | const std::unordered_set<point3D_t>& point3D_ids); |
| | size_t FilterPoints3DWithLargeReprojectionError( |
| | const double max_reproj_error, |
| | const std::unordered_set<point3D_t>& point3D_ids); |
| |
|
| | std::tuple<Eigen::Vector3d, Eigen::Vector3d, Eigen::Vector3d> |
| | ComputeBoundsAndCentroid(const double p0, const double p1, |
| | const bool use_images) const; |
| |
|
| | void ReadCamerasText(const std::string& path); |
| | void ReadImagesText(const std::string& path); |
| | void ReadPoints3DText(const std::string& path); |
| | void ReadCamerasBinary(const std::string& path); |
| | void ReadImagesBinary(const std::string& path); |
| | void ReadPoints3DBinary(const std::string& path); |
| |
|
| | void WriteCamerasText(const std::string& path) const; |
| | void WriteImagesText(const std::string& path) const; |
| | void WritePoints3DText(const std::string& path) const; |
| | void WriteCamerasBinary(const std::string& path) const; |
| | void WriteImagesBinary(const std::string& path) const; |
| | void WritePoints3DBinary(const std::string& path) const; |
| |
|
| | void SetObservationAsTriangulated(const image_t image_id, |
| | const point2D_t point2D_idx, |
| | const bool is_continued_point3D); |
| | void ResetTriObservations(const image_t image_id, const point2D_t point2D_idx, |
| | const bool is_deleted_point3D); |
| |
|
| | const CorrespondenceGraph* correspondence_graph_; |
| |
|
| | EIGEN_STL_UMAP(camera_t, class Camera) cameras_; |
| | EIGEN_STL_UMAP(image_t, class Image) images_; |
| | EIGEN_STL_UMAP(point3D_t, class Point3D) points3D_; |
| |
|
| | std::unordered_map<image_pair_t, ImagePairStat> image_pair_stats_; |
| |
|
| | |
| | std::vector<image_t> reg_image_ids_; |
| |
|
| | |
| | point3D_t num_added_points3D_; |
| | }; |
| |
|
| | |
| | |
| | |
| |
|
| | size_t Reconstruction::NumCameras() const { return cameras_.size(); } |
| |
|
| | size_t Reconstruction::NumImages() const { return images_.size(); } |
| |
|
| | size_t Reconstruction::NumRegImages() const { return reg_image_ids_.size(); } |
| |
|
| | size_t Reconstruction::NumPoints3D() const { return points3D_.size(); } |
| |
|
| | size_t Reconstruction::NumImagePairs() const { |
| | return image_pair_stats_.size(); |
| | } |
| |
|
| | const class Camera& Reconstruction::Camera(const camera_t camera_id) const { |
| | return cameras_.at(camera_id); |
| | } |
| |
|
| | const class Image& Reconstruction::Image(const image_t image_id) const { |
| | return images_.at(image_id); |
| | } |
| |
|
| | const class Point3D& Reconstruction::Point3D(const point3D_t point3D_id) const { |
| | return points3D_.at(point3D_id); |
| | } |
| |
|
| | const Reconstruction::ImagePairStat& Reconstruction::ImagePair( |
| | const image_pair_t pair_id) const { |
| | return image_pair_stats_.at(pair_id); |
| | } |
| |
|
| | const Reconstruction::ImagePairStat& Reconstruction::ImagePair( |
| | const image_t image_id1, const image_t image_id2) const { |
| | const auto pair_id = Database::ImagePairToPairId(image_id1, image_id2); |
| | return image_pair_stats_.at(pair_id); |
| | } |
| |
|
| | class Camera& Reconstruction::Camera(const camera_t camera_id) { |
| | return cameras_.at(camera_id); |
| | } |
| |
|
| | class Image& Reconstruction::Image(const image_t image_id) { |
| | return images_.at(image_id); |
| | } |
| |
|
| | class Point3D& Reconstruction::Point3D(const point3D_t point3D_id) { |
| | return points3D_.at(point3D_id); |
| | } |
| |
|
| | Reconstruction::ImagePairStat& Reconstruction::ImagePair( |
| | const image_pair_t pair_id) { |
| | return image_pair_stats_.at(pair_id); |
| | } |
| |
|
| | Reconstruction::ImagePairStat& Reconstruction::ImagePair( |
| | const image_t image_id1, const image_t image_id2) { |
| | const auto pair_id = Database::ImagePairToPairId(image_id1, image_id2); |
| | return image_pair_stats_.at(pair_id); |
| | } |
| |
|
| | const EIGEN_STL_UMAP(camera_t, Camera) & Reconstruction::Cameras() const { |
| | return cameras_; |
| | } |
| |
|
| | const EIGEN_STL_UMAP(image_t, class Image) & Reconstruction::Images() const { |
| | return images_; |
| | } |
| |
|
| | const std::vector<image_t>& Reconstruction::RegImageIds() const { |
| | return reg_image_ids_; |
| | } |
| |
|
| | const EIGEN_STL_UMAP(point3D_t, Point3D) & Reconstruction::Points3D() const { |
| | return points3D_; |
| | } |
| |
|
| | const std::unordered_map<image_pair_t, Reconstruction::ImagePairStat>& |
| | Reconstruction::ImagePairs() const { |
| | return image_pair_stats_; |
| | } |
| |
|
| | bool Reconstruction::ExistsCamera(const camera_t camera_id) const { |
| | return cameras_.find(camera_id) != cameras_.end(); |
| | } |
| |
|
| | bool Reconstruction::ExistsImage(const image_t image_id) const { |
| | return images_.find(image_id) != images_.end(); |
| | } |
| |
|
| | bool Reconstruction::ExistsPoint3D(const point3D_t point3D_id) const { |
| | return points3D_.find(point3D_id) != points3D_.end(); |
| | } |
| |
|
| | bool Reconstruction::ExistsImagePair(const image_pair_t pair_id) const { |
| | return image_pair_stats_.find(pair_id) != image_pair_stats_.end(); |
| | } |
| |
|
| | bool Reconstruction::IsImageRegistered(const image_t image_id) const { |
| | return Image(image_id).IsRegistered(); |
| | } |
| |
|
| | template <bool kEstimateScale> |
| | bool Reconstruction::Align(const std::vector<std::string>& image_names, |
| | const std::vector<Eigen::Vector3d>& locations, |
| | const int min_common_images, |
| | SimilarityTransform3* tform) { |
| | CHECK_GE(min_common_images, 3); |
| | CHECK_EQ(image_names.size(), locations.size()); |
| |
|
| | |
| | |
| | std::unordered_set<image_t> common_image_ids; |
| | std::vector<Eigen::Vector3d> src; |
| | std::vector<Eigen::Vector3d> dst; |
| | for (size_t i = 0; i < image_names.size(); ++i) { |
| | const class Image* image = FindImageWithName(image_names[i]); |
| | if (image == nullptr) { |
| | continue; |
| | } |
| |
|
| | if (!IsImageRegistered(image->ImageId())) { |
| | continue; |
| | } |
| |
|
| | |
| | if (common_image_ids.count(image->ImageId()) > 0) { |
| | continue; |
| | } |
| |
|
| | common_image_ids.insert(image->ImageId()); |
| | src.push_back(image->ProjectionCenter()); |
| | dst.push_back(locations[i]); |
| | } |
| |
|
| | |
| | if (common_image_ids.size() < static_cast<size_t>(min_common_images)) { |
| | return false; |
| | } |
| |
|
| | SimilarityTransform3 transform; |
| | if (!transform.Estimate<kEstimateScale>(src, dst)) { |
| | return false; |
| | } |
| |
|
| | Transform(transform); |
| |
|
| | if (tform != nullptr) { |
| | *tform = transform; |
| | } |
| |
|
| | return true; |
| | } |
| |
|
| | template <bool kEstimateScale> |
| | bool Reconstruction::AlignRobust(const std::vector<std::string>& image_names, |
| | const std::vector<Eigen::Vector3d>& locations, |
| | const int min_common_images, |
| | const RANSACOptions& ransac_options, |
| | SimilarityTransform3* tform) { |
| | CHECK_GE(min_common_images, 3); |
| | CHECK_EQ(image_names.size(), locations.size()); |
| |
|
| | |
| | |
| | std::unordered_set<image_t> common_image_ids; |
| | std::vector<Eigen::Vector3d> src; |
| | std::vector<Eigen::Vector3d> dst; |
| | for (size_t i = 0; i < image_names.size(); ++i) { |
| | const class Image* image = FindImageWithName(image_names[i]); |
| | if (image == nullptr) { |
| | continue; |
| | } |
| |
|
| | if (!IsImageRegistered(image->ImageId())) { |
| | continue; |
| | } |
| |
|
| | |
| | if (common_image_ids.count(image->ImageId()) > 0) { |
| | continue; |
| | } |
| |
|
| | common_image_ids.insert(image->ImageId()); |
| | src.push_back(image->ProjectionCenter()); |
| | dst.push_back(locations[i]); |
| | } |
| |
|
| | |
| | if (common_image_ids.size() < static_cast<size_t>(min_common_images)) { |
| | return false; |
| | } |
| |
|
| | LORANSAC<SimilarityTransformEstimator<3, kEstimateScale>, |
| | SimilarityTransformEstimator<3, kEstimateScale>> |
| | ransac(ransac_options); |
| |
|
| | const auto report = ransac.Estimate(src, dst); |
| |
|
| | if (report.support.num_inliers < static_cast<size_t>(min_common_images)) { |
| | return false; |
| | } |
| |
|
| | SimilarityTransform3 transform = SimilarityTransform3(report.model); |
| | Transform(transform); |
| |
|
| | if (tform != nullptr) { |
| | *tform = transform; |
| | } |
| |
|
| | return true; |
| | } |
| |
|
| | } |
| |
|
| | #endif |
| |
|