From 578f64c406dda8ef0b5f68b2013fb3b85fc6f03f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Mon, 14 Oct 2024 15:49:51 +0200 Subject: [PATCH 1/4] [sfmData] ImageInfo: Handle focal length in metadata from DJI drones --- src/aliceVision/sfmData/ImageInfo.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/aliceVision/sfmData/ImageInfo.hpp b/src/aliceVision/sfmData/ImageInfo.hpp index 2ed149da85..b19599da11 100644 --- a/src/aliceVision/sfmData/ImageInfo.hpp +++ b/src/aliceVision/sfmData/ImageInfo.hpp @@ -220,6 +220,24 @@ class ImageInfo focalLength = -1; } + // For DJI drones, the focal length may be expressed as a list (e.g. [50000,1000]) + std::string focalLengthList = getMetadata({"focal_length"}); + std::string focalLengthStr = ""; + std::string focalLengthDividerStr = ""; + + if (!focalLengthList.empty() && focalLengthList.find("[") == 0 && focalLengthList.find("]") == focalLengthList.size() - 1) + { + std::size_t delimiterPosition = focalLengthList.find(","); + if (delimiterPosition != std::string::npos) + { + focalLengthStr = focalLengthList.substr(1, delimiterPosition - 1); + focalLengthDividerStr = focalLengthList.substr(delimiterPosition + 1, focalLengthList.size() - delimiterPosition - 2); + } + + // Focal length is provided in µm, hence the required division + focalLength = std::stod(focalLengthStr) / std::stod(focalLengthDividerStr); + } + // Might be available and more precise (especially if the focal length was initially retrieved from a string) double nominativeFocalLength = getDoubleMetadata({"AxialNominalFocalLength"}); if (nominativeFocalLength != -1) From e3f112698a478f941931c05d6f629e78861d7f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 15 Oct 2024 16:08:26 +0200 Subject: [PATCH 2/4] [sfmData] ImageInfo: Handle focal length in metadata from ARRI cameras --- src/aliceVision/sfmData/ImageInfo.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/aliceVision/sfmData/ImageInfo.hpp b/src/aliceVision/sfmData/ImageInfo.hpp index b19599da11..cec6fb8427 100644 --- a/src/aliceVision/sfmData/ImageInfo.hpp +++ b/src/aliceVision/sfmData/ImageInfo.hpp @@ -239,10 +239,16 @@ class ImageInfo } // Might be available and more precise (especially if the focal length was initially retrieved from a string) - double nominativeFocalLength = getDoubleMetadata({"AxialNominalFocalLength"}); - if (nominativeFocalLength != -1) + double nominalFocalLength = getDoubleMetadata({"AxialNominalFocalLength", "axialNominalFocalLength"}); + if (nominalFocalLength != -1) { - focalLength = nominativeFocalLength; + // For ARRI camera, the axial nominal focal length might either be available as mm or µm. + // We assume that if the result is larger than 9999, then the unit cannot be mm + if (nominalFocalLength > 9999) + { + nominalFocalLength /= 1000; + } + focalLength = nominalFocalLength; } return focalLength; From 650d94250b2c0fc2af5147406953e4fbca15ef90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Tue, 15 Oct 2024 16:40:22 +0200 Subject: [PATCH 3/4] [sfmData] ImageInfo: Add debug logs when retrieving specific focal lengths --- src/aliceVision/sfmData/ImageInfo.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/aliceVision/sfmData/ImageInfo.hpp b/src/aliceVision/sfmData/ImageInfo.hpp index cec6fb8427..94fccb460c 100644 --- a/src/aliceVision/sfmData/ImageInfo.hpp +++ b/src/aliceVision/sfmData/ImageInfo.hpp @@ -208,6 +208,8 @@ class ImageInfo focalLength = getDoubleMetadata({"LensZoomActualFocalLength"}); if (focalLength != -1) { + ALICEVISION_LOG_DEBUG("Used Sony metadata 'LensZoomActualFocalLength'. The retrieved focal length (" + << focalLength << ") is in meters and will be multiplied by 1000."); focalLength *= 1000; } } @@ -227,6 +229,8 @@ class ImageInfo if (!focalLengthList.empty() && focalLengthList.find("[") == 0 && focalLengthList.find("]") == focalLengthList.size() - 1) { + ALICEVISION_LOG_DEBUG("Used DJI drones metadata 'focal_length'. The retrieved focal length (" + << focalLengthList << ") will have its first term divided by its second term."); std::size_t delimiterPosition = focalLengthList.find(","); if (delimiterPosition != std::string::npos) { @@ -242,6 +246,8 @@ class ImageInfo double nominalFocalLength = getDoubleMetadata({"AxialNominalFocalLength", "axialNominalFocalLength"}); if (nominalFocalLength != -1) { + ALICEVISION_LOG_DEBUG("Used ARRI metadata 'AxialNominalFocalLength'. The retrieved focal length (" + << nominalFocalLength << ") will need to be converted from mm or µm."); // For ARRI camera, the axial nominal focal length might either be available as mm or µm. // We assume that if the result is larger than 9999, then the unit cannot be mm if (nominalFocalLength > 9999) From 8d519a3c8565628bf055f1d30068b9ba8d3779c7 Mon Sep 17 00:00:00 2001 From: Fabien Servant Date: Wed, 16 Oct 2024 14:02:07 +0200 Subject: [PATCH 4/4] Add catch on stod --- src/aliceVision/sfmData/ImageInfo.cpp | 77 +++++++++++++++++++++++++++ src/aliceVision/sfmData/ImageInfo.hpp | 62 +-------------------- 2 files changed, 78 insertions(+), 61 deletions(-) diff --git a/src/aliceVision/sfmData/ImageInfo.cpp b/src/aliceVision/sfmData/ImageInfo.cpp index 81fc511b77..b3fdb06b8d 100644 --- a/src/aliceVision/sfmData/ImageInfo.cpp +++ b/src/aliceVision/sfmData/ImageInfo.cpp @@ -395,5 +395,82 @@ int ImageInfo::getSensorSize(const std::vector& sensorDatab return errCode; } +double ImageInfo::getMetadataFocalLength() const +{ + double focalLength = getDoubleMetadata({"Exif:FocalLength", "focalLength", "focal length", "lens_focal_length"}); + + if (focalLength == -1) + { + // Sony metadata: the focal length is provided in meters + focalLength = getDoubleMetadata({"LensZoomActualFocalLength"}); + if (focalLength != -1) + { + ALICEVISION_LOG_DEBUG("Used Sony metadata 'LensZoomActualFocalLength'. The retrieved focal length (" + << focalLength << ") is in meters and will be multiplied by 1000."); + focalLength *= 1000; + } + } + + // 32767 = (2^15 - 1) - Maximum of a signed short: means there is no available focal length + // 4294967295 = (2^32 - 1) - Maximum of a signed integer: means there is no available focal length + // -> might be truncated and/or rounded up to 4.29497e+06 + else if (focalLength == USHRT_MAX || focalLength == SHRT_MAX || focalLength == UINT_MAX || focalLength == INT_MAX || focalLength == 4294970) + { + focalLength = -1; + } + + // For DJI drones, the focal length may be expressed as a list (e.g. [50000,1000]) + std::string focalLengthList = getMetadata({"focal_length"}); + std::string focalLengthStr = ""; + std::string focalLengthDividerStr = ""; + + if (!focalLengthList.empty() && focalLengthList.find("[") == 0 && focalLengthList.find("]") == focalLengthList.size() - 1) + { + ALICEVISION_LOG_DEBUG("Used DJI drones metadata 'focal_length'. The retrieved focal length (" + << focalLengthList << ") will have its first term divided by its second term."); + std::size_t delimiterPosition = focalLengthList.find(","); + if (delimiterPosition != std::string::npos) + { + focalLengthStr = focalLengthList.substr(1, delimiterPosition - 1); + focalLengthDividerStr = focalLengthList.substr(delimiterPosition + 1, focalLengthList.size() - delimiterPosition - 2); + } + + // Focal length is provided in µm, hence the required division + double uf = 0.0; + bool valid = true; + + try + { + uf = std::stod(focalLengthStr) / std::stod(focalLengthDividerStr); + } + catch(const std::exception& e) + { + valid = false; + } + + if (valid) + { + focalLength = uf; + } + } + + // Might be available and more precise (especially if the focal length was initially retrieved from a string) + double nominalFocalLength = getDoubleMetadata({"AxialNominalFocalLength", "axialNominalFocalLength"}); + if (nominalFocalLength != -1) + { + ALICEVISION_LOG_DEBUG("Used ARRI metadata 'AxialNominalFocalLength'. The retrieved focal length (" + << nominalFocalLength << ") will need to be converted from mm or µm."); + // For ARRI camera, the axial nominal focal length might either be available as mm or µm. + // We assume that if the result is larger than 9999, then the unit cannot be mm + if (nominalFocalLength > 9999) + { + nominalFocalLength /= 1000; + } + focalLength = nominalFocalLength; + } + + return focalLength; +} + } // namespace sfmData } // namespace aliceVision diff --git a/src/aliceVision/sfmData/ImageInfo.hpp b/src/aliceVision/sfmData/ImageInfo.hpp index 94fccb460c..cb39dc7a85 100644 --- a/src/aliceVision/sfmData/ImageInfo.hpp +++ b/src/aliceVision/sfmData/ImageInfo.hpp @@ -198,67 +198,7 @@ class ImageInfo * @brief Get the corresponding "FocalLength" metadata value * @return the metadata value float or -1 if no corresponding value */ - double getMetadataFocalLength() const - { - double focalLength = getDoubleMetadata({"Exif:FocalLength", "focalLength", "focal length", "lens_focal_length"}); - - if (focalLength == -1) - { - // Sony metadata: the focal length is provided in meters - focalLength = getDoubleMetadata({"LensZoomActualFocalLength"}); - if (focalLength != -1) - { - ALICEVISION_LOG_DEBUG("Used Sony metadata 'LensZoomActualFocalLength'. The retrieved focal length (" - << focalLength << ") is in meters and will be multiplied by 1000."); - focalLength *= 1000; - } - } - - // 32767 = (2^15 - 1) - Maximum of a signed short: means there is no available focal length - // 4294967295 = (2^32 - 1) - Maximum of a signed integer: means there is no available focal length - // -> might be truncated and/or rounded up to 4.29497e+06 - else if (focalLength == USHRT_MAX || focalLength == SHRT_MAX || focalLength == UINT_MAX || focalLength == INT_MAX || focalLength == 4294970) - { - focalLength = -1; - } - - // For DJI drones, the focal length may be expressed as a list (e.g. [50000,1000]) - std::string focalLengthList = getMetadata({"focal_length"}); - std::string focalLengthStr = ""; - std::string focalLengthDividerStr = ""; - - if (!focalLengthList.empty() && focalLengthList.find("[") == 0 && focalLengthList.find("]") == focalLengthList.size() - 1) - { - ALICEVISION_LOG_DEBUG("Used DJI drones metadata 'focal_length'. The retrieved focal length (" - << focalLengthList << ") will have its first term divided by its second term."); - std::size_t delimiterPosition = focalLengthList.find(","); - if (delimiterPosition != std::string::npos) - { - focalLengthStr = focalLengthList.substr(1, delimiterPosition - 1); - focalLengthDividerStr = focalLengthList.substr(delimiterPosition + 1, focalLengthList.size() - delimiterPosition - 2); - } - - // Focal length is provided in µm, hence the required division - focalLength = std::stod(focalLengthStr) / std::stod(focalLengthDividerStr); - } - - // Might be available and more precise (especially if the focal length was initially retrieved from a string) - double nominalFocalLength = getDoubleMetadata({"AxialNominalFocalLength", "axialNominalFocalLength"}); - if (nominalFocalLength != -1) - { - ALICEVISION_LOG_DEBUG("Used ARRI metadata 'AxialNominalFocalLength'. The retrieved focal length (" - << nominalFocalLength << ") will need to be converted from mm or µm."); - // For ARRI camera, the axial nominal focal length might either be available as mm or µm. - // We assume that if the result is larger than 9999, then the unit cannot be mm - if (nominalFocalLength > 9999) - { - nominalFocalLength /= 1000; - } - focalLength = nominalFocalLength; - } - - return focalLength; - } + double getMetadataFocalLength() const; /** * @brief Get the corresponding "ExposureTime" (shutter) metadata value