Skip to content

Commit

Permalink
[pipeline] Simplify intrinsics building error reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
p12tic committed Oct 20, 2022
1 parent 7acf7b4 commit 111b66e
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 116 deletions.
105 changes: 89 additions & 16 deletions src/aliceVision/sfmDataIO/viewIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,84 @@ std::istream& operator>>(std::istream& in, EGroupCameraFallback& s)
return in;
}

void BuildViewIntrinsicsReport::merge(const BuildViewIntrinsicsReport& other)
{
unknownSensors.insert(other.unknownSensors.begin(), other.unknownSensors.end());
unsureSensors.insert(other.unsureSensors.begin(), other.unsureSensors.end());
missingDeviceUID.insert(missingDeviceUID.end(),
other.missingDeviceUID.begin(), other.missingDeviceUID.end());
noMetadataImagePaths.insert(noMetadataImagePaths.end(),
other.noMetadataImagePaths.begin(), other.noMetadataImagePaths.end());
intrinsicsSetFromFocal35mm.insert(other.intrinsicsSetFromFocal35mm.begin(),
other.intrinsicsSetFromFocal35mm.end());
}

void BuildViewIntrinsicsReport::reportToLog()
{
if (!noMetadataImagePaths.empty())
{
std::stringstream ss;
ss << "No metadata in image(s):\n";
for(const auto& imagePath : noMetadataImagePaths)
ss << "\t- '" << imagePath << "'\n";
ALICEVISION_LOG_DEBUG(ss.str());
}

if (!missingDeviceUID.empty())
{
ALICEVISION_LOG_WARNING(
"Some image(s) have no serial number to identify the camera/lens device.\n"
"This makes it impossible to correctly group the images by device if you have used \n"
"multiple identical (same model) camera devices. The reconstruction will assume that \n"
"only one device has been used, so if 2 images share the same focal length \n"
"approximation they will share the same internal camera parameters.\n"
<< missingDeviceUID.size() << " image(s) are concerned.");
ALICEVISION_LOG_DEBUG("The following images are concerned:\n");
ALICEVISION_LOG_DEBUG(boost::algorithm::join(missingDeviceUID, "\n"));
}

if (!unsureSensors.empty())
{
ALICEVISION_LOG_WARNING("The camera found in the database is slightly different for image(s):");
for (const auto& unsureSensor : unsureSensors)
ALICEVISION_LOG_WARNING("image: '" << fs::path(unsureSensor.second.first).filename().string() << "'\n"
<< "\t- image camera brand: " << unsureSensor.first.first << "\n"
<< "\t- image camera model: " << unsureSensor.first.second << "\n"
<< "\t- database camera brand: " << unsureSensor.second.second._brand << "\n"
<< "\t- database camera model: " << unsureSensor.second.second._model << "\n"
<< "\t- database camera sensor width: " << unsureSensor.second.second._sensorWidth << " mm");
ALICEVISION_LOG_WARNING("Please check and correct camera model(s) name in the database.\n");
}

if (!unknownSensors.empty())
{
std::stringstream ss;
ss << "Sensor width doesn't exist in the database for image(s):\n";
for (const auto& unknownSensor : unknownSensors)
{
ss << "\t- camera brand: " << unknownSensor.first.first << "\n"
<< "\t- camera model: " << unknownSensor.first.second << "\n"
<< "\t - image: " << fs::path(unknownSensor.second).filename().string() << "\n";
}
ss << "Please add camera model(s) and sensor width(s) in the database.";

ALICEVISION_LOG_WARNING(ss.str());
}

if (!intrinsicsSetFromFocal35mm.empty())
{
std::stringstream ss;
ss << "Intrinsic(s) initialized from 'FocalLengthIn35mmFilm' exif metadata in image(s):\n";
for (const auto& intrinsicSetFromFocal35mm : intrinsicsSetFromFocal35mm)
{
ss << "\t- image: " << fs::path(intrinsicSetFromFocal35mm.first).filename().string() << "\n"
<< "\t - sensor width: " << intrinsicSetFromFocal35mm.second.first << "\n"
<< "\t - focal length: " << intrinsicSetFromFocal35mm.second.second << "\n";
}
ALICEVISION_LOG_DEBUG(ss.str());
}
}

