| 350 | } |
| 351 | |
| 352 | std::vector<ImageAlignmentError> ComputeImageAlignmentError( |
| 353 | const Reconstruction& src_reconstruction, |
| 354 | const Reconstruction& tgt_reconstruction, |
| 355 | const Sim3d& tgt_from_src) { |
| 356 | const std::vector<std::pair<image_t, image_t>> common_image_ids = |
| 357 | src_reconstruction.FindCommonRegImageIds(tgt_reconstruction); |
| 358 | const int num_common_images = common_image_ids.size(); |
| 359 | std::vector<ImageAlignmentError> errors; |
| 360 | errors.reserve(num_common_images); |
| 361 | for (const auto& image_ids : common_image_ids) { |
| 362 | const auto& src_image = src_reconstruction.Image(image_ids.first); |
| 363 | const Rigid3d tgt_world_from_src_cam = |
| 364 | Inverse(TransformCameraWorld(tgt_from_src, src_image.CamFromWorld())); |
| 365 | const Rigid3d tgt_world_from_tgt_cam = |
| 366 | Inverse(tgt_reconstruction.Image(image_ids.second).CamFromWorld()); |
| 367 | |
| 368 | ImageAlignmentError error; |
| 369 | error.image_name = src_image.Name(); |
| 370 | error.rotation_error_deg = |
| 371 | RadToDeg(tgt_world_from_src_cam.rotation().angularDistance( |
| 372 | tgt_world_from_tgt_cam.rotation())); |
| 373 | error.proj_center_error = (tgt_world_from_src_cam.translation() - |
| 374 | tgt_world_from_tgt_cam.translation()) |
| 375 | .norm(); |
| 376 | errors.push_back(error); |
| 377 | } |
| 378 | return errors; |
| 379 | } |
| 380 | |
| 381 | bool AlignReconstructionsViaPoints(const Reconstruction& src_reconstruction, |
| 382 | const Reconstruction& tgt_reconstruction, |