From d90158a8b38a31fabd17f7041268bedd3b0f4cdf Mon Sep 17 00:00:00 2001 From: fabien servant Date: Tue, 17 Jan 2023 14:46:13 +0100 Subject: [PATCH 1/6] Alignment to nullify X --- src/aliceVision/sfm/utils/alignment.cpp | 17 ++++++++++++++ src/aliceVision/sfm/utils/alignment.hpp | 9 +++++++ src/software/utils/main_sfmTransform.cpp | 30 +++++++++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/aliceVision/sfm/utils/alignment.cpp b/src/aliceVision/sfm/utils/alignment.cpp index 0e25e69413..947a59856c 100644 --- a/src/aliceVision/sfm/utils/alignment.cpp +++ b/src/aliceVision/sfm/utils/alignment.cpp @@ -938,5 +938,22 @@ bool computeNewCoordinateSystemFromGpsData(const sfmData::SfMData& sfmData, std: return aliceVision::geometry::ACRansac_FindRTS(x1, x2, randomNumberGenerator, out_S, out_t, out_R, inliers, refine); } +void getRotationNullifyX(Eigen::Matrix3d & out_R, const Eigen::Vector3d & pt) +{ + /* + 0 = [cos(x) 0 -sin(x)][X] + Y' = [0 1 0 ][Y] + Z' = [sin(x) 0 cos(x)][Z] + + cos(x)X - sin(x)Z = 0 + sin(x)/cos(x) = X/Z + tan(x) = X/Z + x = atan2(X, Z) + */ + + double angle = std::atan2(pt(0), pt(2)); + out_R = Eigen::AngleAxisd(angle, Vec3(0,-1,0)).toRotationMatrix(); +} + } // namespace sfm } // namespace aliceVision diff --git a/src/aliceVision/sfm/utils/alignment.hpp b/src/aliceVision/sfm/utils/alignment.hpp index 70031db405..f265f9d161 100644 --- a/src/aliceVision/sfm/utils/alignment.hpp +++ b/src/aliceVision/sfm/utils/alignment.hpp @@ -306,5 +306,14 @@ bool computeNewCoordinateSystemFromSpecificMarkers(const sfmData::SfMData& sfmDa Mat3& out_R, Vec3& out_t); +/** + * @brief Compute the 3D rotation matrix such that "pt" + * once rotated will have its x component equal to 0. + * This rotation will only affect rotate around the Y axis + * @param[out] out_R the result rotation matrix + * @param[in] pt the input point to nullify on X + */ +void getRotationNullifyX(Eigen::Matrix3d & out_R, const Eigen::Vector3d & pt); + } // namespace sfm } // namespace aliceVision diff --git a/src/software/utils/main_sfmTransform.cpp b/src/software/utils/main_sfmTransform.cpp index 069c3631bc..7bbe5bebad 100644 --- a/src/software/utils/main_sfmTransform.cpp +++ b/src/software/utils/main_sfmTransform.cpp @@ -269,6 +269,20 @@ int aliceVision_main(int argc, char **argv) return EXIT_FAILURE; } + + // Sort views per timestamps + std::vector> sorted_views; + for (auto v : sfmData.getViews()) { + int64_t t = v.second->getMetadataDateTimestamp(); + sorted_views.push_back(std::make_pair(t, v.second->getPoseId())); + } + std::sort(sorted_views.begin(), sorted_views.end()); + + // Get the view which was taken at the middle of the sequence + int median = sorted_views.size() / 2; + IndexT refPoseId = sorted_views[sorted_views.size() - 1].second; + Eigen::Matrix3d ref_R_world = sfmData.getAbsolutePose(refPoseId).getTransform().rotation(); + double S = 1.0; Mat3 R = Mat3::Identity(); Vec3 t = Vec3::Zero(); @@ -306,8 +320,22 @@ int aliceVision_main(int argc, char **argv) break; case EAlignmentMethod::AUTO_FROM_CAMERAS_X_AXIS: + { sfm::computeNewCoordinateSystemFromCamerasXAxis(sfmData, S, R, t); - break; + + Eigen::Matrix3d refcam_R_updatedWorld = ref_R_world * R.transpose(); + Eigen::Matrix3d updatedWorld_R_refcam = refcam_R_updatedWorld.transpose(); + Eigen::Vector3d alignmentVector = updatedWorld_R_refcam * Eigen::Vector3d::UnitZ(); + + Eigen::Matrix3d zeroX_R_world; + sfm::getRotationNullifyX(zeroX_R_world, alignmentVector); + + //(zeroX_R_world * updatedWorld_R_refcam).transpose() + //(zeroX_R_world * (ref_R_world * R.transpose()).transpose()).transpose() + // ref_R_world * R.transpose() * zeroX_R_world.transpose() + R = zeroX_R_world * R; + } + break; case EAlignmentMethod::AUTO_FROM_LANDMARKS: sfm::computeNewCoordinateSystemFromLandmarks(sfmData, feature::EImageDescriberType_stringToEnums(landmarksDescriberTypesName), S, R, t); From 9a67cc838fcba9a6f356bb4b02885964fa173192 Mon Sep 17 00:00:00 2001 From: fabien servant Date: Wed, 18 Jan 2023 13:13:06 +0100 Subject: [PATCH 2/6] accept parameters to control view alignment on panorama --- src/software/utils/main_sfmTransform.cpp | 45 ++++++++++++++++++------ 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/software/utils/main_sfmTransform.cpp b/src/software/utils/main_sfmTransform.cpp index 7bbe5bebad..2a0b91af24 100644 --- a/src/software/utils/main_sfmTransform.cpp +++ b/src/software/utils/main_sfmTransform.cpp @@ -184,6 +184,36 @@ static void parseManualTransform(const std::string& manualTransform, double& S, } // namespace +IndexT getReferenceViewIndex(const sfmData::SfMData & sfmData, const std::string & transform) +{ + IndexT refPoseId; + try + { + refPoseId = sfm::getViewIdFromExpression(sfmData, transform); + } + catch (...) + { + refPoseId = UndefinedIndexT; + } + + if (refPoseId == UndefinedIndexT) + { + // Sort views per timestamps + std::vector> sorted_views; + for (auto v : sfmData.getViews()) { + int64_t t = v.second->getMetadataDateTimestamp(); + sorted_views.push_back(std::make_pair(t, v.second->getPoseId())); + } + std::sort(sorted_views.begin(), sorted_views.end()); + + // Get the view which was taken at the middle of the sequence + int median = sorted_views.size() / 2; + refPoseId = sorted_views[sorted_views.size() - 1].second; + } + + return refPoseId; +} + int aliceVision_main(int argc, char **argv) { // command-line parameters @@ -269,18 +299,8 @@ int aliceVision_main(int argc, char **argv) return EXIT_FAILURE; } + IndexT refPoseId = getReferenceViewIndex(sfmData, transform); - // Sort views per timestamps - std::vector> sorted_views; - for (auto v : sfmData.getViews()) { - int64_t t = v.second->getMetadataDateTimestamp(); - sorted_views.push_back(std::make_pair(t, v.second->getPoseId())); - } - std::sort(sorted_views.begin(), sorted_views.end()); - - // Get the view which was taken at the middle of the sequence - int median = sorted_views.size() / 2; - IndexT refPoseId = sorted_views[sorted_views.size() - 1].second; Eigen::Matrix3d ref_R_world = sfmData.getAbsolutePose(refPoseId).getTransform().rotation(); double S = 1.0; @@ -321,8 +341,10 @@ int aliceVision_main(int argc, char **argv) case EAlignmentMethod::AUTO_FROM_CAMERAS_X_AXIS: { + //Align with x axis sfm::computeNewCoordinateSystemFromCamerasXAxis(sfmData, S, R, t); + //Align with reference image Eigen::Matrix3d refcam_R_updatedWorld = ref_R_world * R.transpose(); Eigen::Matrix3d updatedWorld_R_refcam = refcam_R_updatedWorld.transpose(); Eigen::Vector3d alignmentVector = updatedWorld_R_refcam * Eigen::Vector3d::UnitZ(); @@ -330,6 +352,7 @@ int aliceVision_main(int argc, char **argv) Eigen::Matrix3d zeroX_R_world; sfm::getRotationNullifyX(zeroX_R_world, alignmentVector); + //Cumulate both transformations //(zeroX_R_world * updatedWorld_R_refcam).transpose() //(zeroX_R_world * (ref_R_world * R.transpose()).transpose()).transpose() // ref_R_world * R.transpose() * zeroX_R_world.transpose() From 14ee5e00c4e8d42ef87d92470588122614a12cd6 Mon Sep 17 00:00:00 2001 From: fabien servant Date: Mon, 23 Jan 2023 12:55:07 +0100 Subject: [PATCH 3/6] [sfm] getViewIdFromExpression now looks ancestors --- src/aliceVision/sfm/utils/alignment.cpp | 29 +++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/aliceVision/sfm/utils/alignment.cpp b/src/aliceVision/sfm/utils/alignment.cpp index 947a59856c..7c969c062d 100644 --- a/src/aliceVision/sfm/utils/alignment.cpp +++ b/src/aliceVision/sfm/utils/alignment.cpp @@ -695,8 +695,33 @@ IndexT getViewIdFromExpression(const sfmData::SfMData& sfmData, const std::strin try { viewId = boost::lexical_cast(camName); - if(!sfmData.getViews().count(viewId)) - viewId = -1; + if (!sfmData.getViews().count(viewId)) + { + bool found = false; + //check if this view is an ancestor of a view + for (auto pv : sfmData.getViews()) + { + for (auto ancestor : pv.second->getAncestors()) + { + if (ancestor == viewId) + { + viewId = pv.first; + found = true; + break; + } + } + + if (found) + { + break; + } + } + + if (!found) + { + viewId = -1; + } + } } catch(const boost::bad_lexical_cast &) { From f04b81dab9e98be3848155af95e5bfdb486ab866 Mon Sep 17 00:00:00 2001 From: fabien servant Date: Thu, 16 Feb 2023 09:21:56 +0100 Subject: [PATCH 4/6] Update getReferenceViewId to use viewid instead of poseid --- src/aliceVision/sfm/utils/alignment.cpp | 6 +++++ src/aliceVision/sfm/utils/alignment.hpp | 9 ++++++++ src/software/utils/main_sfmTransform.cpp | 28 ++++++++++-------------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/aliceVision/sfm/utils/alignment.cpp b/src/aliceVision/sfm/utils/alignment.cpp index 7c969c062d..5b1a58c07c 100644 --- a/src/aliceVision/sfm/utils/alignment.cpp +++ b/src/aliceVision/sfm/utils/alignment.cpp @@ -963,6 +963,12 @@ bool computeNewCoordinateSystemFromGpsData(const sfmData::SfMData& sfmData, std: return aliceVision::geometry::ACRansac_FindRTS(x1, x2, randomNumberGenerator, out_S, out_t, out_R, inliers, refine); } +void getRotationNullifyX(Eigen::Matrix3d & out_R, const Eigen::Matrix3d & R) +{ + Eigen::Vector3d alignmentVector = R.transpose() * Eigen::Vector3d::UnitZ(); + getRotationNullifyX(out_R, alignmentVector); +} + void getRotationNullifyX(Eigen::Matrix3d & out_R, const Eigen::Vector3d & pt) { /* diff --git a/src/aliceVision/sfm/utils/alignment.hpp b/src/aliceVision/sfm/utils/alignment.hpp index f265f9d161..fbf2418e8c 100644 --- a/src/aliceVision/sfm/utils/alignment.hpp +++ b/src/aliceVision/sfm/utils/alignment.hpp @@ -306,6 +306,15 @@ bool computeNewCoordinateSystemFromSpecificMarkers(const sfmData::SfMData& sfmDa Mat3& out_R, Vec3& out_t); +/** + * @brief Compute the 3D rotation matrix such that "R.t() * unit_z" + * once rotated will have its x component equal to 0. + * This rotation will only affect rotate around the Y axis + * @param[out] out_R the result rotation matrix + * @param[in] R the input rotation matrix + */ +void getRotationNullifyX(Eigen::Matrix3d & out_R, const Eigen::Matrix3d & R); + /** * @brief Compute the 3D rotation matrix such that "pt" * once rotated will have its x component equal to 0. diff --git a/src/software/utils/main_sfmTransform.cpp b/src/software/utils/main_sfmTransform.cpp index 2a0b91af24..7e2cb5ca1f 100644 --- a/src/software/utils/main_sfmTransform.cpp +++ b/src/software/utils/main_sfmTransform.cpp @@ -184,19 +184,19 @@ static void parseManualTransform(const std::string& manualTransform, double& S, } // namespace -IndexT getReferenceViewIndex(const sfmData::SfMData & sfmData, const std::string & transform) +IndexT getReferenceViewId(const sfmData::SfMData & sfmData, const std::string & transform) { - IndexT refPoseId; + IndexT refViewId; try { - refPoseId = sfm::getViewIdFromExpression(sfmData, transform); + refViewId = sfm::getViewIdFromExpression(sfmData, transform); } catch (...) { - refPoseId = UndefinedIndexT; + refViewId = UndefinedIndexT; } - if (refPoseId == UndefinedIndexT) + if (refViewId == UndefinedIndexT) { // Sort views per timestamps std::vector> sorted_views; @@ -208,10 +208,10 @@ IndexT getReferenceViewIndex(const sfmData::SfMData & sfmData, const std::string // Get the view which was taken at the middle of the sequence int median = sorted_views.size() / 2; - refPoseId = sorted_views[sorted_views.size() - 1].second; + refViewId = sorted_views[sorted_views.size() - 1].second; } - return refPoseId; + return refViewId; } int aliceVision_main(int argc, char **argv) @@ -299,7 +299,8 @@ int aliceVision_main(int argc, char **argv) return EXIT_FAILURE; } - IndexT refPoseId = getReferenceViewIndex(sfmData, transform); + IndexT refViewId = getReferenceViewId(sfmData, transform); + IndexT refPoseId = sfmData.getView(refViewId).getPoseId(); Eigen::Matrix3d ref_R_world = sfmData.getAbsolutePose(refPoseId).getTransform().rotation(); @@ -344,18 +345,11 @@ int aliceVision_main(int argc, char **argv) //Align with x axis sfm::computeNewCoordinateSystemFromCamerasXAxis(sfmData, S, R, t); - //Align with reference image + //Apply x axis alignment before doing the y alignment Eigen::Matrix3d refcam_R_updatedWorld = ref_R_world * R.transpose(); - Eigen::Matrix3d updatedWorld_R_refcam = refcam_R_updatedWorld.transpose(); - Eigen::Vector3d alignmentVector = updatedWorld_R_refcam * Eigen::Vector3d::UnitZ(); Eigen::Matrix3d zeroX_R_world; - sfm::getRotationNullifyX(zeroX_R_world, alignmentVector); - - //Cumulate both transformations - //(zeroX_R_world * updatedWorld_R_refcam).transpose() - //(zeroX_R_world * (ref_R_world * R.transpose()).transpose()).transpose() - // ref_R_world * R.transpose() * zeroX_R_world.transpose() + sfm::getRotationNullifyX(zeroX_R_world, refcam_R_updatedWorld); R = zeroX_R_world * R; } break; From 4df2a49a467211bcb6cbf24b162f67cb0839048f Mon Sep 17 00:00:00 2001 From: Fabien Castan Date: Thu, 16 Feb 2023 21:18:18 +0100 Subject: [PATCH 5/6] [software] sfmTransform: minor cleanup --- src/software/utils/main_sfmTransform.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/software/utils/main_sfmTransform.cpp b/src/software/utils/main_sfmTransform.cpp index 7e2cb5ca1f..00e6dd269a 100644 --- a/src/software/utils/main_sfmTransform.cpp +++ b/src/software/utils/main_sfmTransform.cpp @@ -299,11 +299,6 @@ int aliceVision_main(int argc, char **argv) return EXIT_FAILURE; } - IndexT refViewId = getReferenceViewId(sfmData, transform); - IndexT refPoseId = sfmData.getView(refViewId).getPoseId(); - - Eigen::Matrix3d ref_R_world = sfmData.getAbsolutePose(refPoseId).getTransform().rotation(); - double S = 1.0; Mat3 R = Mat3::Identity(); Vec3 t = Vec3::Zero(); @@ -342,11 +337,15 @@ int aliceVision_main(int argc, char **argv) case EAlignmentMethod::AUTO_FROM_CAMERAS_X_AXIS: { - //Align with x axis + // Align with x axis sfm::computeNewCoordinateSystemFromCamerasXAxis(sfmData, S, R, t); - //Apply x axis alignment before doing the y alignment - Eigen::Matrix3d refcam_R_updatedWorld = ref_R_world * R.transpose(); + const IndexT refViewId = getReferenceViewId(sfmData, transform); + + const Eigen::Matrix3d ref_R_world = sfmData.getPose(sfmData.getView(refViewId)).getTransform().rotation(); + + // Apply x axis alignment before doing the y alignment + const Eigen::Matrix3d refcam_R_updatedWorld = ref_R_world * R.transpose(); Eigen::Matrix3d zeroX_R_world; sfm::getRotationNullifyX(zeroX_R_world, refcam_R_updatedWorld); From 4b60a5655b95b352a4075fb4a351b44e11ec8c10 Mon Sep 17 00:00:00 2001 From: fabien servant Date: Fri, 17 Feb 2023 15:19:57 +0100 Subject: [PATCH 6/6] Replace poseid with viewid in sfmTransform --- src/software/utils/main_sfmTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/software/utils/main_sfmTransform.cpp b/src/software/utils/main_sfmTransform.cpp index 00e6dd269a..e24af4b5af 100644 --- a/src/software/utils/main_sfmTransform.cpp +++ b/src/software/utils/main_sfmTransform.cpp @@ -202,7 +202,7 @@ IndexT getReferenceViewId(const sfmData::SfMData & sfmData, const std::string & std::vector> sorted_views; for (auto v : sfmData.getViews()) { int64_t t = v.second->getMetadataDateTimestamp(); - sorted_views.push_back(std::make_pair(t, v.second->getPoseId())); + sorted_views.push_back(std::make_pair(t, v.first)); } std::sort(sorted_views.begin(), sorted_views.end());