std::shared_ptr<camera::IntrinsicBase>
buildViewIntrinsic(sfmData::View& view,
const std::vector<sensorDB::Datasheet>& sensorDatabase,
Expand All @@ -358,11 +436,7 @@ std::shared_ptr<camera::IntrinsicBase>
camera::EINTRINSIC defaultCameraModel,
camera::EINTRINSIC allowedCameraModels,
EGroupCameraFallback groupCameraFallback,
UnknownSensorsMap& unknownSensors,
UnsureSensorsMap& unsureSensors,
std::vector<std::string>& missingDeviceUID,
std::vector<std::string>& noMetadataImagePaths,
IntrinsicsFromFocal35mmMap& intrinsicsSetFromFocal35mm)
BuildViewIntrinsicsReport& report)
{
IndexT intrinsicId = view.getIntrinsicId();
double sensorWidth = -1;
Expand Down Expand Up @@ -402,7 +476,8 @@ std::shared_ptr<camera::IntrinsicBase>
if (datasheet._model != model)
{
// the camera model in database is slightly different
unsureSensors.emplace(std::make_pair(make, model), std::make_pair(view.getImagePath(), datasheet)); // will throw a warning message
report.unsureSensors.emplace(std::make_pair(make, model),
std::make_pair(view.getImagePath(), datasheet));
}

sensorWidth = datasheet._sensorWidth;
Expand Down Expand Up @@ -437,8 +512,8 @@ std::shared_ptr<camera::IntrinsicBase>
sensorWidthSource = ESensorWidthSource::UNKNOWN;
}

intrinsicsSetFromFocal35mm.emplace(view.getImagePath(),
std::make_pair(sensorWidth, focalLengthmm));
report.intrinsicsSetFromFocal35mm.emplace(view.getImagePath(),
std::make_pair(sensorWidth, focalLengthmm));
intrinsicInitMode = camera::EIntrinsicInitMode::ESTIMATED;
}
else if (sensorWidth > 0 && focalLengthmm <= 0)
Expand All @@ -450,8 +525,8 @@ std::shared_ptr<camera::IntrinsicBase>

focalLengthmm = (sensorDiag * focalIn35mm) / diag24x36;

