123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*M///////////////////////////////////////////////////////////////////////////////////////
- //
- // By downloading, copying, installing or using the software you agree to this license.
- // If you do not agree to this license, do not download, install,
- // copy or use the software.
- //
- //
- // License Agreement
- // For Open Source Computer Vision Library
- // (3-clause BSD License)
- //
- // Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
- // Third party copyrights are property of their respective owners.
- //
- // Redistribution and use in source and binary forms, with or without modification,
- // are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- //
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // * Neither the names of the copyright holders nor the names of the contributors
- // may be used to endorse or promote products derived from this software
- // without specific prior written permission.
- //
- // This software is provided by the copyright holders and contributors "as is" and
- // any express or implied warranties, including, but not limited to, the implied
- // warranties of merchantability and fitness for a particular purpose are disclaimed.
- // In no event shall copyright holders or contributors be liable for any direct,
- // indirect, incidental, special, exemplary, or consequential damages
- // (including, but not limited to, procurement of substitute goods or services;
- // loss of use, data, or profits; or business interruption) however caused
- // and on any theory of liability, whether in contract, strict liability,
- // or tort (including negligence or otherwise) arising in any way out of
- // the use of this software, even if advised of the possibility of such damage.
- //
- //M*/
- #include "test_precomp.hpp"
- namespace opencv_test { namespace {
- CV_ENUM(Method, RANSAC, LMEDS)
- typedef TestWithParam<Method> EstimateAffine2D;
- static float rngIn(float from, float to) { return from + (to-from) * (float)theRNG(); }
- TEST_P(EstimateAffine2D, test3Points)
- {
- // try more transformations
- for (size_t i = 0; i < 500; ++i)
- {
- Mat aff(2, 3, CV_64F);
- cv::randu(aff, 1., 3.);
- Mat fpts(1, 3, CV_32FC2);
- Mat tpts(1, 3, CV_32FC2);
- // setting points that are not in the same line
- fpts.at<Point2f>(0) = Point2f( rngIn(1,2), rngIn(5,6) );
- fpts.at<Point2f>(1) = Point2f( rngIn(3,4), rngIn(3,4) );
- fpts.at<Point2f>(2) = Point2f( rngIn(1,2), rngIn(3,4) );
- transform(fpts, tpts, aff);
- vector<uchar> inliers;
- Mat aff_est = estimateAffine2D(fpts, tpts, inliers, GetParam() /* method */);
- EXPECT_NEAR(0., cvtest::norm(aff_est, aff, NORM_INF), 1e-3);
- // all must be inliers
- EXPECT_EQ(countNonZero(inliers), 3);
- }
- }
- TEST_P(EstimateAffine2D, testNPoints)
- {
- // try more transformations
- for (size_t i = 0; i < 500; ++i)
- {
- Mat aff(2, 3, CV_64F);
- cv::randu(aff, -2., 2.);
- const int method = GetParam();
- const int n = 100;
- int m;
- // LMEDS can't handle more than 50% outliers (by design)
- if (method == LMEDS)
- m = 3*n/5;
- else
- m = 2*n/5;
- const float shift_outl = 15.f;
- const float noise_level = 20.f;
- Mat fpts(1, n, CV_32FC2);
- Mat tpts(1, n, CV_32FC2);
- randu(fpts, 0., 100.);
- transform(fpts, tpts, aff);
- /* adding noise to some points */
- Mat outliers = tpts.colRange(m, n);
- outliers.reshape(1) += shift_outl;
- Mat noise (outliers.size(), outliers.type());
- randu(noise, 0., noise_level);
- outliers += noise;
- vector<uchar> inliers;
- Mat aff_est = estimateAffine2D(fpts, tpts, inliers, method);
- EXPECT_FALSE(aff_est.empty()) << "estimation failed, unable to estimate transform";
- EXPECT_NEAR(0., cvtest::norm(aff_est, aff, NORM_INF), 1e-4);
- bool inliers_good = count(inliers.begin(), inliers.end(), 1) == m &&
- m == accumulate(inliers.begin(), inliers.begin() + m, 0);
- EXPECT_TRUE(inliers_good);
- }
- }
- // test conversion from other datatypes than float
- TEST_P(EstimateAffine2D, testConversion)
- {
- Mat aff(2, 3, CV_32S);
- cv::randu(aff, 1., 3.);
- std::vector<Point> fpts(3);
- std::vector<Point> tpts(3);
- // setting points that are not in the same line
- fpts[0] = Point2f( rngIn(1,2), rngIn(5,6) );
- fpts[1] = Point2f( rngIn(3,4), rngIn(3,4) );
- fpts[2] = Point2f( rngIn(1,2), rngIn(3,4) );
- transform(fpts, tpts, aff);
- vector<uchar> inliers;
- Mat aff_est = estimateAffine2D(fpts, tpts, inliers, GetParam() /* method */);
- ASSERT_FALSE(aff_est.empty());
- aff.convertTo(aff, CV_64F); // need to convert before compare
- EXPECT_NEAR(0., cvtest::norm(aff_est, aff, NORM_INF), 1e-3);
- // all must be inliers
- EXPECT_EQ(countNonZero(inliers), 3);
- }
- INSTANTIATE_TEST_CASE_P(Calib3d, EstimateAffine2D, Method::all());
- // https://github.com/opencv/opencv/issues/14259
- TEST(EstimateAffine2D, issue_14259_dont_change_inputs)
- {
- /*const static*/ float pts0_[10] = {
- 0.0f, 0.0f,
- 0.0f, 8.0f,
- 4.0f, 0.0f, // outlier
- 8.0f, 8.0f,
- 8.0f, 0.0f
- };
- /*const static*/ float pts1_[10] = {
- 0.1f, 0.1f,
- 0.1f, 8.1f,
- 0.0f, 4.0f, // outlier
- 8.1f, 8.1f,
- 8.1f, 0.1f
- };
- Mat pts0(Size(1, 5), CV_32FC2, (void*)pts0_);
- Mat pts1(Size(1, 5), CV_32FC2, (void*)pts1_);
- Mat pts0_copy = pts0.clone();
- Mat pts1_copy = pts1.clone();
- Mat inliers;
- cv::Mat A = cv::estimateAffine2D(pts0, pts1, inliers);
- for(int i = 0; i < pts0.rows; ++i)
- {
- EXPECT_EQ(pts0_copy.at<Vec2f>(i), pts0.at<Vec2f>(i)) << "pts0: i=" << i;
- }
- for(int i = 0; i < pts1.rows; ++i)
- {
- EXPECT_EQ(pts1_copy.at<Vec2f>(i), pts1.at<Vec2f>(i)) << "pts1: i=" << i;
- }
- EXPECT_EQ(0, (int)inliers.at<uchar>(2));
- }
- }} // namespace
|