From d6badc48fdfcc7b766b3e6884c2e362313552f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Candice=20Bent=C3=A9jac?= Date: Wed, 25 Oct 2023 12:58:28 +0200 Subject: [PATCH] [sfmData] Retrieve focal length from metadata for specific cameras For ARRI, RED and Sony cameras, the focal length information might be located at an unsual place in the metadata, or provided with another unit than millimeters. This commit ensures we retrieve it if it is available, and convert it to the correct unit. --- src/aliceVision/sfmData/imageInfo.cpp | 36 ++++++++++++++++++++++++--- src/aliceVision/sfmData/imageInfo.hpp | 34 ++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/aliceVision/sfmData/imageInfo.cpp b/src/aliceVision/sfmData/imageInfo.cpp index a37ae6744e..a371538307 100644 --- a/src/aliceVision/sfmData/imageInfo.cpp +++ b/src/aliceVision/sfmData/imageInfo.cpp @@ -254,11 +254,23 @@ int ImageInfo::getSensorSize(const std::vector& sensorDatab } // try to find / compute with 'FocalLengthIn35mmFilm' metadata - const bool hasFocalIn35mmMetadata = hasDigitMetadata({"Exif:FocalLengthIn35mmFilm", "FocalLengthIn35mmFilm"}); + const bool hasFocalIn35mmMetadata = hasDigitMetadata({ + "Exif:FocalLengthIn35mmFilm", + "FocalLengthIn35mmFilm", + "LensZoom35mmStillCameraEquivalent" + }); + if (hasFocalIn35mmMetadata) { const double diag24x36 = std::sqrt(36.0 * 36.0 + 24.0 * 24.0); - const double focalIn35mm = hasFocalIn35mmMetadata ? getDoubleMetadata({"Exif:FocalLengthIn35mmFilm", "FocalLengthIn35mmFilm"}) : -1.0; + + double focalIn35mm = getDoubleMetadata({"Exif:FocalLengthIn35mmFilm", "FocalLengthIn35mmFilm"}); + if (focalIn35mm == -1) + { + // Info not available in the "classic" metadata, look for the one that's specific to Sony. + // Sony metadata: the 35mm focal length equivalent is provided in meters. + focalIn35mm = getDoubleMetadata({"LensZoom35mmStillCameraEquivalent"}) * 1000; + } if (sensorWidth == -1.0) { @@ -274,7 +286,7 @@ int ImageInfo::getSensorSize(const std::vector& sensorDatab } else { - // no sensorWidth and no focalLength but valid focalLengthIn35mm, so consider sensorWith + // no sensorWidth and no focalLength but valid focalLengthIn35mm, so consider sensorWidth // as 35mm sensorWidth = diag24x36 * std::sqrt(1.0 / (1.0 + invRatio * invRatio)); focalLengthmm = sensorWidth * (focalIn35mm) / 36.0; @@ -316,6 +328,22 @@ int ImageInfo::getSensorSize(const std::vector& sensorDatab } } + // If available, effective sensor width and height are provided in µm (Sony) + const double effectiveSensorWidth = getDoubleMetadata({ "ImageSensorEffectiveWidth" }); + const double effectiveSensorHeight = getDoubleMetadata({ "ImageSensorEffectiveHeight "}); + + // If no sensor width has been found or computed yet and the effective sensor width is available, then use it + const bool effectiveSensorSizeApplied = effectiveSensorWidth != -1.0 && sensorWidth == -1.0; + if (effectiveSensorSizeApplied) + { + sensorWidth = effectiveSensorWidth / 1000.0; + if (effectiveSensorHeight != -1.0) + { + sensorHeight = effectiveSensorHeight / 1000.0; + } + sensorWidthSource = ESensorWidthSource::FROM_METADATA_ESTIMATION; + } + // error handling if (sensorWidth == -1.0) { @@ -369,7 +397,7 @@ int ImageInfo::getSensorSize(const std::vector& sensorDatab sensorWidth = 36.0; sensorHeight = 24.0; } - else + else if (sensorHeight == -1.0) // If the sensor height has already been set with the effective height, don't overwrite it { sensorHeight = (imageRatio > 1.0) ? sensorWidth / imageRatio : sensorWidth * imageRatio; } diff --git a/src/aliceVision/sfmData/imageInfo.hpp b/src/aliceVision/sfmData/imageInfo.hpp index 58f963ee7a..3209fd59b9 100644 --- a/src/aliceVision/sfmData/imageInfo.hpp +++ b/src/aliceVision/sfmData/imageInfo.hpp @@ -183,7 +183,8 @@ class ImageInfo */ const std::string& getMetadataModel() const { - return getMetadata({"Model", "cameraModel", "cameraModelName", "camera model", "camera model name"}); + return getMetadata({"Model", "cameraModel", "cameraModelName", "CameraModel", + "camera model", "camera_model", "camera model name"}); } /** @@ -219,7 +220,7 @@ class ImageInfo */ const std::string& getMetadataLensSerialNumber() const { - return getMetadata({ "Exif:LensSerialNumber", "lensSerialNumber", "lens serial number" }); + return getMetadata({ "Exif:LensSerialNumber", "lensSerialNumber", "lens serial number", "lens_serial_number" }); } /** @@ -228,7 +229,34 @@ class ImageInfo */ double getMetadataFocalLength() const { - return getDoubleMetadata({"Exif:FocalLength", "focalLength", "focal length"}); + 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) + { + focalLength *= 1000; + } + } + + // 32767 = (2^16 - 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 == SHRT_MAX - 1 || focalLength == UINT_MAX - 1 || focalLength == 4294970) + { + focalLength = -1; + } + + // Might be available and more precise (especially if the focal length was initially retrieved from a string) + double nominativeFocalLength = getDoubleMetadata({"AxialNominalFocalLength"}); + if (nominativeFocalLength != -1) + { + focalLength = nominativeFocalLength; + } + + return focalLength; } /**