intrinsicsSetFromFocal35mm.emplace(view.getImagePath(),
std::make_pair(sensorWidth, focalLengthmm));
report.intrinsicsSetFromFocal35mm.emplace(view.getImagePath(),
std::make_pair(sensorWidth, focalLengthmm));
intrinsicInitMode = camera::EIntrinsicInitMode::ESTIMATED;
}
}
Expand All @@ -461,14 +536,13 @@ std::shared_ptr<camera::IntrinsicBase>
{
if (hasCameraMetadata)
{
// Sensor is not in the database. This will throw a warning at the end
unknownSensors.emplace(std::make_pair(make, model), view.getImagePath());
// Sensor is not in the database.
report.unknownSensors.emplace(std::make_pair(make, model), view.getImagePath());
}
else
{
// No metadata 'Make' and 'Model' can't find sensor width.
// This will throw a warning message at the end
noMetadataImagePaths.emplace_back(view.getImagePath());
report.noMetadataImagePaths.emplace_back(view.getImagePath());
}
}
else
Expand Down Expand Up @@ -536,8 +610,7 @@ std::shared_ptr<camera::IntrinsicBase>
else
{
// We have no way to identify a camera device correctly.
// will throw a warning message at the end
missingDeviceUID.emplace_back(view.getImagePath());
report.missingDeviceUID.emplace_back(view.getImagePath());

// To avoid stopping the process, we fallback to a solution selected by the user:
if (groupCameraFallback == EGroupCameraFallback::FOLDER)
Expand Down
36 changes: 20 additions & 16 deletions src/aliceVision/sfmDataIO/viewIO.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,6 @@ bool extractNumberFromFileStem(const std::string& imagePathStem, IndexT& number,
*/
bool viewHasDefinedIntrinsic(const sfmData::SfMData& sfmData, const sfmData::View& view);

// key (make,model), value (first imagePath)
using UnknownSensorsMap = std::map<std::pair<std::string, std::string>, std::string>;

// key (make,model), value (first imagePath,datasheet)
using UnsureSensorsMap = std::map<std::pair<std::string, std::string>,
std::pair<std::string, sensorDB::Datasheet>>;

// key imagePath value (sensor width, focal length)
using IntrinsicsFromFocal35mmMap = std::map<std::string, std::pair<double, double>>;


enum class EGroupCameraFallback {
GLOBAL,
FOLDER,
Expand All @@ -140,10 +129,29 @@ EGroupCameraFallback EGroupCameraFallback_stringToEnum(const std::string& strate
std::ostream& operator<<(std::ostream& os, EGroupCameraFallback s);
std::istream& operator>>(std::istream& in, EGroupCameraFallback& s);

struct BuildViewIntrinsicsReport
{
// key (make,model), value (first imagePath)
std::map<std::pair<std::string, std::string>, std::string> unknownSensors;
// key (make,model), value (first imagePath,datasheet)
std::map<std::pair<std::string, std::string>,
std::pair<std::string, sensorDB::Datasheet>> unsureSensors;

std::vector<std::string> missingDeviceUID;
std::vector<std::string> noMetadataImagePaths;

// key imagePath value (sensor width, focal length)
std::map<std::string, std::pair<double, double>> intrinsicsSetFromFocal35mm;

void merge(const BuildViewIntrinsicsReport& other);
void reportToLog();
};

/**
* @brief Build intrinsic for a view.
* @param[in] view View to build intrinsic for
* @param[in] sensorDatabase The sensor database to fetch sensor from
* @param[out] report Any warnings that have arisen during processing will be added to this variable.
*/
std::shared_ptr<camera::IntrinsicBase>
buildViewIntrinsic(sfmData::View& view,
Expand All @@ -153,11 +161,7 @@ std::shared_ptr<camera::IntrinsicBase>
camera::EINTRINSIC defaultCameraModel,
camera::EINTRINSIC allowedCameraModels,
EGroupCameraFallback groupCameraFallback,
UnknownSensorsMap& unknownSensors,
UnsureSensorsMap& unsureSensors,
std::vector<std::string>& missingDeviceUID,
std::vector<std::string>& noMetadataImagePaths,
IntrinsicsFromFocal35mmMap& intrinsicsSetFromFocal35mm);
BuildViewIntrinsicsReport& report);

} // namespace sfmDataIO
} // namespace aliceVision
92 changes: 8 additions & 84 deletions src/software/pipeline/main_cameraInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,6 @@ int aliceVision_main(int argc, char **argv)
// use current time as seed for random generator for intrinsic Id without metadata
std::srand(std::time(0));

std::vector<std::string> noMetadataImagePaths; // imagePaths
IntrinsicsFromFocal35mmMap intrinsicsSetFromFocal35mm;
std::vector<std::string> missingDeviceUID;
UnknownSensorsMap unknownSensors;
UnsureSensorsMap unsureSensors;
std::map<IndexT, std::map<int, std::size_t>> detectedRigs; // key rigId, value (subPoseId, nbPose)

sfmData::SfMData sfmData;
Expand Down Expand Up @@ -351,6 +346,7 @@ int aliceVision_main(int argc, char **argv)
boost::regex extractComposedNumberRegex("\\d+(?:[\\-\\:\\_\\.]\\d+)*");
boost::regex extractNumberRegex("\\d+");

BuildViewIntrinsicsReport intrinsicsReport;
std::map<IndexT, std::vector<IndexT>> poseGroups;

#pragma omp parallel for
Expand Down Expand Up @@ -419,20 +415,14 @@ int aliceVision_main(int argc, char **argv)
continue;
}

UnknownSensorsMap viewUnknownSensors;
UnsureSensorsMap viewUnsureSensors;
std::vector<std::string> viewMissingDeviceUID;
std::vector<std::string> viewNoMetadataImagePaths;
IntrinsicsFromFocal35mmMap viewIntrinsicsSetFromFocal35mm;
BuildViewIntrinsicsReport viewIntrinsicsReport;


auto intrinsicBase = buildViewIntrinsic(view, sensorDatabase,
defaultFocalLength, defaultFieldOfView,
defaultFocalRatio, defaultOffsetX, defaultOffsetY,
defaultCameraModel, allowedCameraModels,
groupCameraFallback,
viewUnknownSensors, viewUnsureSensors,
viewMissingDeviceUID, viewNoMetadataImagePaths,
viewIntrinsicsSetFromFocal35mm);
groupCameraFallback, viewIntrinsicsReport);

if (intrinsicBase && intrinsicBase->isValid())
{
Expand All @@ -443,14 +433,7 @@ int aliceVision_main(int argc, char **argv)
#pragma omp critical
{
sfmData.getIntrinsics().emplace(view.getIntrinsicId(), intrinsicBase);
unknownSensors.insert(viewUnknownSensors.begin(), viewUnknownSensors.end());
unsureSensors.insert(viewUnsureSensors.begin(), viewUnsureSensors.end());
missingDeviceUID.insert(missingDeviceUID.end(),
viewMissingDeviceUID.begin(), viewMissingDeviceUID.end());
noMetadataImagePaths.insert(noMetadataImagePaths.end(),
viewNoMetadataImagePaths.begin(), viewNoMetadataImagePaths.end());
intrinsicsSetFromFocal35mm.insert(viewIntrinsicsSetFromFocal35mm.begin(),
viewIntrinsicsSetFromFocal35mm.end());
intrinsicsReport.merge(viewIntrinsicsReport);
}
}

