Skip to content

Commit

Permalink
[sfmData] Retrieve focal length from metadata for specific cameras
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cbentejac committed Oct 25, 2023
1 parent 68e253d commit d6badc4
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 7 deletions.
36 changes: 32 additions & 4 deletions src/aliceVision/sfmData/imageInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,23 @@ int ImageInfo::getSensorSize(const std::vector<sensorDB::Datasheet>& 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)
{
Expand All @@ -274,7 +286,7 @@ int ImageInfo::getSensorSize(const std::vector<sensorDB::Datasheet>& 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;
Expand Down Expand Up @@ -316,6 +328,22 @@ int ImageInfo::getSensorSize(const std::vector<sensorDB::Datasheet>& 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)
{
Expand Down Expand Up @@ -369,7 +397,7 @@ int ImageInfo::getSensorSize(const std::vector<sensorDB::Datasheet>& 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;
}
Expand Down
34 changes: 31 additions & 3 deletions src/aliceVision/sfmData/imageInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"});
}

/**
Expand Down Expand Up @@ -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" });
}

/**
Expand All @@ -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;
}

/**
Expand Down

0 comments on commit d6badc4

Please sign in to comment.