sweeneychris / TheiaSfM

An open source library for multiview geometry and structure from motion
Other
904 stars 281 forks source link

calibration application error when setting a focal length prior #255

Open jarrodhaas opened 4 years ago

jarrodhaas commented 4 years ago

When running calibrate_camera_intrinsics.cc, calibration fails with below error, regardless of the prior focal length used:

F0715 16:03:27.631510 210365888 visibility_pyramid.cc:54] Check failed: width_ > 0 (0 vs. 0)

I set the focal length prior by adding a flag:

DEFINE_double(focal_length_prior, 0.0, "Set a prior focal length to initialize intrinsics with.");

and then:

if (FLAGS_focal_length_prior != 0) { prior.focal_length.is_set = true; prior.focal_length.value[0] = FLAGS_focal_length_prior; }

Everything works fine if I don't set a focal prior.

jarrodhaas commented 4 years ago

Looks like this bug is due to a block of code in feature_extractor_and_matcher.cc (below).

When the bundle adjustment estimator function calls:

VisibilityPyramid pyramid( camera.ImageWidth(), camera.ImageHeight(), kNumPyramidLevels);

and passes it image dimensions, those dimensions don't exist if a focal length prior is set. Image size info looks to be obtained through the below call to ExtractEXIFMetadata. But this code block isn't called if focal_length.is_set == true.

`if (!intrinsics.focal_length.is_set) { CHECK(exifreader.ExtractEXIFMetadata(image_filepath, &intrinsics));

// If the focal length still could not be extracted, set it to a reasonable
// value based on a median viewing angle.
if (!options_.only_calibrated_views && !intrinsics.focal_length.is_set) {
  VLOG(2) << "Exif was not detected. Setting it to a reasonable value.";
  intrinsics.focal_length.is_set = true;
  intrinsics.focal_length.value[0] =
      1.2 * static_cast<double>(
                std::max(intrinsics.image_width, intrinsics.image_height));
}

}`

a hacky solution is just to add a condition that pulls exif data, and copies it over to the intrinsic variable for later use:

`CameraIntrinsicsPrior intrinsics_size; CHECK(exifreader.ExtractEXIFMetadata(image_filepath, &intrinsics_size));

if (!intrinsics.focal_length.is_set) { CHECK(exifreader.ExtractEXIFMetadata(image_filepath, &intrinsics));

// If the focal length still could not be extracted, set it to a reasonable
// value based on a median viewing angle.
if (!options_.only_calibrated_views && !intrinsics.focal_length.is_set) {
  VLOG(2) << "Exif was not detected. Setting it to a reasonable value.";
  intrinsics.focal_length.is_set = true;
  intrinsics.focal_length.value[0] =
      1.2 * static_cast<double>(
                std::max(intrinsics.image_width, intrinsics.image_height));
}

} // our hack to ensure that image size is recorded if a focal_length prior is set... else { intrinsics.image_width = intrinsics_size.image_width;
intrinsics.image_height = intrinsics_size.image_height; }`