Expand Down Expand Up @@ -515,67 +498,7 @@ int aliceVision_main(int argc, char **argv)
}
}

if(!noMetadataImagePaths.empty())
{
std::stringstream ss;
ss << "No metadata in image(s):\n";
for(const auto& imagePath : noMetadataImagePaths)
ss << "\t- '" << imagePath << "'\n";
ALICEVISION_LOG_DEBUG(ss.str());
}

if(!missingDeviceUID.empty())
{
ALICEVISION_LOG_WARNING(
"Some image(s) have no serial number to identify the camera/lens device.\n"
"This makes it impossible to correctly group the images by device if you have used multiple identical (same model) camera devices.\n"
"The reconstruction will assume that only one device has been used, "
"so if 2 images share the same focal length approximation they will share the same internal camera parameters.\n"
<< missingDeviceUID.size() << " image(s) are concerned.");
ALICEVISION_LOG_DEBUG("The following images are concerned:\n");
ALICEVISION_LOG_DEBUG(boost::algorithm::join(missingDeviceUID, "\n"));
}

if(!unsureSensors.empty())
{
ALICEVISION_LOG_WARNING("The camera found in the database is slightly different for image(s):");
for(const auto& unsureSensor : unsureSensors)
ALICEVISION_LOG_WARNING("image: '" << fs::path(unsureSensor.second.first).filename().string() << "'" << std::endl
<< "\t- image camera brand: " << unsureSensor.first.first << std::endl
<< "\t- image camera model: " << unsureSensor.first.second << std::endl
<< "\t- database camera brand: " << unsureSensor.second.second._brand << std::endl
<< "\t- database camera model: " << unsureSensor.second.second._model << std::endl
<< "\t- database camera sensor width: " << unsureSensor.second.second._sensorWidth << " mm");
ALICEVISION_LOG_WARNING("Please check and correct camera model(s) name in the database." << std::endl);
}

if(!unknownSensors.empty())
{
std::stringstream ss;
ss << "Sensor width doesn't exist in the database for image(s):\n";
for(const auto& unknownSensor : unknownSensors)
{
ss << "\t- camera brand: " << unknownSensor.first.first << "\n"
<< "\t- camera model: " << unknownSensor.first.second << "\n"
<< "\t - image: " << fs::path(unknownSensor.second).filename().string() << "\n";
}
ss << "Please add camera model(s) and sensor width(s) in the database.";

ALICEVISION_LOG_WARNING(ss.str());
}

if(!intrinsicsSetFromFocal35mm.empty())
{
std::stringstream ss;
ss << "Intrinsic(s) initialized from 'FocalLengthIn35mmFilm' exif metadata in image(s):\n";
for(const auto& intrinsicSetFromFocal35mm : intrinsicsSetFromFocal35mm)
{
ss << "\t- image: " << fs::path(intrinsicSetFromFocal35mm.first).filename().string() << "\n"
<< "\t - sensor width: " << intrinsicSetFromFocal35mm.second.first << "\n"
<< "\t - focal length: " << intrinsicSetFromFocal35mm.second.second << "\n";
}
ALICEVISION_LOG_DEBUG(ss.str());
}
intrinsicsReport.reportToLog();

if(completeViewCount < 1 || (completeViewCount < 2 && !allowSingleView))
{
Expand Down Expand Up @@ -603,7 +526,8 @@ int aliceVision_main(int argc, char **argv)
ALICEVISION_LOG_INFO("CameraInit report:"
<< "\n\t- # views listed: " << sfmData.getViews().size()
<< "\n\t - # views with an initialized intrinsic listed: " << completeViewCount
<< "\n\t - # views without metadata (with a default intrinsic): " << noMetadataImagePaths.size()
<< "\n\t - # views without metadata (with a default intrinsic): "
<< intrinsicsReport.noMetadataImagePaths.size()
<< "\n\t- # intrinsics listed: " << sfmData.getIntrinsics().size());

return EXIT_SUCCESS;
Expand Down

0 comments on commit 111b66e

Please sign in to comment.