| 643 | } |
| 644 | |
| 645 | void TestGuidedMatchingWithCameraDistortion( |
| 646 | const std::function<std::unique_ptr<FeatureMatcher>( |
| 647 | const std::vector<FeatureMatcher::Image>&)>& matcher_factory) { |
| 648 | // Test guided matching with essential matrix using calibrated cameras. |
| 649 | // This exercises the code path that uses normalized coordinates. |
| 650 | // Use kRadial model with strong radial and tangential distortion. |
| 651 | Camera camera = |
| 652 | Camera::CreateFromModelId(1, CameraModelId::kOpenCV, 100.0, 100, 200); |
| 653 | camera.params[3] = 0.5; // k1 |
| 654 | camera.params[4] = -0.5; // k2 |
| 655 | camera.params[5] = 0.5; // p1 |
| 656 | camera.params[6] = -0.5; // p2 |
| 657 | |
| 658 | // Two points on the epipolar line (v=0 in normalized coordinates). |
| 659 | const Eigen::Vector2f img_point11 = |
| 660 | camera.ImgFromCam({-0.5, 0.1, 1.0}).value().cast<float>(); |
| 661 | const Eigen::Vector2f img_point12 = |
| 662 | camera.ImgFromCam({0.4, -0.1, 1.0}).value().cast<float>(); |
| 663 | const Eigen::Vector2f img_point21 = |
| 664 | camera.ImgFromCam({0.3, -0.1, 1.0}).value().cast<float>(); |
| 665 | const Eigen::Vector2f img_point22 = |
| 666 | camera.ImgFromCam({-0.4, 0.1, 1.0}).value().cast<float>(); |
| 667 | |
| 668 | const FeatureMatcher::Image image0 = { |
| 669 | /*image_id=*/0, |
| 670 | /*camera=*/&camera, |
| 671 | std::make_shared<FeatureKeypoints>(0), |
| 672 | std::make_shared<FeatureDescriptors>(CreateEmptyDescriptors())}; |
| 673 | const FeatureMatcher::Image image1 = { |
| 674 | /*image_id=*/1, |
| 675 | /*camera=*/&camera, |
| 676 | std::make_shared<FeatureKeypoints>( |
| 677 | std::vector<FeatureKeypoint>{{img_point11.x(), img_point11.y()}, |
| 678 | {img_point12.x(), img_point12.y()}}), |
| 679 | std::make_shared<FeatureDescriptors>(CreateRandomFeatureDescriptors(2))}; |
| 680 | const FeatureMatcher::Image image2 = { |
| 681 | /*image_id=*/2, |
| 682 | /*camera=*/&camera, |
| 683 | std::make_shared<FeatureKeypoints>( |
| 684 | std::vector<FeatureKeypoint>{{img_point21.x(), img_point21.y()}, |
| 685 | {img_point22.x(), img_point22.y()}}), |
| 686 | std::make_shared<FeatureDescriptors>( |
| 687 | CreateReversedDescriptors(*image1.descriptors))}; |
| 688 | |
| 689 | auto matcher = matcher_factory({image0, image1, image2}); |
| 690 | |
| 691 | TwoViewGeometry two_view_geometry; |
| 692 | two_view_geometry.E = EssentialMatrixFromPose( |
| 693 | Rigid3d(Eigen::Quaterniond::Identity(), Eigen::Vector3d(1, 0, 0))); |
| 694 | two_view_geometry.F = |
| 695 | FundamentalFromEssentialMatrix(camera.CalibrationMatrix(), |
| 696 | two_view_geometry.E.value(), |
| 697 | camera.CalibrationMatrix()); |
| 698 | |
| 699 | constexpr double kMaxError = 1.0; |
| 700 | |
| 701 | // With uncalibrated cameras, the fundamental matrix is used with pixel |
| 702 | // coordinates and no matches are expected to be found due to strong |
no test coverage detected