vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <opencv2/geometry.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
static cv::Matx33d randomK(bool is_projective)
|
||||
{
|
||||
static cv::RNG rng;
|
||||
|
||||
cv::Matx33d K = cv::Matx33d::zeros();
|
||||
K(0, 0) = rng.uniform(100, 1000);
|
||||
K(1, 1) = rng.uniform(100, 1000);
|
||||
if (is_projective)
|
||||
{
|
||||
K(0, 2) = rng.uniform(-100, 100);
|
||||
K(1, 2) = rng.uniform(-100, 100);
|
||||
}
|
||||
K(2, 2) = 1.0;
|
||||
|
||||
return K;
|
||||
}
|
||||
|
||||
void
|
||||
generateScene(size_t n_views, size_t n_points, bool is_projective, cv::Matx33d & K, std::vector<cv::Matx33d> & R,
|
||||
std::vector<cv::Vec3d> & t, std::vector<cv::Matx34d> & P, cv::Mat_<double> & points3d,
|
||||
std::vector<cv::Mat_<double> > & points2d)
|
||||
{
|
||||
R.resize(n_views);
|
||||
t.resize(n_views);
|
||||
|
||||
cv::RNG rng;
|
||||
|
||||
// Generate a bunch of random 3d points in a 0, 1 cube
|
||||
points3d.create(3, n_points);
|
||||
rng.fill(points3d, cv::RNG::UNIFORM, 0, 1);
|
||||
|
||||
// Generate random intrinsics
|
||||
K = randomK(is_projective);
|
||||
|
||||
// Generate random camera poses
|
||||
// TODO deal with smooth camera poses (e.g. from a video sequence)
|
||||
for (size_t i = 0; i < n_views; ++i)
|
||||
{
|
||||
// Get a random rotation axis
|
||||
cv::Vec3d vec;
|
||||
rng.fill(vec, cv::RNG::UNIFORM, 0, 1);
|
||||
// Give a random angle to the rotation vector
|
||||
vec = vec / cv::norm(vec) * rng.uniform(0.0f, float(2 * CV_PI));
|
||||
cv::Rodrigues(vec, R[i]);
|
||||
// Create a random translation
|
||||
t[i] = cv::Vec3d(rng.uniform(-0.5f, 0.5f), rng.uniform(-0.5f, 0.5f), rng.uniform(1.0f, 2.0f));
|
||||
// Make sure the shape is in front of the camera
|
||||
cv::Mat_<double> points3d_transformed = cv::Mat(R[i]) * points3d + cv::Mat(t[i]) * cv::Mat_<double> ::ones(1, n_points);
|
||||
double min_dist, max_dist;
|
||||
cv::minMaxIdx(points3d_transformed.row(2), &min_dist, &max_dist);
|
||||
if (min_dist < 0)
|
||||
t[i][2] = t[i][2] - min_dist + 1.0;
|
||||
}
|
||||
|
||||
// Compute projection matrices
|
||||
P.resize(n_views);
|
||||
for (size_t i = 0; i < n_views; ++i)
|
||||
{
|
||||
cv::Matx33d K3 = K, R3 = R[i];
|
||||
cv::Vec3d t3 = t[i];
|
||||
cv::sfm::projectionFromKRt(K3, R3, t3, P[i]);
|
||||
}
|
||||
|
||||
// Compute homogeneous 3d points
|
||||
cv::Mat_<double> points3d_homogeneous(4, n_points);
|
||||
points3d.copyTo(points3d_homogeneous.rowRange(0, 3));
|
||||
points3d_homogeneous.row(3).setTo(1);
|
||||
// Project those points for every view
|
||||
points2d.resize(n_views);
|
||||
for (size_t i = 0; i < n_views; ++i)
|
||||
{
|
||||
cv::Mat_<double> points2d_tmp = cv::Mat(P[i]) * points3d_homogeneous;
|
||||
points2d[i].create(2, n_points);
|
||||
for (unsigned char j = 0; j < 2; ++j)
|
||||
cv::Mat(points2d_tmp.row(j) / points2d_tmp.row(2)).copyTo(points2d[i].row(j));
|
||||
}
|
||||
|
||||
// TODO: remove a certain number of points per view
|
||||
// TODO: add a certain number of outliers per view
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
void
|
||||
generateScene(size_t n_views, size_t n_points, bool is_projective, cv::Matx33d & K, std::vector<cv::Matx33d> & R,
|
||||
std::vector<cv::Vec3d> & t, std::vector<cv::Matx34d> & P, cv::Mat_<double> & points3d,
|
||||
std::vector<cv::Mat_<double> > & points2d);
|
||||
@@ -0,0 +1,124 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
|
||||
void generateTwoViewRandomScene( TwoViewDataSet &data )
|
||||
{
|
||||
vector<Mat_<double> > points2d;
|
||||
vector<cv::Matx33d> Rs;
|
||||
vector<cv::Vec3d> ts;
|
||||
vector<cv::Matx34d> Ps;
|
||||
Matx33d K;
|
||||
Mat_<double> points3d;
|
||||
|
||||
int nviews = 2;
|
||||
int npoints = 30;
|
||||
bool is_projective = true;
|
||||
|
||||
generateScene(nviews, npoints, is_projective, K, Rs, ts, Ps, points3d, points2d);
|
||||
|
||||
// Internal parameters (same K)
|
||||
data.K1 = K;
|
||||
data.K2 = K;
|
||||
|
||||
// Rotation
|
||||
data.R1 = Rs[0];
|
||||
data.R2 = Rs[1];
|
||||
|
||||
// Translation
|
||||
data.t1 = ts[0];
|
||||
data.t2 = ts[1];
|
||||
|
||||
// Projection matrix, P = K(R|t)
|
||||
data.P1 = Ps[0];
|
||||
data.P2 = Ps[1];
|
||||
|
||||
// Fundamental matrix
|
||||
fundamentalFromProjections( data.P1, data.P2, data.F );
|
||||
|
||||
// 3D points
|
||||
data.X = points3d;
|
||||
|
||||
// Projected points
|
||||
data.x1 = points2d[0];
|
||||
data.x2 = points2d[1];
|
||||
}
|
||||
|
||||
/** Check the properties of a fundamental matrix:
|
||||
*
|
||||
* 1. The determinant is 0 (rank deficient)
|
||||
* 2. The condition x'T*F*x = 0 is satisfied to precision.
|
||||
*/
|
||||
void
|
||||
expectFundamentalProperties( const cv::Matx33d &F,
|
||||
const cv::Mat_<double> &ptsA,
|
||||
const cv::Mat_<double> &ptsB,
|
||||
double precision )
|
||||
{
|
||||
EXPECT_NEAR( 0, determinant(F), precision );
|
||||
|
||||
int n = ptsA.cols;
|
||||
EXPECT_EQ( n, ptsB.cols );
|
||||
|
||||
cv::Mat_<double> x1, x2;
|
||||
euclideanToHomogeneous( ptsA, x1 );
|
||||
euclideanToHomogeneous( ptsB, x2 );
|
||||
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
double residual = Vec3d(x2(0,i),x2(1,i),x2(2,i)).ddot( F * Vec3d(x1(0,i),x1(1,i),x1(2,i)) );
|
||||
EXPECT_NEAR( 0.0, residual, precision );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
parser_2D_tracks(const string &_filename, std::vector<Mat> &points2d )
|
||||
{
|
||||
std::ifstream myfile(_filename.c_str());
|
||||
|
||||
if (!myfile.is_open())
|
||||
CV_Error(cv::Error::StsError, string("Unable to read file: ") + _filename + "\n");
|
||||
else {
|
||||
|
||||
double x, y;
|
||||
string line_str;
|
||||
Mat nan_mat = Mat(2, 1 , CV_64F, -1);
|
||||
int n_frames = 0, n_tracks = 0, track = 0;
|
||||
|
||||
while ( getline(myfile, line_str) )
|
||||
{
|
||||
std::istringstream line(line_str);
|
||||
|
||||
if ( track > n_tracks )
|
||||
{
|
||||
n_tracks = track;
|
||||
|
||||
for (int i = 0; i < n_frames; ++i)
|
||||
cv::hconcat(points2d[i], nan_mat, points2d[i]);
|
||||
}
|
||||
|
||||
for (int frame = 1; line >> x >> y; ++frame)
|
||||
{
|
||||
if ( frame > n_frames )
|
||||
{
|
||||
n_frames = frame;
|
||||
points2d.push_back(nan_mat);
|
||||
}
|
||||
|
||||
points2d[frame-1].at<double>(0,track) = x;
|
||||
points2d[frame-1].at<double>(1,track) = y;
|
||||
}
|
||||
|
||||
++track;
|
||||
}
|
||||
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Sfm_conditioning, normalizePoints)
|
||||
{
|
||||
int n = 4;
|
||||
Mat_<double> points(2, n);
|
||||
points << 0, 0, 1, 1,
|
||||
0, 2, 1, 3;
|
||||
|
||||
Mat_<double> T, normalized_points;
|
||||
normalizePoints( points, normalized_points, T );
|
||||
|
||||
Mat_<double> mean, variance;
|
||||
meanAndVarianceAlongRows(normalized_points, mean, variance);
|
||||
|
||||
EXPECT_NEAR(0, mean(0), 1e-8);
|
||||
EXPECT_NEAR(0, mean(1), 1e-8);
|
||||
EXPECT_NEAR(2, variance(0), 1e-8);
|
||||
EXPECT_NEAR(2, variance(1), 1e-8);
|
||||
}
|
||||
|
||||
TEST(Sfm_conditioning, normalizeIsotropicPoints)
|
||||
{
|
||||
//TODO: implement me
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Sfm_fundamental, fundamentalFromProjections)
|
||||
{
|
||||
double tolerance_prop = 1e-7;
|
||||
double tolerance_near = 1e-15;
|
||||
|
||||
Matx34d P1_gt, P2_gt;
|
||||
P1_gt << 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0;
|
||||
P2_gt << 1, 1, 1, 3,
|
||||
0, 2, 0, 3,
|
||||
0, 1, 1, 0;
|
||||
|
||||
Matx33d F_gt;
|
||||
fundamentalFromProjections(P1_gt, P2_gt, F_gt);
|
||||
|
||||
Matx34d P1, P2;
|
||||
projectionsFromFundamental(F_gt, P1, P2);
|
||||
|
||||
Matx33d F;
|
||||
fundamentalFromProjections(P1, P2, F);
|
||||
|
||||
Matx33d F_gt_norm, F_norm;
|
||||
normalizeFundamental(F_gt, F_gt_norm);
|
||||
normalizeFundamental(F, F_norm);
|
||||
|
||||
EXPECT_MATRIX_PROP(F_gt, F, tolerance_prop);
|
||||
EXPECT_MATRIX_NEAR(F_gt_norm, F_norm, tolerance_near);
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_fundamental, normalizedEightPointSolver)
|
||||
{
|
||||
double tolerance = 1e-14;
|
||||
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene( d );
|
||||
|
||||
Matx33d F;
|
||||
normalizedEightPointSolver( d.x1, d.x2, F );
|
||||
expectFundamentalProperties( F, d.x1, d.x2, tolerance );
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_fundamental, motionFromEssential)
|
||||
{
|
||||
double tolerance = 1e-8;
|
||||
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene(d);
|
||||
|
||||
Matx33d E;
|
||||
essentialFromRt(d.R1, d.t1, d.R2, d.t2, E);
|
||||
|
||||
Matx33d R;
|
||||
cv::Vec3d t;
|
||||
relativeCameraMotion(d.R1, d.t1, d.R2, d.t2, R, t);
|
||||
cv::normalize(t, t);
|
||||
|
||||
std::vector<Mat> Rs;
|
||||
std::vector<cv::Mat> ts;
|
||||
motionFromEssential(E, Rs, ts);
|
||||
bool one_solution_is_correct = false;
|
||||
for ( int i = 0; i < Rs.size(); ++i )
|
||||
{
|
||||
if ( (cvtest::norm(Rs[i], R, NORM_L2) < tolerance) && (cvtest::norm(ts[i], t, NORM_L2) < tolerance) )
|
||||
{
|
||||
one_solution_is_correct = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(one_solution_is_correct);
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_fundamental, fundamentalToAndFromEssential)
|
||||
{
|
||||
double tolerance = 1e-15;
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene(d);
|
||||
|
||||
Matx33d F, E;
|
||||
essentialFromFundamental(d.F, d.K1, d.K2, E);
|
||||
fundamentalFromEssential(E, d.K1, d.K2, F);
|
||||
|
||||
Matx33d F_gt_norm, F_norm;
|
||||
normalizeFundamental(d.F, F_gt_norm);
|
||||
normalizeFundamental(F, F_norm);
|
||||
|
||||
EXPECT_MATRIX_NEAR(F_gt_norm, F_norm, tolerance);
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_fundamental, essentialFromFundamental)
|
||||
{
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene(d);
|
||||
|
||||
Matx33d E_from_Rt;
|
||||
essentialFromRt(d.R1, d.t1, d.R2, d.t2, E_from_Rt);
|
||||
|
||||
Matx33d E_from_F;
|
||||
essentialFromFundamental(d.F, d.K1, d.K2, E_from_F);
|
||||
|
||||
EXPECT_MATRIX_PROP(E_from_Rt, E_from_F, 1e-6);
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_fundamental, motionFromEssentialChooseSolution)
|
||||
{
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene(d);
|
||||
|
||||
Matx33d E;
|
||||
essentialFromRt(d.R1, d.t1, d.R2, d.t2, E);
|
||||
|
||||
Matx33d R;
|
||||
cv::Vec3d t;
|
||||
relativeCameraMotion(d.R1, d.t1, d.R2, d.t2, R, t);
|
||||
normalize(t, t);
|
||||
|
||||
std::vector < Mat > Rs;
|
||||
std::vector < cv::Mat > ts;
|
||||
motionFromEssential(E, Rs, ts);
|
||||
|
||||
cv::Vec2d x1(d.x1(0, 0), d.x1(1, 0));
|
||||
cv::Vec2d x2(d.x2(0, 0), d.x2(1, 0));
|
||||
int solution = motionFromEssentialChooseSolution(Rs, ts, d.K1, x1, d.K2, x2);
|
||||
|
||||
EXPECT_LE(0, solution);
|
||||
EXPECT_LE(solution, 3);
|
||||
EXPECT_LE(cvtest::norm(Rs[solution], Mat(R), NORM_L2), 1e-8);
|
||||
EXPECT_LE(cvtest::norm(ts[solution], Mat(t), NORM_L2), 1e-8);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,6 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
test_meanAndVarianceAlongRows( void )
|
||||
{
|
||||
int n = 4;
|
||||
Mat_<T> points(2,n);
|
||||
points << 0, 0, 1, 1,
|
||||
0, 2, 1, 3;
|
||||
|
||||
Mat_<T> mean, variance;
|
||||
meanAndVarianceAlongRows(points, mean, variance);
|
||||
|
||||
EXPECT_NEAR(0.5, mean(0), 1e-8);
|
||||
EXPECT_NEAR(1.5, mean(1), 1e-8);
|
||||
EXPECT_NEAR(0.25, variance(0), 1e-8);
|
||||
EXPECT_NEAR(1.25, variance(1), 1e-8);
|
||||
}
|
||||
|
||||
TEST(Sfm_numeric, meanAndVarianceAlongRows)
|
||||
{
|
||||
test_meanAndVarianceAlongRows<float>();
|
||||
test_meanAndVarianceAlongRows<double>();
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_numeric, skewMat)
|
||||
{
|
||||
// Testing with floats
|
||||
Vec3f a;
|
||||
a << 1,2,3;
|
||||
|
||||
Matx33f ax = skew(a);
|
||||
|
||||
EXPECT_FLOAT_EQ( 0, trace(ax) );
|
||||
EXPECT_FLOAT_EQ( ax(0,1), -ax(1,0) );
|
||||
EXPECT_FLOAT_EQ( ax(0,2), -ax(2,0) );
|
||||
EXPECT_FLOAT_EQ( ax(1,2), -ax(2,1) );
|
||||
|
||||
// Testing with doubles
|
||||
Vec3d b;
|
||||
b << 1,2,3;
|
||||
|
||||
Matx33d bx = skew(b);
|
||||
|
||||
EXPECT_DOUBLE_EQ( 0, trace(bx) );
|
||||
EXPECT_DOUBLE_EQ( bx(0,1), -bx(1,0) );
|
||||
EXPECT_DOUBLE_EQ( bx(0,2), -bx(2,0) );
|
||||
EXPECT_DOUBLE_EQ( bx(1,2), -bx(2,1) );
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,139 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include <opencv2/sfm.hpp>
|
||||
#include <opencv2/ts.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "scene.h"
|
||||
|
||||
#define OPEN_TESTFILE(FNAME,FS) \
|
||||
FS.open(FNAME, FileStorage::READ); \
|
||||
if (!FS.isOpened())\
|
||||
{\
|
||||
std::cerr << "Cannot find file: " << FNAME << std::endl;\
|
||||
return;\
|
||||
}
|
||||
|
||||
namespace opencv_test
|
||||
{
|
||||
using namespace cv::sfm;
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
EXPECT_MATRIX_NEAR(const T a, const T b, double tolerance)
|
||||
{
|
||||
bool dims_match = (a.rows == b.rows) && (a.cols == b.cols);
|
||||
EXPECT_EQ((int)a.rows, (int)b.rows);
|
||||
EXPECT_EQ((int)a.cols, (int)b.cols);
|
||||
|
||||
if (dims_match)
|
||||
{
|
||||
for (int r = 0; r < a.rows; ++r)
|
||||
{
|
||||
for (int c = 0; c < a.cols; ++c)
|
||||
{
|
||||
EXPECT_NEAR(a(r, c), b(r, c), tolerance) << "r=" << r << ", c=" << c << ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void
|
||||
EXPECT_VECTOR_NEAR(const T a, const T b, double tolerance)
|
||||
{
|
||||
bool dims_match = (a.rows == b.rows);
|
||||
EXPECT_EQ((int)a.rows,(int)b.rows) << "Matrix rows don't match.";
|
||||
|
||||
if (dims_match)
|
||||
{
|
||||
for (int r = 0; r < a.rows; ++r)
|
||||
{
|
||||
EXPECT_NEAR(a(r), b(r), tolerance) << "r=" << r << ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline double
|
||||
cosinusBetweenMatrices(const T &a, const T &b)
|
||||
{
|
||||
double s = cv::sum( a.mul(b) )[0];
|
||||
return ( s / cv::norm(a) / cv::norm(b) );
|
||||
}
|
||||
|
||||
// Check that sin(angle(a, b)) < tolerance
|
||||
template<typename T>
|
||||
inline void
|
||||
EXPECT_MATRIX_PROP(const T a, const T b, double tolerance)
|
||||
{
|
||||
bool dims_match = (a.rows == b.rows) && (a.cols == b.cols);
|
||||
EXPECT_EQ((int)a.rows, (int)b.rows);
|
||||
EXPECT_EQ((int)a.cols, (int)b.cols);
|
||||
|
||||
if (dims_match)
|
||||
{
|
||||
double c = cosinusBetweenMatrices(a, b);
|
||||
if (c * c < 1)
|
||||
{
|
||||
double s = sqrt(1 - c * c);
|
||||
EXPECT_NEAR(0, s, tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct TwoViewDataSet
|
||||
{
|
||||
cv::Matx33d K1, K2; // Internal parameters
|
||||
cv::Matx33d R1, R2; // Rotation
|
||||
cv::Vec3d t1, t2; // Translation
|
||||
cv::Matx34d P1, P2; // Projection matrix, P = K(R|t)
|
||||
cv::Matx33d F; // Fundamental matrix
|
||||
cv::Mat_<double> X; // 3D points
|
||||
cv::Mat_<double> x1, x2; // Projected points
|
||||
};
|
||||
|
||||
void
|
||||
generateTwoViewRandomScene(TwoViewDataSet &data);
|
||||
|
||||
/** Check the properties of a fundamental matrix:
|
||||
*
|
||||
* 1. The determinant is 0 (rank deficient)
|
||||
* 2. The condition x'T*F*x = 0 is satisfied to precision.
|
||||
*/
|
||||
void
|
||||
expectFundamentalProperties( const cv::Matx33d &F,
|
||||
const cv::Mat_<double> &ptsA,
|
||||
const cv::Mat_<double> &ptsB,
|
||||
double precision = 1e-9 );
|
||||
|
||||
/**
|
||||
* 2D tracked points
|
||||
* -----------------
|
||||
*
|
||||
* The format is:
|
||||
*
|
||||
* row1 : x1 y1 x2 y2 ... x36 y36 for track 1
|
||||
* row2 : x1 y1 x2 y2 ... x36 y36 for track 2
|
||||
* etc
|
||||
*
|
||||
* i.e. a row gives the 2D measured position of a point as it is tracked
|
||||
* through frames 1 to 36. If there is no match found in a view then x
|
||||
* and y are -1.
|
||||
*
|
||||
* Each row corresponds to a different point.
|
||||
*
|
||||
*/
|
||||
void
|
||||
parser_2D_tracks(const std::string &_filename, std::vector<cv::Mat> &points2d );
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include <opencv2/sfm/projection.hpp>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Sfm_projection, homogeneousToEuclidean)
|
||||
{
|
||||
Matx33f X(1, 2, 3,
|
||||
4, 5, 6,
|
||||
2, 1, 0);
|
||||
|
||||
Matx23f XEuclidean;
|
||||
homogeneousToEuclidean(X,XEuclidean);
|
||||
|
||||
EXPECT_EQ((int) X.rows-1,(int) XEuclidean.rows );
|
||||
|
||||
for(int y=0;y<X.rows-1;++y)
|
||||
{
|
||||
for(int x=0;x<X.cols;++x)
|
||||
{
|
||||
if (X(X.rows-1,x)!=0)
|
||||
{
|
||||
EXPECT_LE( std::abs(X(y,x)/X(X.rows-1, x) - XEuclidean(y,x)), 1e-4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Sfm_projection, euclideanToHomogeneous)
|
||||
{
|
||||
// Testing with floats
|
||||
Matx33f x(1, 2, 3,
|
||||
4, 5, 6,
|
||||
2, 1, 0);
|
||||
|
||||
Matx43f XHomogeneous;
|
||||
euclideanToHomogeneous(x,XHomogeneous);
|
||||
|
||||
EXPECT_EQ((int) x.rows+1,(int)XHomogeneous.rows );
|
||||
for(int i=0;i<x.cols;++i)
|
||||
EXPECT_EQ( 1,(int) XHomogeneous(x.rows,i) );
|
||||
|
||||
|
||||
// Testing with doubles
|
||||
Vec2d x2(4,3);
|
||||
Vec3d X2;
|
||||
|
||||
euclideanToHomogeneous(x2,X2);
|
||||
|
||||
EXPECT_EQ((int) x2.rows+1,(int)X2.rows );
|
||||
EXPECT_EQ( 4, X2(0) );
|
||||
EXPECT_EQ( 3, X2(1) );
|
||||
EXPECT_EQ( 1, X2(2) );
|
||||
}
|
||||
|
||||
TEST(Sfm_projection, P_From_KRt)
|
||||
{
|
||||
Matx33d K, Kp;
|
||||
K << 10, 1, 30,
|
||||
0, 20, 40,
|
||||
0, 0, 1;
|
||||
|
||||
Matx33d R, Rp;
|
||||
R << 1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1;
|
||||
|
||||
Vec3d t, tp;
|
||||
t << 1, 2, 3;
|
||||
|
||||
Matx34d P(3,4);
|
||||
projectionFromKRt(K, R, t, P);
|
||||
KRtFromProjection(P, Kp, Rp, tp);
|
||||
|
||||
EXPECT_MATRIX_NEAR(K, Kp, 1e-8);
|
||||
EXPECT_MATRIX_NEAR(R, Rp, 1e-8);
|
||||
EXPECT_VECTOR_NEAR(t, tp, 1e-8);
|
||||
|
||||
// TODO: Change the code to ensure det(R) == 1, which is not currently
|
||||
// the case. Also add a test for that here.
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
/* Check projection errors */
|
||||
static void
|
||||
check_projection_errors(const cv::Mat& X_estimated, const std::vector<Matx34d>& Ps,
|
||||
const std::vector<Mat_<double> >& xs, float err_max2d)
|
||||
{
|
||||
cv::Mat X;
|
||||
euclideanToHomogeneous(X_estimated, X); // 3D point
|
||||
|
||||
for (int m = 0; m < xs.size(); ++m)
|
||||
{
|
||||
cv::Mat x;
|
||||
homogeneousToEuclidean(cv::Mat(Ps[m]) * X, x); // 2d projection
|
||||
cv::Mat projerr = xs[m] - x;
|
||||
|
||||
for (int n = 0; n < projerr.cols; ++n)
|
||||
{
|
||||
double d = cv::norm(projerr.col(n));
|
||||
EXPECT_NEAR(0, d, err_max2d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CERES_FOUND
|
||||
|
||||
TEST(Sfm_reconstruct, twoViewProjectiveOutliers)
|
||||
{
|
||||
float err_max2d = 1e-7;
|
||||
int nviews = 2;
|
||||
int npoints = 50;
|
||||
bool is_projective = true;
|
||||
|
||||
std::vector<Mat_<double> > points2d;
|
||||
std::vector<cv::Matx33d> Rs;
|
||||
std::vector<cv::Vec3d> ts;
|
||||
std::vector<cv::Matx34d> Ps;
|
||||
Matx33d K;
|
||||
Mat_<double> points3d;
|
||||
generateScene(nviews, npoints, is_projective, K, Rs, ts, Ps, points3d, points2d);
|
||||
|
||||
Mat_<double> points3d_estimated;
|
||||
std::vector<cv::Mat> Ps_estimated;
|
||||
reconstruct(points2d, Ps_estimated, points3d_estimated, K, is_projective);
|
||||
|
||||
/* Check projection errors on GT */
|
||||
check_projection_errors(points3d, Ps, points2d, err_max2d);
|
||||
|
||||
/* Check projection errors on estimates */
|
||||
std::vector<cv::Matx34d> Ps_estimated_d;
|
||||
Ps_estimated_d.resize(Ps_estimated.size());
|
||||
for(size_t i=0; i<Ps_estimated.size(); ++i)
|
||||
Ps_estimated_d[i] = Ps_estimated[i];
|
||||
check_projection_errors(points3d_estimated, Ps_estimated_d, points2d, err_max2d);
|
||||
}
|
||||
|
||||
#endif /* CERES_FOUND */
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/sfm/robust.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
TEST(Sfm_robust, fundamentalFromCorrespondences8PointRobust)
|
||||
{
|
||||
double tolerance = 1e-8;
|
||||
const int n = 16;
|
||||
Mat_<double> x1(2,n);
|
||||
x1 << 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
|
||||
0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 5;
|
||||
|
||||
Mat_<double> x2 = x1.clone();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
x2(0,i) += i % 2; // Multiple horizontal disparities.
|
||||
}
|
||||
x2(0,n - 1) = 10;
|
||||
x2(1,n - 1) = 10; // The outlier has vertical disparity.
|
||||
|
||||
Matx33d F;
|
||||
vector<int> inliers;
|
||||
fundamentalFromCorrespondences8PointRobust(x1, x2, 0.1, F, inliers);
|
||||
|
||||
// F should be 0, 0, 0,
|
||||
// 0, 0, -1,
|
||||
// 0, 1, 0
|
||||
EXPECT_NEAR(0.0, F(0,0), tolerance);
|
||||
EXPECT_NEAR(0.0, F(0,1), tolerance);
|
||||
EXPECT_NEAR(0.0, F(0,2), tolerance);
|
||||
EXPECT_NEAR(0.0, F(1,0), tolerance);
|
||||
EXPECT_NEAR(0.0, F(1,1), tolerance);
|
||||
EXPECT_NEAR(0.0, F(2,0), tolerance);
|
||||
EXPECT_NEAR(0.0, F(2,2), tolerance);
|
||||
EXPECT_NEAR(F(1,2), -F(2,1), tolerance);
|
||||
|
||||
EXPECT_EQ(n - 1, inliers.size());
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_robust, fundamentalFromCorrespondences8PointRealisticNoOutliers)
|
||||
{
|
||||
double tolerance = 1e-8;
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene(d);
|
||||
|
||||
Matx33d F_estimated;
|
||||
|
||||
vector<int> inliers;
|
||||
fundamentalFromCorrespondences8PointRobust(d.x1, d.x2, 3.0, F_estimated, inliers);
|
||||
EXPECT_EQ(d.x1.cols, inliers.size());
|
||||
|
||||
// Normalize.
|
||||
Matx33d F_gt_norm, F_estimated_norm;
|
||||
normalizeFundamental(d.F, F_gt_norm);
|
||||
normalizeFundamental(F_estimated, F_estimated_norm);
|
||||
EXPECT_MATRIX_NEAR(F_gt_norm, F_estimated_norm, tolerance);
|
||||
|
||||
// Check fundamental properties.
|
||||
expectFundamentalProperties( F_estimated, d.x1, d.x2, tolerance);
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_robust, fundamentalFromCorrespondences7PointRobust)
|
||||
{
|
||||
double tolerance = 1e-8;
|
||||
const int n = 16;
|
||||
Mat_<double> x1(2,n);
|
||||
x1 << 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5,
|
||||
0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 5;
|
||||
|
||||
Mat_<double> x2 = x1.clone();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
x2(0,i) += i % 2; // Multiple horizontal disparities.
|
||||
}
|
||||
x2(0,n - 1) = 10;
|
||||
x2(1,n - 1) = 10; // The outlier has vertical disparity.
|
||||
|
||||
Matx33d F;
|
||||
vector<int> inliers;
|
||||
fundamentalFromCorrespondences7PointRobust(x1, x2, 0.1, F, inliers);
|
||||
|
||||
// F should be 0, 0, 0,
|
||||
// 0, 0, -1,
|
||||
// 0, 1, 0
|
||||
EXPECT_NEAR(0.0, F(0,0), tolerance);
|
||||
EXPECT_NEAR(0.0, F(0,1), tolerance);
|
||||
EXPECT_NEAR(0.0, F(0,2), tolerance);
|
||||
EXPECT_NEAR(0.0, F(1,0), tolerance);
|
||||
EXPECT_NEAR(0.0, F(1,1), tolerance);
|
||||
EXPECT_NEAR(0.0, F(2,0), tolerance);
|
||||
EXPECT_NEAR(0.0, F(2,2), tolerance);
|
||||
EXPECT_NEAR(F(1,2), -F(2,1), tolerance);
|
||||
|
||||
EXPECT_EQ(n - 1, inliers.size());
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_robust, fundamentalFromCorrespondences7PointRealisticNoOutliers)
|
||||
{
|
||||
double tolerance = 1e-8;
|
||||
TwoViewDataSet d;
|
||||
generateTwoViewRandomScene(d);
|
||||
|
||||
Matx33d F_estimated;
|
||||
|
||||
vector<int> inliers;
|
||||
fundamentalFromCorrespondences7PointRobust(d.x1, d.x2, 3.0, F_estimated, inliers);
|
||||
EXPECT_EQ(d.x1.cols, inliers.size());
|
||||
|
||||
// Normalize.
|
||||
Matx33d F_gt_norm, F_estimated_norm;
|
||||
normalizeFundamental(d.F, F_gt_norm);
|
||||
normalizeFundamental(F_estimated, F_estimated_norm);
|
||||
EXPECT_MATRIX_NEAR(F_gt_norm, F_estimated_norm, tolerance);
|
||||
|
||||
// Check fundamental properties.
|
||||
expectFundamentalProperties( F_estimated, d.x1, d.x2, tolerance);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#if CERES_FOUND
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#include <opencv2/sfm/simple_pipeline.hpp>
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
const string SFM_DIR = "sfm";
|
||||
const string TRACK_FILENAME = "backyard_tracks.txt";
|
||||
|
||||
TEST(Sfm_simple_pipeline, backyard)
|
||||
{
|
||||
string trackFilename =
|
||||
string(TS::ptr()->get_data_path()) + SFM_DIR + "/" + TRACK_FILENAME;
|
||||
|
||||
// Get tracks from file: check backyard.blend file
|
||||
std::vector<Mat> points2d;
|
||||
parser_2D_tracks( trackFilename, points2d );
|
||||
|
||||
// Initial reconstruction
|
||||
int keyframe1 = 1, keyframe2 = 30;
|
||||
|
||||
// Camera data
|
||||
double focal_length = 860.986572265625; // f = 24mm (checked debugging blender)
|
||||
double principal_x = 400, principal_y = 225, k1 = -0.158, k2 = 0.131, k3 = 0;
|
||||
|
||||
int refine_intrinsics = SFM_REFINE_FOCAL_LENGTH | SFM_REFINE_PRINCIPAL_POINT | SFM_REFINE_RADIAL_DISTORTION_K1 | SFM_REFINE_RADIAL_DISTORTION_K2;
|
||||
int select_keyframes = 0; // disable automatic keyframes selection
|
||||
int verbosity_level = -1; // mute logs
|
||||
|
||||
libmv_CameraIntrinsicsOptions camera_instrinsic_options =
|
||||
libmv_CameraIntrinsicsOptions(SFM_DISTORTION_MODEL_POLYNOMIAL,
|
||||
focal_length, principal_x, principal_y,
|
||||
k1, k2, k3);
|
||||
libmv_ReconstructionOptions reconstruction_options(keyframe1, keyframe2, refine_intrinsics, select_keyframes, verbosity_level);
|
||||
|
||||
Ptr<SFMLibmvEuclideanReconstruction> euclidean_reconstruction =
|
||||
SFMLibmvEuclideanReconstruction::create(camera_instrinsic_options, reconstruction_options);
|
||||
|
||||
// Run reconstruction pipeline
|
||||
euclidean_reconstruction->run(points2d);
|
||||
|
||||
double error = euclidean_reconstruction->getError();
|
||||
//cout << "euclidean_reconstruction error = " << error << endl;
|
||||
|
||||
EXPECT_LE( error, 1.4 ); // actually 1.38671
|
||||
// UPDATE: 1.38894
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
#endif /* CERES_FOUND */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2009, Willow Garage, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 name of Willow Garage, Inc. nor the names of its
|
||||
* 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 THE
|
||||
* COPYRIGHT OWNER 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
static void
|
||||
checkTriangulation(int nviews, int npoints, bool is_projective, float err_max2d, float err_max3d)
|
||||
{
|
||||
std::vector<Mat_<double> > points2d;
|
||||
std::vector<cv::Matx33d> Rs;
|
||||
std::vector<cv::Vec3d> ts;
|
||||
std::vector<cv::Matx34d> Ps;
|
||||
Matx33d K;
|
||||
Mat_<double> points3d;
|
||||
generateScene(nviews, npoints, is_projective, K, Rs, ts, Ps, points3d, points2d);
|
||||
|
||||
// get 3d points
|
||||
cv::Mat X, X_homogeneous;
|
||||
std::vector<Mat_<double> > Ps_d(Ps.size());
|
||||
for(size_t i=0; i<Ps.size(); ++i)
|
||||
Ps_d[i] = cv::Mat_<double>(Ps[i]);
|
||||
triangulatePoints(points2d, Ps_d, X);
|
||||
euclideanToHomogeneous(X, X_homogeneous);
|
||||
|
||||
for (int i = 0; i < npoints; ++i)
|
||||
{
|
||||
for (int k = 0; k < nviews; ++k)
|
||||
{
|
||||
cv::Mat x_reprojected;
|
||||
homogeneousToEuclidean( cv::Mat(Ps[k])*X_homogeneous.col(i), x_reprojected );
|
||||
|
||||
// Check reprojection error. Should be nearly zero.
|
||||
double error = cvtest::norm(x_reprojected, points2d[k].col(i), NORM_L2);
|
||||
EXPECT_LE(error*error, err_max2d);
|
||||
}
|
||||
|
||||
// Check 3d error. Should be nearly zero.
|
||||
double error = cvtest::norm(X.col(i), points3d.col(i), NORM_L2);
|
||||
EXPECT_LE(error*error, err_max3d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Sfm_triangulate, TriangulateDLT)
|
||||
{
|
||||
int nviews = 2;
|
||||
int npoints = 30;
|
||||
bool is_projective = true;
|
||||
|
||||
checkTriangulation(nviews, npoints, is_projective, 1e-7, 1e-9);
|
||||
}
|
||||
|
||||
TEST(Sfm_triangulate, NViewTriangulate_FiveViews)
|
||||
{
|
||||
int nviews = 5;
|
||||
int npoints = 6;
|
||||
bool is_projective = true;
|
||||
|
||||
checkTriangulation(nviews, npoints, is_projective, 1e-7, 1e-9);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
Reference in New Issue
Block a user