123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- #include <fcntl.h>
- #include <cstdio>
- #include <sstream>
- #include <string>
- #include <vector>
- #ifdef _MSC_VER
- #include <io.h>
- #define open _open
- #define close _close
- typedef unsigned __int32 uint32_t;
- #else
- #include <unistd.h>
- #include <cstdint>
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
- #endif
- #include "ceres/ceres.h"
- #include "ceres/rotation.h"
- #include "gflags/gflags.h"
- #include "glog/logging.h"
- using Mat3 = Eigen::Matrix<double, 3, 3>;
- using Vec6 = Eigen::Matrix<double, 6, 1>;
- using Vec3 = Eigen::Vector3d;
- using Vec4 = Eigen::Vector4d;
- DEFINE_string(input, "", "Input File name");
- DEFINE_string(refine_intrinsics,
- "",
- "Camera intrinsics to be refined. Options are: none, radial.");
- namespace {
- struct EuclideanCamera {
- EuclideanCamera() = default;
- EuclideanCamera(const EuclideanCamera& c) = default;
- int image{-1};
- Mat3 R;
- Vec3 t;
- };
- struct EuclideanPoint {
- EuclideanPoint() = default;
- EuclideanPoint(const EuclideanPoint& p) = default;
- int track{-1};
- Vec3 X;
- };
- struct Marker {
- int image;
- int track;
- double x, y;
- };
- enum BundleIntrinsics {
- BUNDLE_NO_INTRINSICS = 0,
- BUNDLE_FOCAL_LENGTH = 1,
- BUNDLE_PRINCIPAL_POINT = 2,
- BUNDLE_RADIAL_K1 = 4,
- BUNDLE_RADIAL_K2 = 8,
- BUNDLE_RADIAL = 12,
- BUNDLE_TANGENTIAL_P1 = 16,
- BUNDLE_TANGENTIAL_P2 = 32,
- BUNDLE_TANGENTIAL = 48,
- };
- enum BundleConstraints {
- BUNDLE_NO_CONSTRAINTS = 0,
- BUNDLE_NO_TRANSLATION = 1,
- };
- enum {
- OFFSET_FOCAL_LENGTH,
- OFFSET_PRINCIPAL_POINT_X,
- OFFSET_PRINCIPAL_POINT_Y,
- OFFSET_K1,
- OFFSET_K2,
- OFFSET_K3,
- OFFSET_P1,
- OFFSET_P2,
- };
- EuclideanCamera* CameraForImage(std::vector<EuclideanCamera>* all_cameras,
- const int image) {
- if (image < 0 || image >= all_cameras->size()) {
- return nullptr;
- }
- EuclideanCamera* camera = &(*all_cameras)[image];
- if (camera->image == -1) {
- return nullptr;
- }
- return camera;
- }
- const EuclideanCamera* CameraForImage(
- const std::vector<EuclideanCamera>& all_cameras, const int image) {
- if (image < 0 || image >= all_cameras.size()) {
- return nullptr;
- }
- const EuclideanCamera* camera = &all_cameras[image];
- if (camera->image == -1) {
- return nullptr;
- }
- return camera;
- }
- int MaxImage(const std::vector<Marker>& all_markers) {
- if (all_markers.size() == 0) {
- return -1;
- }
- int max_image = all_markers[0].image;
- for (int i = 1; i < all_markers.size(); i++) {
- max_image = std::max(max_image, all_markers[i].image);
- }
- return max_image;
- }
- EuclideanPoint* PointForTrack(std::vector<EuclideanPoint>* all_points,
- const int track) {
- if (track < 0 || track >= all_points->size()) {
- return nullptr;
- }
- EuclideanPoint* point = &(*all_points)[track];
- if (point->track == -1) {
- return nullptr;
- }
- return point;
- }
- class EndianAwareFileReader {
- public:
- EndianAwareFileReader() {
-
- union {
- unsigned char bytes[4];
- uint32_t value;
- } endian_test = {{0, 1, 2, 3}};
- host_endian_type_ = endian_test.value;
- file_endian_type_ = host_endian_type_;
- }
- ~EndianAwareFileReader() {
- if (file_descriptor_ > 0) {
- close(file_descriptor_);
- }
- }
- bool OpenFile(const std::string& file_name) {
- file_descriptor_ = open(file_name.c_str(), O_RDONLY | O_BINARY);
- if (file_descriptor_ < 0) {
- return false;
- }
-
- auto file_endian_type_flag = Read<unsigned char>();
- if (file_endian_type_flag == 'V') {
- file_endian_type_ = kBigEndian;
- } else if (file_endian_type_flag == 'v') {
- file_endian_type_ = kLittleEndian;
- } else {
- LOG(FATAL) << "Problem file is stored in unknown endian type.";
- }
- return true;
- }
-
- template <typename T>
- T Read() const {
- T value;
- CERES_DISABLE_DEPRECATED_WARNING
- CHECK_GT(read(file_descriptor_, &value, sizeof(value)), 0);
- CERES_RESTORE_DEPRECATED_WARNING
-
-
- if (file_endian_type_ != host_endian_type_) {
- value = SwitchEndian<T>(value);
- }
- return value;
- }
- private:
- static constexpr long int kLittleEndian = 0x03020100ul;
- static constexpr long int kBigEndian = 0x00010203ul;
-
- template <typename T>
- T SwitchEndian(const T value) const {
- if (sizeof(T) == 4) {
- auto temp_value = static_cast<unsigned int>(value);
-
- return ((temp_value >> 24)) |
- ((temp_value << 8) & 0x00ff0000) |
- ((temp_value >> 8) & 0x0000ff00) |
- ((temp_value << 24));
-
- } else if (sizeof(T) == 1) {
- return value;
- } else {
- LOG(FATAL) << "Entered non-implemented part of endian "
- "switching function.";
- }
- }
- int host_endian_type_;
- int file_endian_type_;
- int file_descriptor_{-1};
- };
- void ReadMatrix3x3(const EndianAwareFileReader& file_reader, Mat3* matrix) {
- for (int i = 0; i < 9; i++) {
- (*matrix)(i % 3, i / 3) = file_reader.Read<float>();
- }
- }
- void ReadVector3(const EndianAwareFileReader& file_reader, Vec3* vector) {
- for (int i = 0; i < 3; i++) {
- (*vector)(i) = file_reader.Read<float>();
- }
- }
- bool ReadProblemFromFile(const std::string& file_name,
- double camera_intrinsics[8],
- std::vector<EuclideanCamera>* all_cameras,
- std::vector<EuclideanPoint>* all_points,
- bool* is_image_space,
- std::vector<Marker>* all_markers) {
- EndianAwareFileReader file_reader;
- if (!file_reader.OpenFile(file_name)) {
- return false;
- }
-
- auto is_image_space_flag = file_reader.Read<unsigned char>();
- if (is_image_space_flag == 'P') {
- *is_image_space = true;
- } else if (is_image_space_flag == 'N') {
- *is_image_space = false;
- } else {
- LOG(FATAL) << "Problem file contains markers stored in unknown space.";
- }
-
- for (int i = 0; i < 8; i++) {
- camera_intrinsics[i] = file_reader.Read<float>();
- }
-
- int number_of_cameras = file_reader.Read<int>();
- for (int i = 0; i < number_of_cameras; i++) {
- EuclideanCamera camera;
- camera.image = file_reader.Read<int>();
- ReadMatrix3x3(file_reader, &camera.R);
- ReadVector3(file_reader, &camera.t);
- if (camera.image >= all_cameras->size()) {
- all_cameras->resize(camera.image + 1);
- }
- (*all_cameras)[camera.image].image = camera.image;
- (*all_cameras)[camera.image].R = camera.R;
- (*all_cameras)[camera.image].t = camera.t;
- }
- LOG(INFO) << "Read " << number_of_cameras << " cameras.";
-
- int number_of_points = file_reader.Read<int>();
- for (int i = 0; i < number_of_points; i++) {
- EuclideanPoint point;
- point.track = file_reader.Read<int>();
- ReadVector3(file_reader, &point.X);
- if (point.track >= all_points->size()) {
- all_points->resize(point.track + 1);
- }
- (*all_points)[point.track].track = point.track;
- (*all_points)[point.track].X = point.X;
- }
- LOG(INFO) << "Read " << number_of_points << " points.";
-
- int number_of_markers = file_reader.Read<int>();
- for (int i = 0; i < number_of_markers; i++) {
- Marker marker;
- marker.image = file_reader.Read<int>();
- marker.track = file_reader.Read<int>();
- marker.x = file_reader.Read<float>();
- marker.y = file_reader.Read<float>();
- all_markers->push_back(marker);
- }
- LOG(INFO) << "Read " << number_of_markers << " markers.";
- return true;
- }
- template <typename T>
- inline void ApplyRadialDistortionCameraIntrinsics(const T& focal_length_x,
- const T& focal_length_y,
- const T& principal_point_x,
- const T& principal_point_y,
- const T& k1,
- const T& k2,
- const T& k3,
- const T& p1,
- const T& p2,
- const T& normalized_x,
- const T& normalized_y,
- T* image_x,
- T* image_y) {
- T x = normalized_x;
- T y = normalized_y;
-
- T r2 = x * x + y * y;
- T r4 = r2 * r2;
- T r6 = r4 * r2;
- T r_coeff = 1.0 + k1 * r2 + k2 * r4 + k3 * r6;
- T xd = x * r_coeff + 2.0 * p1 * x * y + p2 * (r2 + 2.0 * x * x);
- T yd = y * r_coeff + 2.0 * p2 * x * y + p1 * (r2 + 2.0 * y * y);
-
- *image_x = focal_length_x * xd + principal_point_x;
- *image_y = focal_length_y * yd + principal_point_y;
- }
- struct OpenCVReprojectionError {
- OpenCVReprojectionError(const double observed_x, const double observed_y)
- : observed_x(observed_x), observed_y(observed_y) {}
- template <typename T>
- bool operator()(const T* const intrinsics,
- const T* const R_t,
-
- const T* const X,
- T* residuals) const {
-
- const T& focal_length = intrinsics[OFFSET_FOCAL_LENGTH];
- const T& principal_point_x = intrinsics[OFFSET_PRINCIPAL_POINT_X];
- const T& principal_point_y = intrinsics[OFFSET_PRINCIPAL_POINT_Y];
- const T& k1 = intrinsics[OFFSET_K1];
- const T& k2 = intrinsics[OFFSET_K2];
- const T& k3 = intrinsics[OFFSET_K3];
- const T& p1 = intrinsics[OFFSET_P1];
- const T& p2 = intrinsics[OFFSET_P2];
-
- T x[3];
- ceres::AngleAxisRotatePoint(R_t, X, x);
- x[0] += R_t[3];
- x[1] += R_t[4];
- x[2] += R_t[5];
-
- T xn = x[0] / x[2];
- T yn = x[1] / x[2];
- T predicted_x, predicted_y;
-
-
-
- ApplyRadialDistortionCameraIntrinsics(focal_length,
- focal_length,
- principal_point_x,
- principal_point_y,
- k1,
- k2,
- k3,
- p1,
- p2,
- xn,
- yn,
- &predicted_x,
- &predicted_y);
-
- residuals[0] = predicted_x - observed_x;
- residuals[1] = predicted_y - observed_y;
- return true;
- }
- const double observed_x;
- const double observed_y;
- };
- void BundleIntrinsicsLogMessage(const int bundle_intrinsics) {
- if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
- LOG(INFO) << "Bundling only camera positions.";
- } else {
- std::string bundling_message = "";
- #define APPEND_BUNDLING_INTRINSICS(name, flag) \
- if (bundle_intrinsics & flag) { \
- if (!bundling_message.empty()) { \
- bundling_message += ", "; \
- } \
- bundling_message += name; \
- } \
- (void)0
- APPEND_BUNDLING_INTRINSICS("f", BUNDLE_FOCAL_LENGTH);
- APPEND_BUNDLING_INTRINSICS("px, py", BUNDLE_PRINCIPAL_POINT);
- APPEND_BUNDLING_INTRINSICS("k1", BUNDLE_RADIAL_K1);
- APPEND_BUNDLING_INTRINSICS("k2", BUNDLE_RADIAL_K2);
- APPEND_BUNDLING_INTRINSICS("p1", BUNDLE_TANGENTIAL_P1);
- APPEND_BUNDLING_INTRINSICS("p2", BUNDLE_TANGENTIAL_P2);
- LOG(INFO) << "Bundling " << bundling_message << ".";
- }
- }
- void PrintCameraIntrinsics(const char* text, const double* camera_intrinsics) {
- std::ostringstream intrinsics_output;
- intrinsics_output << "f=" << camera_intrinsics[OFFSET_FOCAL_LENGTH];
- intrinsics_output << " cx=" << camera_intrinsics[OFFSET_PRINCIPAL_POINT_X]
- << " cy=" << camera_intrinsics[OFFSET_PRINCIPAL_POINT_Y];
- #define APPEND_DISTORTION_COEFFICIENT(name, offset) \
- { \
- if (camera_intrinsics[offset] != 0.0) { \
- intrinsics_output << " " name "=" << camera_intrinsics[offset]; \
- } \
- } \
- (void)0
- APPEND_DISTORTION_COEFFICIENT("k1", OFFSET_K1);
- APPEND_DISTORTION_COEFFICIENT("k2", OFFSET_K2);
- APPEND_DISTORTION_COEFFICIENT("k3", OFFSET_K3);
- APPEND_DISTORTION_COEFFICIENT("p1", OFFSET_P1);
- APPEND_DISTORTION_COEFFICIENT("p2", OFFSET_P2);
- #undef APPEND_DISTORTION_COEFFICIENT
- LOG(INFO) << text << intrinsics_output.str();
- }
- std::vector<Vec6> PackCamerasRotationAndTranslation(
- const std::vector<Marker>& all_markers,
- const std::vector<EuclideanCamera>& all_cameras) {
- std::vector<Vec6> all_cameras_R_t;
- int max_image = MaxImage(all_markers);
- all_cameras_R_t.resize(max_image + 1);
- for (int i = 0; i <= max_image; i++) {
- const EuclideanCamera* camera = CameraForImage(all_cameras, i);
- if (!camera) {
- continue;
- }
- ceres::RotationMatrixToAngleAxis(&camera->R(0, 0), &all_cameras_R_t[i](0));
- all_cameras_R_t[i].tail<3>() = camera->t;
- }
- return all_cameras_R_t;
- }
- void UnpackCamerasRotationAndTranslation(
- const std::vector<Marker>& all_markers,
- const std::vector<Vec6>& all_cameras_R_t,
- std::vector<EuclideanCamera>* all_cameras) {
- int max_image = MaxImage(all_markers);
- for (int i = 0; i <= max_image; i++) {
- EuclideanCamera* camera = CameraForImage(all_cameras, i);
- if (!camera) {
- continue;
- }
- ceres::AngleAxisToRotationMatrix(&all_cameras_R_t[i](0), &camera->R(0, 0));
- camera->t = all_cameras_R_t[i].tail<3>();
- }
- }
- void EuclideanBundleCommonIntrinsics(const std::vector<Marker>& all_markers,
- const int bundle_intrinsics,
- const int bundle_constraints,
- double* camera_intrinsics,
- std::vector<EuclideanCamera>* all_cameras,
- std::vector<EuclideanPoint>* all_points) {
- PrintCameraIntrinsics("Original intrinsics: ", camera_intrinsics);
- ceres::Problem::Options problem_options;
- problem_options.cost_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP;
- ceres::Problem problem(problem_options);
-
-
-
-
-
- std::vector<Vec6> all_cameras_R_t =
- PackCamerasRotationAndTranslation(all_markers, *all_cameras);
-
- ceres::SubsetManifold* constant_transform_manifold = nullptr;
- if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
- std::vector<int> constant_translation;
-
- constant_translation.push_back(3);
- constant_translation.push_back(4);
- constant_translation.push_back(5);
- constant_transform_manifold =
- new ceres::SubsetManifold(6, constant_translation);
- }
- std::vector<OpenCVReprojectionError> errors;
- std::vector<ceres::AutoDiffCostFunction<OpenCVReprojectionError, 2, 8, 6, 3>>
- costFunctions;
- errors.reserve(all_markers.size());
- costFunctions.reserve(all_markers.size());
- int num_residuals = 0;
- bool have_locked_camera = false;
- for (const auto& marker : all_markers) {
- EuclideanCamera* camera = CameraForImage(all_cameras, marker.image);
- EuclideanPoint* point = PointForTrack(all_points, marker.track);
- if (camera == nullptr || point == nullptr) {
- continue;
- }
-
-
- double* current_camera_R_t = &all_cameras_R_t[camera->image](0);
- errors.emplace_back(marker.x, marker.y);
- costFunctions.emplace_back(&errors.back(), ceres::DO_NOT_TAKE_OWNERSHIP);
- problem.AddResidualBlock(&costFunctions.back(),
- nullptr,
- camera_intrinsics,
- current_camera_R_t,
- &point->X(0));
-
- if (!have_locked_camera) {
- problem.SetParameterBlockConstant(current_camera_R_t);
- have_locked_camera = true;
- }
- if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
- problem.SetManifold(current_camera_R_t, constant_transform_manifold);
- }
- num_residuals++;
- }
- LOG(INFO) << "Number of residuals: " << num_residuals;
- if (!num_residuals) {
- LOG(INFO) << "Skipping running minimizer with zero residuals";
- return;
- }
- BundleIntrinsicsLogMessage(bundle_intrinsics);
- if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
-
-
- problem.SetParameterBlockConstant(camera_intrinsics);
- } else {
-
-
- std::vector<int> constant_intrinsics;
- #define MAYBE_SET_CONSTANT(bundle_enum, offset) \
- if (!(bundle_intrinsics & bundle_enum)) { \
- constant_intrinsics.push_back(offset); \
- }
- MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH, OFFSET_FOCAL_LENGTH);
- MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_X);
- MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_Y);
- MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1, OFFSET_K1);
- MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2, OFFSET_K2);
- MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1, OFFSET_P1);
- MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2, OFFSET_P2);
- #undef MAYBE_SET_CONSTANT
-
- constant_intrinsics.push_back(OFFSET_K3);
- auto* subset_manifold = new ceres::SubsetManifold(8, constant_intrinsics);
- problem.SetManifold(camera_intrinsics, subset_manifold);
- }
-
- ceres::Solver::Options options;
- options.use_nonmonotonic_steps = true;
- options.preconditioner_type = ceres::SCHUR_JACOBI;
- options.linear_solver_type = ceres::ITERATIVE_SCHUR;
- options.use_inner_iterations = true;
- options.max_num_iterations = 100;
- options.minimizer_progress_to_stdout = true;
-
- ceres::Solver::Summary summary;
- ceres::Solve(options, &problem, &summary);
- std::cout << "Final report:\n" << summary.FullReport();
-
- UnpackCamerasRotationAndTranslation(
- all_markers, all_cameras_R_t, all_cameras);
- PrintCameraIntrinsics("Final intrinsics: ", camera_intrinsics);
- }
- }
- int main(int argc, char** argv) {
- GFLAGS_NAMESPACE::ParseCommandLineFlags(&argc, &argv, true);
- google::InitGoogleLogging(argv[0]);
- if (CERES_GET_FLAG(FLAGS_input).empty()) {
- LOG(ERROR) << "Usage: libmv_bundle_adjuster --input=blender_problem";
- return EXIT_FAILURE;
- }
- double camera_intrinsics[8];
- std::vector<EuclideanCamera> all_cameras;
- std::vector<EuclideanPoint> all_points;
- bool is_image_space;
- std::vector<Marker> all_markers;
- if (!ReadProblemFromFile(CERES_GET_FLAG(FLAGS_input),
- camera_intrinsics,
- &all_cameras,
- &all_points,
- &is_image_space,
- &all_markers)) {
- LOG(ERROR) << "Error reading problem file";
- return EXIT_FAILURE;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- int bundle_intrinsics = BUNDLE_NO_INTRINSICS;
- if (CERES_GET_FLAG(FLAGS_refine_intrinsics).empty()) {
- if (is_image_space) {
- bundle_intrinsics = BUNDLE_FOCAL_LENGTH | BUNDLE_RADIAL;
- }
- } else {
- if (CERES_GET_FLAG(FLAGS_refine_intrinsics) == "radial") {
- bundle_intrinsics = BUNDLE_FOCAL_LENGTH | BUNDLE_RADIAL;
- } else if (CERES_GET_FLAG(FLAGS_refine_intrinsics) != "none") {
- LOG(ERROR) << "Unsupported value for refine-intrinsics";
- return EXIT_FAILURE;
- }
- }
-
- EuclideanBundleCommonIntrinsics(all_markers,
- bundle_intrinsics,
- BUNDLE_NO_CONSTRAINTS,
- camera_intrinsics,
- &all_cameras,
- &all_points);
- return EXIT_SUCCESS;
- }
|