reworked nearly all of the OpenCV tests (except for opencv_gpu tests) - they now use the Google Test engine.
This commit is contained in:
parent
63806c9ab9
commit
061b49e0b2
@ -1275,10 +1275,10 @@ if(BUILD_EXAMPLES OR INSTALL_PYTHON_EXAMPLES)
|
||||
add_subdirectory(samples)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
#if(BUILD_TESTS)
|
||||
# enable_testing()
|
||||
# add_subdirectory(tests)
|
||||
#endif()
|
||||
|
||||
add_subdirectory(3rdparty)
|
||||
|
||||
|
@ -82,13 +82,13 @@ macro(define_opencv_module name)
|
||||
DESTINATION include/opencv2/${name}
|
||||
COMPONENT main)
|
||||
|
||||
if(BUILD_TESTS AND NOT ANDROID AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test)
|
||||
if(BUILD_TESTS AND NOT ANDROID AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test)
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${CMAKE_SOURCE_DIR}/modules/gtest/include")
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
foreach(d ${ARGN})
|
||||
set(test_deps opencv_${name} ${ARGN} opencv_ts opencv_highgui ${EXTRA_${the_target}_DEPS})
|
||||
foreach(d ${test_deps})
|
||||
if(${d} MATCHES "opencv_")
|
||||
if(${d} MATCHES "opencv_lapack")
|
||||
else()
|
||||
@ -101,7 +101,7 @@ macro(define_opencv_module name)
|
||||
file(GLOB test_srcs "test/*.cpp")
|
||||
file(GLOB test_hdrs "test/*.h*")
|
||||
|
||||
set(the_target "opencv_gtest_${name}")
|
||||
set(the_target "opencv_test_${name}")
|
||||
|
||||
add_executable(${the_target} ${test_srcs} ${test_hdrs})
|
||||
|
||||
@ -123,10 +123,10 @@ macro(define_opencv_module name)
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/"
|
||||
)
|
||||
|
||||
add_dependencies(${the_target} ${ARGN} opencv_gtest)
|
||||
add_dependencies(${the_target} ${test_deps})
|
||||
|
||||
# Add the required libraries for linking:
|
||||
target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${ARGN} opencv_gtest)
|
||||
target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${test_deps})
|
||||
|
||||
enable_testing()
|
||||
get_target_property(LOC ${the_target} LOCATION)
|
||||
@ -138,66 +138,3 @@ macro(define_opencv_module name)
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
|
||||
if(0)
|
||||
macro(define_opencv_test name)
|
||||
|
||||
if(BUILD_TESTS AND NOT ANDROID AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test)
|
||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/test"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||
"${CMAKE_SOURCE_DIR}/modules/gtest/include")
|
||||
|
||||
foreach(d ${ARGN})
|
||||
if(${d} MATCHES "opencv_")
|
||||
if(${d} MATCHES "opencv_lapack")
|
||||
else()
|
||||
string(REPLACE "opencv_" "${CMAKE_CURRENT_SOURCE_DIR}/../" d_dir ${d})
|
||||
include_directories("${d_dir}/include")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(GLOB test_srcs "test/*.cpp")
|
||||
file(GLOB test_hdrs "test/*.h*")
|
||||
|
||||
set(the_target "opencv_gtest_${name}")
|
||||
|
||||
add_executable(${the_target} ${test_srcs} ${test_hdrs})
|
||||
|
||||
if(PCHSupport_FOUND)
|
||||
set(pch_header ${CMAKE_CURRENT_SOURCE_DIR}/test/precomp.hpp)
|
||||
if(${CMAKE_GENERATOR} MATCHES "Visual*" OR ${CMAKE_GENERATOR} MATCHES "Xcode*")
|
||||
if(${CMAKE_GENERATOR} MATCHES "Visual*")
|
||||
set(${the_target}_pch "test/precomp.cpp")
|
||||
endif()
|
||||
add_native_precompiled_header(${the_target} ${pch_header})
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX AND ${CMAKE_GENERATOR} MATCHES ".*Makefiles")
|
||||
add_precompiled_header(${the_target} ${pch_header})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Additional target properties
|
||||
set_target_properties(${the_target} PROPERTIES
|
||||
DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/"
|
||||
)
|
||||
|
||||
add_dependencies(${the_target} ${ARGN} opencv_gtest)
|
||||
|
||||
# Add the required libraries for linking:
|
||||
target_link_libraries(${the_target} ${OPENCV_LINKER_LIBS} ${ARGN} opencv_gtest)
|
||||
|
||||
enable_testing()
|
||||
get_target_property(LOC ${the_target} LOCATION)
|
||||
add_test(${the_target} "${LOC}")
|
||||
|
||||
if(WIN32)
|
||||
install(TARGETS ${the_target} RUNTIME DESTINATION bin COMPONENT main)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -13,7 +13,7 @@ if(MSVC OR MINGW)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(gtest)
|
||||
add_subdirectory(ts)
|
||||
add_subdirectory(highgui)
|
||||
add_subdirectory(imgproc)
|
||||
add_subdirectory(legacy)
|
||||
|
@ -534,6 +534,10 @@ CV_EXPORTS_W bool findChessboardCorners( const Mat& image, Size patternSize,
|
||||
int flags=CALIB_CB_ADAPTIVE_THRESH+
|
||||
CALIB_CB_NORMALIZE_IMAGE );
|
||||
|
||||
//! finds subpixel-accurate positions of the chessboard corners
|
||||
CV_EXPORTS bool find4QuadCornerSubpix(const Mat& img, std::vector<Point2f>& corners,
|
||||
Size region_size);
|
||||
|
||||
//! draws the checkerboard pattern (found or partly found) in the image
|
||||
CV_EXPORTS_W void drawChessboardCorners( Mat& image, Size patternSize,
|
||||
const Mat& corners,
|
||||
|
195
modules/calib3d/test/test_affine3d_estimator.cpp
Normal file
195
modules/calib3d/test/test_affine3d_estimator.cpp
Normal file
@ -0,0 +1,195 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
class CV_Affine3D_EstTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_Affine3D_EstTest();
|
||||
~CV_Affine3D_EstTest();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool test4Points();
|
||||
bool testNPoints();
|
||||
};
|
||||
|
||||
CV_Affine3D_EstTest::CV_Affine3D_EstTest()
|
||||
{
|
||||
}
|
||||
CV_Affine3D_EstTest::~CV_Affine3D_EstTest() {}
|
||||
|
||||
|
||||
float rngIn(float from, float to) { return from + (to-from) * (float)theRNG(); }
|
||||
|
||||
|
||||
struct WrapAff
|
||||
{
|
||||
const double *F;
|
||||
WrapAff(const Mat& aff) : F(aff.ptr<double>()) {}
|
||||
Point3f operator()(const Point3f& p)
|
||||
{
|
||||
return Point3d( p.x * F[0] + p.y * F[1] + p.z * F[2] + F[3],
|
||||
p.x * F[4] + p.y * F[5] + p.z * F[6] + F[7],
|
||||
p.x * F[8] + p.y * F[9] + p.z * F[10] + F[11] );
|
||||
}
|
||||
};
|
||||
|
||||
bool CV_Affine3D_EstTest::test4Points()
|
||||
{
|
||||
Mat aff(3, 4, CV_64F);
|
||||
cv::randu(aff, Scalar(1), Scalar(3));
|
||||
|
||||
// setting points that are no in the same line
|
||||
|
||||
Mat fpts(1, 4, CV_32FC3);
|
||||
Mat tpts(1, 4, CV_32FC3);
|
||||
|
||||
fpts.ptr<Point3f>()[0] = Point3f( rngIn(1,2), rngIn(1,2), rngIn(5, 6) );
|
||||
fpts.ptr<Point3f>()[1] = Point3f( rngIn(3,4), rngIn(3,4), rngIn(5, 6) );
|
||||
fpts.ptr<Point3f>()[2] = Point3f( rngIn(1,2), rngIn(3,4), rngIn(5, 6) );
|
||||
fpts.ptr<Point3f>()[3] = Point3f( rngIn(3,4), rngIn(1,2), rngIn(5, 6) );
|
||||
|
||||
transform(fpts.ptr<Point3f>(), fpts.ptr<Point3f>() + 4, tpts.ptr<Point3f>(), WrapAff(aff));
|
||||
|
||||
Mat aff_est;
|
||||
vector<uchar> outliers;
|
||||
estimateAffine3D(fpts, tpts, aff_est, outliers);
|
||||
|
||||
const double thres = 1e-3;
|
||||
if (norm(aff_est, aff, NORM_INF) > thres)
|
||||
{
|
||||
//cout << norm(aff_est, aff, NORM_INF) << endl;
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Noise
|
||||
{
|
||||
float l;
|
||||
Noise(float level) : l(level) {}
|
||||
Point3f operator()(const Point3f& p)
|
||||
{
|
||||
RNG& rng = theRNG();
|
||||
return Point3f( p.x + l * (float)rng, p.y + l * (float)rng, p.z + l * (float)rng);
|
||||
}
|
||||
};
|
||||
|
||||
bool CV_Affine3D_EstTest::testNPoints()
|
||||
{
|
||||
Mat aff(3, 4, CV_64F);
|
||||
cv::randu(aff, Scalar(-2), Scalar(2));
|
||||
|
||||
// setting points that are no in the same line
|
||||
|
||||
const int n = 100;
|
||||
const int m = 3*n/5;
|
||||
const Point3f shift_outl = Point3f(15, 15, 15);
|
||||
const float noise_level = 20.f;
|
||||
|
||||
Mat fpts(1, n, CV_32FC3);
|
||||
Mat tpts(1, n, CV_32FC3);
|
||||
|
||||
randu(fpts, Scalar::all(0), Scalar::all(100));
|
||||
transform(fpts.ptr<Point3f>(), fpts.ptr<Point3f>() + n, tpts.ptr<Point3f>(), WrapAff(aff));
|
||||
|
||||
/* adding noise*/
|
||||
transform(tpts.ptr<Point3f>() + m, tpts.ptr<Point3f>() + n, tpts.ptr<Point3f>() + m, bind2nd(plus<Point3f>(), shift_outl));
|
||||
transform(tpts.ptr<Point3f>() + m, tpts.ptr<Point3f>() + n, tpts.ptr<Point3f>() + m, Noise(noise_level));
|
||||
|
||||
Mat aff_est;
|
||||
vector<uchar> outl;
|
||||
int res = estimateAffine3D(fpts, tpts, aff_est, outl);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
|
||||
const double thres = 1e-4;
|
||||
if (norm(aff_est, aff, NORM_INF) > thres)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool outl_good = count(outl.begin(), outl.end(), 1) == m &&
|
||||
m == accumulate(outl.begin(), outl.begin() + m, 0);
|
||||
|
||||
if (!outl_good)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CV_Affine3D_EstTest::run( int /* start_from */)
|
||||
{
|
||||
cvtest::DefaultRngAuto dra;
|
||||
|
||||
if (!test4Points())
|
||||
return;
|
||||
|
||||
if (!testNPoints())
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Calib3d_EstimateAffineTransform, accuracy) { CV_Affine3D_EstTest test; test.safe_run(); }
|
||||
|
1717
modules/calib3d/test/test_cameracalibration.cpp
Normal file
1717
modules/calib3d/test/test_cameracalibration.cpp
Normal file
File diff suppressed because it is too large
Load Diff
428
modules/calib3d/test/test_cameracalibration_artificial.cpp
Normal file
428
modules/calib3d/test/test_cameracalibration_artificial.cpp
Normal file
@ -0,0 +1,428 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
//template<class T> ostream& operator<<(ostream& out, const Mat_<T>& mat)
|
||||
//{
|
||||
// for(Mat_<T>::const_iterator pos = mat.begin(), end = mat.end(); pos != end; ++pos)
|
||||
// out << *pos << " ";
|
||||
// return out;
|
||||
//}
|
||||
//ostream& operator<<(ostream& out, const Mat& mat) { return out << Mat_<double>(mat); }
|
||||
|
||||
Mat calcRvec(const vector<Point3f>& points, const Size& cornerSize)
|
||||
{
|
||||
Point3f p00 = points[0];
|
||||
Point3f p10 = points[1];
|
||||
Point3f p01 = points[cornerSize.width];
|
||||
|
||||
Vec3d ex(p10.x - p00.x, p10.y - p00.y, p10.z - p00.z);
|
||||
Vec3d ey(p01.x - p00.x, p01.y - p00.y, p01.z - p00.z);
|
||||
Vec3d ez = ex.cross(ey);
|
||||
|
||||
Mat rot(3, 3, CV_64F);
|
||||
*rot.ptr<Vec3d>(0) = ex;
|
||||
*rot.ptr<Vec3d>(1) = ey;
|
||||
*rot.ptr<Vec3d>(2) = ez * (1.0/norm(ez));
|
||||
|
||||
Mat res;
|
||||
Rodrigues(rot.t(), res);
|
||||
return res.reshape(1, 1);
|
||||
}
|
||||
|
||||
class CV_CalibrateCameraArtificialTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_CalibrateCameraArtificialTest()
|
||||
{
|
||||
}
|
||||
~CV_CalibrateCameraArtificialTest() {}
|
||||
protected:
|
||||
int r;
|
||||
|
||||
const static int JUST_FIND_CORNERS = 0;
|
||||
const static int USE_CORNERS_SUBPIX = 1;
|
||||
const static int USE_4QUAD_CORNERS = 2;
|
||||
const static int ARTIFICIAL_CORNERS = 4;
|
||||
|
||||
|
||||
bool checkErr(double a, double a0, double eps, double delta)
|
||||
{
|
||||
return fabs(a - a0) > eps * (fabs(a0) + delta);
|
||||
}
|
||||
|
||||
void compareCameraMatrs(const Mat_<double>& camMat, const Mat& camMat_est)
|
||||
{
|
||||
if ( camMat_est.at<double>(0, 1) != 0 || camMat_est.at<double>(1, 0) != 0 ||
|
||||
camMat_est.at<double>(2, 0) != 0 || camMat_est.at<double>(2, 1) != 0 ||
|
||||
camMat_est.at<double>(2, 2) != 1)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Bad shape of camera matrix returned \n");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
}
|
||||
|
||||
double fx_e = camMat_est.at<double>(0, 0), fy_e = camMat_est.at<double>(1, 1);
|
||||
double cx_e = camMat_est.at<double>(0, 2), cy_e = camMat_est.at<double>(1, 2);
|
||||
|
||||
double fx = camMat(0, 0), fy = camMat(1, 1), cx = camMat(0, 2), cy = camMat(1, 2);
|
||||
|
||||
const double eps = 1e-2;
|
||||
const double dlt = 1e-5;
|
||||
|
||||
bool fail = checkErr(fx_e, fx, eps, dlt) || checkErr(fy_e, fy, eps, dlt) ||
|
||||
checkErr(cx_e, cx, eps, dlt) || checkErr(cy_e, cy, eps, dlt);
|
||||
|
||||
if (fail)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
ts->printf( cvtest::TS::LOG, "%d) Expected [Fx Fy Cx Cy] = [%.3f %.3f %.3f %.3f]\n", r, fx, fy, cx, cy);
|
||||
ts->printf( cvtest::TS::LOG, "%d) Estimated [Fx Fy Cx Cy] = [%.3f %.3f %.3f %.3f]\n", r, fx_e, fy_e, cx_e, cy_e);
|
||||
}
|
||||
|
||||
void compareDistCoeffs(const Mat_<double>& distCoeffs, const Mat& distCoeffs_est)
|
||||
{
|
||||
const double *dt_e = distCoeffs_est.ptr<double>();
|
||||
|
||||
double k1_e = dt_e[0], k2_e = dt_e[1], k3_e = dt_e[4];
|
||||
double p1_e = dt_e[2], p2_e = dt_e[3];
|
||||
|
||||
double k1 = distCoeffs(0, 0), k2 = distCoeffs(0, 1), k3 = distCoeffs(0, 4);
|
||||
double p1 = distCoeffs(0, 2), p2 = distCoeffs(0, 3);
|
||||
|
||||
const double eps = 5e-2;
|
||||
const double dlt = 1e-3;
|
||||
|
||||
const double eps_k3 = 5;
|
||||
const double dlt_k3 = 1e-3;
|
||||
|
||||
bool fail = checkErr(k1_e, k1, eps, dlt) || checkErr(k2_e, k2, eps, dlt) || checkErr(k3_e, k3, eps_k3, dlt_k3) ||
|
||||
checkErr(p1_e, p1, eps, dlt) || checkErr(p2_e, p2, eps, dlt);
|
||||
|
||||
if (fail)
|
||||
{
|
||||
// commented according to vp123's recomendation. TODO - improve accuaracy
|
||||
//ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); ss
|
||||
}
|
||||
ts->printf( cvtest::TS::LOG, "%d) DistCoeff exp=(%.2f, %.2f, %.4f, %.4f %.2f)\n", r, k1, k2, p1, p2, k3);
|
||||
ts->printf( cvtest::TS::LOG, "%d) DistCoeff est=(%.2f, %.2f, %.4f, %.4f %.2f)\n", r, k1_e, k2_e, p1_e, p2_e, k3_e);
|
||||
ts->printf( cvtest::TS::LOG, "%d) AbsError = [%.5f %.5f %.5f %.5f %.5f]\n", r, fabs(k1-k1_e), fabs(k2-k2_e), fabs(p1-p1_e), fabs(p2-p2_e), fabs(k3-k3_e));
|
||||
}
|
||||
|
||||
void compareShiftVecs(const vector<Mat>& tvecs, const vector<Mat>& tvecs_est)
|
||||
{
|
||||
const double eps = 1e-2;
|
||||
const double dlt = 1e-4;
|
||||
|
||||
int err_count = 0;
|
||||
const int errMsgNum = 4;
|
||||
for(size_t i = 0; i < tvecs.size(); ++i)
|
||||
{
|
||||
const Point3d& tvec = *tvecs[i].ptr<Point3d>();
|
||||
const Point3d& tvec_est = *tvecs_est[i].ptr<Point3d>();
|
||||
|
||||
if (norm(tvec_est - tvec) > eps* (norm(tvec) + dlt))
|
||||
{
|
||||
if (err_count++ < errMsgNum)
|
||||
{
|
||||
if (err_count == errMsgNum)
|
||||
ts->printf( cvtest::TS::LOG, "%d) ...\n", r);
|
||||
else
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%d) Bad accuracy in returned tvecs. Index = %d\n", r, i);
|
||||
ts->printf( cvtest::TS::LOG, "%d) norm(tvec_est - tvec) = %f, norm(tvec_exp) = %f \n", r, norm(tvec_est - tvec), norm(tvec));
|
||||
}
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void compareRotationVecs(const vector<Mat>& rvecs, const vector<Mat>& rvecs_est)
|
||||
{
|
||||
const double eps = 2e-2;
|
||||
const double dlt = 1e-4;
|
||||
|
||||
Mat rmat, rmat_est;
|
||||
int err_count = 0;
|
||||
const int errMsgNum = 4;
|
||||
for(size_t i = 0; i < rvecs.size(); ++i)
|
||||
{
|
||||
Rodrigues(rvecs[i], rmat);
|
||||
Rodrigues(rvecs_est[i], rmat_est);
|
||||
|
||||
if (norm(rmat_est, rmat) > eps* (norm(rmat) + dlt))
|
||||
{
|
||||
if (err_count++ < errMsgNum)
|
||||
{
|
||||
if (err_count == errMsgNum)
|
||||
ts->printf( cvtest::TS::LOG, "%d) ...\n", r);
|
||||
else
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%d) Bad accuracy in returned rvecs (rotation matrs). Index = %d\n", r, i);
|
||||
ts->printf( cvtest::TS::LOG, "%d) norm(rot_mat_est - rot_mat_exp) = %f, norm(rot_mat_exp) = %f \n", r, norm(rmat_est, rmat), norm(rmat));
|
||||
|
||||
}
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double reprojectErrorWithoutIntrinsics(const vector<Point3f>& cb3d, const vector<Mat>& rvecs_exp, const vector<Mat>& tvecs_exp,
|
||||
const vector<Mat>& rvecs_est, const vector<Mat>& tvecs_est)
|
||||
{
|
||||
const static Mat eye33 = Mat::eye(3, 3, CV_64F);
|
||||
const static Mat zero15 = Mat::zeros(1, 5, CV_64F);
|
||||
Mat chessboard3D(cb3d);
|
||||
vector<Point2f> uv_exp, uv_est;
|
||||
double res = 0;
|
||||
|
||||
for(size_t i = 0; i < rvecs_exp.size(); ++i)
|
||||
{
|
||||
projectPoints(chessboard3D, rvecs_exp[i], tvecs_exp[i], eye33, zero15, uv_exp);
|
||||
projectPoints(chessboard3D, rvecs_est[i], tvecs_est[i], eye33, zero15, uv_est);
|
||||
for(size_t j = 0; j < cb3d.size(); ++j)
|
||||
res += norm(uv_exp[i] - uv_est[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Size2f sqSile;
|
||||
|
||||
vector<Point3f> chessboard3D;
|
||||
vector<Mat> boards, rvecs_exp, tvecs_exp, rvecs_spnp, tvecs_spnp;
|
||||
vector< vector<Point3f> > objectPoints;
|
||||
vector< vector<Point2f> > imagePoints_art;
|
||||
vector< vector<Point2f> > imagePoints_findCb;
|
||||
|
||||
|
||||
void prepareForTest(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, size_t brdsNum, const ChessBoardGenerator& cbg)
|
||||
{
|
||||
sqSile = Size2f(1.f, 1.f);
|
||||
Size cornersSize = cbg.cornersSize();
|
||||
|
||||
chessboard3D.clear();
|
||||
for(int j = 0; j < cornersSize.height; ++j)
|
||||
for(int i = 0; i < cornersSize.width; ++i)
|
||||
chessboard3D.push_back(Point3f(sqSile.width * i, sqSile.height * j, 0));
|
||||
|
||||
boards.resize(brdsNum);
|
||||
rvecs_exp.resize(brdsNum);
|
||||
tvecs_exp.resize(brdsNum);
|
||||
objectPoints.clear();
|
||||
objectPoints.resize(brdsNum, chessboard3D);
|
||||
imagePoints_art.clear();
|
||||
imagePoints_findCb.clear();
|
||||
|
||||
vector<Point2f> corners_art, corners_fcb;
|
||||
for(size_t i = 0; i < brdsNum; ++i)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
boards[i] = cbg(bg, camMat, distCoeffs, sqSile, corners_art);
|
||||
if(findChessboardCorners(boards[i], cornersSize, corners_fcb))
|
||||
break;
|
||||
}
|
||||
|
||||
//cv::namedWindow("CB"); imshow("CB", boards[i]); cv::waitKey();
|
||||
|
||||
imagePoints_art.push_back(corners_art);
|
||||
imagePoints_findCb.push_back(corners_fcb);
|
||||
|
||||
tvecs_exp[i].create(1, 3, CV_64F);
|
||||
*tvecs_exp[i].ptr<Point3d>() = cbg.corners3d[0];
|
||||
rvecs_exp[i] = calcRvec(cbg.corners3d, cbg.cornersSize());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void runTest(const Size& imgSize, const Mat_<double>& camMat, const Mat_<double>& distCoeffs, size_t brdsNum, const Size& cornersSize, int flag = 0)
|
||||
{
|
||||
const TermCriteria tc(TermCriteria::EPS|TermCriteria::MAX_ITER, 30, 0.1);
|
||||
|
||||
vector< vector<Point2f> > imagePoints;
|
||||
|
||||
switch(flag)
|
||||
{
|
||||
case JUST_FIND_CORNERS: imagePoints = imagePoints_findCb; break;
|
||||
case ARTIFICIAL_CORNERS: imagePoints = imagePoints_art; break;
|
||||
|
||||
case USE_CORNERS_SUBPIX:
|
||||
for(size_t i = 0; i < brdsNum; ++i)
|
||||
{
|
||||
Mat gray;
|
||||
cvtColor(boards[i], gray, CV_BGR2GRAY);
|
||||
vector<Point2f> tmp = imagePoints_findCb[i];
|
||||
cornerSubPix(gray, tmp, Size(5, 5), Size(-1,-1), tc);
|
||||
imagePoints.push_back(tmp);
|
||||
}
|
||||
break;
|
||||
case USE_4QUAD_CORNERS:
|
||||
for(size_t i = 0; i < brdsNum; ++i)
|
||||
{
|
||||
Mat gray;
|
||||
cvtColor(boards[i], gray, CV_BGR2GRAY);
|
||||
vector<Point2f> tmp = imagePoints_findCb[i];
|
||||
find4QuadCornerSubpix(gray, tmp, Size(5, 5));
|
||||
imagePoints.push_back(tmp);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
Mat camMat_est = Mat::eye(3, 3, CV_64F), distCoeffs_est = Mat::zeros(1, 5, CV_64F);
|
||||
vector<Mat> rvecs_est, tvecs_est;
|
||||
|
||||
int flags = /*CV_CALIB_FIX_K3|*/CV_CALIB_FIX_K4|CV_CALIB_FIX_K5|CV_CALIB_FIX_K6; //CALIB_FIX_K3; //CALIB_FIX_ASPECT_RATIO | | CALIB_ZERO_TANGENT_DIST;
|
||||
double rep_error = calibrateCamera(objectPoints, imagePoints, imgSize, camMat_est, distCoeffs_est, rvecs_est, tvecs_est, flags);
|
||||
rep_error /= brdsNum * cornersSize.area();
|
||||
|
||||
const double thres = 1;
|
||||
if (rep_error > thres)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%d) Too big reproject error = %f\n", r, rep_error);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
|
||||
compareCameraMatrs(camMat, camMat_est);
|
||||
compareDistCoeffs(distCoeffs, distCoeffs_est);
|
||||
compareShiftVecs(tvecs_exp, tvecs_est);
|
||||
compareRotationVecs(rvecs_exp, rvecs_est);
|
||||
|
||||
double rep_errorWOI = reprojectErrorWithoutIntrinsics(chessboard3D, rvecs_exp, tvecs_exp, rvecs_est, tvecs_est);
|
||||
rep_errorWOI /= brdsNum * cornersSize.area();
|
||||
|
||||
const double thres2 = 0.01;
|
||||
if (rep_errorWOI > thres2)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "%d) Too big reproject error without intrinsics = %f\n", r, rep_errorWOI);
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
|
||||
ts->printf( cvtest::TS::LOG, "%d) Testing solvePnP...\n", r);
|
||||
rvecs_spnp.resize(brdsNum);
|
||||
tvecs_spnp.resize(brdsNum);
|
||||
for(size_t i = 0; i < brdsNum; ++i)
|
||||
solvePnP(Mat(objectPoints[i]), Mat(imagePoints[i]), camMat, distCoeffs, rvecs_spnp[i], tvecs_spnp[i]);
|
||||
|
||||
compareShiftVecs(tvecs_exp, tvecs_spnp);
|
||||
compareRotationVecs(rvecs_exp, rvecs_spnp);
|
||||
}
|
||||
|
||||
void run(int)
|
||||
{
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
RNG& rng = theRNG();
|
||||
|
||||
int progress = 0;
|
||||
int repeat_num = 3;
|
||||
for(r = 0; r < repeat_num; ++r)
|
||||
{
|
||||
const int brds_num = 20;
|
||||
|
||||
Mat bg(Size(640, 480), CV_8UC3);
|
||||
randu(bg, Scalar::all(32), Scalar::all(255));
|
||||
GaussianBlur(bg, bg, Size(5, 5), 2);
|
||||
|
||||
double fx = 300 + (20 * (double)rng - 10);
|
||||
double fy = 300 + (20 * (double)rng - 10);
|
||||
|
||||
double cx = bg.cols/2 + (40 * (double)rng - 20);
|
||||
double cy = bg.rows/2 + (40 * (double)rng - 20);
|
||||
|
||||
Mat_<double> camMat(3, 3);
|
||||
camMat << fx, 0., cx, 0, fy, cy, 0., 0., 1.;
|
||||
|
||||
double k1 = 0.5 + (double)rng/5;
|
||||
double k2 = (double)rng/5;
|
||||
double k3 = (double)rng/5;
|
||||
|
||||
double p1 = 0.001 + (double)rng/10;
|
||||
double p2 = 0.001 + (double)rng/10;
|
||||
|
||||
Mat_<double> distCoeffs(1, 5, 0.0);
|
||||
distCoeffs << k1, k2, p1, p2, k3;
|
||||
|
||||
ChessBoardGenerator cbg(Size(9, 8));
|
||||
cbg.min_cos = 0.9;
|
||||
cbg.cov = 0.8;
|
||||
|
||||
progress = update_progress(progress, r, repeat_num, 0);
|
||||
ts->printf( cvtest::TS::LOG, "\n");
|
||||
prepareForTest(bg, camMat, distCoeffs, brds_num, cbg);
|
||||
|
||||
ts->printf( cvtest::TS::LOG, "artificial corners\n");
|
||||
runTest(bg.size(), camMat, distCoeffs, brds_num, cbg.cornersSize(), ARTIFICIAL_CORNERS);
|
||||
progress = update_progress(progress, r, repeat_num, 0);
|
||||
|
||||
ts->printf( cvtest::TS::LOG, "findChessboard corners\n");
|
||||
runTest(bg.size(), camMat, distCoeffs, brds_num, cbg.cornersSize(), JUST_FIND_CORNERS);
|
||||
progress = update_progress(progress, r, repeat_num, 0);
|
||||
|
||||
ts->printf( cvtest::TS::LOG, "cornersSubPix corners\n");
|
||||
runTest(bg.size(), camMat, distCoeffs, brds_num, cbg.cornersSize(), USE_CORNERS_SUBPIX);
|
||||
progress = update_progress(progress, r, repeat_num, 0);
|
||||
|
||||
ts->printf( cvtest::TS::LOG, "4quad corners\n");
|
||||
runTest(bg.size(), camMat, distCoeffs, brds_num, cbg.cornersSize(), USE_4QUAD_CORNERS);
|
||||
progress = update_progress(progress, r, repeat_num, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Calib3d_CalibrateCamera_CPP, accuracy_on_artificial_data) { CV_CalibrateCameraArtificialTest test; test.safe_run(); }
|
738
modules/calib3d/test/test_cameracalibration_badarg.cpp
Normal file
738
modules/calib3d/test/test_cameracalibration_badarg.cpp
Normal file
@ -0,0 +1,738 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_CameraCalibrationBadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_CameraCalibrationBadArgTest() : imgSize(800, 600) {}
|
||||
~CV_CameraCalibrationBadArgTest() {}
|
||||
protected:
|
||||
void run(int);
|
||||
void run_func(void) {};
|
||||
|
||||
const static int M = 1;
|
||||
|
||||
Size imgSize;
|
||||
Size corSize;
|
||||
Mat chessBoard;
|
||||
Mat corners;
|
||||
|
||||
struct C_Caller
|
||||
{
|
||||
CvMat* objPts;
|
||||
CvMat* imgPts;
|
||||
CvMat* npoints;
|
||||
Size imageSize;
|
||||
CvMat *cameraMatrix;
|
||||
CvMat *distCoeffs;
|
||||
CvMat *rvecs;
|
||||
CvMat *tvecs;
|
||||
int flags;
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
cvCalibrateCamera2(objPts, imgPts, npoints, imageSize,
|
||||
cameraMatrix, distCoeffs, rvecs, tvecs, flags );
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
void CV_CameraCalibrationBadArgTest::run( int /* start_from */ )
|
||||
{
|
||||
Mat_<float> camMat(3, 3);
|
||||
Mat_<float> distCoeffs0(1, 5);
|
||||
|
||||
camMat << 300.f, 0.f, imgSize.width/2.f, 0, 300.f, imgSize.height/2.f, 0.f, 0.f, 1.f;
|
||||
distCoeffs0 << 1.2f, 0.2f, 0.f, 0.f, 0.f;
|
||||
|
||||
ChessBoardGenerator cbg(Size(8,6));
|
||||
corSize = cbg.cornersSize();
|
||||
vector<Point2f> exp_corn;
|
||||
chessBoard = cbg(Mat(imgSize, CV_8U, Scalar(0)), camMat, distCoeffs0, exp_corn);
|
||||
Mat_<Point2f>(corSize.height, corSize.width, (Point2f*)&exp_corn[0]).copyTo(corners);
|
||||
|
||||
CvMat objPts, imgPts, npoints, cameraMatrix, distCoeffs, rvecs, tvecs;
|
||||
Mat zeros(1, sizeof(CvMat), CV_8U, Scalar(0));
|
||||
|
||||
C_Caller caller, bad_caller;
|
||||
caller.imageSize = imgSize;
|
||||
caller.objPts = &objPts;
|
||||
caller.imgPts = &imgPts;
|
||||
caller.npoints = &npoints;
|
||||
caller.cameraMatrix = &cameraMatrix;
|
||||
caller.distCoeffs = &distCoeffs;
|
||||
caller.rvecs = &rvecs;
|
||||
caller.tvecs = &tvecs;
|
||||
|
||||
/////////////////////////////
|
||||
Mat objPts_cpp;
|
||||
Mat imgPts_cpp;
|
||||
Mat npoints_cpp;
|
||||
Mat cameraMatrix_cpp;
|
||||
Mat distCoeffs_cpp;
|
||||
Mat rvecs_cpp;
|
||||
Mat tvecs_cpp;
|
||||
|
||||
objPts_cpp.create(corSize, CV_32FC3);
|
||||
for(int j = 0; j < corSize.height; ++j)
|
||||
for(int i = 0; i < corSize.width; ++i)
|
||||
objPts_cpp.at<Point3f>(j, i) = Point3i(i, j, 0);
|
||||
objPts_cpp = objPts_cpp.reshape(3, 1);
|
||||
|
||||
imgPts_cpp = corners.clone().reshape(2, 1);
|
||||
npoints_cpp = Mat_<int>(M, 1, corSize.width * corSize.height);
|
||||
cameraMatrix_cpp.create(3, 3, CV_32F);
|
||||
distCoeffs_cpp.create(5, 1, CV_32F);
|
||||
rvecs_cpp.create(M, 1, CV_32FC3);
|
||||
tvecs_cpp.create(M, 1, CV_32FC3);
|
||||
|
||||
caller.flags = 0;
|
||||
//CV_CALIB_USE_INTRINSIC_GUESS; //CV_CALIB_FIX_ASPECT_RATIO
|
||||
//CV_CALIB_USE_INTRINSIC_GUESS //CV_CALIB_FIX_ASPECT_RATIO
|
||||
//CV_CALIB_FIX_PRINCIPAL_POINT //CV_CALIB_ZERO_TANGENT_DIST
|
||||
//CV_CALIB_FIX_FOCAL_LENGTH //CV_CALIB_FIX_K1 //CV_CALIB_FIX_K2 //CV_CALIB_FIX_K3
|
||||
|
||||
objPts = objPts_cpp;
|
||||
imgPts = imgPts_cpp;
|
||||
npoints = npoints_cpp;
|
||||
cameraMatrix = cameraMatrix_cpp;
|
||||
distCoeffs = distCoeffs_cpp;
|
||||
rvecs = rvecs_cpp;
|
||||
tvecs = tvecs_cpp;
|
||||
|
||||
/* /*//*/ */
|
||||
int errors = 0;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.objPts = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero passed in objPts", bad_caller);
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.imgPts = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero passed in imgPts", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.npoints = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero passed in npoints", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.cameraMatrix = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero passed in cameraMatrix", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero passed in distCoeffs", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.imageSize.width = -1;
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad image width", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.imageSize.height = -1;
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad image height", bad_caller );
|
||||
|
||||
Mat bad_nts_cpp1 = Mat_<float>(M, 1, 1.f);
|
||||
Mat bad_nts_cpp2 = Mat_<int>(3, 3, corSize.width * corSize.height);
|
||||
CvMat bad_npts_c1 = bad_nts_cpp1;
|
||||
CvMat bad_npts_c2 = bad_nts_cpp2;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.npoints = &bad_npts_c1;
|
||||
errors += run_test_case( CV_StsUnsupportedFormat, "Bad npoints format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.npoints = &bad_npts_c2;
|
||||
errors += run_test_case( CV_StsUnsupportedFormat, "Bad npoints size", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.rvecs = (CvMat*)zeros.ptr();
|
||||
errors += run_test_case( CV_StsBadArg, "Bad rvecs header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.tvecs = (CvMat*)zeros.ptr();
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvecs header", bad_caller );
|
||||
|
||||
Mat bad_rvecs_cpp1(M+1, 1, CV_32FC3); CvMat bad_rvecs_c1 = bad_rvecs_cpp1;
|
||||
Mat bad_tvecs_cpp1(M+1, 1, CV_32FC3); CvMat bad_tvecs_c1 = bad_tvecs_cpp1;
|
||||
|
||||
|
||||
|
||||
Mat bad_rvecs_cpp2(M, 2, CV_32FC3); CvMat bad_rvecs_c2 = bad_rvecs_cpp2;
|
||||
Mat bad_tvecs_cpp2(M, 2, CV_32FC3); CvMat bad_tvecs_c2 = bad_tvecs_cpp2;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.rvecs = &bad_rvecs_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvecs header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.rvecs = &bad_rvecs_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvecs header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.tvecs = &bad_tvecs_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvecs header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.tvecs = &bad_tvecs_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvecs header", bad_caller );
|
||||
|
||||
Mat bad_cameraMatrix_cpp1(3, 3, CV_32S); CvMat bad_cameraMatrix_c1 = bad_cameraMatrix_cpp1;
|
||||
Mat bad_cameraMatrix_cpp2(2, 3, CV_32F); CvMat bad_cameraMatrix_c2 = bad_cameraMatrix_cpp2;
|
||||
Mat bad_cameraMatrix_cpp3(3, 2, CV_64F); CvMat bad_cameraMatrix_c3 = bad_cameraMatrix_cpp3;
|
||||
|
||||
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.cameraMatrix = &bad_cameraMatrix_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad camearaMatrix header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.cameraMatrix = &bad_cameraMatrix_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad camearaMatrix header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.cameraMatrix = &bad_cameraMatrix_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad camearaMatrix header", bad_caller );
|
||||
|
||||
Mat bad_distCoeffs_cpp1(1, 5, CV_32S); CvMat bad_distCoeffs_c1 = bad_distCoeffs_cpp1;
|
||||
Mat bad_distCoeffs_cpp2(2, 2, CV_64F); CvMat bad_distCoeffs_c2 = bad_distCoeffs_cpp2;
|
||||
Mat bad_distCoeffs_cpp3(1, 6, CV_64F); CvMat bad_distCoeffs_c3 = bad_distCoeffs_cpp3;
|
||||
|
||||
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &bad_distCoeffs_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs header", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &bad_distCoeffs_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs header", bad_caller );
|
||||
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &bad_distCoeffs_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs header", bad_caller );
|
||||
|
||||
double CM[] = {0, 0, 0, /**/0, 0, 0, /**/0, 0, 0};
|
||||
Mat bad_cameraMatrix_cpp4(3, 3, CV_64F, CM); CvMat bad_cameraMatrix_c4 = bad_cameraMatrix_cpp4;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.flags |= CV_CALIB_USE_INTRINSIC_GUESS;
|
||||
bad_caller.cameraMatrix = &bad_cameraMatrix_c4;
|
||||
CM[0] = 0; //bad fx
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[0] = 500; CM[4] = 0; //bad fy
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[0] = 500; CM[4] = 500; CM[2] = -1; //bad cx
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[0] = 500; CM[4] = 500; CM[2] = imgSize.width*2; //bad cx
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[0] = 500; CM[4] = 500; CM[2] = imgSize.width/2; CM[5] = -1; //bad cy
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[0] = 500; CM[4] = 500; CM[2] = imgSize.width/2; CM[5] = imgSize.height*2; //bad cy
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[0] = 500; CM[4] = 500; CM[2] = imgSize.width/2; CM[5] = imgSize.height/2;
|
||||
CM[1] = 0.1; //Non-zero skew
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[1] = 0;
|
||||
CM[3] = 0.1; /* mad matrix shape */
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[3] = 0; CM[6] = 0.1; /* mad matrix shape */
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[3] = 0; CM[6] = 0; CM[7] = 0.1; /* mad matrix shape */
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
|
||||
CM[3] = 0; CM[6] = 0; CM[7] = 0; CM[8] = 1.1; /* mad matrix shape */
|
||||
errors += run_test_case( CV_StsOutOfRange, "Bad camearaMatrix data", bad_caller );
|
||||
CM[8] = 1.0;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
bad_caller = caller;
|
||||
Mat bad_objPts_cpp5 = objPts_cpp.clone(); CvMat bad_objPts_c5 = bad_objPts_cpp5;
|
||||
bad_caller.objPts = &bad_objPts_c5;
|
||||
|
||||
cv::RNG& rng = theRNG();
|
||||
for(int i = 0; i < bad_objPts_cpp5.rows; ++i)
|
||||
bad_objPts_cpp5.at<Point3f>(0, i).z += ((float)rng - 0.5f);
|
||||
|
||||
errors += run_test_case( CV_StsBadArg, "Bad objPts data", bad_caller );
|
||||
|
||||
if (errors)
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
else
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
|
||||
//try { caller(); }
|
||||
//catch (...)
|
||||
//{
|
||||
// ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
// printf("+!");
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
class CV_Rodrigues2BadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_Rodrigues2BadArgTest() {}
|
||||
~CV_Rodrigues2BadArgTest() {}
|
||||
protected:
|
||||
void run_func(void) {};
|
||||
|
||||
struct C_Caller
|
||||
{
|
||||
CvMat* src;
|
||||
CvMat* dst;
|
||||
CvMat* jacobian;
|
||||
|
||||
void operator()() { cvRodrigues2(src, dst, jacobian); }
|
||||
};
|
||||
|
||||
void run(int /* start_from */ )
|
||||
{
|
||||
Mat zeros(1, sizeof(CvMat), CV_8U, Scalar(0));
|
||||
CvMat src_c, dst_c, jacobian_c;
|
||||
|
||||
Mat src_cpp(3, 1, CV_32F); src_c = src_cpp;
|
||||
Mat dst_cpp(3, 3, CV_32F); dst_c = dst_cpp;
|
||||
Mat jacobian_cpp(3, 9, CV_32F); jacobian_c = jacobian_cpp;
|
||||
|
||||
C_Caller caller, bad_caller;
|
||||
caller.src = &src_c;
|
||||
caller.dst = &dst_c;
|
||||
caller.jacobian = &jacobian_c;
|
||||
|
||||
/* try { caller(); }
|
||||
catch (...)
|
||||
{
|
||||
printf("badasfas");
|
||||
}*/
|
||||
|
||||
/*/*//*/*/
|
||||
int errors = 0;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.src = 0;
|
||||
errors += run_test_case( CV_StsNullPtr, "Src is zero pointer", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dst = 0;
|
||||
errors += run_test_case( CV_StsNullPtr, "Dst is zero pointer", bad_caller );
|
||||
|
||||
Mat bad_src_cpp1(3, 1, CV_8U); CvMat bad_src_c1 = bad_src_cpp1;
|
||||
Mat bad_dst_cpp1(3, 1, CV_8U); CvMat bad_dst_c1 = bad_dst_cpp1;
|
||||
Mat bad_jac_cpp1(3, 1, CV_8U); CvMat bad_jac_c1 = bad_jac_cpp1;
|
||||
Mat bad_jac_cpp2(3, 1, CV_32FC2); CvMat bad_jac_c2 = bad_jac_cpp2;
|
||||
Mat bad_jac_cpp3(3, 1, CV_32F); CvMat bad_jac_c3 = bad_jac_cpp3;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.src = &bad_src_c1;
|
||||
errors += run_test_case( CV_StsUnsupportedFormat, "Bad src formart", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dst = &bad_dst_c1;
|
||||
errors += run_test_case( CV_StsUnmatchedFormats, "Bad dst formart", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.jacobian = (CvMat*)zeros.ptr();
|
||||
errors += run_test_case( CV_StsBadArg, "Bad jacobian ", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.jacobian = &bad_jac_c1;
|
||||
errors += run_test_case( CV_StsUnmatchedFormats, "Bad jacobian format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.jacobian = &bad_jac_c2;
|
||||
errors += run_test_case( CV_StsUnmatchedFormats, "Bad jacobian format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.jacobian = &bad_jac_c3;
|
||||
errors += run_test_case( CV_StsBadSize, "Bad jacobian format", bad_caller );
|
||||
|
||||
Mat bad_src_cpp2(1, 1, CV_32F); CvMat bad_src_c2 = bad_src_cpp2;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.src = &bad_src_c2;
|
||||
errors += run_test_case( CV_StsBadSize, "Bad src format", bad_caller );
|
||||
|
||||
Mat bad_dst_cpp2(2, 1, CV_32F); CvMat bad_dst_c2 = bad_dst_cpp2;
|
||||
Mat bad_dst_cpp3(3, 2, CV_32F); CvMat bad_dst_c3 = bad_dst_cpp3;
|
||||
Mat bad_dst_cpp4(3, 3, CV_32FC2); CvMat bad_dst_c4 = bad_dst_cpp4;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dst = &bad_dst_c2;
|
||||
errors += run_test_case( CV_StsBadSize, "Bad dst format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dst = &bad_dst_c3;
|
||||
errors += run_test_case( CV_StsBadSize, "Bad dst format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dst = &bad_dst_c4;
|
||||
errors += run_test_case( CV_StsBadSize, "Bad dst format", bad_caller );
|
||||
|
||||
|
||||
/********/
|
||||
src_cpp.create(3, 3, CV_32F); src_c = src_cpp;
|
||||
dst_cpp.create(3, 1, CV_32F); dst_c = dst_cpp;
|
||||
|
||||
|
||||
Mat bad_dst_cpp5(5, 5, CV_32F); CvMat bad_dst_c5 = bad_dst_cpp5;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dst = &bad_dst_c5;
|
||||
errors += run_test_case( CV_StsBadSize, "Bad dst format", bad_caller );
|
||||
|
||||
|
||||
if (errors)
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
else
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
class CV_ProjectPoints2BadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_ProjectPoints2BadArgTest() : camMat(3, 3), distCoeffs(1, 5)
|
||||
{
|
||||
Size imsSize(800, 600);
|
||||
camMat << 300.f, 0.f, imsSize.width/2.f, 0, 300.f, imsSize.height/2.f, 0.f, 0.f, 1.f;
|
||||
distCoeffs << 1.2f, 0.2f, 0.f, 0.f, 0.f;
|
||||
};
|
||||
~CV_ProjectPoints2BadArgTest() {} ;
|
||||
protected:
|
||||
void run_func(void) {};
|
||||
|
||||
Mat_<float> camMat;
|
||||
Mat_<float> distCoeffs;
|
||||
|
||||
struct C_Caller
|
||||
{
|
||||
CvMat* objectPoints;
|
||||
CvMat* r_vec;
|
||||
CvMat* t_vec;
|
||||
CvMat* A;
|
||||
CvMat* distCoeffs;
|
||||
CvMat* imagePoints;
|
||||
CvMat* dpdr;
|
||||
CvMat* dpdt;
|
||||
CvMat* dpdf;
|
||||
CvMat* dpdc;
|
||||
CvMat* dpdk;
|
||||
double aspectRatio;
|
||||
|
||||
void operator()()
|
||||
{
|
||||
cvProjectPoints2( objectPoints, r_vec, t_vec, A, distCoeffs, imagePoints,
|
||||
dpdr, dpdt, dpdf, dpdc, dpdk, aspectRatio );
|
||||
}
|
||||
};
|
||||
|
||||
void run(int /* start_from */ )
|
||||
{
|
||||
CvMat zeros;
|
||||
memset(&zeros, 0, sizeof(zeros));
|
||||
|
||||
C_Caller caller, bad_caller;
|
||||
CvMat objectPoints_c, r_vec_c, t_vec_c, A_c, distCoeffs_c, imagePoints_c,
|
||||
dpdr_c, dpdt_c, dpdf_c, dpdc_c, dpdk_c;
|
||||
|
||||
const int n = 10;
|
||||
|
||||
Mat imagePoints_cpp(1, n, CV_32FC2); imagePoints_c = imagePoints_cpp;
|
||||
|
||||
Mat objectPoints_cpp(1, n, CV_32FC3);
|
||||
randu(objectPoints_cpp, Scalar::all(1), Scalar::all(10));
|
||||
objectPoints_c = objectPoints_cpp;
|
||||
|
||||
Mat t_vec_cpp(Mat::zeros(1, 3, CV_32F)); t_vec_c = t_vec_cpp;
|
||||
Mat r_vec_cpp;
|
||||
Rodrigues(Mat::eye(3, 3, CV_32F), r_vec_cpp); r_vec_c = r_vec_cpp;
|
||||
|
||||
Mat A_cpp = camMat.clone(); A_c = A_cpp;
|
||||
Mat distCoeffs_cpp = distCoeffs.clone(); distCoeffs_c = distCoeffs_cpp;
|
||||
|
||||
Mat dpdr_cpp(2*n, 3, CV_32F); dpdr_c = dpdr_cpp;
|
||||
Mat dpdt_cpp(2*n, 3, CV_32F); dpdt_c = dpdt_cpp;
|
||||
Mat dpdf_cpp(2*n, 2, CV_32F); dpdf_c = dpdf_cpp;
|
||||
Mat dpdc_cpp(2*n, 2, CV_32F); dpdc_c = dpdc_cpp;
|
||||
Mat dpdk_cpp(2*n, 4, CV_32F); dpdk_c = dpdk_cpp;
|
||||
|
||||
caller.aspectRatio = 1.0;
|
||||
caller.objectPoints = &objectPoints_c;
|
||||
caller.r_vec = &r_vec_c;
|
||||
caller.t_vec = &t_vec_c;
|
||||
caller.A = &A_c;
|
||||
caller.distCoeffs = &distCoeffs_c;
|
||||
caller.imagePoints = &imagePoints_c;
|
||||
caller.dpdr = &dpdr_c;
|
||||
caller.dpdt = &dpdt_c;
|
||||
caller.dpdf = &dpdf_c;
|
||||
caller.dpdc = &dpdc_c;
|
||||
caller.dpdk = &dpdk_c;
|
||||
|
||||
/********************/
|
||||
int errors = 0;
|
||||
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.objectPoints = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero objectPoints", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.r_vec = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero r_vec", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.t_vec = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero t_vec", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.A = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero camMat", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.imagePoints = 0;
|
||||
errors += run_test_case( CV_StsBadArg, "Zero imagePoints", bad_caller );
|
||||
|
||||
/****************************/
|
||||
Mat bad_r_vec_cpp1(r_vec_cpp.size(), CV_32S); CvMat bad_r_vec_c1 = bad_r_vec_cpp1;
|
||||
Mat bad_r_vec_cpp2(2, 2, CV_32F); CvMat bad_r_vec_c2 = bad_r_vec_cpp2;
|
||||
Mat bad_r_vec_cpp3(r_vec_cpp.size(), CV_32FC2); CvMat bad_r_vec_c3 = bad_r_vec_cpp3;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.r_vec = &bad_r_vec_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad rvec format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.r_vec = &bad_r_vec_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad rvec format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.r_vec = &bad_r_vec_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad rvec format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
Mat bad_t_vec_cpp1(t_vec_cpp.size(), CV_32S); CvMat bad_t_vec_c1 = bad_t_vec_cpp1;
|
||||
Mat bad_t_vec_cpp2(2, 2, CV_32F); CvMat bad_t_vec_c2 = bad_t_vec_cpp2;
|
||||
Mat bad_t_vec_cpp3(1, 1, CV_32FC2); CvMat bad_t_vec_c3 = bad_t_vec_cpp3;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.t_vec = &bad_t_vec_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvec format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.t_vec = &bad_t_vec_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvec format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.t_vec = &bad_t_vec_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad tvec format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
Mat bad_A_cpp1(A_cpp.size(), CV_32S); CvMat bad_A_c1 = bad_A_cpp1;
|
||||
Mat bad_A_cpp2(2, 2, CV_32F); CvMat bad_A_c2 = bad_A_cpp2;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.A = &bad_A_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad A format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.A = &bad_A_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad A format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
Mat bad_distCoeffs_cpp1(distCoeffs_cpp.size(), CV_32S); CvMat bad_distCoeffs_c1 = bad_distCoeffs_cpp1;
|
||||
Mat bad_distCoeffs_cpp2(2, 2, CV_32F); CvMat bad_distCoeffs_c2 = bad_distCoeffs_cpp2;
|
||||
Mat bad_distCoeffs_cpp3(1, 7, CV_32F); CvMat bad_distCoeffs_c3 = bad_distCoeffs_cpp3;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &zeros;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &bad_distCoeffs_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &bad_distCoeffs_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = &bad_distCoeffs_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad distCoeffs format", bad_caller );
|
||||
|
||||
|
||||
/****************************/
|
||||
Mat bad_dpdr_cpp1(dpdr_cpp.size(), CV_32S); CvMat bad_dpdr_c1 = bad_dpdr_cpp1;
|
||||
Mat bad_dpdr_cpp2(dpdr_cpp.cols+1, 3, CV_32F); CvMat bad_dpdr_c2 = bad_dpdr_cpp2;
|
||||
Mat bad_dpdr_cpp3(dpdr_cpp.cols, 7, CV_32F); CvMat bad_dpdr_c3 = bad_dpdr_cpp3;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdr = &zeros;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdr format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdr = &bad_dpdr_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdr format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdr = &bad_dpdr_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdr format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdr = &bad_dpdr_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdr format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdt = &zeros;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdt format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdt = &bad_dpdr_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdt format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdt = &bad_dpdr_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdt format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdt = &bad_dpdr_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdt format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
|
||||
Mat bad_dpdf_cpp2(dpdr_cpp.cols+1, 2, CV_32F); CvMat bad_dpdf_c2 = bad_dpdf_cpp2;
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdf = &zeros;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdf format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdf = &bad_dpdr_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdf format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdf = &bad_dpdf_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdf format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdf = &bad_dpdr_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdf format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdc = &zeros;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdc format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdc = &bad_dpdr_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdc format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdc = &bad_dpdf_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdc format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdc = &bad_dpdr_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdc format", bad_caller );
|
||||
|
||||
/****************************/
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdk = &zeros;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdk format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdk = &bad_dpdr_c1;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdk format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdk = &bad_dpdf_c2;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdk format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.dpdk = &bad_dpdr_c3;
|
||||
errors += run_test_case( CV_StsBadArg, "Bad dpdk format", bad_caller );
|
||||
|
||||
bad_caller = caller;
|
||||
bad_caller.distCoeffs = 0;
|
||||
errors += run_test_case( CV_StsNullPtr, "distCoeffs is NULL while dpdk is not", bad_caller );
|
||||
|
||||
|
||||
if (errors)
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
else
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(Calib3d_CalibrateCamera_C, badarg) { CV_CameraCalibrationBadArgTest test; test.safe_run(); }
|
||||
TEST(Calib3d_Rodrigues_C, badarg) { CV_Rodrigues2BadArgTest test; test.safe_run(); }
|
||||
TEST(Calib3d_ProjectPoints_C, badarg) { CV_ProjectPoints2BadArgTest test; test.safe_run(); }
|
||||
|
||||
|
332
modules/calib3d/test/test_chessboardgenerator.cpp
Normal file
332
modules/calib3d/test/test_chessboardgenerator.cpp
Normal file
@ -0,0 +1,332 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
ChessBoardGenerator::ChessBoardGenerator(const Size& _patternSize) : sensorWidth(32), sensorHeight(24),
|
||||
squareEdgePointsNum(200), min_cos(sqrt(2.f)*0.5f), cov(0.5),
|
||||
patternSize(_patternSize), rendererResolutionMultiplier(4), tvec(Mat::zeros(1, 3, CV_32F))
|
||||
{
|
||||
Rodrigues(Mat::eye(3, 3, CV_32F), rvec);
|
||||
}
|
||||
|
||||
void cv::ChessBoardGenerator::generateEdge(const Point3f& p1, const Point3f& p2, vector<Point3f>& out) const
|
||||
{
|
||||
Point3f step = (p2 - p1) * (1.f/squareEdgePointsNum);
|
||||
for(size_t n = 0; n < squareEdgePointsNum; ++n)
|
||||
out.push_back( p1 + step * (float)n);
|
||||
}
|
||||
|
||||
Size cv::ChessBoardGenerator::cornersSize() const
|
||||
{
|
||||
return Size(patternSize.width-1, patternSize.height-1);
|
||||
}
|
||||
|
||||
struct Mult
|
||||
{
|
||||
float m;
|
||||
Mult(int mult) : m((float)mult) {}
|
||||
Point2f operator()(const Point2f& p)const { return p * m; }
|
||||
};
|
||||
|
||||
void cv::ChessBoardGenerator::generateBasis(Point3f& pb1, Point3f& pb2) const
|
||||
{
|
||||
RNG& rng = theRNG();
|
||||
|
||||
Vec3f n;
|
||||
for(;;)
|
||||
{
|
||||
n[0] = rng.uniform(-1.f, 1.f);
|
||||
n[1] = rng.uniform(-1.f, 1.f);
|
||||
n[2] = rng.uniform(-1.f, 1.f);
|
||||
float len = (float)norm(n);
|
||||
n[0]/=len;
|
||||
n[1]/=len;
|
||||
n[2]/=len;
|
||||
|
||||
if (n[2] > min_cos)
|
||||
break;
|
||||
}
|
||||
|
||||
Vec3f n_temp = n; n_temp[0] += 100;
|
||||
Vec3f b1 = n.cross(n_temp);
|
||||
Vec3f b2 = n.cross(b1);
|
||||
float len_b1 = (float)norm(b1);
|
||||
float len_b2 = (float)norm(b2);
|
||||
|
||||
pb1 = Point3f(b1[0]/len_b1, b1[1]/len_b1, b1[2]/len_b1);
|
||||
pb2 = Point3f(b2[0]/len_b1, b2[1]/len_b2, b2[2]/len_b2);
|
||||
}
|
||||
|
||||
|
||||
Mat cv::ChessBoardGenerator::generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Point3f& zero, const Point3f& pb1, const Point3f& pb2,
|
||||
float sqWidth, float sqHeight, const vector<Point3f>& whole,
|
||||
vector<Point2f>& corners) const
|
||||
{
|
||||
vector< vector<Point> > squares_black;
|
||||
for(int i = 0; i < patternSize.width; ++i)
|
||||
for(int j = 0; j < patternSize.height; ++j)
|
||||
if ( (i % 2 == 0 && j % 2 == 0) || (i % 2 != 0 && j % 2 != 0) )
|
||||
{
|
||||
vector<Point3f> pts_square3d;
|
||||
vector<Point2f> pts_square2d;
|
||||
|
||||
Point3f p1 = zero + (i + 0) * sqWidth * pb1 + (j + 0) * sqHeight * pb2;
|
||||
Point3f p2 = zero + (i + 1) * sqWidth * pb1 + (j + 0) * sqHeight * pb2;
|
||||
Point3f p3 = zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2;
|
||||
Point3f p4 = zero + (i + 0) * sqWidth * pb1 + (j + 1) * sqHeight * pb2;
|
||||
generateEdge(p1, p2, pts_square3d);
|
||||
generateEdge(p2, p3, pts_square3d);
|
||||
generateEdge(p3, p4, pts_square3d);
|
||||
generateEdge(p4, p1, pts_square3d);
|
||||
|
||||
projectPoints(Mat(pts_square3d), rvec, tvec, camMat, distCoeffs, pts_square2d);
|
||||
squares_black.resize(squares_black.size() + 1);
|
||||
vector<Point2f> temp;
|
||||
approxPolyDP(Mat(pts_square2d), temp, 1.0, true);
|
||||
transform(temp.begin(), temp.end(), back_inserter(squares_black.back()), Mult(rendererResolutionMultiplier));
|
||||
}
|
||||
|
||||
/* calculate corners */
|
||||
corners3d.clear();
|
||||
for(int j = 0; j < patternSize.height - 1; ++j)
|
||||
for(int i = 0; i < patternSize.width - 1; ++i)
|
||||
corners3d.push_back(zero + (i + 1) * sqWidth * pb1 + (j + 1) * sqHeight * pb2);
|
||||
corners.clear();
|
||||
projectPoints(Mat(corners3d), rvec, tvec, camMat, distCoeffs, corners);
|
||||
|
||||
vector<Point3f> whole3d;
|
||||
vector<Point2f> whole2d;
|
||||
generateEdge(whole[0], whole[1], whole3d);
|
||||
generateEdge(whole[1], whole[2], whole3d);
|
||||
generateEdge(whole[2], whole[3], whole3d);
|
||||
generateEdge(whole[3], whole[0], whole3d);
|
||||
projectPoints(Mat(whole3d), rvec, tvec, camMat, distCoeffs, whole2d);
|
||||
vector<Point2f> temp_whole2d;
|
||||
approxPolyDP(Mat(whole2d), temp_whole2d, 1.0, true);
|
||||
|
||||
vector< vector<Point > > whole_contour(1);
|
||||
transform(temp_whole2d.begin(), temp_whole2d.end(),
|
||||
back_inserter(whole_contour.front()), Mult(rendererResolutionMultiplier));
|
||||
|
||||
Mat result;
|
||||
if (rendererResolutionMultiplier == 1)
|
||||
{
|
||||
result = bg.clone();
|
||||
drawContours(result, whole_contour, -1, Scalar::all(255), CV_FILLED, CV_AA);
|
||||
drawContours(result, squares_black, -1, Scalar::all(0), CV_FILLED, CV_AA);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat tmp;
|
||||
resize(bg, tmp, bg.size() * rendererResolutionMultiplier);
|
||||
drawContours(tmp, whole_contour, -1, Scalar::all(255), CV_FILLED, CV_AA);
|
||||
drawContours(tmp, squares_black, -1, Scalar::all(0), CV_FILLED, CV_AA);
|
||||
resize(tmp, result, bg.size(), 0, 0, INTER_AREA);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat cv::ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, vector<Point2f>& corners) const
|
||||
{
|
||||
cov = min(cov, 0.8);
|
||||
double fovx, fovy, focalLen;
|
||||
Point2d principalPoint;
|
||||
double aspect;
|
||||
calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight,
|
||||
fovx, fovy, focalLen, principalPoint, aspect);
|
||||
|
||||
RNG& rng = theRNG();
|
||||
|
||||
float d1 = static_cast<float>(rng.uniform(0.1, 10.0));
|
||||
float ah = static_cast<float>(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180);
|
||||
float av = static_cast<float>(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180);
|
||||
|
||||
Point3f p;
|
||||
p.z = cos(ah) * d1;
|
||||
p.x = sin(ah) * d1;
|
||||
p.y = p.z * tan(av);
|
||||
|
||||
Point3f pb1, pb2;
|
||||
generateBasis(pb1, pb2);
|
||||
|
||||
float cbHalfWidth = static_cast<float>(norm(p) * sin( min(fovx, fovy) * 0.5 * CV_PI / 180));
|
||||
float cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width;
|
||||
|
||||
float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
|
||||
vector<Point3f> pts3d(4);
|
||||
vector<Point2f> pts2d(4);
|
||||
for(;;)
|
||||
{
|
||||
pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
|
||||
/* can remake with better perf */
|
||||
projectPoints(Mat(pts3d), rvec, tvec, camMat, distCoeffs, pts2d);
|
||||
|
||||
bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0;
|
||||
bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0;
|
||||
bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0;
|
||||
bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0;
|
||||
|
||||
if (inrect1 && inrect2 && inrect3 && inrect4)
|
||||
break;
|
||||
|
||||
cbHalfWidth*=0.8f;
|
||||
cbHalfHeight = cbHalfWidth * patternSize.height / patternSize.width;
|
||||
|
||||
cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
}
|
||||
|
||||
Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;
|
||||
float sqWidth = 2 * cbHalfWidth/patternSize.width;
|
||||
float sqHeight = 2 * cbHalfHeight/patternSize.height;
|
||||
|
||||
return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2, sqWidth, sqHeight, pts3d, corners);
|
||||
}
|
||||
|
||||
|
||||
Mat cv::ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Size2f& squareSize, vector<Point2f>& corners) const
|
||||
{
|
||||
cov = min(cov, 0.8);
|
||||
double fovx, fovy, focalLen;
|
||||
Point2d principalPoint;
|
||||
double aspect;
|
||||
calibrationMatrixValues( camMat, bg.size(), sensorWidth, sensorHeight,
|
||||
fovx, fovy, focalLen, principalPoint, aspect);
|
||||
|
||||
RNG& rng = theRNG();
|
||||
|
||||
float d1 = static_cast<float>(rng.uniform(0.1, 10.0));
|
||||
float ah = static_cast<float>(rng.uniform(-fovx/2 * cov, fovx/2 * cov) * CV_PI / 180);
|
||||
float av = static_cast<float>(rng.uniform(-fovy/2 * cov, fovy/2 * cov) * CV_PI / 180);
|
||||
|
||||
Point3f p;
|
||||
p.z = cos(ah) * d1;
|
||||
p.x = sin(ah) * d1;
|
||||
p.y = p.z * tan(av);
|
||||
|
||||
Point3f pb1, pb2;
|
||||
generateBasis(pb1, pb2);
|
||||
|
||||
float cbHalfWidth = squareSize.width * patternSize.width * 0.5f;
|
||||
float cbHalfHeight = squareSize.height * patternSize.height * 0.5f;
|
||||
|
||||
float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
|
||||
vector<Point3f> pts3d(4);
|
||||
vector<Point2f> pts2d(4);
|
||||
for(;;)
|
||||
{
|
||||
pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
|
||||
/* can remake with better perf */
|
||||
projectPoints(Mat(pts3d), rvec, tvec, camMat, distCoeffs, pts2d);
|
||||
|
||||
bool inrect1 = pts2d[0].x < bg.cols && pts2d[0].y < bg.rows && pts2d[0].x > 0 && pts2d[0].y > 0;
|
||||
bool inrect2 = pts2d[1].x < bg.cols && pts2d[1].y < bg.rows && pts2d[1].x > 0 && pts2d[1].y > 0;
|
||||
bool inrect3 = pts2d[2].x < bg.cols && pts2d[2].y < bg.rows && pts2d[2].x > 0 && pts2d[2].y > 0;
|
||||
bool inrect4 = pts2d[3].x < bg.cols && pts2d[3].y < bg.rows && pts2d[3].x > 0 && pts2d[3].y > 0;
|
||||
|
||||
if ( inrect1 && inrect2 && inrect3 && inrect4)
|
||||
break;
|
||||
|
||||
p.z *= 1.1f;
|
||||
}
|
||||
|
||||
Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;
|
||||
|
||||
return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2,
|
||||
squareSize.width, squareSize.height, pts3d, corners);
|
||||
}
|
||||
|
||||
Mat cv::ChessBoardGenerator::operator ()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Size2f& squareSize, const Point3f& pos, vector<Point2f>& corners) const
|
||||
{
|
||||
cov = min(cov, 0.8);
|
||||
Point3f p = pos;
|
||||
Point3f pb1, pb2;
|
||||
generateBasis(pb1, pb2);
|
||||
|
||||
float cbHalfWidth = squareSize.width * patternSize.width * 0.5f;
|
||||
float cbHalfHeight = squareSize.height * patternSize.height * 0.5f;
|
||||
|
||||
float cbHalfWidthEx = cbHalfWidth * ( patternSize.width + 1) / patternSize.width;
|
||||
float cbHalfHeightEx = cbHalfHeight * (patternSize.height + 1) / patternSize.height;
|
||||
|
||||
vector<Point3f> pts3d(4);
|
||||
vector<Point2f> pts2d(4);
|
||||
|
||||
pts3d[0] = p + pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
pts3d[1] = p + pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[2] = p - pb1 * cbHalfWidthEx - cbHalfHeightEx * pb2;
|
||||
pts3d[3] = p - pb1 * cbHalfWidthEx + cbHalfHeightEx * pb2;
|
||||
|
||||
/* can remake with better perf */
|
||||
projectPoints(Mat(pts3d), rvec, tvec, camMat, distCoeffs, pts2d);
|
||||
|
||||
Point3f zero = p - pb1 * cbHalfWidth - cbHalfHeight * pb2;
|
||||
|
||||
return generateChessBoard(bg, camMat, distCoeffs, zero, pb1, pb2,
|
||||
squareSize.width, squareSize.height, pts3d, corners);
|
||||
}
|
||||
|
40
modules/calib3d/test/test_chessboardgenerator.hpp
Normal file
40
modules/calib3d/test/test_chessboardgenerator.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef CV_CHESSBOARDGENERATOR_H143KJTVYM389YTNHKFDHJ89NYVMO3VLMEJNTBGUEIYVCM203P
|
||||
#define CV_CHESSBOARDGENERATOR_H143KJTVYM389YTNHKFDHJ89NYVMO3VLMEJNTBGUEIYVCM203P
|
||||
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class ChessBoardGenerator
|
||||
{
|
||||
public:
|
||||
double sensorWidth;
|
||||
double sensorHeight;
|
||||
size_t squareEdgePointsNum;
|
||||
double min_cos;
|
||||
mutable double cov;
|
||||
Size patternSize;
|
||||
int rendererResolutionMultiplier;
|
||||
|
||||
ChessBoardGenerator(const Size& patternSize = Size(8, 6));
|
||||
Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, vector<Point2f>& corners) const;
|
||||
Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, const Size2f& squareSize, vector<Point2f>& corners) const;
|
||||
Mat operator()(const Mat& bg, const Mat& camMat, const Mat& distCoeffs, const Size2f& squareSize, const Point3f& pos, vector<Point2f>& corners) const;
|
||||
Size cornersSize() const;
|
||||
|
||||
mutable vector<Point3f> corners3d;
|
||||
private:
|
||||
void generateEdge(const Point3f& p1, const Point3f& p2, vector<Point3f>& out) const;
|
||||
Mat generateChessBoard(const Mat& bg, const Mat& camMat, const Mat& distCoeffs,
|
||||
const Point3f& zero, const Point3f& pb1, const Point3f& pb2,
|
||||
float sqWidth, float sqHeight, const vector<Point3f>& whole, vector<Point2f>& corners) const;
|
||||
void generateBasis(Point3f& pb1, Point3f& pb2) const;
|
||||
|
||||
Mat rvec, tvec;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
443
modules/calib3d/test/test_chesscorners.cpp
Normal file
443
modules/calib3d/test/test_chesscorners.cpp
Normal file
@ -0,0 +1,443 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
#define _L2_ERR
|
||||
|
||||
void show_points( const Mat& gray, const Mat& u, const vector<Point2f>& v, Size pattern_size, bool was_found )
|
||||
{
|
||||
Mat rgb( gray.size(), CV_8U);
|
||||
merge(vector<Mat>(3, gray), rgb);
|
||||
|
||||
for(size_t i = 0; i < v.size(); i++ )
|
||||
circle( rgb, v[i], 3, CV_RGB(255, 0, 0), CV_FILLED);
|
||||
|
||||
if( !u.empty() )
|
||||
{
|
||||
const Point2f* u_data = u.ptr<Point2f>();
|
||||
size_t count = u.cols * u.rows;
|
||||
for(size_t i = 0; i < count; i++ )
|
||||
circle( rgb, u_data[i], 3, CV_RGB(0, 255, 0), CV_FILLED);
|
||||
}
|
||||
if (!v.empty())
|
||||
{
|
||||
Mat corners((int)v.size(), 1, CV_32FC2, (void*)&v[0]);
|
||||
drawChessboardCorners( rgb, pattern_size, corners, was_found );
|
||||
}
|
||||
//namedWindow( "test", 0 ); imshow( "test", rgb ); waitKey(0);
|
||||
}
|
||||
|
||||
|
||||
enum Pattern { CHESSBOARD, CIRCLES_GRID };
|
||||
|
||||
class CV_ChessboardDetectorTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ChessboardDetectorTest( Pattern pattern );
|
||||
protected:
|
||||
void run(int);
|
||||
void run_batch(const string& filename);
|
||||
bool checkByGenerator();
|
||||
|
||||
Pattern pattern;
|
||||
};
|
||||
|
||||
CV_ChessboardDetectorTest::CV_ChessboardDetectorTest( Pattern _pattern )
|
||||
{
|
||||
pattern = _pattern;
|
||||
}
|
||||
|
||||
double calcError(const vector<Point2f>& v, const Mat& u)
|
||||
{
|
||||
int count_exp = u.cols * u.rows;
|
||||
const Point2f* u_data = u.ptr<Point2f>();
|
||||
|
||||
double err = numeric_limits<double>::max();
|
||||
for( int k = 0; k < 2; ++k )
|
||||
{
|
||||
double err1 = 0;
|
||||
for( int j = 0; j < count_exp; ++j )
|
||||
{
|
||||
int j1 = k == 0 ? j : count_exp - j - 1;
|
||||
double dx = fabs( v[j].x - u_data[j1].x );
|
||||
double dy = fabs( v[j].y - u_data[j1].y );
|
||||
|
||||
#if defined(_L2_ERR)
|
||||
err1 += dx*dx + dy*dy;
|
||||
#else
|
||||
dx = MAX( dx, dy );
|
||||
if( dx > err1 )
|
||||
err1 = dx;
|
||||
#endif //_L2_ERR
|
||||
//printf("dx = %f\n", dx);
|
||||
}
|
||||
//printf("\n");
|
||||
err = min(err, err1);
|
||||
}
|
||||
|
||||
#if defined(_L2_ERR)
|
||||
err = sqrt(err/count_exp);
|
||||
#endif //_L2_ERR
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
const double rough_success_error_level = 2.5;
|
||||
const double precise_success_error_level = 2;
|
||||
|
||||
|
||||
/* ///////////////////// chess_corner_test ///////////////////////// */
|
||||
void CV_ChessboardDetectorTest::run( int /*start_from */)
|
||||
{
|
||||
/*if (!checkByGenerator())
|
||||
return;*/
|
||||
switch( pattern )
|
||||
{
|
||||
case CHESSBOARD:
|
||||
checkByGenerator();
|
||||
run_batch("chessboard_list.dat");
|
||||
run_batch("chessboard_list_subpixel.dat");
|
||||
break;
|
||||
case CIRCLES_GRID:
|
||||
run_batch("circles_list.dat");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CV_ChessboardDetectorTest::run_batch( const string& filename )
|
||||
{
|
||||
cvtest::TS& ts = *this->ts;
|
||||
ts.set_failed_test_info( cvtest::TS::OK );
|
||||
|
||||
ts.printf(cvtest::TS::LOG, "\nRunning batch %s\n", filename.c_str());
|
||||
//#define WRITE_POINTS 1
|
||||
#ifndef WRITE_POINTS
|
||||
double max_rough_error = 0, max_precise_error = 0;
|
||||
#endif
|
||||
string folder;
|
||||
switch( pattern )
|
||||
{
|
||||
case CHESSBOARD:
|
||||
folder = string(ts.get_data_path()) + "cameracalibration/";
|
||||
break;
|
||||
case CIRCLES_GRID:
|
||||
folder = string(ts.get_data_path()) + "cameracalibration/circles/";
|
||||
break;
|
||||
}
|
||||
|
||||
FileStorage fs( folder + filename, FileStorage::READ );
|
||||
FileNode board_list = fs["boards"];
|
||||
|
||||
if( !fs.isOpened() || board_list.empty() || !board_list.isSeq() || board_list.size() % 2 != 0 )
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "%s can not be readed or is not valid\n", (folder + filename).c_str() );
|
||||
ts.printf( cvtest::TS::LOG, "fs.isOpened=%d, board_list.empty=%d, board_list.isSeq=%d,board_list.size()%2=%d\n",
|
||||
fs.isOpened(), (int)board_list.empty(), board_list.isSeq(), board_list.size()%2);
|
||||
ts.set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
int progress = 0;
|
||||
int max_idx = board_list.node->data.seq->total/2;
|
||||
double sum_error = 0.0;
|
||||
int count = 0;
|
||||
|
||||
for(int idx = 0; idx < max_idx; ++idx )
|
||||
{
|
||||
ts.update_context( this, idx, true );
|
||||
|
||||
/* read the image */
|
||||
string img_file = board_list[idx * 2];
|
||||
Mat gray = imread( folder + img_file, 0);
|
||||
|
||||
if( gray.empty() )
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", img_file.c_str() );
|
||||
ts.set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
|
||||
continue;
|
||||
}
|
||||
|
||||
string filename = folder + (string)board_list[idx * 2 + 1];
|
||||
Mat expected;
|
||||
{
|
||||
CvMat *u = (CvMat*)cvLoad( filename.c_str() );
|
||||
if(!u )
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "one of chessboard corner files can't be read: %s\n", filename.c_str() );
|
||||
ts.set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
|
||||
continue;
|
||||
}
|
||||
expected = Mat(u, true);
|
||||
cvReleaseMat( &u );
|
||||
}
|
||||
size_t count_exp = static_cast<size_t>(expected.cols * expected.rows);
|
||||
Size pattern_size = expected.size();
|
||||
|
||||
vector<Point2f> v;
|
||||
bool result = false;
|
||||
switch( pattern )
|
||||
{
|
||||
case CHESSBOARD:
|
||||
result = findChessboardCorners(gray, pattern_size, v, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);
|
||||
break;
|
||||
case CIRCLES_GRID:
|
||||
result = findCirclesGrid(gray, pattern_size, v);
|
||||
break;
|
||||
}
|
||||
show_points( gray, Mat(), v, pattern_size, result );
|
||||
if( !result || v.size() != count_exp )
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "chessboard is not found in %s\n", img_file.c_str() );
|
||||
ts.set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef WRITE_POINTS
|
||||
double err = calcError(v, expected);
|
||||
#if 0
|
||||
if( err > rough_success_error_level )
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "bad accuracy of corner guesses\n" );
|
||||
ts.set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
max_rough_error = MAX( max_rough_error, err );
|
||||
#endif
|
||||
if( pattern == CHESSBOARD )
|
||||
cornerSubPix( gray, v, Size(5, 5), Size(-1,-1), TermCriteria(TermCriteria::EPS|TermCriteria::MAX_ITER, 30, 0.1));
|
||||
//find4QuadCornerSubpix(gray, v, Size(5, 5));
|
||||
show_points( gray, expected, v, pattern_size, result );
|
||||
|
||||
#ifndef WRITE_POINTS
|
||||
// printf("called find4QuadCornerSubpix\n");
|
||||
err = calcError(v, expected);
|
||||
sum_error += err;
|
||||
count++;
|
||||
#if 1
|
||||
if( err > precise_success_error_level )
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "Image %s: bad accuracy of adjusted corners %f\n", img_file.c_str(), err );
|
||||
ts.set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
ts.printf(cvtest::TS::LOG, "Error on %s is %f\n", img_file.c_str(), err);
|
||||
max_precise_error = MAX( max_precise_error, err );
|
||||
#else
|
||||
Mat mat_v(pattern_size, CV_32FC2, (void*)&v[0]);
|
||||
CvMat cvmat_v = mat_v;
|
||||
cvSave( filename.c_str(), &cvmat_v );
|
||||
#endif
|
||||
progress = update_progress( progress, idx, max_idx, 0 );
|
||||
}
|
||||
|
||||
sum_error /= count;
|
||||
ts.printf(cvtest::TS::LOG, "Average error is %f\n", sum_error);
|
||||
}
|
||||
|
||||
double calcErrorMinError(const Size& cornSz, const vector<Point2f>& corners_found, const vector<Point2f>& corners_generated)
|
||||
{
|
||||
Mat m1(cornSz, CV_32FC2, (Point2f*)&corners_generated[0]);
|
||||
Mat m2; flip(m1, m2, 0);
|
||||
|
||||
Mat m3; flip(m1, m3, 1); m3 = m3.t(); flip(m3, m3, 1);
|
||||
|
||||
Mat m4 = m1.t(); flip(m4, m4, 1);
|
||||
|
||||
double min1 = min(calcError(corners_found, m1), calcError(corners_found, m2));
|
||||
double min2 = min(calcError(corners_found, m3), calcError(corners_found, m4));
|
||||
return min(min1, min2);
|
||||
}
|
||||
|
||||
bool validateData(const ChessBoardGenerator& cbg, const Size& imgSz,
|
||||
const vector<Point2f>& corners_generated)
|
||||
{
|
||||
Size cornersSize = cbg.cornersSize();
|
||||
Mat_<Point2f> mat(cornersSize.height, cornersSize.width, (Point2f*)&corners_generated[0]);
|
||||
|
||||
double minNeibDist = std::numeric_limits<double>::max();
|
||||
double tmp = 0;
|
||||
for(int i = 1; i < mat.rows - 2; ++i)
|
||||
for(int j = 1; j < mat.cols - 2; ++j)
|
||||
{
|
||||
const Point2f& cur = mat(i, j);
|
||||
|
||||
tmp = norm( cur - mat(i + 1, j + 1) );
|
||||
if (tmp < minNeibDist)
|
||||
tmp = minNeibDist;
|
||||
|
||||
tmp = norm( cur - mat(i - 1, j + 1 ) );
|
||||
if (tmp < minNeibDist)
|
||||
tmp = minNeibDist;
|
||||
|
||||
tmp = norm( cur - mat(i + 1, j - 1) );
|
||||
if (tmp < minNeibDist)
|
||||
tmp = minNeibDist;
|
||||
|
||||
tmp = norm( cur - mat(i - 1, j - 1) );
|
||||
if (tmp < minNeibDist)
|
||||
tmp = minNeibDist;
|
||||
}
|
||||
|
||||
const double threshold = 0.25;
|
||||
double cbsize = (max(cornersSize.width, cornersSize.height) + 1) * minNeibDist;
|
||||
int imgsize = min(imgSz.height, imgSz.width);
|
||||
return imgsize * threshold < cbsize;
|
||||
}
|
||||
|
||||
bool CV_ChessboardDetectorTest::checkByGenerator()
|
||||
{
|
||||
bool res = true;
|
||||
//theRNG() = 0x58e6e895b9913160;
|
||||
//cv::DefaultRngAuto dra;
|
||||
//theRNG() = *ts->get_rng();
|
||||
|
||||
Mat bg(Size(800, 600), CV_8UC3, Scalar::all(255));
|
||||
randu(bg, Scalar::all(0), Scalar::all(255));
|
||||
GaussianBlur(bg, bg, Size(7,7), 3.0);
|
||||
|
||||
Mat_<float> camMat(3, 3);
|
||||
camMat << 300.f, 0.f, bg.cols/2.f, 0, 300.f, bg.rows/2.f, 0.f, 0.f, 1.f;
|
||||
|
||||
Mat_<float> distCoeffs(1, 5);
|
||||
distCoeffs << 1.2f, 0.2f, 0.f, 0.f, 0.f;
|
||||
|
||||
const Size sizes[] = { Size(6, 6), Size(8, 6), Size(11, 12), Size(5, 4) };
|
||||
const size_t sizes_num = sizeof(sizes)/sizeof(sizes[0]);
|
||||
const int test_num = 16;
|
||||
int progress = 0;
|
||||
for(int i = 0; i < test_num; ++i)
|
||||
{
|
||||
progress = update_progress( progress, i, test_num, 0 );
|
||||
ChessBoardGenerator cbg(sizes[i % sizes_num]);
|
||||
|
||||
vector<Point2f> corners_generated;
|
||||
|
||||
Mat cb = cbg(bg, camMat, distCoeffs, corners_generated);
|
||||
|
||||
if(!validateData(cbg, cb.size(), corners_generated))
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Chess board skipped - too small" );
|
||||
continue;
|
||||
}
|
||||
|
||||
/*cb = cb * 0.8 + Scalar::all(30);
|
||||
GaussianBlur(cb, cb, Size(3, 3), 0.8); */
|
||||
//cv::addWeighted(cb, 0.8, bg, 0.2, 20, cb);
|
||||
//cv::namedWindow("CB"); cv::imshow("CB", cb); cv::waitKey();
|
||||
|
||||
vector<Point2f> corners_found;
|
||||
int flags = i % 8; // need to check branches for all flags
|
||||
bool found = findChessboardCorners(cb, cbg.cornersSize(), corners_found, flags);
|
||||
if (!found)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Chess board corners not found\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
res = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
double err = calcErrorMinError(cbg.cornersSize(), corners_found, corners_generated);
|
||||
if( err > rough_success_error_level )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of corner guesses" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
res = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* ***** negative ***** */
|
||||
{
|
||||
vector<Point2f> corners_found;
|
||||
bool found = findChessboardCorners(bg, Size(8, 7), corners_found);
|
||||
if (found)
|
||||
res = false;
|
||||
|
||||
ChessBoardGenerator cbg(Size(8, 7));
|
||||
|
||||
vector<Point2f> cg;
|
||||
Mat cb = cbg(bg, camMat, distCoeffs, cg);
|
||||
|
||||
found = findChessboardCorners(cb, Size(3, 4), corners_found);
|
||||
if (found)
|
||||
res = false;
|
||||
|
||||
Point2f c = std::accumulate(cg.begin(), cg.end(), Point2f(), plus<Point2f>()) * (1.f/cg.size());
|
||||
|
||||
Mat_<double> aff(2, 3);
|
||||
aff << 1.0, 0.0, -(double)c.x, 0.0, 1.0, 0.0;
|
||||
Mat sh;
|
||||
warpAffine(cb, sh, aff, cb.size());
|
||||
|
||||
found = findChessboardCorners(sh, cbg.cornersSize(), corners_found);
|
||||
if (found)
|
||||
res = false;
|
||||
|
||||
vector< vector<Point> > cnts(1);
|
||||
vector<Point>& cnt = cnts[0];
|
||||
cnt.push_back(cg[ 0]); cnt.push_back(cg[0+2]);
|
||||
cnt.push_back(cg[7+0]); cnt.push_back(cg[7+2]);
|
||||
cv::drawContours(cb, cnts, -1, Scalar::all(128), CV_FILLED);
|
||||
|
||||
found = findChessboardCorners(cb, cbg.cornersSize(), corners_found);
|
||||
if (found)
|
||||
res = false;
|
||||
|
||||
cv::drawChessboardCorners(cb, cbg.cornersSize(), Mat(corners_found), found);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(Calib3d_ChessboardDetector, accuracy) { CV_ChessboardDetectorTest test( CHESSBOARD ); test.safe_run(); }
|
||||
TEST(Calib3d_CirclesPatternDetector, accuracy) { CV_ChessboardDetectorTest test( CIRCLES_GRID ); test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
145
modules/calib3d/test/test_chesscorners_badarg.cpp
Normal file
145
modules/calib3d/test/test_chesscorners_badarg.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class CV_ChessboardDetectorBadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_ChessboardDetectorBadArgTest();
|
||||
protected:
|
||||
void run(int);
|
||||
bool checkByGenerator();
|
||||
|
||||
bool cpp;
|
||||
|
||||
/* cpp interface */
|
||||
Mat img;
|
||||
Size pattern_size;
|
||||
int flags;
|
||||
vector<Point2f> corners;
|
||||
|
||||
/* c interface */
|
||||
CvMat arr;
|
||||
CvPoint2D32f* out_corners;
|
||||
int* out_corner_count;
|
||||
|
||||
|
||||
/* c interface draw corners */
|
||||
bool drawCorners;
|
||||
CvMat drawCorImg;
|
||||
bool was_found;
|
||||
|
||||
void run_func()
|
||||
{
|
||||
if (cpp)
|
||||
findChessboardCorners(img, pattern_size, corners, flags);
|
||||
else
|
||||
if (!drawCorners)
|
||||
cvFindChessboardCorners( &arr, pattern_size, out_corners, out_corner_count, flags );
|
||||
else
|
||||
cvDrawChessboardCorners( &drawCorImg, pattern_size,
|
||||
(CvPoint2D32f*)&corners[0], (int)corners.size(), was_found);
|
||||
}
|
||||
};
|
||||
|
||||
CV_ChessboardDetectorBadArgTest::CV_ChessboardDetectorBadArgTest() {}
|
||||
|
||||
/* ///////////////////// chess_corner_test ///////////////////////// */
|
||||
void CV_ChessboardDetectorBadArgTest::run( int /*start_from */)
|
||||
{
|
||||
Mat bg(800, 600, CV_8U, Scalar(0));
|
||||
Mat_<float> camMat(3, 3);
|
||||
camMat << 300.f, 0.f, bg.cols/2.f, 0, 300.f, bg.rows/2.f, 0.f, 0.f, 1.f;
|
||||
Mat_<float> distCoeffs(1, 5);
|
||||
distCoeffs << 1.2f, 0.2f, 0.f, 0.f, 0.f;
|
||||
|
||||
ChessBoardGenerator cbg(Size(8,6));
|
||||
vector<Point2f> exp_corn;
|
||||
Mat cb = cbg(bg, camMat, distCoeffs, exp_corn);
|
||||
|
||||
/* /*//*/ */
|
||||
int errors = 0;
|
||||
flags = CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE;
|
||||
cpp = true;
|
||||
|
||||
img = cb.clone();
|
||||
pattern_size = Size(2,2);
|
||||
errors += run_test_case( CV_StsOutOfRange, "Invlid pattern size" );
|
||||
|
||||
pattern_size = cbg.cornersSize();
|
||||
cb.convertTo(img, CV_32F);
|
||||
errors += run_test_case( CV_StsUnsupportedFormat, "Not 8-bit image" );
|
||||
|
||||
cv::merge(vector<Mat>(2, cb), img);
|
||||
errors += run_test_case( CV_StsUnsupportedFormat, "2 channel image" );
|
||||
|
||||
cpp = false;
|
||||
drawCorners = false;
|
||||
|
||||
img = cb.clone();
|
||||
arr = img;
|
||||
out_corner_count = 0;
|
||||
out_corners = 0;
|
||||
errors += run_test_case( CV_StsNullPtr, "Null pointer to corners" );
|
||||
|
||||
drawCorners = true;
|
||||
Mat cvdrawCornImg(img.size(), CV_8UC2);
|
||||
drawCorImg = cvdrawCornImg;
|
||||
was_found = true;
|
||||
errors += run_test_case( CV_StsUnsupportedFormat, "2 channel image" );
|
||||
|
||||
|
||||
if (errors)
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
else
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Calib3d_ChessboardDetector, badarg) { CV_ChessboardDetectorBadArgTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
189
modules/calib3d/test/test_chesscorners_timing.cpp
Normal file
189
modules/calib3d/test/test_chesscorners_timing.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
class CV_ChessboardDetectorTimingTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ChessboardDetectorTimingTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
CV_ChessboardDetectorTimingTest::CV_ChessboardDetectorTimingTest()
|
||||
{
|
||||
}
|
||||
|
||||
/* ///////////////////// chess_corner_test ///////////////////////// */
|
||||
void CV_ChessboardDetectorTimingTest::run( int start_from )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
/* test parameters */
|
||||
char filepath[1000];
|
||||
char filename[1000];
|
||||
|
||||
CvMat* _v = 0;
|
||||
CvPoint2D32f* v;
|
||||
|
||||
IplImage* img = 0;
|
||||
IplImage* gray = 0;
|
||||
IplImage* thresh = 0;
|
||||
|
||||
int idx, max_idx;
|
||||
int progress = 0;
|
||||
|
||||
sprintf( filepath, "%scameracalibration/", ts->get_data_path().c_str() );
|
||||
sprintf( filename, "%schessboard_timing_list.dat", filepath );
|
||||
printf("Reading file %s\n", filename);
|
||||
CvFileStorage* fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ );
|
||||
CvFileNode* board_list = fs ? cvGetFileNodeByName( fs, 0, "boards" ) : 0;
|
||||
|
||||
if( !fs || !board_list || !CV_NODE_IS_SEQ(board_list->tag) ||
|
||||
board_list->data.seq->total % 4 != 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "chessboard_timing_list.dat can not be readed or is not valid" );
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
max_idx = board_list->data.seq->total/4;
|
||||
|
||||
for( idx = start_from; idx < max_idx; idx++ )
|
||||
{
|
||||
int count0 = -1;
|
||||
int count = 0;
|
||||
CvSize pattern_size;
|
||||
int result, result1 = 0;
|
||||
|
||||
const char* imgname = cvReadString((CvFileNode*)cvGetSeqElem(board_list->data.seq,idx*4), "dummy.txt");
|
||||
int is_chessboard = cvReadInt((CvFileNode*)cvGetSeqElem(board_list->data.seq,idx*4+1), 0);
|
||||
pattern_size.width = cvReadInt((CvFileNode*)cvGetSeqElem(board_list->data.seq,idx*4 + 2), -1);
|
||||
pattern_size.height = cvReadInt((CvFileNode*)cvGetSeqElem(board_list->data.seq,idx*4 + 3), -1);
|
||||
|
||||
ts->update_context( this, idx-1, true );
|
||||
|
||||
/* read the image */
|
||||
sprintf( filename, "%s%s", filepath, imgname );
|
||||
|
||||
img = cvLoadImage( filename );
|
||||
|
||||
if( !img )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "one of chessboard images can't be read: %s\n", filename );
|
||||
if( max_idx == 1 )
|
||||
{
|
||||
code = cvtest::TS::FAIL_MISSING_TEST_DATA;
|
||||
goto _exit_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ts->printf(cvtest::TS::LOG, "%s: chessboard %d:\n", imgname, is_chessboard);
|
||||
|
||||
gray = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 );
|
||||
thresh = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 );
|
||||
cvCvtColor( img, gray, CV_BGR2GRAY );
|
||||
|
||||
|
||||
count0 = pattern_size.width*pattern_size.height;
|
||||
|
||||
/* allocate additional buffers */
|
||||
_v = cvCreateMat(1, count0, CV_32FC2);
|
||||
count = count0;
|
||||
|
||||
v = (CvPoint2D32f*)_v->data.fl;
|
||||
|
||||
int64 _time0 = cvGetTickCount();
|
||||
result = cvCheckChessboard(gray, pattern_size);
|
||||
int64 _time01 = cvGetTickCount();
|
||||
|
||||
OPENCV_CALL( result1 = cvFindChessboardCorners(
|
||||
gray, pattern_size, v, &count, 15 ));
|
||||
int64 _time1 = cvGetTickCount();
|
||||
|
||||
if( result != is_chessboard )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Error: chessboard was %sdetected in the image %s\n",
|
||||
result ? "" : "not ", imgname );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
if(result != result1)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Warning: results differ cvCheckChessboard %d, cvFindChessboardCorners %d\n",
|
||||
result, result1);
|
||||
}
|
||||
|
||||
int num_pixels = gray->width*gray->height;
|
||||
float check_chessboard_time = float(_time01 - _time0)/(float)cvGetTickFrequency(); // in us
|
||||
ts->printf(cvtest::TS::LOG, " cvCheckChessboard time s: %f, us per pixel: %f\n",
|
||||
check_chessboard_time*1e-6, check_chessboard_time/num_pixels);
|
||||
|
||||
float find_chessboard_time = float(_time1 - _time01)/(float)cvGetTickFrequency();
|
||||
ts->printf(cvtest::TS::LOG, " cvFindChessboard time s: %f, us per pixel: %f\n",
|
||||
find_chessboard_time*1e-6, find_chessboard_time/num_pixels);
|
||||
|
||||
cvReleaseMat( &_v );
|
||||
cvReleaseImage( &img );
|
||||
cvReleaseImage( &gray );
|
||||
cvReleaseImage( &thresh );
|
||||
progress = update_progress( progress, idx-1, max_idx, 0 );
|
||||
}
|
||||
|
||||
_exit_:
|
||||
|
||||
/* release occupied memory */
|
||||
cvReleaseMat( &_v );
|
||||
cvReleaseFileStorage( &fs );
|
||||
cvReleaseImage( &img );
|
||||
cvReleaseImage( &gray );
|
||||
cvReleaseImage( &thresh );
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(Calib3d_ChessboardDetector, timing) { CV_ChessboardDetectorTimingTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
216
modules/calib3d/test/test_compose_rt.cpp
Normal file
216
modules/calib3d/test/test_compose_rt.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class Differential
|
||||
{
|
||||
public:
|
||||
typedef Mat_<double> mat_t;
|
||||
|
||||
Differential(double eps_, const mat_t& rv1_, const mat_t& tv1_, const mat_t& rv2_, const mat_t& tv2_)
|
||||
: rv1(rv1_), tv1(tv1_), rv2(rv2_), tv2(tv2_), eps(eps_), ev(3, 1) {}
|
||||
|
||||
void dRv1(mat_t& dr3_dr1, mat_t& dt3_dr1)
|
||||
{
|
||||
dr3_dr1.create(3, 3); dt3_dr1.create(3, 3);
|
||||
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
ev.setTo(Scalar(0)); ev(i, 0) = eps;
|
||||
|
||||
composeRT( rv1 + ev, tv1, rv2, tv2, rv3_p, tv3_p);
|
||||
composeRT( rv1 - ev, tv1, rv2, tv2, rv3_m, tv3_m);
|
||||
|
||||
dr3_dr1.col(i) = rv3_p - rv3_m;
|
||||
dt3_dr1.col(i) = tv3_p - tv3_m;
|
||||
}
|
||||
dr3_dr1 /= 2 * eps; dt3_dr1 /= 2 * eps;
|
||||
}
|
||||
|
||||
void dRv2(mat_t& dr3_dr2, mat_t& dt3_dr2)
|
||||
{
|
||||
dr3_dr2.create(3, 3); dt3_dr2.create(3, 3);
|
||||
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
ev.setTo(Scalar(0)); ev(i, 0) = eps;
|
||||
|
||||
composeRT( rv1, tv1, rv2 + ev, tv2, rv3_p, tv3_p);
|
||||
composeRT( rv1, tv1, rv2 - ev, tv2, rv3_m, tv3_m);
|
||||
|
||||
dr3_dr2.col(i) = rv3_p - rv3_m;
|
||||
dt3_dr2.col(i) = tv3_p - tv3_m;
|
||||
}
|
||||
dr3_dr2 /= 2 * eps; dt3_dr2 /= 2 * eps;
|
||||
}
|
||||
|
||||
void dTv1(mat_t& drt3_dt1, mat_t& dt3_dt1)
|
||||
{
|
||||
drt3_dt1.create(3, 3); dt3_dt1.create(3, 3);
|
||||
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
ev.setTo(Scalar(0)); ev(i, 0) = eps;
|
||||
|
||||
composeRT( rv1, tv1 + ev, rv2, tv2, rv3_p, tv3_p);
|
||||
composeRT( rv1, tv1 - ev, rv2, tv2, rv3_m, tv3_m);
|
||||
|
||||
drt3_dt1.col(i) = rv3_p - rv3_m;
|
||||
dt3_dt1.col(i) = tv3_p - tv3_m;
|
||||
}
|
||||
drt3_dt1 /= 2 * eps; dt3_dt1 /= 2 * eps;
|
||||
}
|
||||
|
||||
void dTv2(mat_t& dr3_dt2, mat_t& dt3_dt2)
|
||||
{
|
||||
dr3_dt2.create(3, 3); dt3_dt2.create(3, 3);
|
||||
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
ev.setTo(Scalar(0)); ev(i, 0) = eps;
|
||||
|
||||
composeRT( rv1, tv1, rv2, tv2 + ev, rv3_p, tv3_p);
|
||||
composeRT( rv1, tv1, rv2, tv2 - ev, rv3_m, tv3_m);
|
||||
|
||||
dr3_dt2.col(i) = rv3_p - rv3_m;
|
||||
dt3_dt2.col(i) = tv3_p - tv3_m;
|
||||
}
|
||||
dr3_dt2 /= 2 * eps; dt3_dt2 /= 2 * eps;
|
||||
}
|
||||
|
||||
private:
|
||||
const mat_t& rv1, tv1, rv2, tv2;
|
||||
double eps;
|
||||
Mat_<double> ev;
|
||||
|
||||
Differential& operator=(const Differential&);
|
||||
Mat rv3_m, tv3_m, rv3_p, tv3_p;
|
||||
};
|
||||
|
||||
class CV_composeRT_Test : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_composeRT_Test() {}
|
||||
~CV_composeRT_Test() {}
|
||||
protected:
|
||||
|
||||
void run(int)
|
||||
{
|
||||
cvtest::TS& ts = *this->ts;
|
||||
ts.set_failed_test_info(cvtest::TS::OK);
|
||||
|
||||
Mat_<double> rvec1(3, 1), tvec1(3, 1), rvec2(3, 1), tvec2(3, 1);
|
||||
|
||||
randu(rvec1, Scalar(0), Scalar(6.29));
|
||||
randu(rvec2, Scalar(0), Scalar(6.29));
|
||||
|
||||
randu(tvec1, Scalar(-2), Scalar(2));
|
||||
randu(tvec2, Scalar(-2), Scalar(2));
|
||||
|
||||
Mat rvec3, tvec3;
|
||||
composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3);
|
||||
|
||||
Mat rvec3_exp, tvec3_exp;
|
||||
|
||||
Mat rmat1, rmat2;
|
||||
Rodrigues(rvec1, rmat1);
|
||||
Rodrigues(rvec2, rmat2);
|
||||
Rodrigues(rmat2 * rmat1, rvec3_exp);
|
||||
|
||||
tvec3_exp = rmat2 * tvec1 + tvec2;
|
||||
|
||||
const double thres = 1e-5;
|
||||
if (norm(rvec3_exp, rvec3) > thres || norm(tvec3_exp, tvec3) > thres)
|
||||
ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
|
||||
const double eps = 1e-3;
|
||||
Differential diff(eps, rvec1, tvec1, rvec2, tvec2);
|
||||
|
||||
Mat dr3dr1, dr3dt1, dr3dr2, dr3dt2, dt3dr1, dt3dt1, dt3dr2, dt3dt2;
|
||||
|
||||
composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3,
|
||||
dr3dr1, dr3dt1, dr3dr2, dr3dt2, dt3dr1, dt3dt1, dt3dr2, dt3dt2);
|
||||
|
||||
Mat_<double> dr3_dr1, dt3_dr1;
|
||||
diff.dRv1(dr3_dr1, dt3_dr1);
|
||||
|
||||
if (norm(dr3_dr1, dr3dr1) > thres || norm(dt3_dr1, dt3dr1) > thres)
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "Invalid derivates by r1\n" );
|
||||
ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
|
||||
Mat_<double> dr3_dr2, dt3_dr2;
|
||||
diff.dRv2(dr3_dr2, dt3_dr2);
|
||||
|
||||
if (norm(dr3_dr2, dr3dr2) > thres || norm(dt3_dr2, dt3dr2) > thres)
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "Invalid derivates by r2\n" );
|
||||
ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
|
||||
Mat_<double> dr3_dt1, dt3_dt1;
|
||||
diff.dTv1(dr3_dt1, dt3_dt1);
|
||||
|
||||
if (norm(dr3_dt1, dr3dt1) > thres || norm(dt3_dt1, dt3dt1) > thres)
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "Invalid derivates by t1\n" );
|
||||
ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
|
||||
Mat_<double> dr3_dt2, dt3_dt2;
|
||||
diff.dTv2(dr3_dt2, dt3_dt2);
|
||||
|
||||
if (norm(dr3_dt2, dr3dt2) > thres || norm(dt3_dt2, dt3dt2) > thres)
|
||||
{
|
||||
ts.printf( cvtest::TS::LOG, "Invalid derivates by t2\n" );
|
||||
ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Calib3d_ComposeRT, accuracy) { CV_composeRT_Test test; test.safe_run(); }
|
||||
|
242
modules/calib3d/test/test_cornerssubpix.cpp
Normal file
242
modules/calib3d/test/test_cornerssubpix.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
#include <limits>
|
||||
#include "test_chessboardgenerator.hpp"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class CV_ChessboardSubpixelTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ChessboardSubpixelTest();
|
||||
|
||||
protected:
|
||||
Mat intrinsic_matrix_;
|
||||
Mat distortion_coeffs_;
|
||||
Size image_size_;
|
||||
|
||||
void run(int);
|
||||
void generateIntrinsicParams();
|
||||
};
|
||||
|
||||
|
||||
int calcDistance(const vector<Point2f>& set1, const vector<Point2f>& set2, double& mean_dist)
|
||||
{
|
||||
if(set1.size() != set2.size())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<int> indices;
|
||||
double sum_dist = 0.0;
|
||||
for(size_t i = 0; i < set1.size(); i++)
|
||||
{
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
int min_idx = -1;
|
||||
|
||||
for(int j = 0; j < (int)set2.size(); j++)
|
||||
{
|
||||
double dist = norm(set1[i] - set2[j]);
|
||||
if(dist < min_dist)
|
||||
{
|
||||
min_idx = j;
|
||||
min_dist = dist;
|
||||
}
|
||||
}
|
||||
|
||||
// check validity of min_idx
|
||||
if(min_idx == -1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
std::vector<int>::iterator it = std::find(indices.begin(), indices.end(), min_idx);
|
||||
if(it != indices.end())
|
||||
{
|
||||
// there are two points in set1 corresponding to the same point in set2
|
||||
return 0;
|
||||
}
|
||||
indices.push_back(min_idx);
|
||||
|
||||
// printf("dist %d = %f\n", (int)i, min_dist);
|
||||
|
||||
sum_dist += min_dist*min_dist;
|
||||
}
|
||||
|
||||
mean_dist = sqrt(sum_dist/set1.size());
|
||||
// printf("sum_dist = %f, set1.size() = %d, mean_dist = %f\n", sum_dist, (int)set1.size(), mean_dist);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CV_ChessboardSubpixelTest::CV_ChessboardSubpixelTest() :
|
||||
intrinsic_matrix_(Size(3, 3), CV_64FC1), distortion_coeffs_(Size(1, 4), CV_64FC1),
|
||||
image_size_(640, 480)
|
||||
{
|
||||
}
|
||||
|
||||
/* ///////////////////// chess_corner_test ///////////////////////// */
|
||||
void CV_ChessboardSubpixelTest::run( int )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
int progress = 0;
|
||||
|
||||
RNG& rng = ts->get_rng();
|
||||
|
||||
const int runs_count = 20;
|
||||
const int max_pattern_size = 8;
|
||||
const int min_pattern_size = 5;
|
||||
Mat bg(image_size_, CV_8UC1);
|
||||
bg = Scalar(0);
|
||||
|
||||
double sum_dist = 0.0;
|
||||
int count = 0;
|
||||
for(int i = 0; i < runs_count; i++)
|
||||
{
|
||||
const int pattern_width = min_pattern_size + cvtest::randInt(rng) % (max_pattern_size - min_pattern_size);
|
||||
const int pattern_height = min_pattern_size + cvtest::randInt(rng) % (max_pattern_size - min_pattern_size);
|
||||
Size pattern_size;
|
||||
if(pattern_width > pattern_height)
|
||||
{
|
||||
pattern_size = Size(pattern_height, pattern_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern_size = Size(pattern_width, pattern_height);
|
||||
}
|
||||
ChessBoardGenerator gen_chessboard(Size(pattern_size.width + 1, pattern_size.height + 1));
|
||||
|
||||
// generates intrinsic camera and distortion matrices
|
||||
generateIntrinsicParams();
|
||||
|
||||
vector<Point2f> corners;
|
||||
Mat chessboard_image = gen_chessboard(bg, intrinsic_matrix_, distortion_coeffs_, corners);
|
||||
|
||||
vector<Point2f> test_corners;
|
||||
bool result = findChessboardCorners(chessboard_image, pattern_size, test_corners, 15);
|
||||
if(!result)
|
||||
{
|
||||
#if 0
|
||||
ts->printf(cvtest::TS::LOG, "Warning: chessboard was not detected! Writing image to test.jpg\n");
|
||||
ts->printf(cvtest::TS::LOG, "Size = %d, %d\n", pattern_size.width, pattern_size.height);
|
||||
ts->printf(cvtest::TS::LOG, "Intrinsic params: fx = %f, fy = %f, cx = %f, cy = %f\n",
|
||||
intrinsic_matrix_.at<double>(0, 0), intrinsic_matrix_.at<double>(1, 1),
|
||||
intrinsic_matrix_.at<double>(0, 2), intrinsic_matrix_.at<double>(1, 2));
|
||||
ts->printf(cvtest::TS::LOG, "Distortion matrix: %f, %f, %f, %f, %f\n",
|
||||
distortion_coeffs_.at<double>(0, 0), distortion_coeffs_.at<double>(0, 1),
|
||||
distortion_coeffs_.at<double>(0, 2), distortion_coeffs_.at<double>(0, 3),
|
||||
distortion_coeffs_.at<double>(0, 4));
|
||||
|
||||
imwrite("test.jpg", chessboard_image);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
double dist1 = 0.0;
|
||||
int ret = calcDistance(corners, test_corners, dist1);
|
||||
if(ret == 0)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "findChessboardCorners returns invalid corner coordinates!\n");
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
break;
|
||||
}
|
||||
|
||||
IplImage chessboard_image_header = chessboard_image;
|
||||
cvFindCornerSubPix(&chessboard_image_header, (CvPoint2D32f*)&test_corners[0],
|
||||
(int)test_corners.size(), cvSize(3, 3), cvSize(1, 1), cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,300,0.1));
|
||||
find4QuadCornerSubpix(chessboard_image, test_corners, Size(5, 5));
|
||||
|
||||
double dist2 = 0.0;
|
||||
ret = calcDistance(corners, test_corners, dist2);
|
||||
if(ret == 0)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "findCornerSubpix returns invalid corner coordinates!\n");
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
break;
|
||||
}
|
||||
|
||||
ts->printf(cvtest::TS::LOG, "Error after findChessboardCorners: %f, after findCornerSubPix: %f\n",
|
||||
dist1, dist2);
|
||||
sum_dist += dist2;
|
||||
count++;
|
||||
|
||||
const double max_reduce_factor = 0.8;
|
||||
if(dist1 < dist2*max_reduce_factor)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "findCornerSubPix increases average error!\n");
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
break;
|
||||
}
|
||||
|
||||
progress = update_progress( progress, i-1, runs_count, 0 );
|
||||
}
|
||||
sum_dist /= count;
|
||||
ts->printf(cvtest::TS::LOG, "Average error after findCornerSubpix: %f\n", sum_dist);
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
void CV_ChessboardSubpixelTest::generateIntrinsicParams()
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
const double max_focus_length = 1000.0;
|
||||
const double max_focus_diff = 5.0;
|
||||
|
||||
double fx = cvtest::randReal(rng)*max_focus_length;
|
||||
double fy = fx + cvtest::randReal(rng)*max_focus_diff;
|
||||
double cx = image_size_.width/2;
|
||||
double cy = image_size_.height/2;
|
||||
|
||||
double k1 = 0.5*cvtest::randReal(rng);
|
||||
double k2 = 0.05*cvtest::randReal(rng);
|
||||
double p1 = 0.05*cvtest::randReal(rng);
|
||||
double p2 = 0.05*cvtest::randReal(rng);
|
||||
double k3 = 0.0;
|
||||
|
||||
intrinsic_matrix_ = (Mat_<double>(3, 3) << fx, 0.0, cx, 0.0, fy, cy, 0.0, 0.0, 1.0);
|
||||
distortion_coeffs_ = (Mat_<double>(1, 5) << k1, k2, p1, p2, k3);
|
||||
}
|
||||
|
||||
TEST(Calib3d_ChessboardSubPixDetector, accuracy) { CV_ChessboardSubpixelTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
1363
modules/calib3d/test/test_fundam.cpp
Normal file
1363
modules/calib3d/test/test_fundam.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3
modules/calib3d/test/test_main.cpp
Normal file
3
modules/calib3d/test/test_main.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
221
modules/calib3d/test/test_posit.cpp
Normal file
221
modules/calib3d/test/test_posit.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_POSITTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_POSITTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
CV_POSITTest::CV_POSITTest()
|
||||
{
|
||||
test_case_count = 20;
|
||||
}
|
||||
|
||||
void CV_POSITTest::run( int start_from )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
/* fixed parameters output */
|
||||
/*float rot[3][3]={ 0.49010f, 0.85057f, 0.19063f,
|
||||
-0.56948f, 0.14671f, 0.80880f,
|
||||
0.65997f, -0.50495f, 0.55629f };
|
||||
|
||||
float trans[3] = { 0.0f, 0.0f, 40.02637f };
|
||||
*/
|
||||
|
||||
/* Some variables */
|
||||
int i, counter;
|
||||
|
||||
CvTermCriteria criteria;
|
||||
CvPoint3D32f* obj_points;
|
||||
CvPoint2D32f* img_points;
|
||||
CvPOSITObject* object;
|
||||
|
||||
float angleX, angleY, angleZ;
|
||||
RNG& rng = ts->get_rng();
|
||||
int progress = 0;
|
||||
|
||||
CvMat* true_rotationX = cvCreateMat( 3, 3, CV_32F );
|
||||
CvMat* true_rotationY = cvCreateMat( 3, 3, CV_32F );
|
||||
CvMat* true_rotationZ = cvCreateMat( 3, 3, CV_32F );
|
||||
CvMat* tmp_matrix = cvCreateMat( 3, 3, CV_32F );
|
||||
CvMat* true_rotation = cvCreateMat( 3, 3, CV_32F );
|
||||
CvMat* rotation = cvCreateMat( 3, 3, CV_32F );
|
||||
CvMat* translation = cvCreateMat( 3, 1, CV_32F );
|
||||
CvMat* true_translation = cvCreateMat( 3, 1, CV_32F );
|
||||
|
||||
const float flFocalLength = 760.f;
|
||||
const float flEpsilon = 0.5f;
|
||||
|
||||
/* Initilization */
|
||||
criteria.type = CV_TERMCRIT_EPS|CV_TERMCRIT_ITER;
|
||||
criteria.epsilon = flEpsilon;
|
||||
criteria.max_iter = 10000;
|
||||
|
||||
/* Allocating source arrays; */
|
||||
obj_points = (CvPoint3D32f*)cvAlloc( 8 * sizeof(CvPoint3D32f) );
|
||||
img_points = (CvPoint2D32f*)cvAlloc( 8 * sizeof(CvPoint2D32f) );
|
||||
|
||||
/* Fill points arrays with values */
|
||||
|
||||
/* cube model with edge size 10 */
|
||||
obj_points[0].x = 0; obj_points[0].y = 0; obj_points[0].z = 0;
|
||||
obj_points[1].x = 10; obj_points[1].y = 0; obj_points[1].z = 0;
|
||||
obj_points[2].x = 10; obj_points[2].y = 10; obj_points[2].z = 0;
|
||||
obj_points[3].x = 0; obj_points[3].y = 10; obj_points[3].z = 0;
|
||||
obj_points[4].x = 0; obj_points[4].y = 0; obj_points[4].z = 10;
|
||||
obj_points[5].x = 10; obj_points[5].y = 0; obj_points[5].z = 10;
|
||||
obj_points[6].x = 10; obj_points[6].y = 10; obj_points[6].z = 10;
|
||||
obj_points[7].x = 0; obj_points[7].y = 10; obj_points[7].z = 10;
|
||||
|
||||
/* Loop for test some random object positions */
|
||||
for( counter = start_from; counter < test_case_count; counter++ )
|
||||
{
|
||||
ts->update_context( this, counter, true );
|
||||
progress = update_progress( progress, counter, test_case_count, 0 );
|
||||
|
||||
/* set all rotation matrix to zero */
|
||||
cvZero( true_rotationX );
|
||||
cvZero( true_rotationY );
|
||||
cvZero( true_rotationZ );
|
||||
|
||||
/* fill random rotation matrix */
|
||||
angleX = (float)(cvtest::randReal(rng)*2*CV_PI);
|
||||
angleY = (float)(cvtest::randReal(rng)*2*CV_PI);
|
||||
angleZ = (float)(cvtest::randReal(rng)*2*CV_PI);
|
||||
|
||||
true_rotationX->data.fl[0 *3+ 0] = 1;
|
||||
true_rotationX->data.fl[1 *3+ 1] = (float)cos(angleX);
|
||||
true_rotationX->data.fl[2 *3+ 2] = true_rotationX->data.fl[1 *3+ 1];
|
||||
true_rotationX->data.fl[1 *3+ 2] = -(float)sin(angleX);
|
||||
true_rotationX->data.fl[2 *3+ 1] = -true_rotationX->data.fl[1 *3+ 2];
|
||||
|
||||
true_rotationY->data.fl[1 *3+ 1] = 1;
|
||||
true_rotationY->data.fl[0 *3+ 0] = (float)cos(angleY);
|
||||
true_rotationY->data.fl[2 *3+ 2] = true_rotationY->data.fl[0 *3+ 0];
|
||||
true_rotationY->data.fl[0 *3+ 2] = -(float)sin(angleY);
|
||||
true_rotationY->data.fl[2 *3+ 0] = -true_rotationY->data.fl[0 *3+ 2];
|
||||
|
||||
true_rotationZ->data.fl[2 *3+ 2] = 1;
|
||||
true_rotationZ->data.fl[0 *3+ 0] = (float)cos(angleZ);
|
||||
true_rotationZ->data.fl[1 *3+ 1] = true_rotationZ->data.fl[0 *3+ 0];
|
||||
true_rotationZ->data.fl[0 *3+ 1] = -(float)sin(angleZ);
|
||||
true_rotationZ->data.fl[1 *3+ 0] = -true_rotationZ->data.fl[0 *3+ 1];
|
||||
|
||||
cvMatMul( true_rotationX, true_rotationY, tmp_matrix);
|
||||
cvMatMul( tmp_matrix, true_rotationZ, true_rotation);
|
||||
|
||||
/* fill translation vector */
|
||||
true_translation->data.fl[2] = (float)(cvtest::randReal(rng)*(2*flFocalLength-40) + 60);
|
||||
true_translation->data.fl[0] = (float)((cvtest::randReal(rng)*2-1)*true_translation->data.fl[2]);
|
||||
true_translation->data.fl[1] = (float)((cvtest::randReal(rng)*2-1)*true_translation->data.fl[2]);
|
||||
|
||||
/* calculate perspective projection */
|
||||
for ( i = 0; i < 8; i++ )
|
||||
{
|
||||
float vec[3];
|
||||
CvMat Vec = cvMat( 3, 1, CV_32F, vec );
|
||||
CvMat Obj_point = cvMat( 3, 1, CV_32F, &obj_points[i].x );
|
||||
|
||||
cvMatMul( true_rotation, &Obj_point, &Vec );
|
||||
|
||||
vec[0] += true_translation->data.fl[0];
|
||||
vec[1] += true_translation->data.fl[1];
|
||||
vec[2] += true_translation->data.fl[2];
|
||||
|
||||
img_points[i].x = flFocalLength * vec[0] / vec[2];
|
||||
img_points[i].y = flFocalLength * vec[1] / vec[2];
|
||||
}
|
||||
|
||||
/*img_points[0].x = 0 ; img_points[0].y = 0;
|
||||
img_points[1].x = 80; img_points[1].y = -93;
|
||||
img_points[2].x = 245;img_points[2].y = -77;
|
||||
img_points[3].x = 185;img_points[3].y = 32;
|
||||
img_points[4].x = 32; img_points[4].y = 135;
|
||||
img_points[5].x = 99; img_points[5].y = 35;
|
||||
img_points[6].x = 247; img_points[6].y = 62;
|
||||
img_points[7].x = 195; img_points[7].y = 179;
|
||||
*/
|
||||
|
||||
object = cvCreatePOSITObject( obj_points, 8 );
|
||||
cvPOSIT( object, img_points, flFocalLength, criteria,
|
||||
rotation->data.fl, translation->data.fl );
|
||||
cvReleasePOSITObject( &object );
|
||||
|
||||
//Mat _rotation = cvarrToMat(rotation), _true_rotation = cvarrToMat(true_rotation);
|
||||
//Mat _translation = cvarrToMat(translation), _true_translation = cvarrToMat(true_translation);
|
||||
code = cvtest::cmpEps2( ts, rotation, true_rotation, flEpsilon, false, "rotation matrix" );
|
||||
if( code < 0 )
|
||||
break;
|
||||
|
||||
code = cvtest::cmpEps2( ts, translation, true_translation, flEpsilon, false, "translation vector" );
|
||||
if( code < 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
cvFree( &obj_points );
|
||||
cvFree( &img_points );
|
||||
|
||||
cvReleaseMat( &true_rotationX );
|
||||
cvReleaseMat( &true_rotationY );
|
||||
cvReleaseMat( &true_rotationZ );
|
||||
cvReleaseMat( &tmp_matrix );
|
||||
cvReleaseMat( &true_rotation );
|
||||
cvReleaseMat( &rotation );
|
||||
cvReleaseMat( &translation );
|
||||
cvReleaseMat( &true_translation );
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(Calib3d_POSIT, accuracy) { CV_POSITTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
1
modules/calib3d/test/test_precomp.cpp
Normal file
1
modules/calib3d/test/test_precomp.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "test_precomp.hpp"
|
17
modules/calib3d/test/test_precomp.hpp
Normal file
17
modules/calib3d/test/test_precomp.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts/ts.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace cvtest
|
||||
{
|
||||
void Rodrigues(const Mat& src, Mat& dst, Mat* jac=0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
175
modules/calib3d/test/test_reproject_image_to_3d.cpp
Normal file
175
modules/calib3d/test/test_reproject_image_to_3d.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
template<class T> double thres() { return 1.0; }
|
||||
template<> double thres<float>() { return 1e-5; }
|
||||
|
||||
class CV_ReprojectImageTo3DTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ReprojectImageTo3DTest() {}
|
||||
~CV_ReprojectImageTo3DTest() {}
|
||||
protected:
|
||||
|
||||
|
||||
void run(int)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
int progress = 0;
|
||||
int caseId = 0;
|
||||
|
||||
progress = update_progress( progress, 1, 14, 0 );
|
||||
runCase<float, float>(++caseId, -100.f, 100.f);
|
||||
progress = update_progress( progress, 2, 14, 0 );
|
||||
runCase<int, float>(++caseId, -100, 100);
|
||||
progress = update_progress( progress, 3, 14, 0 );
|
||||
runCase<short, float>(++caseId, -100, 100);
|
||||
progress = update_progress( progress, 4, 14, 0 );
|
||||
runCase<unsigned char, float>(++caseId, 10, 100);
|
||||
progress = update_progress( progress, 5, 14, 0 );
|
||||
|
||||
runCase<float, int>(++caseId, -100.f, 100.f);
|
||||
progress = update_progress( progress, 6, 14, 0 );
|
||||
runCase<int, int>(++caseId, -100, 100);
|
||||
progress = update_progress( progress, 7, 14, 0 );
|
||||
runCase<short, int>(++caseId, -100, 100);
|
||||
progress = update_progress( progress, 8, 14, 0 );
|
||||
runCase<unsigned char, int>(++caseId, 10, 100);
|
||||
progress = update_progress( progress, 10, 14, 0 );
|
||||
|
||||
runCase<float, short>(++caseId, -100.f, 100.f);
|
||||
progress = update_progress( progress, 11, 14, 0 );
|
||||
runCase<int, short>(++caseId, -100, 100);
|
||||
progress = update_progress( progress, 12, 14, 0 );
|
||||
runCase<short, short>(++caseId, -100, 100);
|
||||
progress = update_progress( progress, 13, 14, 0 );
|
||||
runCase<unsigned char, short>(++caseId, 10, 100);
|
||||
progress = update_progress( progress, 14, 14, 0 );
|
||||
}
|
||||
|
||||
template<class U, class V> double error(const Vec<U, 3>& v1, const Vec<V, 3>& v2) const
|
||||
{
|
||||
double tmp, sum = 0;
|
||||
double nsum = 0;
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
tmp = v1[i];
|
||||
nsum += tmp * tmp;
|
||||
|
||||
tmp = tmp - v2[i];
|
||||
sum += tmp * tmp;
|
||||
|
||||
}
|
||||
return sqrt(sum)/(sqrt(nsum)+1.);
|
||||
}
|
||||
|
||||
template<class InT, class OutT> void runCase(int caseId, InT min, InT max)
|
||||
{
|
||||
typedef Vec<OutT, 3> out3d_t;
|
||||
|
||||
bool handleMissingValues = (unsigned)theRNG() % 2 == 0;
|
||||
|
||||
Mat_<InT> disp(Size(320, 240));
|
||||
randu(disp, Scalar(min), Scalar(max));
|
||||
|
||||
if (handleMissingValues)
|
||||
disp(disp.rows/2, disp.cols/2) = min - 1;
|
||||
|
||||
Mat_<double> Q(4, 4);
|
||||
randu(Q, Scalar(-5), Scalar(5));
|
||||
|
||||
Mat_<out3d_t> _3dImg(disp.size());
|
||||
|
||||
CvMat cvdisp = disp; CvMat cv_3dImg = _3dImg; CvMat cvQ = Q;
|
||||
cvReprojectImageTo3D( &cvdisp, &cv_3dImg, &cvQ, handleMissingValues );
|
||||
|
||||
if (numeric_limits<OutT>::max() == numeric_limits<float>::max())
|
||||
reprojectImageTo3D(disp, _3dImg, Q, handleMissingValues);
|
||||
|
||||
for(int y = 0; y < disp.rows; ++y)
|
||||
for(int x = 0; x < disp.cols; ++x)
|
||||
{
|
||||
InT d = disp(y, x);
|
||||
|
||||
double from[4] = { x, y, d, 1 };
|
||||
Mat_<double> res = Q * Mat_<double>(4, 1, from);
|
||||
res /= res(3, 0);
|
||||
|
||||
out3d_t pixel_exp = *(Vec3d*)res.data;
|
||||
out3d_t pixel_out = _3dImg(y, x);
|
||||
|
||||
const int largeZValue = 10000; /* see documentation */
|
||||
|
||||
if (handleMissingValues && y == disp.rows/2 && x == disp.cols/2)
|
||||
{
|
||||
if (pixel_out[2] == largeZValue)
|
||||
continue;
|
||||
|
||||
ts->printf(cvtest::TS::LOG, "Missing values are handled improperly\n");
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
double err = error(pixel_out, pixel_exp), t = thres<OutT>();
|
||||
if ( err > t )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "case %d. too big error at (%d, %d): %g vs expected %g: res = (%g, %g, %g, w=%g) vs pixel_out = (%g, %g, %g)\n",
|
||||
caseId, x, y, err, t, res(0,0), res(1,0), res(2,0), res(3,0),
|
||||
(double)pixel_out[0], (double)pixel_out[1], (double)pixel_out[2]);
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Calib3d_ReprojectImageTo3D, accuracy) { CV_ReprojectImageTo3DTest test; test.safe_run(); }
|
||||
|
832
modules/calib3d/test/test_stereomatching.cpp
Executable file
832
modules/calib3d/test/test_stereomatching.cpp
Executable file
@ -0,0 +1,832 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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*/
|
||||
|
||||
/*
|
||||
This is a regression test for stereo matching algorithms. This test gets some quality metrics
|
||||
discribed in "A Taxonomy and Evaluation of Dense Two-Frame Stereo Correspondence Algorithms".
|
||||
Daniel Scharstein, Richard Szeliski
|
||||
*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include <limits>
|
||||
#include <cstdio>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
const float EVAL_BAD_THRESH = 1.f;
|
||||
const int EVAL_TEXTURELESS_WIDTH = 3;
|
||||
const float EVAL_TEXTURELESS_THRESH = 4.f;
|
||||
const float EVAL_DISP_THRESH = 1.f;
|
||||
const float EVAL_DISP_GAP = 2.f;
|
||||
const int EVAL_DISCONT_WIDTH = 9;
|
||||
const int EVAL_IGNORE_BORDER = 10;
|
||||
|
||||
const int ERROR_KINDS_COUNT = 6;
|
||||
|
||||
//============================== quality measuring functions =================================================
|
||||
|
||||
/*
|
||||
Calculate textureless regions of image (regions where the squared horizontal intensity gradient averaged over
|
||||
a square window of size=evalTexturelessWidth is below a threshold=evalTexturelessThresh) and textured regions.
|
||||
*/
|
||||
void computeTextureBasedMasks( const Mat& _img, Mat* texturelessMask, Mat* texturedMask,
|
||||
int texturelessWidth = EVAL_TEXTURELESS_WIDTH, float texturelessThresh = EVAL_TEXTURELESS_THRESH )
|
||||
{
|
||||
if( !texturelessMask && !texturedMask )
|
||||
return;
|
||||
if( _img.empty() )
|
||||
CV_Error( CV_StsBadArg, "img is empty" );
|
||||
|
||||
Mat img = _img;
|
||||
if( _img.channels() > 1)
|
||||
{
|
||||
Mat tmp; cvtColor( _img, tmp, CV_BGR2GRAY ); img = tmp;
|
||||
}
|
||||
Mat dxI; Sobel( img, dxI, CV_32FC1, 1, 0, 3 );
|
||||
Mat dxI2; pow( dxI / 8.f/*normalize*/, 2, dxI2 );
|
||||
Mat avgDxI2; boxFilter( dxI2, avgDxI2, CV_32FC1, Size(texturelessWidth,texturelessWidth) );
|
||||
|
||||
if( texturelessMask )
|
||||
*texturelessMask = avgDxI2 < texturelessThresh;
|
||||
if( texturedMask )
|
||||
*texturedMask = avgDxI2 >= texturelessThresh;
|
||||
}
|
||||
|
||||
void checkTypeAndSizeOfDisp( const Mat& dispMap, const Size* sz )
|
||||
{
|
||||
if( dispMap.empty() )
|
||||
CV_Error( CV_StsBadArg, "dispMap is empty" );
|
||||
if( dispMap.type() != CV_32FC1 )
|
||||
CV_Error( CV_StsBadArg, "dispMap must have CV_32FC1 type" );
|
||||
if( sz && (dispMap.rows != sz->height || dispMap.cols != sz->width) )
|
||||
CV_Error( CV_StsBadArg, "dispMap has incorrect size" );
|
||||
}
|
||||
|
||||
void checkTypeAndSizeOfMask( const Mat& mask, Size sz )
|
||||
{
|
||||
if( mask.empty() )
|
||||
CV_Error( CV_StsBadArg, "mask is empty" );
|
||||
if( mask.type() != CV_8UC1 )
|
||||
CV_Error( CV_StsBadArg, "mask must have CV_8UC1 type" );
|
||||
if( mask.rows != sz.height || mask.cols != sz.width )
|
||||
CV_Error( CV_StsBadArg, "mask has incorrect size" );
|
||||
}
|
||||
|
||||
void checkDispMapsAndUnknDispMasks( const Mat& leftDispMap, const Mat& rightDispMap,
|
||||
const Mat& leftUnknDispMask, const Mat& rightUnknDispMask )
|
||||
{
|
||||
// check type and size of disparity maps
|
||||
checkTypeAndSizeOfDisp( leftDispMap, 0 );
|
||||
if( !rightDispMap.empty() )
|
||||
{
|
||||
Size sz = leftDispMap.size();
|
||||
checkTypeAndSizeOfDisp( rightDispMap, &sz );
|
||||
}
|
||||
|
||||
// check size and type of unknown disparity maps
|
||||
if( !leftUnknDispMask.empty() )
|
||||
checkTypeAndSizeOfMask( leftUnknDispMask, leftDispMap.size() );
|
||||
if( !rightUnknDispMask.empty() )
|
||||
checkTypeAndSizeOfMask( rightUnknDispMask, rightDispMap.size() );
|
||||
|
||||
// check values of disparity maps (known disparity values musy be positive)
|
||||
double leftMinVal = 0, rightMinVal = 0;
|
||||
if( leftUnknDispMask.empty() )
|
||||
minMaxLoc( leftDispMap, &leftMinVal );
|
||||
else
|
||||
minMaxLoc( leftDispMap, &leftMinVal, 0, 0, 0, ~leftUnknDispMask );
|
||||
if( !rightDispMap.empty() )
|
||||
{
|
||||
if( rightUnknDispMask.empty() )
|
||||
minMaxLoc( rightDispMap, &rightMinVal );
|
||||
else
|
||||
minMaxLoc( rightDispMap, &rightMinVal, 0, 0, 0, ~rightUnknDispMask );
|
||||
}
|
||||
if( leftMinVal < 0 || rightMinVal < 0)
|
||||
CV_Error( CV_StsBadArg, "known disparity values must be positive" );
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate occluded regions of reference image (left image) (regions that are occluded in the matching image (right image),
|
||||
i.e., where the forward-mapped disparity lands at a location with a larger (nearer) disparity) and non occluded regions.
|
||||
*/
|
||||
void computeOcclusionBasedMasks( const Mat& leftDisp, const Mat& _rightDisp,
|
||||
Mat* occludedMask, Mat* nonOccludedMask,
|
||||
const Mat& leftUnknDispMask = Mat(), const Mat& rightUnknDispMask = Mat(),
|
||||
float dispThresh = EVAL_DISP_THRESH )
|
||||
{
|
||||
if( !occludedMask && !nonOccludedMask )
|
||||
return;
|
||||
checkDispMapsAndUnknDispMasks( leftDisp, _rightDisp, leftUnknDispMask, rightUnknDispMask );
|
||||
|
||||
Mat rightDisp;
|
||||
if( _rightDisp.empty() )
|
||||
{
|
||||
if( !rightUnknDispMask.empty() )
|
||||
CV_Error( CV_StsBadArg, "rightUnknDispMask must be empty if _rightDisp is empty" );
|
||||
rightDisp.create(leftDisp.size(), CV_32FC1);
|
||||
rightDisp.setTo(Scalar::all(0) );
|
||||
for( int leftY = 0; leftY < leftDisp.rows; leftY++ )
|
||||
{
|
||||
for( int leftX = 0; leftX < leftDisp.cols; leftX++ )
|
||||
{
|
||||
if( !leftUnknDispMask.empty() && leftUnknDispMask.at<uchar>(leftY,leftX) )
|
||||
continue;
|
||||
float leftDispVal = leftDisp.at<float>(leftY, leftX);
|
||||
int rightX = leftX - cvRound(leftDispVal), rightY = leftY;
|
||||
if( rightX >= 0)
|
||||
rightDisp.at<float>(rightY,rightX) = max(rightDisp.at<float>(rightY,rightX), leftDispVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
_rightDisp.copyTo(rightDisp);
|
||||
|
||||
if( occludedMask )
|
||||
{
|
||||
occludedMask->create(leftDisp.size(), CV_8UC1);
|
||||
occludedMask->setTo(Scalar::all(0) );
|
||||
}
|
||||
if( nonOccludedMask )
|
||||
{
|
||||
nonOccludedMask->create(leftDisp.size(), CV_8UC1);
|
||||
nonOccludedMask->setTo(Scalar::all(0) );
|
||||
}
|
||||
for( int leftY = 0; leftY < leftDisp.rows; leftY++ )
|
||||
{
|
||||
for( int leftX = 0; leftX < leftDisp.cols; leftX++ )
|
||||
{
|
||||
if( !leftUnknDispMask.empty() && leftUnknDispMask.at<uchar>(leftY,leftX) )
|
||||
continue;
|
||||
float leftDispVal = leftDisp.at<float>(leftY, leftX);
|
||||
int rightX = leftX - cvRound(leftDispVal), rightY = leftY;
|
||||
if( rightX < 0 && occludedMask )
|
||||
occludedMask->at<uchar>(leftY, leftX) = 255;
|
||||
else
|
||||
{
|
||||
if( !rightUnknDispMask.empty() && rightUnknDispMask.at<uchar>(rightY,rightX) )
|
||||
continue;
|
||||
float rightDispVal = rightDisp.at<float>(rightY, rightX);
|
||||
if( rightDispVal > leftDispVal + dispThresh )
|
||||
{
|
||||
if( occludedMask )
|
||||
occludedMask->at<uchar>(leftY, leftX) = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( nonOccludedMask )
|
||||
nonOccludedMask->at<uchar>(leftY, leftX) = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate depth discontinuty regions: pixels whose neiboring disparities differ by more than
|
||||
dispGap, dilated by window of width discontWidth.
|
||||
*/
|
||||
void computeDepthDiscontMask( const Mat& disp, Mat& depthDiscontMask, const Mat& unknDispMask = Mat(),
|
||||
float dispGap = EVAL_DISP_GAP, int discontWidth = EVAL_DISCONT_WIDTH )
|
||||
{
|
||||
if( disp.empty() )
|
||||
CV_Error( CV_StsBadArg, "disp is empty" );
|
||||
if( disp.type() != CV_32FC1 )
|
||||
CV_Error( CV_StsBadArg, "disp must have CV_32FC1 type" );
|
||||
if( !unknDispMask.empty() )
|
||||
checkTypeAndSizeOfMask( unknDispMask, disp.size() );
|
||||
|
||||
Mat curDisp; disp.copyTo( curDisp );
|
||||
if( !unknDispMask.empty() )
|
||||
curDisp.setTo( Scalar(numeric_limits<float>::min()), unknDispMask );
|
||||
Mat maxNeighbDisp; dilate( curDisp, maxNeighbDisp, Mat(3, 3, CV_8UC1, Scalar(1)) );
|
||||
if( !unknDispMask.empty() )
|
||||
curDisp.setTo( Scalar(numeric_limits<float>::max()), unknDispMask );
|
||||
Mat minNeighbDisp; erode( curDisp, minNeighbDisp, Mat(3, 3, CV_8UC1, Scalar(1)) );
|
||||
depthDiscontMask = max( (Mat)(maxNeighbDisp-disp), (Mat)(disp-minNeighbDisp) ) > dispGap;
|
||||
if( !unknDispMask.empty() )
|
||||
depthDiscontMask &= ~unknDispMask;
|
||||
dilate( depthDiscontMask, depthDiscontMask, Mat(discontWidth, discontWidth, CV_8UC1, Scalar(1)) );
|
||||
}
|
||||
|
||||
/*
|
||||
Get evaluation masks excluding a border.
|
||||
*/
|
||||
Mat getBorderedMask( Size maskSize, int border = EVAL_IGNORE_BORDER )
|
||||
{
|
||||
CV_Assert( border >= 0 );
|
||||
Mat mask(maskSize, CV_8UC1, Scalar(0));
|
||||
int w = maskSize.width - 2*border, h = maskSize.height - 2*border;
|
||||
if( w < 0 || h < 0 )
|
||||
mask.setTo(Scalar(0));
|
||||
else
|
||||
mask( Rect(Point(border,border),Size(w,h)) ).setTo(Scalar(255));
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate root-mean-squared error between the computed disparity map (computedDisp) and ground truth map (groundTruthDisp).
|
||||
*/
|
||||
float dispRMS( const Mat& computedDisp, const Mat& groundTruthDisp, const Mat& mask )
|
||||
{
|
||||
checkTypeAndSizeOfDisp( groundTruthDisp, 0 );
|
||||
Size sz = groundTruthDisp.size();
|
||||
checkTypeAndSizeOfDisp( computedDisp, &sz );
|
||||
|
||||
int pointsCount = sz.height*sz.width;
|
||||
if( !mask.empty() )
|
||||
{
|
||||
checkTypeAndSizeOfMask( mask, sz );
|
||||
pointsCount = countNonZero(mask);
|
||||
}
|
||||
return 1.f/sqrt((float)pointsCount) * (float)norm(computedDisp, groundTruthDisp, NORM_L2, mask);
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate fraction of bad matching pixels.
|
||||
*/
|
||||
float badMatchPxlsFraction( const Mat& computedDisp, const Mat& groundTruthDisp, const Mat& mask,
|
||||
float _badThresh = EVAL_BAD_THRESH )
|
||||
{
|
||||
int badThresh = cvRound(_badThresh);
|
||||
checkTypeAndSizeOfDisp( groundTruthDisp, 0 );
|
||||
Size sz = groundTruthDisp.size();
|
||||
checkTypeAndSizeOfDisp( computedDisp, &sz );
|
||||
|
||||
Mat badPxlsMap;
|
||||
absdiff( computedDisp, groundTruthDisp, badPxlsMap );
|
||||
badPxlsMap = badPxlsMap > badThresh;
|
||||
int pointsCount = sz.height*sz.width;
|
||||
if( !mask.empty() )
|
||||
{
|
||||
checkTypeAndSizeOfMask( mask, sz );
|
||||
badPxlsMap = badPxlsMap & mask;
|
||||
pointsCount = countNonZero(mask);
|
||||
}
|
||||
return 1.f/pointsCount * countNonZero(badPxlsMap);
|
||||
}
|
||||
|
||||
//===================== regression test for stereo matching algorithms ==============================
|
||||
|
||||
const string ALGORITHMS_DIR = "stereomatching/algorithms/";
|
||||
const string DATASETS_DIR = "stereomatching/datasets/";
|
||||
const string DATASETS_FILE = "datasets.xml";
|
||||
|
||||
const string RUN_PARAMS_FILE = "_params.xml";
|
||||
const string RESULT_FILE = "_res.xml";
|
||||
|
||||
const string LEFT_IMG_NAME = "im2.png";
|
||||
const string RIGHT_IMG_NAME = "im6.png";
|
||||
const string TRUE_LEFT_DISP_NAME = "disp2.png";
|
||||
const string TRUE_RIGHT_DISP_NAME = "disp6.png";
|
||||
|
||||
string ERROR_PREFIXES[] = { "borderedAll",
|
||||
"borderedNoOccl",
|
||||
"borderedOccl",
|
||||
"borderedTextured",
|
||||
"borderedTextureless",
|
||||
"borderedDepthDiscont" }; // size of ERROR_KINDS_COUNT
|
||||
|
||||
|
||||
const string RMS_STR = "RMS";
|
||||
const string BAD_PXLS_FRACTION_STR = "BadPxlsFraction";
|
||||
|
||||
class QualityEvalParams
|
||||
{
|
||||
public:
|
||||
QualityEvalParams() { setDefaults(); }
|
||||
QualityEvalParams( int _ignoreBorder )
|
||||
{
|
||||
setDefaults();
|
||||
ignoreBorder = _ignoreBorder;
|
||||
}
|
||||
void setDefaults()
|
||||
{
|
||||
badThresh = EVAL_BAD_THRESH;
|
||||
texturelessWidth = EVAL_TEXTURELESS_WIDTH;
|
||||
texturelessThresh = EVAL_TEXTURELESS_THRESH;
|
||||
dispThresh = EVAL_DISP_THRESH;
|
||||
dispGap = EVAL_DISP_GAP;
|
||||
discontWidth = EVAL_DISCONT_WIDTH;
|
||||
ignoreBorder = EVAL_IGNORE_BORDER;
|
||||
}
|
||||
float badThresh;
|
||||
int texturelessWidth;
|
||||
float texturelessThresh;
|
||||
float dispThresh;
|
||||
float dispGap;
|
||||
int discontWidth;
|
||||
int ignoreBorder;
|
||||
};
|
||||
|
||||
class CV_StereoMatchingTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_StereoMatchingTest()
|
||||
{ rmsEps.resize( ERROR_KINDS_COUNT, 0.01f ); fracEps.resize( ERROR_KINDS_COUNT, 1.e-6f ); }
|
||||
protected:
|
||||
// assumed that left image is a reference image
|
||||
virtual int runStereoMatchingAlgorithm( const Mat& leftImg, const Mat& rightImg,
|
||||
Mat& leftDisp, Mat& rightDisp, int caseIdx ) = 0; // return ignored border width
|
||||
|
||||
int readDatasetsParams( FileStorage& fs );
|
||||
virtual int readRunParams( FileStorage& fs );
|
||||
void writeErrors( const string& errName, const vector<float>& errors, FileStorage* fs = 0 );
|
||||
void readErrors( FileNode& fn, const string& errName, vector<float>& errors );
|
||||
int compareErrors( const vector<float>& calcErrors, const vector<float>& validErrors,
|
||||
const vector<float>& eps, const string& errName );
|
||||
int processStereoMatchingResults( FileStorage& fs, int caseIdx, bool isWrite,
|
||||
const Mat& leftImg, const Mat& rightImg,
|
||||
const Mat& trueLeftDisp, const Mat& trueRightDisp,
|
||||
const Mat& leftDisp, const Mat& rightDisp,
|
||||
const QualityEvalParams& qualityEvalParams );
|
||||
void run( int );
|
||||
|
||||
vector<float> rmsEps;
|
||||
vector<float> fracEps;
|
||||
|
||||
struct DatasetParams
|
||||
{
|
||||
int dispScaleFactor;
|
||||
int dispUnknVal;
|
||||
};
|
||||
map<string, DatasetParams> datasetsParams;
|
||||
|
||||
vector<string> caseNames;
|
||||
vector<string> caseDatasets;
|
||||
};
|
||||
|
||||
void CV_StereoMatchingTest::run(int)
|
||||
{
|
||||
string dataPath = ts->get_data_path();
|
||||
string algorithmName = name;
|
||||
assert( !algorithmName.empty() );
|
||||
if( dataPath.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "dataPath is empty" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ARG_CHECK );
|
||||
return;
|
||||
}
|
||||
|
||||
FileStorage datasetsFS( dataPath + DATASETS_DIR + DATASETS_FILE, FileStorage::READ );
|
||||
int code = readDatasetsParams( datasetsFS );
|
||||
if( code != cvtest::TS::OK )
|
||||
{
|
||||
ts->set_failed_test_info( code );
|
||||
return;
|
||||
}
|
||||
FileStorage runParamsFS( dataPath + ALGORITHMS_DIR + algorithmName + RUN_PARAMS_FILE, FileStorage::READ );
|
||||
code = readRunParams( runParamsFS );
|
||||
if( code != cvtest::TS::OK )
|
||||
{
|
||||
ts->set_failed_test_info( code );
|
||||
return;
|
||||
}
|
||||
|
||||
string fullResultFilename = dataPath + ALGORITHMS_DIR + algorithmName + RESULT_FILE;
|
||||
FileStorage resFS( fullResultFilename, FileStorage::READ );
|
||||
bool isWrite = true; // write or compare results
|
||||
if( resFS.isOpened() )
|
||||
isWrite = false;
|
||||
else
|
||||
{
|
||||
resFS.open( fullResultFilename, FileStorage::WRITE );
|
||||
if( !resFS.isOpened() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "file %s can not be read or written\n", fullResultFilename.c_str() );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ARG_CHECK );
|
||||
return;
|
||||
}
|
||||
resFS << "stereo_matching" << "{";
|
||||
}
|
||||
|
||||
int progress = 0, caseCount = (int)caseNames.size();
|
||||
for( int ci = 0; ci < caseCount; ci++)
|
||||
{
|
||||
progress = update_progress( progress, ci, caseCount, 0 );
|
||||
|
||||
string datasetName = caseDatasets[ci];
|
||||
string datasetFullDirName = dataPath + DATASETS_DIR + datasetName + "/";
|
||||
Mat leftImg = imread(datasetFullDirName + LEFT_IMG_NAME);
|
||||
Mat rightImg = imread(datasetFullDirName + RIGHT_IMG_NAME);
|
||||
Mat trueLeftDisp = imread(datasetFullDirName + TRUE_LEFT_DISP_NAME, 0);
|
||||
Mat trueRightDisp = imread(datasetFullDirName + TRUE_RIGHT_DISP_NAME, 0);
|
||||
|
||||
if( leftImg.empty() || rightImg.empty() || trueLeftDisp.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "images or left ground-truth disparities of dataset %s can not be read", datasetName.c_str() );
|
||||
code = cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
continue;
|
||||
}
|
||||
int dispScaleFactor = datasetsParams[datasetName].dispScaleFactor;
|
||||
Mat tmp; trueLeftDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); trueLeftDisp = tmp; tmp.release();
|
||||
if( !trueRightDisp.empty() )
|
||||
trueRightDisp.convertTo( tmp, CV_32FC1, 1.f/dispScaleFactor ); trueRightDisp = tmp; tmp.release();
|
||||
|
||||
Mat leftDisp, rightDisp;
|
||||
int ignBorder = max(runStereoMatchingAlgorithm(leftImg, rightImg, leftDisp, rightDisp, ci), EVAL_IGNORE_BORDER);
|
||||
leftDisp.convertTo( tmp, CV_32FC1 ); leftDisp = tmp; tmp.release();
|
||||
rightDisp.convertTo( tmp, CV_32FC1 ); rightDisp = tmp; tmp.release();
|
||||
|
||||
int tempCode = processStereoMatchingResults( resFS, ci, isWrite,
|
||||
leftImg, rightImg, trueLeftDisp, trueRightDisp, leftDisp, rightDisp, QualityEvalParams(ignBorder));
|
||||
code = tempCode==cvtest::TS::OK ? code : tempCode;
|
||||
}
|
||||
|
||||
if( isWrite )
|
||||
resFS << "}"; // "stereo_matching"
|
||||
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
void calcErrors( const Mat& leftImg, const Mat& /*rightImg*/,
|
||||
const Mat& trueLeftDisp, const Mat& trueRightDisp,
|
||||
const Mat& trueLeftUnknDispMask, const Mat& trueRightUnknDispMask,
|
||||
const Mat& calcLeftDisp, const Mat& /*calcRightDisp*/,
|
||||
vector<float>& rms, vector<float>& badPxlsFractions,
|
||||
const QualityEvalParams& qualityEvalParams )
|
||||
{
|
||||
Mat texturelessMask, texturedMask;
|
||||
computeTextureBasedMasks( leftImg, &texturelessMask, &texturedMask,
|
||||
qualityEvalParams.texturelessWidth, qualityEvalParams.texturelessThresh );
|
||||
Mat occludedMask, nonOccludedMask;
|
||||
computeOcclusionBasedMasks( trueLeftDisp, trueRightDisp, &occludedMask, &nonOccludedMask,
|
||||
trueLeftUnknDispMask, trueRightUnknDispMask, qualityEvalParams.dispThresh);
|
||||
Mat depthDiscontMask;
|
||||
computeDepthDiscontMask( trueLeftDisp, depthDiscontMask, trueLeftUnknDispMask,
|
||||
qualityEvalParams.dispGap, qualityEvalParams.discontWidth);
|
||||
|
||||
Mat borderedKnownMask = getBorderedMask( leftImg.size(), qualityEvalParams.ignoreBorder ) & ~trueLeftUnknDispMask;
|
||||
|
||||
nonOccludedMask &= borderedKnownMask;
|
||||
occludedMask &= borderedKnownMask;
|
||||
texturedMask &= nonOccludedMask; // & borderedKnownMask
|
||||
texturelessMask &= nonOccludedMask; // & borderedKnownMask
|
||||
depthDiscontMask &= nonOccludedMask; // & borderedKnownMask
|
||||
|
||||
rms.resize(ERROR_KINDS_COUNT);
|
||||
rms[0] = dispRMS( calcLeftDisp, trueLeftDisp, borderedKnownMask );
|
||||
rms[1] = dispRMS( calcLeftDisp, trueLeftDisp, nonOccludedMask );
|
||||
rms[2] = dispRMS( calcLeftDisp, trueLeftDisp, occludedMask );
|
||||
rms[3] = dispRMS( calcLeftDisp, trueLeftDisp, texturedMask );
|
||||
rms[4] = dispRMS( calcLeftDisp, trueLeftDisp, texturelessMask );
|
||||
rms[5] = dispRMS( calcLeftDisp, trueLeftDisp, depthDiscontMask );
|
||||
|
||||
badPxlsFractions.resize(ERROR_KINDS_COUNT);
|
||||
badPxlsFractions[0] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, borderedKnownMask, qualityEvalParams.badThresh );
|
||||
badPxlsFractions[1] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, nonOccludedMask, qualityEvalParams.badThresh );
|
||||
badPxlsFractions[2] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, occludedMask, qualityEvalParams.badThresh );
|
||||
badPxlsFractions[3] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, texturedMask, qualityEvalParams.badThresh );
|
||||
badPxlsFractions[4] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, texturelessMask, qualityEvalParams.badThresh );
|
||||
badPxlsFractions[5] = badMatchPxlsFraction( calcLeftDisp, trueLeftDisp, depthDiscontMask, qualityEvalParams.badThresh );
|
||||
}
|
||||
|
||||
int CV_StereoMatchingTest::processStereoMatchingResults( FileStorage& fs, int caseIdx, bool isWrite,
|
||||
const Mat& leftImg, const Mat& rightImg,
|
||||
const Mat& trueLeftDisp, const Mat& trueRightDisp,
|
||||
const Mat& leftDisp, const Mat& rightDisp,
|
||||
const QualityEvalParams& qualityEvalParams )
|
||||
{
|
||||
// rightDisp is not used in current test virsion
|
||||
int code = cvtest::TS::OK;
|
||||
assert( fs.isOpened() );
|
||||
assert( trueLeftDisp.type() == CV_32FC1 && trueRightDisp.type() == CV_32FC1 );
|
||||
assert( leftDisp.type() == CV_32FC1 && rightDisp.type() == CV_32FC1 );
|
||||
|
||||
// get masks for unknown ground truth disparity values
|
||||
Mat leftUnknMask, rightUnknMask;
|
||||
DatasetParams params = datasetsParams[caseDatasets[caseIdx]];
|
||||
absdiff( trueLeftDisp, Scalar(params.dispUnknVal), leftUnknMask );
|
||||
leftUnknMask = leftUnknMask < numeric_limits<float>::epsilon();
|
||||
assert(leftUnknMask.type() == CV_8UC1);
|
||||
if( !trueRightDisp.empty() )
|
||||
{
|
||||
absdiff( trueRightDisp, Scalar(params.dispUnknVal), rightUnknMask );
|
||||
rightUnknMask = rightUnknMask < numeric_limits<float>::epsilon();
|
||||
assert(leftUnknMask.type() == CV_8UC1);
|
||||
}
|
||||
|
||||
// calculate errors
|
||||
vector<float> rmss, badPxlsFractions;
|
||||
calcErrors( leftImg, rightImg, trueLeftDisp, trueRightDisp, leftUnknMask, rightUnknMask,
|
||||
leftDisp, rightDisp, rmss, badPxlsFractions, qualityEvalParams );
|
||||
|
||||
if( isWrite )
|
||||
{
|
||||
fs << caseNames[caseIdx] << "{";
|
||||
cvWriteComment( fs.fs, RMS_STR.c_str(), 0 );
|
||||
writeErrors( RMS_STR, rmss, &fs );
|
||||
cvWriteComment( fs.fs, BAD_PXLS_FRACTION_STR.c_str(), 0 );
|
||||
writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions, &fs );
|
||||
fs << "}"; // datasetName
|
||||
}
|
||||
else // compare
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "\nquality of case named %s\n", caseNames[caseIdx].c_str() );
|
||||
ts->printf( cvtest::TS::LOG, "%s\n", RMS_STR.c_str() );
|
||||
writeErrors( RMS_STR, rmss );
|
||||
ts->printf( cvtest::TS::LOG, "%s\n", BAD_PXLS_FRACTION_STR.c_str() );
|
||||
writeErrors( BAD_PXLS_FRACTION_STR, badPxlsFractions );
|
||||
|
||||
FileNode fn = fs.getFirstTopLevelNode()[caseNames[caseIdx]];
|
||||
vector<float> validRmss, validBadPxlsFractions;
|
||||
|
||||
readErrors( fn, RMS_STR, validRmss );
|
||||
readErrors( fn, BAD_PXLS_FRACTION_STR, validBadPxlsFractions );
|
||||
int tempCode = compareErrors( rmss, validRmss, rmsEps, RMS_STR );
|
||||
code = tempCode==cvtest::TS::OK ? code : tempCode;
|
||||
tempCode = compareErrors( badPxlsFractions, validBadPxlsFractions, fracEps, BAD_PXLS_FRACTION_STR );
|
||||
code = tempCode==cvtest::TS::OK ? code : tempCode;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int CV_StereoMatchingTest::readDatasetsParams( FileStorage& fs )
|
||||
{
|
||||
if( !fs.isOpened() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "datasetsParams can not be read " );
|
||||
return cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
datasetsParams.clear();
|
||||
FileNode fn = fs.getFirstTopLevelNode();
|
||||
assert(fn.isSeq());
|
||||
for( int i = 0; i < (int)fn.size(); i+=3 )
|
||||
{
|
||||
string name = fn[i];
|
||||
DatasetParams params;
|
||||
string sf = fn[i+1]; params.dispScaleFactor = atoi(sf.c_str());
|
||||
string uv = fn[i+2]; params.dispUnknVal = atoi(uv.c_str());
|
||||
datasetsParams[name] = params;
|
||||
}
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int CV_StereoMatchingTest::readRunParams( FileStorage& fs )
|
||||
{
|
||||
if( !fs.isOpened() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "runParams can not be read " );
|
||||
return cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
caseNames.clear();;
|
||||
caseDatasets.clear();
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
void CV_StereoMatchingTest::writeErrors( const string& errName, const vector<float>& errors, FileStorage* fs )
|
||||
{
|
||||
assert( (int)errors.size() == ERROR_KINDS_COUNT );
|
||||
vector<float>::const_iterator it = errors.begin();
|
||||
if( fs )
|
||||
for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++it )
|
||||
*fs << ERROR_PREFIXES[i] + errName << *it;
|
||||
else
|
||||
for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++it )
|
||||
ts->printf( cvtest::TS::LOG, "%s = %f\n", string(ERROR_PREFIXES[i]+errName).c_str(), *it );
|
||||
}
|
||||
|
||||
void CV_StereoMatchingTest::readErrors( FileNode& fn, const string& errName, vector<float>& errors )
|
||||
{
|
||||
errors.resize( ERROR_KINDS_COUNT );
|
||||
vector<float>::iterator it = errors.begin();
|
||||
for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++it )
|
||||
fn[ERROR_PREFIXES[i]+errName] >> *it;
|
||||
}
|
||||
|
||||
int CV_StereoMatchingTest::compareErrors( const vector<float>& calcErrors, const vector<float>& validErrors,
|
||||
const vector<float>& eps, const string& errName )
|
||||
{
|
||||
assert( (int)calcErrors.size() == ERROR_KINDS_COUNT );
|
||||
assert( (int)validErrors.size() == ERROR_KINDS_COUNT );
|
||||
assert( (int)eps.size() == ERROR_KINDS_COUNT );
|
||||
vector<float>::const_iterator calcIt = calcErrors.begin(),
|
||||
validIt = validErrors.begin(),
|
||||
epsIt = eps.begin();
|
||||
bool ok = true;
|
||||
for( int i = 0; i < ERROR_KINDS_COUNT; i++, ++calcIt, ++validIt, ++epsIt )
|
||||
if( *calcIt - *validIt > *epsIt )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of %s (valid=%f; calc=%f)\n", string(ERROR_PREFIXES[i]+errName).c_str(), *validIt, *calcIt );
|
||||
ok = false;
|
||||
}
|
||||
return ok ? cvtest::TS::OK : cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
//----------------------------------- StereoBM test -----------------------------------------------------
|
||||
|
||||
class CV_StereoBMTest : public CV_StereoMatchingTest
|
||||
{
|
||||
public:
|
||||
CV_StereoBMTest()
|
||||
{
|
||||
name = "stereobm";
|
||||
fill(rmsEps.begin(), rmsEps.end(), 0.4f);
|
||||
fill(fracEps.begin(), fracEps.end(), 0.022f);
|
||||
}
|
||||
|
||||
protected:
|
||||
struct RunParams
|
||||
{
|
||||
int ndisp;
|
||||
int winSize;
|
||||
};
|
||||
vector<RunParams> caseRunParams;
|
||||
|
||||
virtual int readRunParams( FileStorage& fs )
|
||||
{
|
||||
int code = CV_StereoMatchingTest::readRunParams( fs );
|
||||
FileNode fn = fs.getFirstTopLevelNode();
|
||||
assert(fn.isSeq());
|
||||
for( int i = 0; i < (int)fn.size(); i+=4 )
|
||||
{
|
||||
string caseName = fn[i], datasetName = fn[i+1];
|
||||
RunParams params;
|
||||
string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str());
|
||||
string winSize = fn[i+3]; params.winSize = atoi(winSize.c_str());
|
||||
caseNames.push_back( caseName );
|
||||
caseDatasets.push_back( datasetName );
|
||||
caseRunParams.push_back( params );
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
virtual int runStereoMatchingAlgorithm( const Mat& _leftImg, const Mat& _rightImg,
|
||||
Mat& leftDisp, Mat& /*rightDisp*/, int caseIdx )
|
||||
{
|
||||
RunParams params = caseRunParams[caseIdx];
|
||||
assert( params.ndisp%16 == 0 );
|
||||
assert( _leftImg.type() == CV_8UC3 && _rightImg.type() == CV_8UC3 );
|
||||
Mat leftImg; cvtColor( _leftImg, leftImg, CV_BGR2GRAY );
|
||||
Mat rightImg; cvtColor( _rightImg, rightImg, CV_BGR2GRAY );
|
||||
|
||||
StereoBM bm( StereoBM::BASIC_PRESET, params.ndisp, params.winSize );
|
||||
bm( leftImg, rightImg, leftDisp, CV_32F );
|
||||
return params.winSize/2;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------- StereoGC test -----------------------------------------------------
|
||||
|
||||
class CV_StereoGCTest : public CV_StereoMatchingTest
|
||||
{
|
||||
public:
|
||||
CV_StereoGCTest()
|
||||
{
|
||||
name = "stereogc";
|
||||
fill(rmsEps.begin(), rmsEps.end(), 3.f);
|
||||
fracEps[0] = 0.05f; // all
|
||||
fracEps[1] = 0.05f; // noOccl
|
||||
fracEps[2] = 0.25f; // occl
|
||||
fracEps[3] = 0.05f; // textured
|
||||
fracEps[4] = 0.10f; // textureless
|
||||
fracEps[5] = 0.10f; // borderedDepthDiscont
|
||||
}
|
||||
protected:
|
||||
struct RunParams
|
||||
{
|
||||
int ndisp;
|
||||
int iterCount;
|
||||
};
|
||||
vector<RunParams> caseRunParams;
|
||||
|
||||
virtual int readRunParams( FileStorage& fs )
|
||||
{
|
||||
int code = CV_StereoMatchingTest::readRunParams(fs);
|
||||
FileNode fn = fs.getFirstTopLevelNode();
|
||||
assert(fn.isSeq());
|
||||
for( int i = 0; i < (int)fn.size(); i+=4 )
|
||||
{
|
||||
string caseName = fn[i], datasetName = fn[i+1];
|
||||
RunParams params;
|
||||
string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str());
|
||||
string iterCount = fn[i+3]; params.iterCount = atoi(iterCount.c_str());
|
||||
caseNames.push_back( caseName );
|
||||
caseDatasets.push_back( datasetName );
|
||||
caseRunParams.push_back( params );
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
virtual int runStereoMatchingAlgorithm( const Mat& _leftImg, const Mat& _rightImg,
|
||||
Mat& leftDisp, Mat& rightDisp, int caseIdx )
|
||||
{
|
||||
RunParams params = caseRunParams[caseIdx];
|
||||
assert( _leftImg.type() == CV_8UC3 && _rightImg.type() == CV_8UC3 );
|
||||
Mat leftImg, rightImg, tmp;
|
||||
cvtColor( _leftImg, leftImg, CV_BGR2GRAY );
|
||||
cvtColor( _rightImg, rightImg, CV_BGR2GRAY );
|
||||
|
||||
leftDisp.create( leftImg.size(), CV_16SC1 );
|
||||
rightDisp.create( rightImg.size(), CV_16SC1 );
|
||||
|
||||
CvMat _limg = leftImg, _rimg = rightImg, _ldisp = leftDisp, _rdisp = rightDisp;
|
||||
CvStereoGCState *state = cvCreateStereoGCState( params.ndisp, params.iterCount );
|
||||
cvFindStereoCorrespondenceGC( &_limg, &_rimg, &_ldisp, &_rdisp, state );
|
||||
cvReleaseStereoGCState( &state );
|
||||
|
||||
leftDisp = - leftDisp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------- StereoSGBM test -----------------------------------------------------
|
||||
|
||||
class CV_StereoSGBMTest : public CV_StereoMatchingTest
|
||||
{
|
||||
public:
|
||||
CV_StereoSGBMTest()
|
||||
{
|
||||
name = "stereosgbm";
|
||||
fill(rmsEps.begin(), rmsEps.end(), 0.25f);
|
||||
fill(fracEps.begin(), fracEps.end(), 0.01f);
|
||||
}
|
||||
|
||||
protected:
|
||||
struct RunParams
|
||||
{
|
||||
int ndisp;
|
||||
int winSize;
|
||||
bool fullDP;
|
||||
};
|
||||
vector<RunParams> caseRunParams;
|
||||
|
||||
virtual int readRunParams( FileStorage& fs )
|
||||
{
|
||||
int code = CV_StereoMatchingTest::readRunParams(fs);
|
||||
FileNode fn = fs.getFirstTopLevelNode();
|
||||
assert(fn.isSeq());
|
||||
for( int i = 0; i < (int)fn.size(); i+=5 )
|
||||
{
|
||||
string caseName = fn[i], datasetName = fn[i+1];
|
||||
RunParams params;
|
||||
string ndisp = fn[i+2]; params.ndisp = atoi(ndisp.c_str());
|
||||
string winSize = fn[i+3]; params.winSize = atoi(winSize.c_str());
|
||||
string fullDP = fn[i+4]; params.fullDP = atoi(fullDP.c_str()) == 0 ? false : true;
|
||||
caseNames.push_back( caseName );
|
||||
caseDatasets.push_back( datasetName );
|
||||
caseRunParams.push_back( params );
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
virtual int runStereoMatchingAlgorithm( const Mat& leftImg, const Mat& rightImg,
|
||||
Mat& leftDisp, Mat& /*rightDisp*/, int caseIdx )
|
||||
{
|
||||
RunParams params = caseRunParams[caseIdx];
|
||||
assert( params.ndisp%16 == 0 );
|
||||
StereoSGBM sgbm( 0, params.ndisp, params.winSize, 10*params.winSize*params.winSize, 40*params.winSize*params.winSize,
|
||||
1, 63, 10, 100, 32, params.fullDP );
|
||||
sgbm( leftImg, rightImg, leftDisp );
|
||||
assert( leftDisp.type() == CV_16SC1 );
|
||||
leftDisp/=16;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(Calib3d_StereoBM, regression) { CV_StereoBMTest test; test.safe_run(); }
|
||||
TEST(Calib3d_StereoGC, regression) { CV_StereoGCTest test; test.safe_run(); }
|
||||
TEST(Calib3d_StereoSGBM, regression) { CV_StereoSGBMTest test; test.safe_run(); }
|
928
modules/calib3d/test/test_undistort.cpp
Normal file
928
modules/calib3d/test/test_undistort.cpp
Normal file
@ -0,0 +1,928 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_DefaultNewCameraMatrixTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_DefaultNewCameraMatrixTest();
|
||||
protected:
|
||||
int prepare_test_case (int test_case_idx);
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
void run_func();
|
||||
|
||||
private:
|
||||
cv::Size img_size;
|
||||
cv::Mat camera_mat;
|
||||
cv::Mat new_camera_mat;
|
||||
|
||||
int matrix_type;
|
||||
|
||||
bool center_principal_point;
|
||||
|
||||
static const int MAX_X = 2048;
|
||||
static const int MAX_Y = 2048;
|
||||
static const int MAX_VAL = 10000;
|
||||
};
|
||||
|
||||
CV_DefaultNewCameraMatrixTest::CV_DefaultNewCameraMatrixTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
}
|
||||
|
||||
void CV_DefaultNewCameraMatrixTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes(test_case_idx,sizes,types);
|
||||
RNG& rng = ts->get_rng();
|
||||
matrix_type = types[INPUT][0] = types[OUTPUT][0]= types[REF_OUTPUT][0] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(3,3);
|
||||
}
|
||||
|
||||
int CV_DefaultNewCameraMatrixTest::prepare_test_case(int test_case_idx)
|
||||
{
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
|
||||
if (code <= 0)
|
||||
return code;
|
||||
|
||||
RNG& rng = ts->get_rng();
|
||||
|
||||
img_size.width = cvtest::randInt(rng) % MAX_X + 1;
|
||||
img_size.height = cvtest::randInt(rng) % MAX_Y + 1;
|
||||
|
||||
center_principal_point = ((cvtest::randInt(rng) % 2)!=0);
|
||||
|
||||
// Generating camera_mat matrix
|
||||
double sz = MAX(img_size.width, img_size.height);
|
||||
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
|
||||
double a[9] = {0,0,0,0,0,0,0,0,1};
|
||||
Mat _a(3,3,CV_64F,a);
|
||||
a[2] = (img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
a[5] = (img_size.height - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
a[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
|
||||
a[4] = aspect_ratio*a[0];
|
||||
|
||||
Mat& _a0 = test_mat[INPUT][0];
|
||||
cvtest::convert(_a, _a0, _a0.type());
|
||||
camera_mat = _a0;
|
||||
|
||||
return code;
|
||||
|
||||
}
|
||||
|
||||
void CV_DefaultNewCameraMatrixTest::run_func()
|
||||
{
|
||||
new_camera_mat = cv::getDefaultNewCameraMatrix(camera_mat,img_size,center_principal_point);
|
||||
}
|
||||
|
||||
void CV_DefaultNewCameraMatrixTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
const Mat& src = test_mat[INPUT][0];
|
||||
Mat& dst = test_mat[REF_OUTPUT][0];
|
||||
Mat& test_output = test_mat[OUTPUT][0];
|
||||
Mat& output = new_camera_mat;
|
||||
cvtest::convert( output, test_output, test_output.type() );
|
||||
if (!center_principal_point)
|
||||
{
|
||||
cvtest::copy(src, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
double a[9] = {0,0,0,0,0,0,0,0,1};
|
||||
Mat _a(3,3,CV_64F,a);
|
||||
if (matrix_type == CV_64F)
|
||||
{
|
||||
a[0] = src.at<double>(0,0);
|
||||
a[4] = src.at<double>(1,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
a[0] = src.at<float>(0,0);
|
||||
a[4] = src.at<float>(1,1);
|
||||
}
|
||||
a[2] = (img_size.width - 1)*0.5;
|
||||
a[5] = (img_size.height - 1)*0.5;
|
||||
cvtest::convert( _a, dst, dst.type() );
|
||||
}
|
||||
}
|
||||
|
||||
//---------
|
||||
|
||||
class CV_UndistortPointsTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_UndistortPointsTest();
|
||||
protected:
|
||||
int prepare_test_case (int test_case_idx);
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void distortPoints(const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix,
|
||||
const CvMat* _distCoeffs, const CvMat* matR, const CvMat* matP);
|
||||
|
||||
private:
|
||||
bool useCPlus;
|
||||
bool useDstMat;
|
||||
static const int N_POINTS = 10;
|
||||
static const int MAX_X = 2048;
|
||||
static const int MAX_Y = 2048;
|
||||
|
||||
bool zero_new_cam;
|
||||
bool zero_distortion;
|
||||
bool zero_R;
|
||||
|
||||
cv::Size img_size;
|
||||
cv::Mat dst_points_mat;
|
||||
|
||||
cv::Mat camera_mat;
|
||||
cv::Mat R;
|
||||
cv::Mat P;
|
||||
cv::Mat distortion_coeffs;
|
||||
cv::Mat src_points;
|
||||
std::vector<cv::Point2f> dst_points;
|
||||
};
|
||||
|
||||
CV_UndistortPointsTest::CV_UndistortPointsTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL); // points matrix
|
||||
test_array[INPUT].push_back(NULL); // camera matrix
|
||||
test_array[INPUT].push_back(NULL); // distortion coeffs
|
||||
test_array[INPUT].push_back(NULL); // R matrix
|
||||
test_array[INPUT].push_back(NULL); // P matrix
|
||||
test_array[OUTPUT].push_back(NULL); // distorted dst points
|
||||
test_array[TEMP].push_back(NULL); // dst points
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
}
|
||||
|
||||
void CV_UndistortPointsTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes(test_case_idx,sizes,types);
|
||||
RNG& rng = ts->get_rng();
|
||||
useCPlus = ((cvtest::randInt(rng) % 2)!=0);
|
||||
//useCPlus = 0;
|
||||
if (useCPlus)
|
||||
{
|
||||
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0]= CV_32FC2;
|
||||
}
|
||||
else
|
||||
{
|
||||
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = types[TEMP][0]= cvtest::randInt(rng)%2 ? CV_64FC2 : CV_32FC2;
|
||||
}
|
||||
types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
types[INPUT][3] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
types[INPUT][4] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
|
||||
sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = sizes[TEMP][0]= cvtest::randInt(rng)%2 ? cvSize(1,N_POINTS) : cvSize(N_POINTS,1);
|
||||
sizes[INPUT][1] = sizes[INPUT][3] = cvSize(3,3);
|
||||
sizes[INPUT][4] = cvtest::randInt(rng)%2 ? cvSize(3,3) : cvSize(4,3);
|
||||
|
||||
if (cvtest::randInt(rng)%2)
|
||||
{
|
||||
if (cvtest::randInt(rng)%2)
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(1,4);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(1,5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cvtest::randInt(rng)%2)
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(4,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(5,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CV_UndistortPointsTest::prepare_test_case(int test_case_idx)
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
|
||||
if (code <= 0)
|
||||
return code;
|
||||
|
||||
useDstMat = (cvtest::randInt(rng) % 2) == 0;
|
||||
|
||||
img_size.width = cvtest::randInt(rng) % MAX_X + 1;
|
||||
img_size.height = cvtest::randInt(rng) % MAX_Y + 1;
|
||||
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
|
||||
double cam[9] = {0,0,0,0,0,0,0,0,1};
|
||||
vector<double> dist(dist_size);
|
||||
vector<double> proj(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
|
||||
vector<Point2d> points(N_POINTS);
|
||||
|
||||
Mat _camera(3,3,CV_64F,cam);
|
||||
Mat _distort(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,&dist[0]);
|
||||
Mat _proj(test_mat[INPUT][4].size(), CV_64F, &proj[0]);
|
||||
Mat _points(test_mat[INPUT][0].size(), CV_64FC2, &points[0]);
|
||||
|
||||
_proj = Scalar::all(0);
|
||||
|
||||
//Generating points
|
||||
for( int i = 0; i < N_POINTS; i++ )
|
||||
{
|
||||
points[i].x = cvtest::randReal(rng)*img_size.width;
|
||||
points[i].y = cvtest::randReal(rng)*img_size.height;
|
||||
}
|
||||
|
||||
//Generating camera matrix
|
||||
double sz = MAX(img_size.width,img_size.height);
|
||||
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
|
||||
cam[2] = (img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
cam[5] = (img_size.height - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
cam[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
|
||||
cam[4] = aspect_ratio*cam[0];
|
||||
|
||||
//Generating distortion coeffs
|
||||
dist[0] = cvtest::randReal(rng)*0.06 - 0.03;
|
||||
dist[1] = cvtest::randReal(rng)*0.06 - 0.03;
|
||||
if( dist[0]*dist[1] > 0 )
|
||||
dist[1] = -dist[1];
|
||||
if( cvtest::randInt(rng)%4 != 0 )
|
||||
{
|
||||
dist[2] = cvtest::randReal(rng)*0.004 - 0.002;
|
||||
dist[3] = cvtest::randReal(rng)*0.004 - 0.002;
|
||||
if (dist_size > 4)
|
||||
dist[4] = cvtest::randReal(rng)*0.004 - 0.002;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist[2] = dist[3] = 0;
|
||||
if (dist_size > 4)
|
||||
dist[4] = 0;
|
||||
}
|
||||
|
||||
//Generating P matrix (projection)
|
||||
if( test_mat[INPUT][4].cols != 4 )
|
||||
{
|
||||
proj[8] = 1;
|
||||
if (cvtest::randInt(rng)%2 == 0) // use identity new camera matrix
|
||||
{
|
||||
proj[0] = 1;
|
||||
proj[4] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
proj[0] = cam[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[0]; //10%
|
||||
proj[4] = cam[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[4]; //10%
|
||||
proj[2] = cam[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.width; //15%
|
||||
proj[5] = cam[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.height; //15%
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
proj[10] = 1;
|
||||
proj[0] = cam[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[0]; //10%
|
||||
proj[5] = cam[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[4]; //10%
|
||||
proj[2] = cam[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.width; //15%
|
||||
proj[6] = cam[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.height; //15%
|
||||
|
||||
proj[3] = (img_size.height + img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
proj[7] = (img_size.height + img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
proj[11] = (img_size.height + img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
}
|
||||
|
||||
//Generating R matrix
|
||||
Mat _rot(3,3,CV_64F);
|
||||
Mat rotation(1,3,CV_64F);
|
||||
rotation.at<double>(0) = CV_PI*(cvtest::randReal(rng) - (double)0.5); // phi
|
||||
rotation.at<double>(1) = CV_PI*(cvtest::randReal(rng) - (double)0.5); // ksi
|
||||
rotation.at<double>(2) = CV_PI*(cvtest::randReal(rng) - (double)0.5); //khi
|
||||
cvtest::Rodrigues(rotation, _rot);
|
||||
|
||||
//copying data
|
||||
//src_points = &_points;
|
||||
_points.convertTo(test_mat[INPUT][0], test_mat[INPUT][0].type());
|
||||
_camera.convertTo(test_mat[INPUT][1], test_mat[INPUT][1].type());
|
||||
_distort.convertTo(test_mat[INPUT][2], test_mat[INPUT][2].type());
|
||||
_rot.convertTo(test_mat[INPUT][3], test_mat[INPUT][3].type());
|
||||
_proj.convertTo(test_mat[INPUT][4], test_mat[INPUT][4].type());
|
||||
|
||||
zero_distortion = (cvtest::randInt(rng)%2) == 0 ? false : true;
|
||||
zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
|
||||
zero_R = (cvtest::randInt(rng)%2) == 0 ? false : true;
|
||||
|
||||
if (useCPlus)
|
||||
{
|
||||
_points.convertTo(src_points, CV_32F);
|
||||
|
||||
camera_mat = test_mat[INPUT][1];
|
||||
distortion_coeffs = test_mat[INPUT][2];
|
||||
R = test_mat[INPUT][3];
|
||||
P = test_mat[INPUT][4];
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void CV_UndistortPointsTest::prepare_to_validation(int /*test_case_idx*/)
|
||||
{
|
||||
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
|
||||
double cam[9] = {0,0,0,0,0,0,0,0,1};
|
||||
double rot[9] = {1,0,0,0,1,0,0,0,1};
|
||||
|
||||
double* dist = new double[dist_size ];
|
||||
double* proj = new double[test_mat[INPUT][4].cols * test_mat[INPUT][4].rows];
|
||||
double* points = new double[N_POINTS*2];
|
||||
double* r_points = new double[N_POINTS*2];
|
||||
//Run reference calculations
|
||||
CvMat ref_points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,r_points);
|
||||
CvMat _camera = cvMat(3,3,CV_64F,cam);
|
||||
CvMat _rot = cvMat(3,3,CV_64F,rot);
|
||||
CvMat _distort = cvMat(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,dist);
|
||||
CvMat _proj = cvMat(test_mat[INPUT][4].rows,test_mat[INPUT][4].cols,CV_64F,proj);
|
||||
CvMat _points= cvMat(test_mat[TEMP][0].rows,test_mat[TEMP][0].cols,CV_64FC2,points);
|
||||
|
||||
Mat __camera = cvarrToMat(&_camera);
|
||||
Mat __distort = cvarrToMat(&_distort);
|
||||
Mat __rot = cvarrToMat(&_rot);
|
||||
Mat __proj = cvarrToMat(&_proj);
|
||||
Mat __points = cvarrToMat(&_points);
|
||||
Mat _ref_points = cvarrToMat(&ref_points);
|
||||
|
||||
cvtest::convert(test_mat[INPUT][1], __camera, __camera.type());
|
||||
cvtest::convert(test_mat[INPUT][2], __distort, __distort.type());
|
||||
cvtest::convert(test_mat[INPUT][3], __rot, __rot.type());
|
||||
cvtest::convert(test_mat[INPUT][4], __proj, __proj.type());
|
||||
|
||||
if (useCPlus)
|
||||
{
|
||||
if (useDstMat)
|
||||
{
|
||||
CvMat temp = dst_points_mat;
|
||||
for (int i=0;i<N_POINTS*2;i++)
|
||||
{
|
||||
points[i] = temp.data.fl[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0;i<N_POINTS;i++)
|
||||
{
|
||||
points[2*i] = dst_points[i].x;
|
||||
points[2*i+1] = dst_points[i].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cvtest::convert(test_mat[TEMP][0],__points, __points.type());
|
||||
}
|
||||
|
||||
CvMat* input2 = zero_distortion ? 0 : &_distort;
|
||||
CvMat* input3 = zero_R ? 0 : &_rot;
|
||||
CvMat* input4 = zero_new_cam ? 0 : &_proj;
|
||||
distortPoints(&_points,&ref_points,&_camera,input2,input3,input4);
|
||||
|
||||
Mat& dst = test_mat[REF_OUTPUT][0];
|
||||
cvtest::convert(_ref_points, dst, dst.type());
|
||||
|
||||
cvtest::copy(test_mat[INPUT][0], test_mat[OUTPUT][0]);
|
||||
|
||||
delete[] dist;
|
||||
delete[] proj;
|
||||
delete[] points;
|
||||
delete[] r_points;
|
||||
}
|
||||
|
||||
void CV_UndistortPointsTest::run_func()
|
||||
{
|
||||
|
||||
if (useCPlus)
|
||||
{
|
||||
cv::Mat input2,input3,input4;
|
||||
input2 = zero_distortion ? cv::Mat() : cv::Mat(test_mat[INPUT][2]);
|
||||
input3 = zero_R ? cv::Mat() : cv::Mat(test_mat[INPUT][3]);
|
||||
input4 = zero_new_cam ? cv::Mat() : cv::Mat(test_mat[INPUT][4]);
|
||||
|
||||
if (useDstMat)
|
||||
{
|
||||
//cv::undistortPoints(src_points,dst_points_mat,camera_mat,distortion_coeffs,R,P);
|
||||
cv::undistortPoints(src_points,dst_points_mat,camera_mat,input2,input3,input4);
|
||||
}
|
||||
else
|
||||
{
|
||||
//cv::undistortPoints(src_points,dst_points,camera_mat,distortion_coeffs,R,P);
|
||||
cv::undistortPoints(src_points,dst_points,camera_mat,input2,input3,input4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CvMat _input0 = test_mat[INPUT][0], _input1 = test_mat[INPUT][1], _input2, _input3, _input4;
|
||||
CvMat _output = test_mat[TEMP][0];
|
||||
if(!zero_distortion)
|
||||
_input2 = test_mat[INPUT][2];
|
||||
if(!zero_R)
|
||||
_input3 = test_mat[INPUT][3];
|
||||
if(!zero_new_cam)
|
||||
_input4 = test_mat[INPUT][4];
|
||||
cvUndistortPoints(&_input0, &_output, &_input1,
|
||||
zero_distortion ? 0 : &_input2,
|
||||
zero_R ? 0 : &_input3,
|
||||
zero_new_cam ? 0 : &_input4);
|
||||
}
|
||||
}
|
||||
|
||||
void CV_UndistortPointsTest::distortPoints(const CvMat* _src, CvMat* _dst, const CvMat* _cameraMatrix,
|
||||
const CvMat* _distCoeffs,
|
||||
const CvMat* matR, const CvMat* matP)
|
||||
{
|
||||
double a[9];
|
||||
|
||||
CvMat* __P;
|
||||
if ((!matP)||(matP->cols == 3))
|
||||
__P = cvCreateMat(3,3,CV_64F);
|
||||
else
|
||||
__P = cvCreateMat(3,4,CV_64F);
|
||||
if (matP)
|
||||
{
|
||||
cvTsConvert(matP,__P);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvZero(__P);
|
||||
__P->data.db[0] = 1;
|
||||
__P->data.db[4] = 1;
|
||||
__P->data.db[8] = 1;
|
||||
}
|
||||
CvMat* __R = cvCreateMat(3,3,CV_64F);;
|
||||
if (matR)
|
||||
{
|
||||
cvCopy(matR,__R);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvZero(__R);
|
||||
__R->data.db[0] = 1;
|
||||
__R->data.db[4] = 1;
|
||||
__R->data.db[8] = 1;
|
||||
}
|
||||
for (int i=0;i<N_POINTS;i++)
|
||||
{
|
||||
int movement = __P->cols > 3 ? 1 : 0;
|
||||
double x = (_src->data.db[2*i]-__P->data.db[2])/__P->data.db[0];
|
||||
double y = (_src->data.db[2*i+1]-__P->data.db[5+movement])/__P->data.db[4+movement];
|
||||
CvMat inverse = cvMat(3,3,CV_64F,a);
|
||||
cvInvert(__R,&inverse);
|
||||
double w1 = x*inverse.data.db[6]+y*inverse.data.db[7]+inverse.data.db[8];
|
||||
double _x = (x*inverse.data.db[0]+y*inverse.data.db[1]+inverse.data.db[2])/w1;
|
||||
double _y = (x*inverse.data.db[3]+y*inverse.data.db[4]+inverse.data.db[5])/w1;
|
||||
|
||||
//Distortions
|
||||
|
||||
double __x = _x;
|
||||
double __y = _y;
|
||||
if (_distCoeffs)
|
||||
{
|
||||
double r2 = _x*_x+_y*_y;
|
||||
|
||||
__x = _x*(1+_distCoeffs->data.db[0]*r2+_distCoeffs->data.db[1]*r2*r2)+
|
||||
2*_distCoeffs->data.db[2]*_x*_y+_distCoeffs->data.db[3]*(r2+2*_x*_x);
|
||||
__y = _y*(1+_distCoeffs->data.db[0]*r2+_distCoeffs->data.db[1]*r2*r2)+
|
||||
2*_distCoeffs->data.db[3]*_x*_y+_distCoeffs->data.db[2]*(r2+2*_y*_y);
|
||||
if ((_distCoeffs->cols > 4) || (_distCoeffs->rows > 4))
|
||||
{
|
||||
__x+=_x*_distCoeffs->data.db[4]*r2*r2*r2;
|
||||
__y+=_y*_distCoeffs->data.db[4]*r2*r2*r2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_dst->data.db[2*i] = __x*_cameraMatrix->data.db[0]+_cameraMatrix->data.db[2];
|
||||
_dst->data.db[2*i+1] = __y*_cameraMatrix->data.db[4]+_cameraMatrix->data.db[5];
|
||||
|
||||
}
|
||||
|
||||
cvReleaseMat(&__R);
|
||||
cvReleaseMat(&__P);
|
||||
|
||||
}
|
||||
|
||||
|
||||
double CV_UndistortPointsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return 5e-2;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
class CV_InitUndistortRectifyMapTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_InitUndistortRectifyMapTest();
|
||||
protected:
|
||||
int prepare_test_case (int test_case_idx);
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
|
||||
private:
|
||||
bool useCPlus;
|
||||
static const int N_POINTS = 100;
|
||||
static const int MAX_X = 2048;
|
||||
static const int MAX_Y = 2048;
|
||||
bool zero_new_cam;
|
||||
bool zero_distortion;
|
||||
bool zero_R;
|
||||
|
||||
|
||||
cv::Size img_size;
|
||||
|
||||
cv::Mat camera_mat;
|
||||
cv::Mat R;
|
||||
cv::Mat new_camera_mat;
|
||||
cv::Mat distortion_coeffs;
|
||||
cv::Mat mapx;
|
||||
cv::Mat mapy;
|
||||
CvMat* _mapx;
|
||||
CvMat* _mapy;
|
||||
int mat_type;
|
||||
};
|
||||
|
||||
CV_InitUndistortRectifyMapTest::CV_InitUndistortRectifyMapTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL); // test points matrix
|
||||
test_array[INPUT].push_back(NULL); // camera matrix
|
||||
test_array[INPUT].push_back(NULL); // distortion coeffs
|
||||
test_array[INPUT].push_back(NULL); // R matrix
|
||||
test_array[INPUT].push_back(NULL); // new camera matrix
|
||||
test_array[OUTPUT].push_back(NULL); // distorted dst points
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
}
|
||||
|
||||
void CV_InitUndistortRectifyMapTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes(test_case_idx,sizes,types);
|
||||
RNG& rng = ts->get_rng();
|
||||
useCPlus = ((cvtest::randInt(rng) % 2)!=0);
|
||||
//useCPlus = 0;
|
||||
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC2;
|
||||
|
||||
types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
types[INPUT][3] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
types[INPUT][4] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
|
||||
|
||||
sizes[INPUT][0] = sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(N_POINTS,1);
|
||||
sizes[INPUT][1] = sizes[INPUT][3] = cvSize(3,3);
|
||||
sizes[INPUT][4] = cvSize(3,3);
|
||||
|
||||
if (cvtest::randInt(rng)%2)
|
||||
{
|
||||
if (cvtest::randInt(rng)%2)
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(1,4);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(1,5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cvtest::randInt(rng)%2)
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(4,1);
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes[INPUT][2] = cvSize(5,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CV_InitUndistortRectifyMapTest::prepare_test_case(int test_case_idx)
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
|
||||
if (code <= 0)
|
||||
return code;
|
||||
|
||||
img_size.width = cvtest::randInt(rng) % MAX_X + 1;
|
||||
img_size.height = cvtest::randInt(rng) % MAX_Y + 1;
|
||||
|
||||
if (useCPlus)
|
||||
{
|
||||
mat_type = (cvtest::randInt(rng) % 2) == 0 ? CV_32FC1 : CV_16SC2;
|
||||
if ((cvtest::randInt(rng) % 4) == 0)
|
||||
mat_type = -1;
|
||||
if ((cvtest::randInt(rng) % 4) == 0)
|
||||
mat_type = CV_32FC2;
|
||||
_mapx = 0;
|
||||
_mapy = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int typex = (cvtest::randInt(rng) % 2) == 0 ? CV_32FC1 : CV_16SC2;
|
||||
//typex = CV_32FC1; ///!!!!!!!!!!!!!!!!
|
||||
int typey = (typex == CV_32FC1) ? CV_32FC1 : CV_16UC1;
|
||||
|
||||
_mapx = cvCreateMat(img_size.height,img_size.width,typex);
|
||||
_mapy = cvCreateMat(img_size.height,img_size.width,typey);
|
||||
|
||||
|
||||
}
|
||||
|
||||
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
|
||||
double cam[9] = {0,0,0,0,0,0,0,0,1};
|
||||
vector<double> dist(dist_size);
|
||||
vector<double> new_cam(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
|
||||
vector<Point2d> points(N_POINTS);
|
||||
|
||||
Mat _camera(3,3,CV_64F,cam);
|
||||
Mat _distort(test_mat[INPUT][2].size(),CV_64F,&dist[0]);
|
||||
Mat _new_cam(test_mat[INPUT][4].size(),CV_64F,&new_cam[0]);
|
||||
Mat _points(test_mat[INPUT][0].size(),CV_64FC2, &points[0]);
|
||||
|
||||
//Generating points
|
||||
for (int i=0;i<N_POINTS;i++)
|
||||
{
|
||||
points[i].x = cvtest::randReal(rng)*img_size.width;
|
||||
points[i].y = cvtest::randReal(rng)*img_size.height;
|
||||
}
|
||||
|
||||
//Generating camera matrix
|
||||
double sz = MAX(img_size.width,img_size.height);
|
||||
double aspect_ratio = cvtest::randReal(rng)*0.6 + 0.7;
|
||||
cam[2] = (img_size.width - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
cam[5] = (img_size.height - 1)*0.5 + cvtest::randReal(rng)*10 - 5;
|
||||
cam[0] = sz/(0.9 - cvtest::randReal(rng)*0.6);
|
||||
cam[4] = aspect_ratio*cam[0];
|
||||
|
||||
//Generating distortion coeffs
|
||||
dist[0] = cvtest::randReal(rng)*0.06 - 0.03;
|
||||
dist[1] = cvtest::randReal(rng)*0.06 - 0.03;
|
||||
if( dist[0]*dist[1] > 0 )
|
||||
dist[1] = -dist[1];
|
||||
if( cvtest::randInt(rng)%4 != 0 )
|
||||
{
|
||||
dist[2] = cvtest::randReal(rng)*0.004 - 0.002;
|
||||
dist[3] = cvtest::randReal(rng)*0.004 - 0.002;
|
||||
if (dist_size > 4)
|
||||
dist[4] = cvtest::randReal(rng)*0.004 - 0.002;
|
||||
}
|
||||
else
|
||||
{
|
||||
dist[2] = dist[3] = 0;
|
||||
if (dist_size > 4)
|
||||
dist[4] = 0;
|
||||
}
|
||||
|
||||
//Generating new camera matrix
|
||||
_new_cam = Scalar::all(0);
|
||||
new_cam[8] = 1;
|
||||
|
||||
//new_cam[0] = cam[0];
|
||||
//new_cam[4] = cam[4];
|
||||
//new_cam[2] = cam[2];
|
||||
//new_cam[5] = cam[5];
|
||||
|
||||
new_cam[0] = cam[0] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[0]; //10%
|
||||
new_cam[4] = cam[4] + (cvtest::randReal(rng) - (double)0.5)*0.2*cam[4]; //10%
|
||||
new_cam[2] = cam[2] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.width; //15%
|
||||
new_cam[5] = cam[5] + (cvtest::randReal(rng) - (double)0.5)*0.3*img_size.height; //15%
|
||||
|
||||
|
||||
//Generating R matrix
|
||||
Mat _rot(3,3,CV_64F);
|
||||
Mat rotation(1,3,CV_64F);
|
||||
rotation.at<double>(0) = CV_PI/8*(cvtest::randReal(rng) - (double)0.5); // phi
|
||||
rotation.at<double>(1) = CV_PI/8*(cvtest::randReal(rng) - (double)0.5); // ksi
|
||||
rotation.at<double>(2) = CV_PI/3*(cvtest::randReal(rng) - (double)0.5); //khi
|
||||
cvtest::Rodrigues(rotation, _rot);
|
||||
|
||||
//cvSetIdentity(_rot);
|
||||
//copying data
|
||||
cvtest::convert( _points, test_mat[INPUT][0], test_mat[INPUT][0].type());
|
||||
cvtest::convert( _camera, test_mat[INPUT][1], test_mat[INPUT][1].type());
|
||||
cvtest::convert( _distort, test_mat[INPUT][2], test_mat[INPUT][2].type());
|
||||
cvtest::convert( _rot, test_mat[INPUT][3], test_mat[INPUT][3].type());
|
||||
cvtest::convert( _new_cam, test_mat[INPUT][4], test_mat[INPUT][4].type());
|
||||
|
||||
zero_distortion = (cvtest::randInt(rng)%2) == 0 ? false : true;
|
||||
zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
|
||||
zero_R = (cvtest::randInt(rng)%2) == 0 ? false : true;
|
||||
|
||||
if (useCPlus)
|
||||
{
|
||||
camera_mat = test_mat[INPUT][1];
|
||||
distortion_coeffs = test_mat[INPUT][2];
|
||||
R = test_mat[INPUT][3];
|
||||
new_camera_mat = test_mat[INPUT][4];
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void CV_InitUndistortRectifyMapTest::prepare_to_validation(int/* test_case_idx*/)
|
||||
{
|
||||
#if 0
|
||||
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
|
||||
double cam[9] = {0,0,0,0,0,0,0,0,1};
|
||||
double rot[9] = {1,0,0,0,1,0,0,0,1};
|
||||
vector<double> dist(dist_size);
|
||||
vector<double> new_cam(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
|
||||
vector<Point2d> points(N_POINTS);
|
||||
vector<Point2d> r_points(N_POINTS);
|
||||
//Run reference calculations
|
||||
Mat ref_points(test_mat[INPUT][0].size(),CV_64FC2,&r_points[0]);
|
||||
Mat _camera(3,3,CV_64F,cam);
|
||||
Mat _rot(3,3,CV_64F,rot);
|
||||
Mat _distort(test_mat[INPUT][2].size(),CV_64F,&dist[0]);
|
||||
Mat _new_cam(test_mat[INPUT][4].size(),CV_64F,&new_cam[0]);
|
||||
Mat _points(test_mat[INPUT][0].size(),CV_64FC2,&points[0]);
|
||||
|
||||
cvtest::convert(test_mat[INPUT][1],_camera,_camera.type());
|
||||
cvtest::convert(test_mat[INPUT][2],_distort,_distort.type());
|
||||
cvtest::convert(test_mat[INPUT][3],_rot,_rot.type());
|
||||
cvtest::convert(test_mat[INPUT][4],_new_cam,_new_cam.type());
|
||||
|
||||
//Applying precalculated undistort rectify map
|
||||
if (!useCPlus)
|
||||
{
|
||||
mapx = cv::Mat(_mapx);
|
||||
mapy = cv::Mat(_mapy);
|
||||
}
|
||||
cv::Mat map1,map2;
|
||||
cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
|
||||
CvMat _map1 = map1;
|
||||
CvMat _map2 = map2;
|
||||
const Point2d* sptr = (const Point2d*)test_mat[INPUT][0].data;
|
||||
for( int i = 0;i < N_POINTS; i++ )
|
||||
{
|
||||
int u = saturate_cast<int>(sptr[i].x);
|
||||
int v = saturate_cast<int>(sptr[i].y);
|
||||
points[i].x = _map1.data.fl[v*_map1.cols + u];
|
||||
points[i].y = _map2.data.fl[v*_map2.cols + u];
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
cv::undistortPoints(_points, ref_points, _camera,
|
||||
zero_distortion ? Mat() : _distort,
|
||||
zero_R ? Mat::eye(3,3,CV_64F) : _rot,
|
||||
zero_new_cam ? _camera : _new_cam);
|
||||
//cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
|
||||
cvtest::convert(ref_points, test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type());
|
||||
cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
|
||||
|
||||
cvReleaseMat(&_mapx);
|
||||
cvReleaseMat(&_mapy);
|
||||
#else
|
||||
int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
|
||||
double cam[9] = {0,0,0,0,0,0,0,0,1};
|
||||
double rot[9] = {1,0,0,0,1,0,0,0,1};
|
||||
double* dist = new double[dist_size ];
|
||||
double* new_cam = new double[test_mat[INPUT][4].cols * test_mat[INPUT][4].rows];
|
||||
double* points = new double[N_POINTS*2];
|
||||
double* r_points = new double[N_POINTS*2];
|
||||
//Run reference calculations
|
||||
CvMat ref_points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,r_points);
|
||||
CvMat _camera = cvMat(3,3,CV_64F,cam);
|
||||
CvMat _rot = cvMat(3,3,CV_64F,rot);
|
||||
CvMat _distort = cvMat(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,dist);
|
||||
CvMat _new_cam = cvMat(test_mat[INPUT][4].rows,test_mat[INPUT][4].cols,CV_64F,new_cam);
|
||||
CvMat _points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,points);
|
||||
|
||||
CvMat _input1 = test_mat[INPUT][1];
|
||||
CvMat _input2 = test_mat[INPUT][2];
|
||||
CvMat _input3 = test_mat[INPUT][3];
|
||||
CvMat _input4 = test_mat[INPUT][4];
|
||||
|
||||
cvTsConvert(&_input1,&_camera);
|
||||
cvTsConvert(&_input2,&_distort);
|
||||
cvTsConvert(&_input3,&_rot);
|
||||
cvTsConvert(&_input4,&_new_cam);
|
||||
|
||||
//Applying precalculated undistort rectify map
|
||||
if (!useCPlus)
|
||||
{
|
||||
mapx = cv::Mat(_mapx);
|
||||
mapy = cv::Mat(_mapy);
|
||||
}
|
||||
cv::Mat map1,map2;
|
||||
cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
|
||||
CvMat _map1 = map1;
|
||||
CvMat _map2 = map2;
|
||||
for (int i=0;i<N_POINTS;i++)
|
||||
{
|
||||
double u = test_mat[INPUT][0].ptr<double>()[2*i];
|
||||
double v = test_mat[INPUT][0].ptr<double>()[2*i+1];
|
||||
_points.data.db[2*i] = (double)_map1.data.fl[(int)v*_map1.cols+(int)u];
|
||||
_points.data.db[2*i+1] = (double)_map2.data.fl[(int)v*_map2.cols+(int)u];
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
cvUndistortPoints(&_points,&ref_points,&_camera,
|
||||
zero_distortion ? 0 : &_distort, zero_R ? 0 : &_rot, zero_new_cam ? &_camera : &_new_cam);
|
||||
//cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
|
||||
CvMat dst = test_mat[REF_OUTPUT][0];
|
||||
cvTsConvert(&ref_points,&dst);
|
||||
|
||||
cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
|
||||
|
||||
delete[] dist;
|
||||
delete[] new_cam;
|
||||
delete[] points;
|
||||
delete[] r_points;
|
||||
cvReleaseMat(&_mapx);
|
||||
cvReleaseMat(&_mapy);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CV_InitUndistortRectifyMapTest::run_func()
|
||||
{
|
||||
if (useCPlus)
|
||||
{
|
||||
cv::Mat input2,input3,input4;
|
||||
input2 = zero_distortion ? cv::Mat() : test_mat[INPUT][2];
|
||||
input3 = zero_R ? cv::Mat() : test_mat[INPUT][3];
|
||||
input4 = zero_new_cam ? cv::Mat() : test_mat[INPUT][4];
|
||||
cv::initUndistortRectifyMap(camera_mat,input2,input3,input4,img_size,mat_type,mapx,mapy);
|
||||
}
|
||||
else
|
||||
{
|
||||
CvMat input1 = test_mat[INPUT][1], input2, input3, input4;
|
||||
if( !zero_distortion )
|
||||
input2 = test_mat[INPUT][2];
|
||||
if( !zero_R )
|
||||
input3 = test_mat[INPUT][3];
|
||||
if( !zero_new_cam )
|
||||
input4 = test_mat[INPUT][4];
|
||||
cvInitUndistortRectifyMap(&input1,
|
||||
zero_distortion ? 0 : &input2,
|
||||
zero_R ? 0 : &input3,
|
||||
zero_new_cam ? 0 : &input4,
|
||||
_mapx,_mapy);
|
||||
}
|
||||
}
|
||||
|
||||
double CV_InitUndistortRectifyMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(Calib3d_DefaultNewCameraMatrix, accuracy) { CV_DefaultNewCameraMatrixTest test; test.safe_run(); }
|
||||
TEST(Calib3d_UndistortPoints, accuracy) { CV_UndistortPointsTest test; test.safe_run(); }
|
||||
TEST(Calib3d_InitUndistortRectifyMap, accuracy) { CV_InitUndistortRectifyMapTest test; test.safe_run(); }
|
518
modules/calib3d/test/test_undistort_badarg.cpp
Normal file
518
modules/calib3d/test/test_undistort_badarg.cpp
Normal file
@ -0,0 +1,518 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
class CV_UndistortPointsBadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_UndistortPointsBadArgTest();
|
||||
protected:
|
||||
void run(int);
|
||||
void run_func();
|
||||
|
||||
private:
|
||||
//common
|
||||
cv::Size img_size;
|
||||
bool useCPlus;
|
||||
//static const int N_POINTS = 1;
|
||||
static const int N_POINTS2 = 2;
|
||||
|
||||
//C
|
||||
CvMat* _camera_mat;
|
||||
CvMat* matR;
|
||||
CvMat* matP;
|
||||
CvMat* _distortion_coeffs;
|
||||
CvMat* _src_points;
|
||||
CvMat* _dst_points;
|
||||
|
||||
|
||||
//C++
|
||||
cv::Mat camera_mat;
|
||||
cv::Mat R;
|
||||
cv::Mat P;
|
||||
cv::Mat distortion_coeffs;
|
||||
cv::Mat src_points;
|
||||
std::vector<cv::Point2f> dst_points;
|
||||
|
||||
};
|
||||
|
||||
CV_UndistortPointsBadArgTest::CV_UndistortPointsBadArgTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void CV_UndistortPointsBadArgTest::run_func()
|
||||
{
|
||||
if (useCPlus)
|
||||
{
|
||||
cv::undistortPoints(src_points,dst_points,camera_mat,distortion_coeffs,R,P);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvUndistortPoints(_src_points,_dst_points,_camera_mat,_distortion_coeffs,matR,matP);
|
||||
}
|
||||
}
|
||||
|
||||
void CV_UndistortPointsBadArgTest::run(int)
|
||||
{
|
||||
//RNG& rng = ts->get_rng();
|
||||
int errcount = 0;
|
||||
useCPlus = false;
|
||||
//initializing
|
||||
img_size.width = 800;
|
||||
img_size.height = 600;
|
||||
double cam[9] = {150.f, 0.f, img_size.width/2.f, 0, 300.f, img_size.height/2.f, 0.f, 0.f, 1.f};
|
||||
double dist[4] = {0.01,0.02,0.001,0.0005};
|
||||
double s_points[N_POINTS2] = {img_size.width/4,img_size.height/4};
|
||||
double d_points[N_POINTS2];
|
||||
double p[9] = {155.f, 0.f, img_size.width/2.f+img_size.width/50.f, 0, 310.f, img_size.height/2.f+img_size.height/50.f, 0.f, 0.f, 1.f};
|
||||
double r[9] = {1,0,0,0,1,0,0,0,1};
|
||||
|
||||
CvMat _camera_mat_orig = cvMat(3,3,CV_64F,cam);
|
||||
CvMat _distortion_coeffs_orig = cvMat(1,4,CV_64F,dist);
|
||||
CvMat _P_orig = cvMat(3,3,CV_64F,p);
|
||||
CvMat _R_orig = cvMat(3,3,CV_64F,r);
|
||||
CvMat _src_points_orig = cvMat(1,4,CV_64FC2,s_points);
|
||||
CvMat _dst_points_orig = cvMat(1,4,CV_64FC2,d_points);
|
||||
|
||||
_camera_mat = &_camera_mat_orig;
|
||||
_distortion_coeffs = &_distortion_coeffs_orig;
|
||||
matP = &_P_orig;
|
||||
matR = &_R_orig;
|
||||
_src_points = &_src_points_orig;
|
||||
_dst_points = &_dst_points_orig;
|
||||
|
||||
//tests
|
||||
CvMat* temp1;
|
||||
CvMat* temp;
|
||||
IplImage* temp_img = cvCreateImage(cvSize(img_size.width,img_size.height),8,3);
|
||||
|
||||
//-----------
|
||||
temp = (CvMat*)temp_img;
|
||||
_src_points = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Input data is not CvMat*" );
|
||||
_src_points = &_src_points_orig;
|
||||
|
||||
temp = (CvMat*)temp_img;
|
||||
_dst_points = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Output data is not CvMat*" );
|
||||
_dst_points = &_dst_points_orig;
|
||||
|
||||
temp = cvCreateMat(2,3,CV_64F);
|
||||
_src_points = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid input data matrix size" );
|
||||
_src_points = &_src_points_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(2,3,CV_64F);
|
||||
_dst_points = temp;
|
||||
errcount += run_test_case(CV_StsAssert, "Invalid output data matrix size" );
|
||||
_dst_points = &_dst_points_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(1,3,CV_64F);
|
||||
temp1 = cvCreateMat(4,1,CV_64F);
|
||||
_dst_points = temp;
|
||||
_src_points = temp1;
|
||||
errcount += run_test_case(CV_StsAssert, "Output and input data sizes mismatch" );
|
||||
_dst_points = &_dst_points_orig;
|
||||
_src_points = &_src_points_orig;
|
||||
cvReleaseMat(&temp);
|
||||
cvReleaseMat(&temp1);
|
||||
|
||||
temp = cvCreateMat(1,3,CV_32S);
|
||||
_dst_points = temp;
|
||||
errcount += run_test_case(CV_StsAssert, "Invalid output data matrix type" );
|
||||
_dst_points = &_dst_points_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(1,3,CV_32S);
|
||||
_src_points = temp;
|
||||
errcount += run_test_case(CV_StsAssert, "Invalid input data matrix type" );
|
||||
_src_points = &_src_points_orig;
|
||||
cvReleaseMat(&temp);
|
||||
//------------
|
||||
temp = cvCreateMat(2,3,CV_64F);
|
||||
_camera_mat = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid camera data matrix size" );
|
||||
_camera_mat = &_camera_mat_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(3,4,CV_64F);
|
||||
_camera_mat = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid camera data matrix size" );
|
||||
_camera_mat = &_camera_mat_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = (CvMat*)temp_img;
|
||||
_camera_mat = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Camera data is not CvMat*" );
|
||||
_camera_mat = &_camera_mat_orig;
|
||||
//----------
|
||||
|
||||
temp = (CvMat*)temp_img;
|
||||
_distortion_coeffs = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Distortion coefficients data is not CvMat*" );
|
||||
_distortion_coeffs = &_distortion_coeffs_orig;
|
||||
|
||||
temp = cvCreateMat(1,6,CV_64F);
|
||||
_distortion_coeffs = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid distortion coefficients data matrix size" );
|
||||
_distortion_coeffs = &_distortion_coeffs_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(3,3,CV_64F);
|
||||
_distortion_coeffs = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid distortion coefficients data matrix size" );
|
||||
_distortion_coeffs = &_distortion_coeffs_orig;
|
||||
cvReleaseMat(&temp);
|
||||
//----------
|
||||
temp = (CvMat*)temp_img;
|
||||
matR = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "R data is not CvMat*" );
|
||||
matR = &_R_orig;
|
||||
|
||||
temp = cvCreateMat(4,3,CV_64F);
|
||||
matR = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid R data matrix size" );
|
||||
matR = &_R_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(3,2,CV_64F);
|
||||
matR = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid R data matrix size" );
|
||||
matR = &_R_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
//-----------
|
||||
temp = (CvMat*)temp_img;
|
||||
matP = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "P data is not CvMat*" );
|
||||
matP = &_P_orig;
|
||||
|
||||
temp = cvCreateMat(4,3,CV_64F);
|
||||
matP = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid P data matrix size" );
|
||||
matP = &_P_orig;
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(3,2,CV_64F);
|
||||
matP = temp;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid P data matrix size" );
|
||||
matP = &_P_orig;
|
||||
cvReleaseMat(&temp);
|
||||
//------------
|
||||
//C++ tests
|
||||
useCPlus = true;
|
||||
|
||||
camera_mat = cv::Mat(&_camera_mat_orig);
|
||||
distortion_coeffs = cv::Mat(&_distortion_coeffs_orig);
|
||||
P = cv::Mat(&_P_orig);
|
||||
R = cv::Mat(&_R_orig);
|
||||
src_points = cv::Mat(&_src_points_orig);
|
||||
|
||||
temp = cvCreateMat(2,2,CV_32FC2);
|
||||
src_points = cv::Mat(temp);
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid input data matrix size" );
|
||||
src_points = cv::Mat(&_src_points_orig);
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(1,4,CV_64FC2);
|
||||
src_points = cv::Mat(temp);
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid input data matrix type" );
|
||||
src_points = cv::Mat(&_src_points_orig);
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
src_points = cv::Mat();
|
||||
errcount += run_test_case( CV_StsAssert, "Input data matrix is not continuous" );
|
||||
src_points = cv::Mat(&_src_points_orig);
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
|
||||
|
||||
//------------
|
||||
cvReleaseImage(&temp_img);
|
||||
ts->set_failed_test_info(errcount > 0 ? cvtest::TS::FAIL_BAD_ARG_CHECK : cvtest::TS::OK);
|
||||
}
|
||||
|
||||
|
||||
//=========
|
||||
class CV_InitUndistortRectifyMapBadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_InitUndistortRectifyMapBadArgTest();
|
||||
protected:
|
||||
void run(int);
|
||||
void run_func();
|
||||
|
||||
private:
|
||||
//common
|
||||
cv::Size img_size;
|
||||
bool useCPlus;
|
||||
|
||||
//C
|
||||
CvMat* _camera_mat;
|
||||
CvMat* matR;
|
||||
CvMat* _new_camera_mat;
|
||||
CvMat* _distortion_coeffs;
|
||||
CvMat* _mapx;
|
||||
CvMat* _mapy;
|
||||
|
||||
|
||||
//C++
|
||||
cv::Mat camera_mat;
|
||||
cv::Mat R;
|
||||
cv::Mat new_camera_mat;
|
||||
cv::Mat distortion_coeffs;
|
||||
cv::Mat mapx;
|
||||
cv::Mat mapy;
|
||||
int mat_type;
|
||||
|
||||
};
|
||||
|
||||
CV_InitUndistortRectifyMapBadArgTest::CV_InitUndistortRectifyMapBadArgTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void CV_InitUndistortRectifyMapBadArgTest::run_func()
|
||||
{
|
||||
if (useCPlus)
|
||||
{
|
||||
cv::initUndistortRectifyMap(camera_mat,distortion_coeffs,R,new_camera_mat,img_size,mat_type,mapx,mapy);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvInitUndistortRectifyMap(_camera_mat,_distortion_coeffs,matR,_new_camera_mat,_mapx,_mapy);
|
||||
}
|
||||
}
|
||||
|
||||
void CV_InitUndistortRectifyMapBadArgTest::run(int)
|
||||
{
|
||||
int errcount = 0;
|
||||
//initializing
|
||||
img_size.width = 800;
|
||||
img_size.height = 600;
|
||||
double cam[9] = {150.f, 0.f, img_size.width/2.f, 0, 300.f, img_size.height/2.f, 0.f, 0.f, 1.f};
|
||||
double dist[4] = {0.01,0.02,0.001,0.0005};
|
||||
float* arr_mapx = new float[img_size.width*img_size.height];
|
||||
float* arr_mapy = new float[img_size.width*img_size.height];
|
||||
double arr_new_camera_mat[9] = {155.f, 0.f, img_size.width/2.f+img_size.width/50.f, 0, 310.f, img_size.height/2.f+img_size.height/50.f, 0.f, 0.f, 1.f};
|
||||
double r[9] = {1,0,0,0,1,0,0,0,1};
|
||||
|
||||
CvMat _camera_mat_orig = cvMat(3,3,CV_64F,cam);
|
||||
CvMat _distortion_coeffs_orig = cvMat(1,4,CV_64F,dist);
|
||||
CvMat _new_camera_mat_orig = cvMat(3,3,CV_64F,arr_new_camera_mat);
|
||||
CvMat _R_orig = cvMat(3,3,CV_64F,r);
|
||||
CvMat _mapx_orig = cvMat(img_size.height,img_size.width,CV_32FC1,arr_mapx);
|
||||
CvMat _mapy_orig = cvMat(img_size.height,img_size.width,CV_32FC1,arr_mapy);
|
||||
int mat_type_orig = CV_32FC1;
|
||||
|
||||
_camera_mat = &_camera_mat_orig;
|
||||
_distortion_coeffs = &_distortion_coeffs_orig;
|
||||
_new_camera_mat = &_new_camera_mat_orig;
|
||||
matR = &_R_orig;
|
||||
_mapx = &_mapx_orig;
|
||||
_mapy = &_mapy_orig;
|
||||
mat_type = mat_type_orig;
|
||||
|
||||
//tests
|
||||
useCPlus = true;
|
||||
CvMat* temp;
|
||||
|
||||
//C++ tests
|
||||
useCPlus = true;
|
||||
|
||||
camera_mat = cv::Mat(&_camera_mat_orig);
|
||||
distortion_coeffs = cv::Mat(&_distortion_coeffs_orig);
|
||||
new_camera_mat = cv::Mat(&_new_camera_mat_orig);
|
||||
R = cv::Mat(&_R_orig);
|
||||
mapx = cv::Mat(&_mapx_orig);
|
||||
mapy = cv::Mat(&_mapy_orig);
|
||||
|
||||
|
||||
mat_type = CV_64F;
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid map matrix type" );
|
||||
mat_type = mat_type_orig;
|
||||
|
||||
temp = cvCreateMat(3,2,CV_32FC1);
|
||||
camera_mat = cv::Mat(temp);
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid camera data matrix size" );
|
||||
camera_mat = cv::Mat(&_camera_mat_orig);
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(4,3,CV_32FC1);
|
||||
R = cv::Mat(temp);
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid R data matrix size" );
|
||||
R = cv::Mat(&_R_orig);
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
temp = cvCreateMat(6,1,CV_32FC1);
|
||||
distortion_coeffs = cv::Mat(temp);
|
||||
errcount += run_test_case( CV_StsAssert, "Invalid distortion coefficients data matrix size" );
|
||||
distortion_coeffs = cv::Mat(&_distortion_coeffs_orig);
|
||||
cvReleaseMat(&temp);
|
||||
|
||||
//------------
|
||||
delete[] arr_mapx;
|
||||
delete[] arr_mapy;
|
||||
ts->set_failed_test_info(errcount > 0 ? cvtest::TS::FAIL_BAD_ARG_CHECK : cvtest::TS::OK);
|
||||
}
|
||||
|
||||
|
||||
//=========
|
||||
class CV_UndistortBadArgTest : public cvtest::BadArgTest
|
||||
{
|
||||
public:
|
||||
CV_UndistortBadArgTest();
|
||||
protected:
|
||||
void run(int);
|
||||
void run_func();
|
||||
|
||||
private:
|
||||
//common
|
||||
cv::Size img_size;
|
||||
bool useCPlus;
|
||||
|
||||
//C
|
||||
CvMat* _camera_mat;
|
||||
CvMat* _new_camera_mat;
|
||||
CvMat* _distortion_coeffs;
|
||||
CvMat* _src;
|
||||
CvMat* _dst;
|
||||
|
||||
|
||||
//C++
|
||||
cv::Mat camera_mat;
|
||||
cv::Mat new_camera_mat;
|
||||
cv::Mat distortion_coeffs;
|
||||
cv::Mat src;
|
||||
cv::Mat dst;
|
||||
|
||||
};
|
||||
|
||||
CV_UndistortBadArgTest::CV_UndistortBadArgTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void CV_UndistortBadArgTest::run_func()
|
||||
{
|
||||
if (useCPlus)
|
||||
{
|
||||
cv::undistort(src,dst,camera_mat,distortion_coeffs,new_camera_mat);
|
||||
}
|
||||
else
|
||||
{
|
||||
cvUndistort2(_src,_dst,_camera_mat,_distortion_coeffs,_new_camera_mat);
|
||||
}
|
||||
}
|
||||
|
||||
void CV_UndistortBadArgTest::run(int)
|
||||
{
|
||||
int errcount = 0;
|
||||
//initializing
|
||||
img_size.width = 800;
|
||||
img_size.height = 600;
|
||||
double cam[9] = {150.f, 0.f, img_size.width/2.f, 0, 300.f, img_size.height/2.f, 0.f, 0.f, 1.f};
|
||||
double dist[4] = {0.01,0.02,0.001,0.0005};
|
||||
float* arr_src = new float[img_size.width*img_size.height];
|
||||
float* arr_dst = new float[img_size.width*img_size.height];
|
||||
double arr_new_camera_mat[9] = {155.f, 0.f, img_size.width/2.f+img_size.width/50.f, 0, 310.f, img_size.height/2.f+img_size.height/50.f, 0.f, 0.f, 1.f};
|
||||
|
||||
CvMat _camera_mat_orig = cvMat(3,3,CV_64F,cam);
|
||||
CvMat _distortion_coeffs_orig = cvMat(1,4,CV_64F,dist);
|
||||
CvMat _new_camera_mat_orig = cvMat(3,3,CV_64F,arr_new_camera_mat);
|
||||
CvMat _src_orig = cvMat(img_size.height,img_size.width,CV_32FC1,arr_src);
|
||||
CvMat _dst_orig = cvMat(img_size.height,img_size.width,CV_32FC1,arr_dst);
|
||||
|
||||
_camera_mat = &_camera_mat_orig;
|
||||
_distortion_coeffs = &_distortion_coeffs_orig;
|
||||
_new_camera_mat = &_new_camera_mat_orig;
|
||||
_src = &_src_orig;
|
||||
_dst = &_dst_orig;
|
||||
|
||||
//tests
|
||||
useCPlus = true;
|
||||
CvMat* temp;
|
||||
CvMat* temp1;
|
||||
|
||||
//C tests
|
||||
useCPlus = false;
|
||||
|
||||
temp = cvCreateMat(800,600,CV_32F);
|
||||
temp1 = cvCreateMat(800,601,CV_32F);
|
||||
_src = temp;
|
||||
_dst = temp1;
|
||||
errcount += run_test_case( CV_StsAssert, "Input and output data matrix sizes mismatch" );
|
||||
_src = &_src_orig;
|
||||
_dst = &_dst_orig;
|
||||
cvReleaseMat(&temp);
|
||||
cvReleaseMat(&temp1);
|
||||
|
||||
temp = cvCreateMat(800,600,CV_32F);
|
||||
temp1 = cvCreateMat(800,600,CV_64F);
|
||||
_src = temp;
|
||||
_dst = temp1;
|
||||
errcount += run_test_case( CV_StsAssert, "Input and output data matrix types mismatch" );
|
||||
_src = &_src_orig;
|
||||
_dst = &_dst_orig;
|
||||
cvReleaseMat(&temp);
|
||||
cvReleaseMat(&temp1);
|
||||
|
||||
//C++ tests
|
||||
useCPlus = true;
|
||||
|
||||
camera_mat = cv::Mat(&_camera_mat_orig);
|
||||
distortion_coeffs = cv::Mat(&_distortion_coeffs_orig);
|
||||
new_camera_mat = cv::Mat(&_new_camera_mat_orig);
|
||||
src = cv::Mat(&_src_orig);
|
||||
dst = cv::Mat(&_dst_orig);
|
||||
|
||||
//------------
|
||||
delete[] arr_src;
|
||||
delete[] arr_dst;
|
||||
ts->set_failed_test_info(errcount > 0 ? cvtest::TS::FAIL_BAD_ARG_CHECK : cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Calib3d_UndistortPoints, badarg) { CV_UndistortPointsBadArgTest test; test.safe_run(); }
|
||||
TEST(Calib3d_InitUndistortRectifyMap, badarg) { CV_InitUndistortRectifyMapBadArgTest test; test.safe_run(); }
|
||||
TEST(Calib3d_Undistort, badarg) { CV_UndistortBadArgTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
@ -549,8 +549,6 @@ namespace cv
|
||||
};
|
||||
|
||||
|
||||
CV_EXPORTS bool find4QuadCornerSubpix(const Mat& img, std::vector<Point2f>& corners, Size region_size);
|
||||
|
||||
CV_EXPORTS int chamerMatching( Mat& img, Mat& templ,
|
||||
vector<vector<Point> >& results, vector<float>& cost,
|
||||
double templScale=1, int maxMatches = 20,
|
||||
|
@ -288,14 +288,6 @@ CV_INLINE IppiSize ippiSize(int width, int height)
|
||||
/* ! DO NOT make it an inline function */
|
||||
#define cvStackAlloc(size) cvAlignPtr( alloca((size) + CV_MALLOC_ALIGN), CV_MALLOC_ALIGN )
|
||||
|
||||
#if defined _MSC_VER || defined __BORLANDC__
|
||||
#define CV_BIG_INT(n) n##I64
|
||||
#define CV_BIG_UINT(n) n##UI64
|
||||
#else
|
||||
#define CV_BIG_INT(n) n##LL
|
||||
#define CV_BIG_UINT(n) n##ULL
|
||||
#endif
|
||||
|
||||
#ifndef CV_IMPL
|
||||
#define CV_IMPL CV_EXTERN_C
|
||||
#endif
|
||||
|
@ -145,9 +145,13 @@
|
||||
#if defined _MSC_VER || defined __BORLANDC__
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#define CV_BIG_INT(n) n##I64
|
||||
#define CV_BIG_UINT(n) n##UI64
|
||||
#else
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
#define CV_BIG_INT(n) n##LL
|
||||
#define CV_BIG_UINT(n) n##ULL
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_IPL
|
||||
|
@ -1158,10 +1158,10 @@ div_( const Mat& srcmat1, const Mat& srcmat2, Mat& dstmat, double scale )
|
||||
b *= d;
|
||||
a *= d;
|
||||
|
||||
T z0 = saturate_cast<T>(src2[i+1] * src1[i] * b);
|
||||
T z1 = saturate_cast<T>(src2[i] * src1[i+1] * b);
|
||||
T z2 = saturate_cast<T>(src2[i+3] * src1[i+2] * a);
|
||||
T z3 = saturate_cast<T>(src2[i+2] * src1[i+3] * a);
|
||||
T z0 = saturate_cast<T>(src2[i+1] * ((double)src1[i] * b));
|
||||
T z1 = saturate_cast<T>(src2[i] * ((double)src1[i+1] * b));
|
||||
T z2 = saturate_cast<T>(src2[i+3] * ((double)src1[i+2] * a));
|
||||
T z3 = saturate_cast<T>(src2[i+2] * ((double)src1[i+3] * a));
|
||||
|
||||
dst[i] = z0; dst[i+1] = z1;
|
||||
dst[i+2] = z2; dst[i+3] = z3;
|
||||
@ -1193,7 +1193,7 @@ void divide(const Mat& src1, const Mat& src2, Mat& dst, double scale)
|
||||
};
|
||||
|
||||
MulDivFunc func = tab[src1.depth()];
|
||||
CV_Assert( src1.size() == src2.size() && src1.type() == src2.type() && func != 0 );
|
||||
CV_Assert( src1.type() == src2.type() && func != 0 );
|
||||
|
||||
if( src1.dims > 2 || src2.dims > 2 )
|
||||
{
|
||||
@ -1446,7 +1446,7 @@ void addWeighted( const Mat& src1, double alpha, const Mat& src2,
|
||||
addWeighted_<ushort, float>,
|
||||
addWeighted_<short, float>,
|
||||
addWeighted_<int, double>,
|
||||
addWeighted_<float, float>,
|
||||
addWeighted_<float, double>,
|
||||
addWeighted_<double, double>,
|
||||
0
|
||||
};
|
||||
@ -1952,7 +1952,7 @@ void compare( const Mat& src1, double value, Mat& dst, int cmpOp )
|
||||
{
|
||||
func( it.planes[0], it.planes[1], value );
|
||||
if( invflag )
|
||||
bitwise_not(it.planes[2], it.planes[2]);
|
||||
bitwise_not(it.planes[1], it.planes[1]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ static const int FBITS = 15;
|
||||
typedef void (*CvtFunc)( const Mat& src, Mat& dst );
|
||||
typedef void (*CvtScaleFunc)( const Mat& src, Mat& dst, double scale, double shift );
|
||||
|
||||
void convertScaleAbs( const Mat& src, Mat& dst, double scale, double shift )
|
||||
void convertScaleAbs( const Mat& src0, Mat& dst, double scale, double shift )
|
||||
{
|
||||
static CvtScaleFunc tab[] =
|
||||
{
|
||||
@ -632,15 +632,27 @@ void convertScaleAbs( const Mat& src, Mat& dst, double scale, double shift )
|
||||
cvtScale_<double, OpCvtAbs<double, uchar> >, 0
|
||||
};
|
||||
|
||||
Mat src0 = src;
|
||||
dst.create( src.size(), CV_8UC(src.channels()) );
|
||||
CvtScaleFunc func = tab[src0.depth()];
|
||||
Mat src = src0;
|
||||
dst.create( src.dims, src.size, CV_8UC(src.channels()) );
|
||||
CvtScaleFunc func = tab[src.depth()];
|
||||
CV_Assert( func != 0 );
|
||||
func( src0, dst, scale, shift );
|
||||
|
||||
if( src.dims <= 2 )
|
||||
{
|
||||
func( src, dst, scale, shift );
|
||||
}
|
||||
else
|
||||
{
|
||||
const Mat* arrays[] = {&src, &dst, 0};
|
||||
Mat planes[2];
|
||||
NAryMatIterator it(arrays, planes);
|
||||
|
||||
for( int i = 0; i < it.nplanes; i++, ++it )
|
||||
func(it.planes[0], it.planes[1], scale, shift);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
|
||||
{
|
||||
static CvtFunc tab[8][8] =
|
||||
@ -699,7 +711,7 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
|
||||
cvtScaleInt_<ushort, OpCvtFixPt<int, ushort, FBITS>, OpCvt<float, ushort>, 0>,
|
||||
cvtScaleInt_<ushort, OpCvtFixPt<int, short, FBITS>, OpCvt<float, short>, 0>,
|
||||
cvtScale_<ushort, OpCvt<double, int> >,
|
||||
cvtScale_<ushort, OpCvt<float, float> >,
|
||||
cvtScale_<ushort, OpCvt<double, float> >,
|
||||
cvtScale_<ushort, OpCvt<double, double> >, 0,
|
||||
},
|
||||
|
||||
@ -709,7 +721,7 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
|
||||
cvtScaleInt_<short, OpCvtFixPt<int, ushort, FBITS>, OpCvt<float, ushort>, 1<<15>,
|
||||
cvtScaleInt_<short, OpCvtFixPt<int, short, FBITS>, OpCvt<float, short>, 1<<15>,
|
||||
cvtScale_<short, OpCvt<double, int> >,
|
||||
cvtScale_<short, OpCvt<float, float> >,
|
||||
cvtScale_<short, OpCvt<double, float> >,
|
||||
cvtScale_<short, OpCvt<double, double> >, 0,
|
||||
},
|
||||
|
||||
@ -719,7 +731,7 @@ void Mat::convertTo(Mat& dst, int _type, double alpha, double beta) const
|
||||
cvtScale_<int, OpCvt<double, ushort> >,
|
||||
cvtScale_<int, OpCvt<double, short> >,
|
||||
cvtScale_<int, OpCvt<double, int> >,
|
||||
cvtScale_<int, OpCvt<float, float> >,
|
||||
cvtScale_<int, OpCvt<double, float> >,
|
||||
cvtScale_<int, OpCvt<double, double> >, 0,
|
||||
},
|
||||
|
||||
|
@ -47,37 +47,17 @@ namespace cv
|
||||
{
|
||||
|
||||
static const int MAX_BLOCK_SIZE = 1024;
|
||||
|
||||
typedef CvStatus (CV_STDCALL * MathFunc)(const void* src, void* dst, int len);
|
||||
|
||||
#define ICV_MATH_BLOCK_SIZE 256
|
||||
|
||||
#define _CV_SQRT_MAGIC 0xbe6f0000
|
||||
|
||||
#define _CV_SQRT_MAGIC_DBL CV_BIG_UINT(0xbfcd460000000000)
|
||||
|
||||
#define _CV_ATAN_CF0 (-15.8131890796f)
|
||||
#define _CV_ATAN_CF1 (61.0941945596f)
|
||||
#define _CV_ATAN_CF2 0.f /*(-0.140500406322f)*/
|
||||
|
||||
static const float icvAtanTab[8] = { 0.f + _CV_ATAN_CF2, 90.f - _CV_ATAN_CF2,
|
||||
180.f - _CV_ATAN_CF2, 90.f + _CV_ATAN_CF2,
|
||||
360.f - _CV_ATAN_CF2, 270.f + _CV_ATAN_CF2,
|
||||
180.f + _CV_ATAN_CF2, 270.f - _CV_ATAN_CF2
|
||||
};
|
||||
|
||||
static const int icvAtanSign[8] =
|
||||
{ 0, 0x80000000, 0x80000000, 0, 0x80000000, 0, 0, 0x80000000 };
|
||||
|
||||
float fastAtan2( float y, float x )
|
||||
{
|
||||
double a, x2 = (double)x*x, y2 = (double)y*y;
|
||||
if( y2 <= x2 )
|
||||
{
|
||||
a = (180./CV_PI)*x*y/(x2 + 0.28*y2 + DBL_EPSILON);
|
||||
a = (180./CV_PI)*x*y*(x2 + 0.43157974*y2)/(x2*x2 + y2*(0.76443945*x2 + 0.05831938*y2) + DBL_EPSILON);
|
||||
return (float)(x < 0 ? a + 180 : y >= 0 ? a : 360+a);
|
||||
}
|
||||
a = (180./CV_PI)*x*y/(y2 + 0.28*x2 + DBL_EPSILON);
|
||||
a = (180./CV_PI)*x*y*(y2 + 0.43157974*x2)/(y2*y2 + x2*(0.76443945*y2 + 0.05831938*x2) + DBL_EPSILON);
|
||||
return (float)(y >= 0 ? 90 - a : 270 - a);
|
||||
}
|
||||
|
||||
@ -95,15 +75,20 @@ static CvStatus CV_STDCALL FastAtan2_32f(const float *Y, const float *X, float *
|
||||
Cv32suf iabsmask; iabsmask.i = 0x7fffffff;
|
||||
__m128 eps = _mm_set1_ps((float)DBL_EPSILON), absmask = _mm_set1_ps(iabsmask.f);
|
||||
__m128 _90 = _mm_set1_ps((float)(CV_PI*0.5)), _180 = _mm_set1_ps((float)CV_PI), _360 = _mm_set1_ps((float)(CV_PI*2));
|
||||
__m128 zero = _mm_setzero_ps(), _0_28 = _mm_set1_ps(0.28f), scale4 = _mm_set1_ps(scale);
|
||||
__m128 zero = _mm_setzero_ps(), scale4 = _mm_set1_ps(scale);
|
||||
__m128 p0 = _mm_set1_ps(0.43157974f), q0 = _mm_set1_ps(0.76443945f), q1 = _mm_set1_ps(0.05831938f);
|
||||
|
||||
for( ; i <= len - 4; i += 4 )
|
||||
{
|
||||
__m128 x4 = _mm_loadu_ps(X + i), y4 = _mm_loadu_ps(Y + i);
|
||||
__m128 xq4 = _mm_mul_ps(x4, x4), yq4 = _mm_mul_ps(y4, y4);
|
||||
__m128 xly = _mm_cmplt_ps(xq4, yq4);
|
||||
__m128 z4 = _mm_div_ps(_mm_mul_ps(x4, y4), _mm_add_ps(_mm_add_ps(_mm_max_ps(xq4, yq4),
|
||||
_mm_mul_ps(_mm_min_ps(xq4, yq4), _0_28)), eps));
|
||||
__m128 t = _mm_min_ps(xq4, yq4);
|
||||
xq4 = _mm_max_ps(xq4, yq4); yq4 = t;
|
||||
__m128 z4 = _mm_div_ps(_mm_mul_ps(_mm_mul_ps(x4, y4), _mm_add_ps(xq4, _mm_mul_ps(yq4, p0))),
|
||||
_mm_add_ps(eps, _mm_add_ps(_mm_mul_ps(xq4, xq4),
|
||||
_mm_mul_ps(yq4, _mm_add_ps(_mm_mul_ps(xq4, q0),
|
||||
_mm_mul_ps(yq4, q1))))));
|
||||
|
||||
// a4 <- x < y ? 90 : 0;
|
||||
__m128 a4 = _mm_and_ps(xly, _90);
|
||||
@ -121,15 +106,19 @@ static CvStatus CV_STDCALL FastAtan2_32f(const float *Y, const float *X, float *
|
||||
}
|
||||
#endif
|
||||
|
||||
for( ; i < len; i++ )
|
||||
for( ; i < len; i++ )
|
||||
{
|
||||
float x = X[i], y = Y[i];
|
||||
float a, x2 = x*x, y2 = y*y;
|
||||
if( y2 <= x2 )
|
||||
a = x*y/(x2 + 0.28f*y2 + (float)DBL_EPSILON) + (float)(x < 0 ? CV_PI : y >= 0 ? 0 : CV_PI*2);
|
||||
else
|
||||
a = (float)(y >= 0 ? CV_PI*0.5 : CV_PI*1.5) - x*y/(y2 + 0.28f*x2 + (float)DBL_EPSILON);
|
||||
angle[i] = a*scale;
|
||||
double x = X[i], y = Y[i], x2 = x*x, y2 = y*y, a;
|
||||
|
||||
if( y2 <= x2 )
|
||||
a = (x < 0 ? CV_PI : y >= 0 ? 0 : CV_PI*2) +
|
||||
x*y*(x2 + 0.43157974*y2)/(x2*x2 + y2*(0.76443945*x2 + 0.05831938*y2) + (float)DBL_EPSILON);
|
||||
else
|
||||
{
|
||||
a = (y >= 0 ? CV_PI*0.5 : CV_PI*1.5) -
|
||||
x*y*(y2 + 0.43157974*x2)/(y2*y2 + x2*(0.76443945*y2 + 0.05831938*x2) + (float)DBL_EPSILON);
|
||||
}
|
||||
angle[i] = a*scale;
|
||||
}
|
||||
|
||||
return CV_OK;
|
||||
|
@ -102,6 +102,7 @@ static inline void setSize( Mat& m, int _dims, const int* _sz,
|
||||
m.step.p = (size_t*)fastMalloc(_dims*sizeof(m.step.p[0]) + (_dims+1)*sizeof(m.size.p[0]));
|
||||
m.size.p = (int*)(m.step.p + _dims) + 1;
|
||||
m.size.p[-1] = _dims;
|
||||
m.rows = m.cols = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -711,10 +712,19 @@ void insertImageCOI(const Mat& ch, CvArr* arr, int coi)
|
||||
|
||||
Mat Mat::reshape(int new_cn, int new_rows) const
|
||||
{
|
||||
CV_Assert( dims <= 2 );
|
||||
Mat hdr = *this;
|
||||
|
||||
int cn = channels();
|
||||
Mat hdr = *this;
|
||||
|
||||
if( dims > 2 && new_rows == 0 && new_cn != 0 && size[dims-1]*cn % new_cn == 0 )
|
||||
{
|
||||
hdr.flags = (hdr.flags & ~CV_MAT_CN_MASK) | ((new_cn-1) << CV_CN_SHIFT);
|
||||
hdr.step[dims-1] = CV_ELEM_SIZE(hdr.flags);
|
||||
hdr.size[dims-1] = hdr.size[dims-1]*cn / new_cn;
|
||||
return hdr;
|
||||
}
|
||||
|
||||
CV_Assert( dims <= 2 );
|
||||
|
||||
if( new_cn == 0 )
|
||||
new_cn = cn;
|
||||
|
||||
|
@ -409,7 +409,7 @@ template<> inline Vec<double, 4> SqrC4<uchar, double>::operator() (const Vec<uch
|
||||
|
||||
|
||||
template<class SqrOp> static void
|
||||
meanStdDev_( const Mat& srcmat, Scalar& _mean, Scalar& _stddev )
|
||||
meanStdDev_( const Mat& srcmat, Scalar& _sum, Scalar& _sqsum )
|
||||
{
|
||||
SqrOp sqr;
|
||||
typedef typename SqrOp::type1 T;
|
||||
@ -430,20 +430,13 @@ meanStdDev_( const Mat& srcmat, Scalar& _mean, Scalar& _stddev )
|
||||
sq += sqr(v);
|
||||
}
|
||||
}
|
||||
|
||||
_mean = _stddev = Scalar();
|
||||
double scale = 1./std::max(size.width*size.height, 1);
|
||||
for( int i = 0; i < DataType<ST>::channels; i++ )
|
||||
{
|
||||
double t = ((ST1*)&s)[i]*scale;
|
||||
_mean.val[i] = t;
|
||||
_stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i]*scale - t*t, 0.));
|
||||
}
|
||||
_sum = rawToScalar(s);
|
||||
_sqsum = rawToScalar(sq);
|
||||
}
|
||||
|
||||
template<class SqrOp> static void
|
||||
meanStdDevMask_( const Mat& srcmat, const Mat& maskmat,
|
||||
Scalar& _mean, Scalar& _stddev )
|
||||
Scalar& _sum, Scalar& _sqsum, int& _nz )
|
||||
{
|
||||
SqrOp sqr;
|
||||
typedef typename SqrOp::type1 T;
|
||||
@ -470,20 +463,15 @@ meanStdDevMask_( const Mat& srcmat, const Mat& maskmat,
|
||||
pix++;
|
||||
}
|
||||
}
|
||||
_mean = _stddev = Scalar();
|
||||
double scale = 1./std::max(pix, 1);
|
||||
for( int i = 0; i < DataType<ST>::channels; i++ )
|
||||
{
|
||||
double t = ((ST1*)&s)[i]*scale;
|
||||
_mean.val[i] = t;
|
||||
_stddev.val[i] = std::sqrt(std::max(((ST1*)&sq)[i]*scale - t*t, 0.));
|
||||
}
|
||||
_sum = rawToScalar(s);
|
||||
_sqsum = rawToScalar(sq);
|
||||
_nz = pix;
|
||||
}
|
||||
|
||||
typedef void (*MeanStdDevFunc)(const Mat& src, Scalar& mean, Scalar& stddev);
|
||||
typedef void (*MeanStdDevFunc)(const Mat& src, Scalar& s, Scalar& sq);
|
||||
|
||||
typedef void (*MeanStdDevMaskFunc)(const Mat& src, const Mat& mask,
|
||||
Scalar& mean, Scalar& stddev);
|
||||
Scalar& s, Scalar& sq, int& nz);
|
||||
|
||||
void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
|
||||
{
|
||||
@ -551,55 +539,53 @@ void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
|
||||
|
||||
CV_Assert( m.channels() <= 4 && (mask.empty() || mask.type() == CV_8U) );
|
||||
|
||||
Scalar sum, sqsum;
|
||||
int total = 0;
|
||||
MeanStdDevFunc func = tab[m.type()];
|
||||
MeanStdDevMaskFunc mfunc = mtab[m.type()];
|
||||
CV_Assert( func != 0 || mfunc != 0 );
|
||||
CV_Assert( func != 0 && mfunc != 0 );
|
||||
|
||||
if( m.dims > 2 )
|
||||
{
|
||||
Scalar s, sq;
|
||||
double total = 0;
|
||||
|
||||
const Mat* arrays[] = {&m, &mask, 0};
|
||||
Mat planes[2];
|
||||
NAryMatIterator it(arrays, planes);
|
||||
int k, cn = m.channels();
|
||||
int nz = (int)planes[0].total();
|
||||
|
||||
for( int i = 0; i < it.nplanes; i++, ++it )
|
||||
{
|
||||
Scalar _mean, _stddev;
|
||||
double nz = (double)(mask.data ? countNonZero(it.planes[1]) : it.planes[0].rows*it.planes[0].cols);
|
||||
Scalar s, sq;
|
||||
|
||||
if( func )
|
||||
func(it.planes[0], _mean, _stddev);
|
||||
if( mask.empty() )
|
||||
func(it.planes[0], s, sq);
|
||||
else
|
||||
mfunc(it.planes[0], it.planes[1], _mean, _stddev);
|
||||
mfunc(it.planes[0], it.planes[1], s, sq, nz);
|
||||
|
||||
total += nz;
|
||||
for( k = 0; k < cn; k++ )
|
||||
{
|
||||
s[k] += _mean[k]*nz;
|
||||
sq[k] += (_stddev[k]*_stddev[k] + _mean[k]*_mean[k])*nz;
|
||||
}
|
||||
sum += s;
|
||||
sqsum += sq;
|
||||
}
|
||||
|
||||
mean = stddev = Scalar();
|
||||
total = 1./std::max(total, 1.);
|
||||
for( k = 0; k < cn; k++ )
|
||||
{
|
||||
mean[k] = s[k]*total;
|
||||
stddev[k] = std::sqrt(std::max(sq[k]*total - mean[k]*mean[k], 0.));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( mask.data )
|
||||
{
|
||||
CV_Assert( mask.size() == m.size() );
|
||||
mfunc( m, mask, mean, stddev );
|
||||
}
|
||||
else
|
||||
func( m, mean, stddev );
|
||||
{
|
||||
if( mask.data )
|
||||
{
|
||||
CV_Assert( mask.size() == m.size() );
|
||||
mfunc( m, mask, sum, sqsum, total );
|
||||
}
|
||||
else
|
||||
{
|
||||
func( m, sum, sqsum );
|
||||
total = (int)m.total();
|
||||
}
|
||||
}
|
||||
|
||||
double scale = 1./std::max(total, 1);
|
||||
for( int k = 0; k < 4; k++ )
|
||||
{
|
||||
mean[k] = sum[k]*scale;
|
||||
stddev[k] = std::sqrt(std::max(sqsum[k]*scale - mean[k]*mean[k], 0.));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -607,45 +593,46 @@ void meanStdDev( const Mat& m, Scalar& mean, Scalar& stddev, const Mat& mask )
|
||||
* minMaxLoc *
|
||||
\****************************************************************************************/
|
||||
|
||||
template<typename T> static void
|
||||
minMaxIndx_( const Mat& srcmat, double* minVal, double* maxVal, int* minLoc, int* maxLoc )
|
||||
template<typename T, typename WT> static void
|
||||
minMaxIndx_( const Mat& srcmat, double* _minVal, double* _maxVal,
|
||||
size_t startIdx, size_t* _minIdx, size_t* _maxIdx )
|
||||
{
|
||||
assert( DataType<T>::type == srcmat.type() );
|
||||
const T* src = (const T*)srcmat.data;
|
||||
size_t step = srcmat.step/sizeof(src[0]);
|
||||
T min_val = src[0], max_val = min_val;
|
||||
int min_loc = 0, max_loc = 0;
|
||||
int x, loc = 0;
|
||||
WT minVal = saturate_cast<WT>(*_minVal), maxVal = saturate_cast<WT>(*_maxVal);
|
||||
size_t minIdx = *_minIdx, maxIdx = *_maxIdx;
|
||||
Size size = getContinuousSize( srcmat );
|
||||
|
||||
for( ; size.height--; src += step, loc += size.width )
|
||||
for( ; size.height--; src += step, startIdx += size.width )
|
||||
{
|
||||
for( x = 0; x < size.width; x++ )
|
||||
for( int x = 0; x < size.width; x++ )
|
||||
{
|
||||
T val = src[x];
|
||||
if( val < min_val )
|
||||
if( val < minVal )
|
||||
{
|
||||
min_val = val;
|
||||
min_loc = loc + x;
|
||||
minVal = val;
|
||||
minIdx = startIdx + x;
|
||||
}
|
||||
else if( val > max_val )
|
||||
if( val > maxVal )
|
||||
{
|
||||
max_val = val;
|
||||
max_loc = loc + x;
|
||||
maxVal = val;
|
||||
maxIdx = startIdx + x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*minLoc = min_loc;
|
||||
*maxLoc = max_loc;
|
||||
*minVal = min_val;
|
||||
*maxVal = max_val;
|
||||
*_minIdx = minIdx;
|
||||
*_maxIdx = maxIdx;
|
||||
*_minVal = minVal;
|
||||
*_maxVal = maxVal;
|
||||
}
|
||||
|
||||
|
||||
template<typename T> static void
|
||||
template<typename T, typename WT> static void
|
||||
minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat,
|
||||
double* minVal, double* maxVal, int* minLoc, int* maxLoc )
|
||||
double* _minVal, double* _maxVal,
|
||||
size_t startIdx, size_t* _minIdx, size_t* _maxIdx )
|
||||
{
|
||||
assert( DataType<T>::type == srcmat.type() &&
|
||||
CV_8U == maskmat.type() &&
|
||||
@ -654,54 +641,40 @@ minMaxIndxMask_( const Mat& srcmat, const Mat& maskmat,
|
||||
const uchar* mask = maskmat.data;
|
||||
size_t step = srcmat.step/sizeof(src[0]);
|
||||
size_t maskstep = maskmat.step;
|
||||
T min_val = 0, max_val = 0;
|
||||
int min_loc = -1, max_loc = -1;
|
||||
int x = 0, y, loc = 0;
|
||||
WT minVal = saturate_cast<WT>(*_minVal), maxVal = saturate_cast<WT>(*_maxVal);
|
||||
size_t minIdx = *_minIdx, maxIdx = *_maxIdx;
|
||||
Size size = getContinuousSize( srcmat, maskmat );
|
||||
|
||||
for( y = 0; y < size.height; y++, src += step, mask += maskstep, loc += size.width )
|
||||
for( ; size.height--; src += step, mask += maskstep, startIdx += size.width )
|
||||
{
|
||||
for( x = 0; x < size.width; x++ )
|
||||
if( mask[x] != 0 )
|
||||
{
|
||||
min_loc = max_loc = loc + x;
|
||||
min_val = max_val = src[x];
|
||||
break;
|
||||
}
|
||||
if( x < size.width )
|
||||
break;
|
||||
}
|
||||
|
||||
for( ; y < size.height; x = 0, y++, src += step, mask += maskstep, loc += size.width )
|
||||
{
|
||||
for( ; x < size.width; x++ )
|
||||
for( int x = 0; x < size.width; x++ )
|
||||
{
|
||||
T val = src[x];
|
||||
int m = mask[x];
|
||||
|
||||
if( val < min_val && m )
|
||||
|
||||
if( val < minVal && m )
|
||||
{
|
||||
min_val = val;
|
||||
min_loc = loc + x;
|
||||
minVal = val;
|
||||
minIdx = startIdx + x;
|
||||
}
|
||||
else if( val > max_val && m )
|
||||
if( val > maxVal && m )
|
||||
{
|
||||
max_val = val;
|
||||
max_loc = loc + x;
|
||||
maxVal = val;
|
||||
maxIdx = startIdx + x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*minLoc = min_loc;
|
||||
*maxLoc = max_loc;
|
||||
*minVal = min_val;
|
||||
*maxVal = max_val;
|
||||
*_minIdx = minIdx;
|
||||
*_maxIdx = maxIdx;
|
||||
*_minVal = minVal;
|
||||
*_maxVal = maxVal;
|
||||
}
|
||||
|
||||
typedef void (*MinMaxIndxFunc)(const Mat&, double*, double*, int*, int*);
|
||||
typedef void (*MinMaxIndxFunc)(const Mat&, double*, double*, size_t, size_t*, size_t*);
|
||||
|
||||
typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&,
|
||||
double*, double*, int*, int*);
|
||||
typedef void (*MinMaxIndxMaskFunc)(const Mat&, const Mat&, double*, double*,
|
||||
size_t, size_t*, size_t*);
|
||||
|
||||
void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
|
||||
Point* minLoc, Point* maxLoc, const Mat& mask )
|
||||
@ -709,15 +682,20 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
|
||||
CV_Assert(img.dims <= 2);
|
||||
|
||||
static MinMaxIndxFunc tab[] =
|
||||
{minMaxIndx_<uchar>, 0, minMaxIndx_<ushort>, minMaxIndx_<short>,
|
||||
minMaxIndx_<int>, minMaxIndx_<float>, minMaxIndx_<double>, 0};
|
||||
{
|
||||
minMaxIndx_<uchar, int>, 0, minMaxIndx_<ushort, int>, minMaxIndx_<short, int>,
|
||||
minMaxIndx_<int, int>, minMaxIndx_<float, float>, minMaxIndx_<double, double>, 0
|
||||
};
|
||||
static MinMaxIndxMaskFunc tabm[] =
|
||||
{minMaxIndxMask_<uchar>, 0, minMaxIndxMask_<ushort>, minMaxIndxMask_<short>,
|
||||
minMaxIndxMask_<int>, minMaxIndxMask_<float>, minMaxIndxMask_<double>, 0};
|
||||
{
|
||||
minMaxIndxMask_<uchar, int>, 0, minMaxIndxMask_<ushort, int>, minMaxIndxMask_<short, int>,
|
||||
minMaxIndxMask_<int, int>, minMaxIndxMask_<float, float>, minMaxIndxMask_<double, double>, 0
|
||||
};
|
||||
|
||||
int depth = img.depth();
|
||||
double minval=0, maxval=0;
|
||||
int minloc=0, maxloc=0;
|
||||
double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX;
|
||||
double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX;
|
||||
size_t minidx = 0, maxidx = 0, startidx = 1;
|
||||
|
||||
CV_Assert( img.channels() == 1 );
|
||||
|
||||
@ -725,36 +703,41 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
|
||||
{
|
||||
MinMaxIndxFunc func = tab[depth];
|
||||
CV_Assert( func != 0 );
|
||||
func( img, &minval, &maxval, &minloc, &maxloc );
|
||||
func( img, &minval, &maxval, startidx, &minidx, &maxidx );
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Assert( img.size() == mask.size() && mask.type() == CV_8U );
|
||||
MinMaxIndxMaskFunc func = tabm[depth];
|
||||
CV_Assert( func != 0 );
|
||||
func( img, mask, &minval, &maxval, &minloc, &maxloc );
|
||||
func( img, mask, &minval, &maxval, startidx, &minidx, &maxidx );
|
||||
}
|
||||
|
||||
if( minidx == 0 )
|
||||
minVal = maxVal = 0;
|
||||
|
||||
if( minVal )
|
||||
*minVal = minval;
|
||||
if( maxVal )
|
||||
*maxVal = maxval;
|
||||
if( minLoc )
|
||||
{
|
||||
if( minloc >= 0 )
|
||||
if( minidx > 0 )
|
||||
{
|
||||
minLoc->y = minloc/img.cols;
|
||||
minLoc->x = minloc - minLoc->y*img.cols;
|
||||
minidx--;
|
||||
minLoc->y = minidx/img.cols;
|
||||
minLoc->x = minidx - minLoc->y*img.cols;
|
||||
}
|
||||
else
|
||||
minLoc->x = minLoc->y = -1;
|
||||
}
|
||||
if( maxLoc )
|
||||
{
|
||||
if( maxloc >= 0 )
|
||||
if( maxidx > 0 )
|
||||
{
|
||||
maxLoc->y = maxloc/img.cols;
|
||||
maxLoc->x = maxloc - maxLoc->y*img.cols;
|
||||
maxidx--;
|
||||
maxLoc->y = maxidx/img.cols;
|
||||
maxLoc->x = maxidx - maxLoc->y*img.cols;
|
||||
}
|
||||
else
|
||||
maxLoc->x = maxLoc->y = -1;
|
||||
@ -764,10 +747,20 @@ void minMaxLoc( const Mat& img, double* minVal, double* maxVal,
|
||||
static void ofs2idx(const Mat& a, size_t ofs, int* idx)
|
||||
{
|
||||
int i, d = a.dims;
|
||||
for( i = 0; i < d; i++ )
|
||||
if( ofs > 0 )
|
||||
{
|
||||
idx[i] = (int)(ofs / a.step[i]);
|
||||
ofs %= a.step[i];
|
||||
ofs--;
|
||||
for( i = d-1; i >= 0; i-- )
|
||||
{
|
||||
int sz = a.size[i];
|
||||
idx[i] = (int)(ofs % sz);
|
||||
ofs /= sz;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = d-1; i >= 0; i-- )
|
||||
idx[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -780,43 +773,60 @@ void minMaxIdx(const Mat& a, double* minVal,
|
||||
Point minLoc, maxLoc;
|
||||
minMaxLoc(a, minVal, maxVal, &minLoc, &maxLoc, mask);
|
||||
if( minIdx )
|
||||
minIdx[0] = minLoc.x, minIdx[1] = minLoc.y;
|
||||
minIdx[0] = minLoc.y, minIdx[1] = minLoc.x;
|
||||
if( maxIdx )
|
||||
maxIdx[0] = maxLoc.x, maxIdx[1] = maxLoc.y;
|
||||
maxIdx[0] = maxLoc.y, maxIdx[1] = maxLoc.x;
|
||||
return;
|
||||
}
|
||||
|
||||
static MinMaxIndxFunc tab[] =
|
||||
{
|
||||
minMaxIndx_<uchar, int>, 0, minMaxIndx_<ushort, int>, minMaxIndx_<short, int>,
|
||||
minMaxIndx_<int, int>, minMaxIndx_<float, float>, minMaxIndx_<double, double>, 0
|
||||
};
|
||||
static MinMaxIndxMaskFunc tabm[] =
|
||||
{
|
||||
minMaxIndxMask_<uchar, int>, 0, minMaxIndxMask_<ushort, int>, minMaxIndxMask_<short, int>,
|
||||
minMaxIndxMask_<int, int>, minMaxIndxMask_<float, float>, minMaxIndxMask_<double, double>, 0
|
||||
};
|
||||
|
||||
const Mat* arrays[] = {&a, &mask, 0};
|
||||
Mat planes[2];
|
||||
NAryMatIterator it(arrays, planes);
|
||||
double minval = DBL_MAX, maxval = -DBL_MAX;
|
||||
size_t minofs = 0, maxofs = 0, esz = a.elemSize();
|
||||
|
||||
for( int i = 0; i < it.nplanes; i++, ++it )
|
||||
int depth = a.depth();
|
||||
double minval = depth < CV_32F ? INT_MAX : depth == CV_32F ? FLT_MAX : DBL_MAX;
|
||||
double maxval = depth < CV_32F ? INT_MIN : depth == CV_32F ? -FLT_MAX : -DBL_MAX;
|
||||
size_t minidx = 0, maxidx = 0;
|
||||
size_t startidx = 1, planeSize = planes[0].total();
|
||||
MinMaxIndxFunc func = 0;
|
||||
MinMaxIndxMaskFunc mfunc = 0;
|
||||
|
||||
if( mask.empty() )
|
||||
func = tab[depth];
|
||||
else
|
||||
mfunc = tabm[depth];
|
||||
CV_Assert( func != 0 || mfunc != 0 );
|
||||
|
||||
for( int i = 0; i < it.nplanes; i++, ++it, startidx += planeSize )
|
||||
{
|
||||
double val0 = 0, val1 = 0;
|
||||
Point pt0, pt1;
|
||||
minMaxLoc( it.planes[0], &val0, &val1, &pt0, &pt1, it.planes[1] );
|
||||
if( val0 < minval )
|
||||
{
|
||||
minval = val0;
|
||||
minofs = (it.planes[0].data - a.data) + pt0.x*esz;
|
||||
}
|
||||
if( val1 > maxval )
|
||||
{
|
||||
maxval = val1;
|
||||
maxofs = (it.planes[0].data - a.data) + pt1.x*esz;
|
||||
}
|
||||
if( func )
|
||||
func( planes[0], &minval, &maxval, startidx, &minidx, &maxidx );
|
||||
else
|
||||
mfunc( planes[0], planes[1], &minval, &maxval, startidx, &minidx, &maxidx );
|
||||
}
|
||||
|
||||
if( minidx == 0 )
|
||||
minVal = maxVal = 0;
|
||||
|
||||
if( minVal )
|
||||
*minVal = minval;
|
||||
if( maxVal )
|
||||
*maxVal = maxval;
|
||||
if( minIdx )
|
||||
ofs2idx(a, minofs, minIdx);
|
||||
ofs2idx(a, minidx, minIdx);
|
||||
if( maxIdx )
|
||||
ofs2idx(a, maxofs, maxIdx);
|
||||
ofs2idx(a, maxidx, maxIdx);
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
@ -922,6 +932,7 @@ static double normMaskBlock_( const Mat& srcmat, const Mat& maskmat )
|
||||
ST s0 = 0;
|
||||
WT s = 0;
|
||||
int y, remaining = BLOCK_SIZE;
|
||||
int cn = srcmat.channels();
|
||||
|
||||
for( y = 0; y < size.height; y++ )
|
||||
{
|
||||
@ -933,21 +944,25 @@ static double normMaskBlock_( const Mat& srcmat, const Mat& maskmat )
|
||||
int limit = std::min( remaining, size.width - x );
|
||||
remaining -= limit;
|
||||
limit += x;
|
||||
for( ; x <= limit - 4; x += 4 )
|
||||
int x0 = x;
|
||||
for( int c = 0; c < cn; c++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src[x]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (WT)f(src[x+1]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (WT)f(src[x+2]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (WT)f(src[x+3]));
|
||||
}
|
||||
for( ; x < limit; x++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src[x]));
|
||||
for( x = x0; x <= limit - 4; x += 4 )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src[x*cn + c]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (WT)f(src[(x+1)*cn + c]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (WT)f(src[(x+2)*cn + c]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (WT)f(src[(x+3)*cn + c]));
|
||||
}
|
||||
for( ; x < limit; x++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src[x*cn + c]));
|
||||
}
|
||||
}
|
||||
if( remaining == 0 || (x == size.width && y == size.height-1) )
|
||||
{
|
||||
@ -971,27 +986,31 @@ static double normMask_( const Mat& srcmat, const Mat& maskmat )
|
||||
assert( DataType<T>::depth == srcmat.depth() );
|
||||
Size size = getContinuousSize( srcmat, maskmat );
|
||||
ST s = 0;
|
||||
|
||||
int cn = srcmat.channels();
|
||||
|
||||
for( int y = 0; y < size.height; y++ )
|
||||
{
|
||||
const T* src = (const T*)(srcmat.data + srcmat.step*y);
|
||||
const uchar* mask = maskmat.data + maskmat.step*y;
|
||||
int x = 0;
|
||||
for( ; x <= size.width - 4; x += 4 )
|
||||
for( int c = 0; c < cn; c++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src[x]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (ST)f(src[x+1]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (ST)f(src[x+2]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (ST)f(src[x+3]));
|
||||
}
|
||||
for( ; x < size.width; x++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src[x]));
|
||||
int x = 0;
|
||||
for( ; x <= size.width - 4; x += 4 )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src[x*cn + c]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (ST)f(src[(x+1)*cn + c]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (ST)f(src[(x+2)*cn + c]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (ST)f(src[(x+3)*cn + c]));
|
||||
}
|
||||
for( ; x < size.width; x++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src[x*cn + c]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
@ -1085,6 +1104,7 @@ static double normDiffMaskBlock_( const Mat& srcmat1, const Mat& srcmat2, const
|
||||
ST s0 = 0;
|
||||
WT s = 0;
|
||||
int y, remaining = BLOCK_SIZE;
|
||||
int cn = srcmat1.channels();
|
||||
|
||||
for( y = 0; y < size.height; y++ )
|
||||
{
|
||||
@ -1097,20 +1117,24 @@ static double normDiffMaskBlock_( const Mat& srcmat1, const Mat& srcmat2, const
|
||||
int limit = std::min( remaining, size.width - x );
|
||||
remaining -= limit;
|
||||
limit += x;
|
||||
for( ; x <= limit - 4; x += 4 )
|
||||
int x0 = x;
|
||||
for( int c = 0; c < cn; c++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src1[x] - src2[x]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (WT)f(src1[x+1] - src2[x+1]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (WT)f(src1[x+2] - src2[x+2]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (WT)f(src1[x+3] - src2[x+3]));
|
||||
for( x = x0; x <= limit - 4; x += 4 )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src1[x*cn + c] - src2[x*cn + c]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (WT)f(src1[(x+1)*cn + c] - src2[(x+1)*cn + c]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (WT)f(src1[(x+2)*cn + c] - src2[(x+2)*cn + c]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (WT)f(src1[(x+3)*cn + c] - src2[(x+3)*cn + c]));
|
||||
}
|
||||
for( ; x < limit; x++ )
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src1[x*cn + c] - src2[x*cn + c]));
|
||||
}
|
||||
for( ; x < limit; x++ )
|
||||
if( mask[x] )
|
||||
s = update(s, (WT)f(src1[x] - src2[x]));
|
||||
if( remaining == 0 || (x == size.width && y == size.height-1) )
|
||||
{
|
||||
s0 = globUpdate(s0, (ST)s);
|
||||
@ -1132,28 +1156,31 @@ static double normDiffMask_( const Mat& srcmat1, const Mat& srcmat2, const Mat&
|
||||
assert( DataType<T>::depth == srcmat1.depth() );
|
||||
Size size = getContinuousSize( srcmat1, srcmat2, maskmat );
|
||||
ST s = 0;
|
||||
int cn = srcmat1.channels();
|
||||
|
||||
for( int y = 0; y < size.height; y++ )
|
||||
{
|
||||
const T* src1 = (const T*)(srcmat1.data + srcmat1.step*y);
|
||||
const T* src2 = (const T*)(srcmat2.data + srcmat2.step*y);
|
||||
const uchar* mask = maskmat.data + maskmat.step*y;
|
||||
int x = 0;
|
||||
for( ; x <= size.width - 4; x += 4 )
|
||||
for( int c = 0; c < cn; c++ )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src1[x] - src2[x]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (ST)f(src1[x+1] - src2[x+1]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (ST)f(src1[x+2] - src2[x+2]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (ST)f(src1[x+3] - src2[x+3]));
|
||||
int x = 0;
|
||||
for( ; x <= size.width - 4; x += 4 )
|
||||
{
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src1[x*cn + c] - src2[x*cn + c]));
|
||||
if( mask[x+1] )
|
||||
s = update(s, (ST)f(src1[(x+1)*cn + c] - src2[(x+1)*cn + c]));
|
||||
if( mask[x+2] )
|
||||
s = update(s, (ST)f(src1[(x+2)*cn + c] - src2[(x+2)*cn + c]));
|
||||
if( mask[x+3] )
|
||||
s = update(s, (ST)f(src1[(x+3)*cn + c] - src2[(x+3)*cn + c]));
|
||||
}
|
||||
for( ; x < size.width; x++ )
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src1[x*cn + c] - src2[x*cn + c]));
|
||||
}
|
||||
for( ; x < size.width; x++ )
|
||||
if( mask[x] )
|
||||
s = update(s, (ST)f(src1[x] - src2[x]));
|
||||
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -1265,8 +1292,7 @@ double norm( const Mat& a, int normType, const Mat& mask )
|
||||
return norm(a, normType);
|
||||
|
||||
normType &= 7;
|
||||
CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) &&
|
||||
mask.type() == CV_8U && a.channels() == 1);
|
||||
CV_Assert((normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) && mask.type() == CV_8U);
|
||||
NormMaskFunc func = tab[normType >> 1][a.depth()];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
@ -1405,7 +1431,7 @@ double norm( const Mat& a, const Mat& b, int normType, const Mat& mask )
|
||||
if( !mask.data )
|
||||
return norm(a, b, normType);
|
||||
|
||||
CV_Assert( a.type() == b.type() && mask.type() == CV_8U && a.channels() == 1);
|
||||
CV_Assert( a.type() == b.type() && mask.type() == CV_8U);
|
||||
bool isRelative = (normType & NORM_RELATIVE) != 0;
|
||||
normType &= 7;
|
||||
CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2);
|
||||
|
File diff suppressed because it is too large
Load Diff
2122
modules/core/test/test_ds.cpp
Normal file
2122
modules/core/test/test_ds.cpp
Normal file
File diff suppressed because it is too large
Load Diff
829
modules/core/test/test_dxt.cpp
Normal file
829
modules/core/test/test_dxt.cpp
Normal file
@ -0,0 +1,829 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
namespace cvtest
|
||||
{
|
||||
|
||||
static Mat initDFTWave( int n, bool inv )
|
||||
{
|
||||
int i;
|
||||
double angle = (inv ? 1 : -1)*CV_PI*2/n;
|
||||
Complexd wi, w1;
|
||||
Mat wave(1, n, CV_64FC2);
|
||||
Complexd* w = wave.ptr<Complexd>();
|
||||
|
||||
w1.re = cos(angle);
|
||||
w1.im = sin(angle);
|
||||
w[0].re = wi.re = 1.;
|
||||
w[0].im = wi.im = 0.;
|
||||
|
||||
for( i = 1; i < n; i++ )
|
||||
{
|
||||
double t = wi.re*w1.re - wi.im*w1.im;
|
||||
wi.im = wi.re*w1.im + wi.im*w1.re;
|
||||
wi.re = t;
|
||||
w[i] = wi;
|
||||
}
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
||||
|
||||
static void DFT_1D( const Mat& _src, Mat& _dst, int flags, const Mat& _wave=Mat())
|
||||
{
|
||||
_dst.create(_src.size(), _src.type());
|
||||
int i, j, k, n = _dst.cols + _dst.rows - 1;
|
||||
Mat wave = _wave;
|
||||
double scale = (flags & DFT_SCALE) ? 1./n : 1.;
|
||||
size_t esz = _src.elemSize();
|
||||
size_t srcstep = esz, dststep = esz;
|
||||
const uchar* src0 = _src.data;
|
||||
uchar* dst0 = _dst.data;
|
||||
|
||||
CV_Assert( _src.cols + _src.rows - 1 == n );
|
||||
|
||||
if( wave.empty() )
|
||||
wave = initDFTWave( n, (flags & DFT_INVERSE) != 0 );
|
||||
|
||||
const Complexd* w = wave.ptr<Complexd>();
|
||||
if( !_src.isContinuous() )
|
||||
srcstep = _src.step;
|
||||
if( !_dst.isContinuous() )
|
||||
dststep = _dst.step;
|
||||
|
||||
if( _src.type() == CV_32FC2 )
|
||||
{
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
Complexf* dst = (Complexf*)(dst0 + i*dststep);
|
||||
Complexd sum(0,0);
|
||||
int delta = i;
|
||||
k = 0;
|
||||
|
||||
for( j = 0; j < n; j++ )
|
||||
{
|
||||
const Complexf* src = (const Complexf*)(src0 + j*srcstep);
|
||||
sum.re += src->re*w[k].re - src->im*w[k].im;
|
||||
sum.im += src->re*w[k].im + src->im*w[k].re;
|
||||
k += delta;
|
||||
k -= (k >= n ? n : 0);
|
||||
}
|
||||
|
||||
dst->re = (float)(sum.re*scale);
|
||||
dst->im = (float)(sum.im*scale);
|
||||
}
|
||||
}
|
||||
else if( _src.type() == CV_64FC2 )
|
||||
{
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
Complexd* dst = (Complexd*)(dst0 + i*dststep);
|
||||
Complexd sum(0,0);
|
||||
int delta = i;
|
||||
k = 0;
|
||||
|
||||
for( j = 0; j < n; j++ )
|
||||
{
|
||||
const Complexd* src = (const Complexd*)(src0 + j*srcstep);
|
||||
sum.re += src->re*w[k].re - src->im*w[k].im;
|
||||
sum.im += src->re*w[k].im + src->im*w[k].re;
|
||||
k += delta;
|
||||
k -= (k >= n ? n : 0);
|
||||
}
|
||||
|
||||
dst->re = sum.re*scale;
|
||||
dst->im = sum.im*scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
CV_Error(CV_StsUnsupportedFormat, "");
|
||||
}
|
||||
|
||||
|
||||
static void DFT_2D( const Mat& src, Mat& dst, int flags )
|
||||
{
|
||||
const int cn = 2;
|
||||
int i;
|
||||
dst.create(src.size(), src.type());
|
||||
Mat tmp( src.cols, src.rows, src.type());
|
||||
Mat wave = initDFTWave( dst.cols, (flags & DFT_INVERSE) != 0 );
|
||||
|
||||
// 1. row-wise transform
|
||||
for( i = 0; i < dst.rows; i++ )
|
||||
{
|
||||
Mat srci = src.row(i).reshape(cn, src.cols), dsti = tmp.col(i);
|
||||
DFT_1D(srci, dsti, flags, wave );
|
||||
}
|
||||
|
||||
if( (flags & DFT_ROWS) == 0 )
|
||||
{
|
||||
if( dst.cols != dst.rows )
|
||||
wave = initDFTWave( dst.rows, (flags & DFT_INVERSE) != 0 );
|
||||
|
||||
// 2. column-wise transform
|
||||
for( i = 0; i < dst.cols; i++ )
|
||||
{
|
||||
Mat srci = tmp.row(i).reshape(cn, tmp.cols), dsti = dst.col(i);
|
||||
DFT_1D(srci, dsti, flags, wave );
|
||||
}
|
||||
}
|
||||
else
|
||||
cvtest::transpose(tmp, dst);
|
||||
}
|
||||
|
||||
|
||||
static Mat initDCTWave( int n, bool inv )
|
||||
{
|
||||
int i, k;
|
||||
double angle = CV_PI*0.5/n;
|
||||
Mat wave(n, n, CV_64F);
|
||||
|
||||
double scale = sqrt(1./n);
|
||||
for( k = 0; k < n; k++ )
|
||||
wave.at<double>(0, k) = scale;
|
||||
scale *= sqrt(2.);
|
||||
for( i = 1; i < n; i++ )
|
||||
for( k = 0; k < n; k++ )
|
||||
wave.at<double>(i, k) = scale*cos( angle*i*(2*k + 1) );
|
||||
|
||||
if( inv )
|
||||
cv::transpose( wave, wave );
|
||||
|
||||
return wave;
|
||||
}
|
||||
|
||||
|
||||
static void DCT_1D( const Mat& _src, Mat& _dst, int flags, const Mat& _wave=Mat() )
|
||||
{
|
||||
_dst.create( _src.size(), _src.type() );
|
||||
int i, j, n = _dst.cols + _dst.rows - 1;
|
||||
Mat wave = _wave;
|
||||
int srcstep = 1, dststep = 1;
|
||||
double* w;
|
||||
|
||||
CV_Assert( _src.cols + _src.rows - 1 == n);
|
||||
|
||||
if( wave.empty() )
|
||||
wave = initDCTWave( n, (flags & DFT_INVERSE) != 0 );
|
||||
w = wave.ptr<double>();
|
||||
|
||||
if( !_src.isContinuous() )
|
||||
srcstep = _src.step/_src.elemSize();
|
||||
if( !_dst.isContinuous() )
|
||||
dststep = _dst.step/_dst.elemSize();
|
||||
|
||||
if( _src.type() == CV_32FC1 )
|
||||
{
|
||||
float *dst = _dst.ptr<float>();
|
||||
|
||||
for( i = 0; i < n; i++, dst += dststep )
|
||||
{
|
||||
const float* src = _src.ptr<float>();
|
||||
double sum = 0;
|
||||
|
||||
for( j = 0; j < n; j++, src += srcstep )
|
||||
sum += src[0]*w[j];
|
||||
w += n;
|
||||
dst[0] = (float)sum;
|
||||
}
|
||||
}
|
||||
else if( _src.type() == CV_64FC1 )
|
||||
{
|
||||
double *dst = _dst.ptr<double>();
|
||||
|
||||
for( i = 0; i < n; i++, dst += dststep )
|
||||
{
|
||||
const double* src = _src.ptr<double>();
|
||||
double sum = 0;
|
||||
|
||||
for( j = 0; j < n; j++, src += srcstep )
|
||||
sum += src[0]*w[j];
|
||||
w += n;
|
||||
dst[0] = sum;
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
static void DCT_2D( const Mat& src, Mat& dst, int flags )
|
||||
{
|
||||
const int cn = 1;
|
||||
int i;
|
||||
dst.create( src.size(), src.type() );
|
||||
Mat tmp(dst.cols, dst.rows, dst.type() );
|
||||
Mat wave = initDCTWave( dst.cols, (flags & DCT_INVERSE) != 0 );
|
||||
|
||||
// 1. row-wise transform
|
||||
for( i = 0; i < dst.rows; i++ )
|
||||
{
|
||||
Mat srci = src.row(i).reshape(cn, src.cols);
|
||||
Mat dsti = tmp.col(i);
|
||||
DCT_1D(srci, dsti, flags, wave);
|
||||
}
|
||||
|
||||
if( (flags & DCT_ROWS) == 0 )
|
||||
{
|
||||
if( dst.cols != dst.rows )
|
||||
wave = initDCTWave( dst.rows, (flags & DCT_INVERSE) != 0 );
|
||||
|
||||
// 2. column-wise transform
|
||||
for( i = 0; i < dst.cols; i++ )
|
||||
{
|
||||
Mat srci = tmp.row(i).reshape(cn, tmp.cols);
|
||||
Mat dsti = dst.col(i);
|
||||
DCT_1D( srci, dsti, flags, wave );
|
||||
}
|
||||
}
|
||||
else
|
||||
cvtest::transpose( tmp, dst );
|
||||
}
|
||||
|
||||
|
||||
static void convertFromCCS( const Mat& _src0, const Mat& _src1, Mat& _dst, int flags )
|
||||
{
|
||||
if( _dst.rows > 1 && (_dst.cols > 1 || (flags & DFT_ROWS)) )
|
||||
{
|
||||
int i, count = _dst.rows, len = _dst.cols;
|
||||
bool is2d = (flags & DFT_ROWS) == 0;
|
||||
Mat src0row, src1row, dstrow;
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
int j = !is2d || i == 0 ? i : count - i;
|
||||
src0row = _src0.row(i);
|
||||
src1row = _src1.row(j);
|
||||
dstrow = _dst.row(i);
|
||||
convertFromCCS( src0row, src1row, dstrow, 0 );
|
||||
}
|
||||
|
||||
if( is2d )
|
||||
{
|
||||
src0row = _src0.col(0);
|
||||
dstrow = _dst.col(0);
|
||||
convertFromCCS( src0row, src0row, dstrow, 0 );
|
||||
if( (len & 1) == 0 )
|
||||
{
|
||||
src0row = _src0.col(_src0.cols - 1);
|
||||
dstrow = _dst.col(len/2);
|
||||
convertFromCCS( src0row, src0row, dstrow, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, n = _dst.cols + _dst.rows - 1, n2 = (n+1) >> 1;
|
||||
int cn = _src0.channels();
|
||||
int srcstep = cn, dststep = 1;
|
||||
|
||||
if( !_dst.isContinuous() )
|
||||
dststep = _dst.step/_dst.elemSize();
|
||||
|
||||
if( !_src0.isContinuous() )
|
||||
srcstep = _src0.step/_src0.elemSize1();
|
||||
|
||||
if( _dst.depth() == CV_32F )
|
||||
{
|
||||
Complexf* dst = _dst.ptr<Complexf>();
|
||||
const float* src0 = _src0.ptr<float>();
|
||||
const float* src1 = _src1.ptr<float>();
|
||||
int delta0, delta1;
|
||||
|
||||
dst->re = src0[0];
|
||||
dst->im = 0;
|
||||
|
||||
if( (n & 1) == 0 )
|
||||
{
|
||||
dst[n2*dststep].re = src0[(cn == 1 ? n-1 : n2)*srcstep];
|
||||
dst[n2*dststep].im = 0;
|
||||
}
|
||||
|
||||
delta0 = srcstep;
|
||||
delta1 = delta0 + (cn == 1 ? srcstep : 1);
|
||||
if( cn == 1 )
|
||||
srcstep *= 2;
|
||||
|
||||
for( i = 1; i < n2; i++, delta0 += srcstep, delta1 += srcstep )
|
||||
{
|
||||
float t0 = src0[delta0];
|
||||
float t1 = src0[delta1];
|
||||
|
||||
dst[i*dststep].re = t0;
|
||||
dst[i*dststep].im = t1;
|
||||
|
||||
t0 = src1[delta0];
|
||||
t1 = -src1[delta1];
|
||||
|
||||
dst[(n-i)*dststep].re = t0;
|
||||
dst[(n-i)*dststep].im = t1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Complexd* dst = _dst.ptr<Complexd>();
|
||||
const double* src0 = _src0.ptr<double>();
|
||||
const double* src1 = _src1.ptr<double>();
|
||||
int delta0, delta1;
|
||||
|
||||
dst->re = src0[0];
|
||||
dst->im = 0;
|
||||
|
||||
if( (n & 1) == 0 )
|
||||
{
|
||||
dst[n2*dststep].re = src0[(cn == 1 ? n-1 : n2)*srcstep];
|
||||
dst[n2*dststep].im = 0;
|
||||
}
|
||||
|
||||
delta0 = srcstep;
|
||||
delta1 = delta0 + (cn == 1 ? srcstep : 1);
|
||||
if( cn == 1 )
|
||||
srcstep *= 2;
|
||||
|
||||
for( i = 1; i < n2; i++, delta0 += srcstep, delta1 += srcstep )
|
||||
{
|
||||
double t0 = src0[delta0];
|
||||
double t1 = src0[delta1];
|
||||
|
||||
dst[i*dststep].re = t0;
|
||||
dst[i*dststep].im = t1;
|
||||
|
||||
t0 = src1[delta0];
|
||||
t1 = -src1[delta1];
|
||||
|
||||
dst[(n-i)*dststep].re = t0;
|
||||
dst[(n-i)*dststep].im = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fixCCS( Mat& mat, int cols, int flags )
|
||||
{
|
||||
int i, rows = mat.rows;
|
||||
int rows2 = (flags & DFT_ROWS) ? rows : rows/2 + 1, cols2 = cols/2 + 1;
|
||||
|
||||
CV_Assert( cols2 == mat.cols );
|
||||
|
||||
if( mat.type() == CV_32FC2 )
|
||||
{
|
||||
for( i = 0; i < rows2; i++ )
|
||||
{
|
||||
Complexf* row = mat.ptr<Complexf>(i);
|
||||
if( (flags & DFT_ROWS) || i == 0 || (i == rows2 - 1 && rows % 2 == 0) )
|
||||
{
|
||||
row[0].im = 0;
|
||||
if( cols % 2 == 0 )
|
||||
row[cols2-1].im = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Complexf* row2 = mat.ptr<Complexf>(rows-i);
|
||||
row2[0].re = row[0].re;
|
||||
row2[0].im = -row[0].im;
|
||||
|
||||
if( cols % 2 == 0 )
|
||||
{
|
||||
row2[cols2-1].re = row[cols2-1].re;
|
||||
row2[cols2-1].im = -row[cols2-1].im;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( mat.type() == CV_64FC2 )
|
||||
{
|
||||
for( i = 0; i < rows2; i++ )
|
||||
{
|
||||
Complexd* row = mat.ptr<Complexd>(i);
|
||||
if( (flags & DFT_ROWS) || i == 0 || (i == rows2 - 1 && rows % 2 == 0) )
|
||||
{
|
||||
row[0].im = 0;
|
||||
if( cols % 2 == 0 )
|
||||
row[cols2-1].im = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Complexd* row2 = mat.ptr<Complexd>(rows-i);
|
||||
row2[0].re = row[0].re;
|
||||
row2[0].im = -row[0].im;
|
||||
|
||||
if( cols % 2 == 0 )
|
||||
{
|
||||
row2[cols2-1].re = row[cols2-1].re;
|
||||
row2[cols2-1].im = -row[cols2-1].im;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void mulComplex( const Mat& src1, const Mat& src2, Mat& dst, int flags )
|
||||
{
|
||||
dst.create(src1.rows, src1.cols, src1.type());
|
||||
int i, j, depth = src1.depth(), cols = src1.cols*2;
|
||||
|
||||
CV_Assert( src1.size == src2.size && src1.type() == src2.type() &&
|
||||
(src1.type() == CV_32FC2 || src1.type() == CV_64FC2) );
|
||||
|
||||
for( i = 0; i < dst.rows; i++ )
|
||||
{
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
const float* a = src1.ptr<float>(i);
|
||||
const float* b = src2.ptr<float>(i);
|
||||
float* c = dst.ptr<float>(i);
|
||||
|
||||
if( !(flags & CV_DXT_MUL_CONJ) )
|
||||
for( j = 0; j < cols; j += 2 )
|
||||
{
|
||||
double re = (double)a[j]*b[j] - (double)a[j+1]*b[j+1];
|
||||
double im = (double)a[j+1]*b[j] + (double)a[j]*b[j+1];
|
||||
|
||||
c[j] = (float)re;
|
||||
c[j+1] = (float)im;
|
||||
}
|
||||
else
|
||||
for( j = 0; j < cols; j += 2 )
|
||||
{
|
||||
double re = (double)a[j]*b[j] + (double)a[j+1]*b[j+1];
|
||||
double im = (double)a[j+1]*b[j] - (double)a[j]*b[j+1];
|
||||
|
||||
c[j] = (float)re;
|
||||
c[j+1] = (float)im;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const double* a = src1.ptr<double>(i);
|
||||
const double* b = src2.ptr<double>(i);
|
||||
double* c = dst.ptr<double>(i);
|
||||
|
||||
if( !(flags & CV_DXT_MUL_CONJ) )
|
||||
for( j = 0; j < cols; j += 2 )
|
||||
{
|
||||
double re = a[j]*b[j] - a[j+1]*b[j+1];
|
||||
double im = a[j+1]*b[j] + a[j]*b[j+1];
|
||||
|
||||
c[j] = re;
|
||||
c[j+1] = im;
|
||||
}
|
||||
else
|
||||
for( j = 0; j < cols; j += 2 )
|
||||
{
|
||||
double re = a[j]*b[j] + a[j+1]*b[j+1];
|
||||
double im = a[j+1]*b[j] - a[j]*b[j+1];
|
||||
|
||||
c[j] = re;
|
||||
c[j+1] = im;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class CxCore_DXTBaseTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
typedef cvtest::ArrayTest Base;
|
||||
CxCore_DXTBaseTest( bool _allow_complex=false, bool _allow_odd=false,
|
||||
bool _spectrum_mode=false );
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
int prepare_test_case( int test_case_idx );
|
||||
double get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ );
|
||||
int flags; // transformation flags
|
||||
bool allow_complex; // whether input/output may be complex or not:
|
||||
// true for DFT and MulSpectrums, false for DCT
|
||||
bool allow_odd; // whether input/output may be have odd (!=1) dimensions:
|
||||
// true for DFT and MulSpectrums, false for DCT
|
||||
bool spectrum_mode; // (2 complex/ccs inputs, 1 complex/ccs output):
|
||||
// true for MulSpectrums, false for DFT and DCT
|
||||
bool inplace; // inplace operation (set for each individual test case)
|
||||
bool temp_dst; // use temporary destination (for real->ccs DFT and ccs MulSpectrums)
|
||||
};
|
||||
|
||||
|
||||
CxCore_DXTBaseTest::CxCore_DXTBaseTest( bool _allow_complex, bool _allow_odd, bool _spectrum_mode )
|
||||
: Base(), flags(0), allow_complex(_allow_complex), allow_odd(_allow_odd),
|
||||
spectrum_mode(_spectrum_mode), inplace(false), temp_dst(false)
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
if( spectrum_mode )
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
test_array[TEMP].push_back(NULL);
|
||||
test_array[TEMP].push_back(NULL);
|
||||
|
||||
max_log_array_size = 9;
|
||||
element_wise_relative_error = spectrum_mode;
|
||||
}
|
||||
|
||||
|
||||
void CxCore_DXTBaseTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes,
|
||||
vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int bits = cvtest::randInt(rng);
|
||||
int depth = cvtest::randInt(rng)%2 + CV_32F;
|
||||
int cn = !allow_complex || !(bits & 256) ? 1 : 2;
|
||||
Size size;
|
||||
Base::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
|
||||
flags = bits & (CV_DXT_INVERSE | CV_DXT_SCALE | CV_DXT_ROWS | CV_DXT_MUL_CONJ);
|
||||
if( spectrum_mode )
|
||||
flags &= ~CV_DXT_INVERSE;
|
||||
types[TEMP][0] = types[TEMP][1] = types[INPUT][0] =
|
||||
types[OUTPUT][0] = CV_MAKETYPE(depth, cn);
|
||||
size = sizes[INPUT][0];
|
||||
|
||||
temp_dst = false;
|
||||
|
||||
if( flags & CV_DXT_ROWS && (bits&1024) )
|
||||
{
|
||||
if( bits&16 )
|
||||
size.width = 1;
|
||||
else
|
||||
size.height = 1;
|
||||
flags &= ~CV_DXT_ROWS;
|
||||
}
|
||||
|
||||
const int P2_MIN_SIZE = 32;
|
||||
if( ((bits >> 10) & 1) == 0 )
|
||||
{
|
||||
size.width = (size.width / P2_MIN_SIZE)*P2_MIN_SIZE;
|
||||
size.width = MAX(size.width, 1);
|
||||
size.height = (size.height / P2_MIN_SIZE)*P2_MIN_SIZE;
|
||||
size.height = MAX(size.height, 1);
|
||||
}
|
||||
|
||||
if( !allow_odd )
|
||||
{
|
||||
if( size.width > 1 && (size.width&1) != 0 )
|
||||
size.width = (size.width + 1) & -2;
|
||||
|
||||
if( size.height > 1 && (size.height&1) != 0 && !(flags & CV_DXT_ROWS) )
|
||||
size.height = (size.height + 1) & -2;
|
||||
}
|
||||
|
||||
sizes[INPUT][0] = sizes[OUTPUT][0] = size;
|
||||
sizes[TEMP][0] = sizes[TEMP][1] = cvSize(0,0);
|
||||
|
||||
if( spectrum_mode )
|
||||
{
|
||||
if( cn == 1 )
|
||||
{
|
||||
types[OUTPUT][0] = depth + 8;
|
||||
sizes[TEMP][0] = size;
|
||||
}
|
||||
sizes[INPUT][0] = sizes[INPUT][1] = size;
|
||||
types[INPUT][1] = types[INPUT][0];
|
||||
}
|
||||
else if( /*(cn == 2 && (bits&32)) ||*/ (cn == 1 && allow_complex) )
|
||||
{
|
||||
types[TEMP][0] = depth + 8; // CV_??FC2
|
||||
sizes[TEMP][0] = size;
|
||||
size = cvSize(size.width/2+1, size.height);
|
||||
|
||||
if( flags & CV_DXT_INVERSE )
|
||||
{
|
||||
if( cn == 2 )
|
||||
{
|
||||
types[OUTPUT][0] = depth;
|
||||
sizes[INPUT][0] = size;
|
||||
}
|
||||
types[TEMP][1] = types[TEMP][0];
|
||||
sizes[TEMP][1] = sizes[TEMP][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( allow_complex )
|
||||
types[OUTPUT][0] = depth + 8;
|
||||
|
||||
if( cn == 2 )
|
||||
{
|
||||
types[INPUT][0] = depth;
|
||||
types[TEMP][1] = types[TEMP][0];
|
||||
sizes[TEMP][1] = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
types[TEMP][1] = depth;
|
||||
sizes[TEMP][1] = sizes[TEMP][0];
|
||||
}
|
||||
temp_dst = true;
|
||||
}
|
||||
}
|
||||
|
||||
inplace = false;
|
||||
if( spectrum_mode ||
|
||||
(!temp_dst && types[INPUT][0] == types[OUTPUT][0]) ||
|
||||
(temp_dst && types[INPUT][0] == types[TEMP][1]) )
|
||||
inplace = (bits & 64) != 0;
|
||||
|
||||
types[REF_OUTPUT][0] = types[OUTPUT][0];
|
||||
sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
|
||||
}
|
||||
|
||||
|
||||
double CxCore_DXTBaseTest::get_success_error_level( int test_case_idx, int i, int j )
|
||||
{
|
||||
return Base::get_success_error_level( test_case_idx, i, j );
|
||||
}
|
||||
|
||||
|
||||
int CxCore_DXTBaseTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int code = Base::prepare_test_case( test_case_idx );
|
||||
if( code > 0 )
|
||||
{
|
||||
int in_type = test_mat[INPUT][0].type();
|
||||
int out_type = test_mat[OUTPUT][0].type();
|
||||
|
||||
if( CV_MAT_CN(in_type) == 2 && CV_MAT_CN(out_type) == 1 )
|
||||
cvtest::fixCCS( test_mat[INPUT][0], test_mat[OUTPUT][0].cols, flags );
|
||||
|
||||
if( inplace )
|
||||
cvtest::copy( test_mat[INPUT][test_case_idx & (int)spectrum_mode],
|
||||
temp_dst ? test_mat[TEMP][1] :
|
||||
in_type == out_type ? test_mat[OUTPUT][0] :
|
||||
test_mat[TEMP][0] );
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
////////////////////// FFT ////////////////////////
|
||||
class CxCore_DFTTest : public CxCore_DXTBaseTest
|
||||
{
|
||||
public:
|
||||
CxCore_DFTTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
};
|
||||
|
||||
|
||||
CxCore_DFTTest::CxCore_DFTTest() : CxCore_DXTBaseTest( true, true, false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CxCore_DFTTest::run_func()
|
||||
{
|
||||
Mat& dst = temp_dst ? test_mat[TEMP][1] : test_mat[OUTPUT][0];
|
||||
const Mat& src = inplace ? dst : test_mat[INPUT][0];
|
||||
|
||||
if(!(flags & CV_DXT_INVERSE))
|
||||
cv::dft( src, dst, flags );
|
||||
else
|
||||
cv::idft(src, dst, flags & ~CV_DXT_INVERSE);
|
||||
}
|
||||
|
||||
|
||||
void CxCore_DFTTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
Mat& src = test_mat[INPUT][0];
|
||||
Mat& dst = test_mat[REF_OUTPUT][0];
|
||||
Mat* tmp_src = &src;
|
||||
Mat* tmp_dst = &dst;
|
||||
int src_cn = src.channels();
|
||||
int dst_cn = dst.channels();
|
||||
|
||||
if( src_cn != 2 || dst_cn != 2 )
|
||||
{
|
||||
tmp_src = &test_mat[TEMP][0];
|
||||
|
||||
if( !(flags & CV_DXT_INVERSE ) )
|
||||
{
|
||||
Mat& cvdft_dst = test_mat[TEMP][1];
|
||||
cvtest::convertFromCCS( cvdft_dst, cvdft_dst,
|
||||
test_mat[OUTPUT][0], flags );
|
||||
*tmp_src = Scalar::all(0);
|
||||
cvtest::insert( src, *tmp_src, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
cvtest::convertFromCCS( src, src, *tmp_src, flags );
|
||||
tmp_dst = &test_mat[TEMP][1];
|
||||
}
|
||||
}
|
||||
|
||||
if( src.rows == 1 || (src.cols == 1 && !(flags & CV_DXT_ROWS)) )
|
||||
cvtest::DFT_1D( *tmp_src, *tmp_dst, flags );
|
||||
else
|
||||
cvtest::DFT_2D( *tmp_src, *tmp_dst, flags );
|
||||
|
||||
if( tmp_dst != &dst )
|
||||
cvtest::extract( *tmp_dst, dst, 0 );
|
||||
}
|
||||
|
||||
////////////////////// DCT ////////////////////////
|
||||
class CxCore_DCTTest : public CxCore_DXTBaseTest
|
||||
{
|
||||
public:
|
||||
CxCore_DCTTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
};
|
||||
|
||||
|
||||
CxCore_DCTTest::CxCore_DCTTest() : CxCore_DXTBaseTest( false, false, false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CxCore_DCTTest::run_func()
|
||||
{
|
||||
Mat& dst = test_mat[OUTPUT][0];
|
||||
const Mat& src = inplace ? dst : test_mat[INPUT][0];
|
||||
|
||||
if(!(flags & CV_DXT_INVERSE))
|
||||
cv::dct( src, dst, flags );
|
||||
else
|
||||
cv::idct( src, dst, flags & ~CV_DXT_INVERSE);
|
||||
}
|
||||
|
||||
|
||||
void CxCore_DCTTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
const Mat& src = test_mat[INPUT][0];
|
||||
Mat& dst = test_mat[REF_OUTPUT][0];
|
||||
|
||||
if( src.rows == 1 || (src.cols == 1 && !(flags & CV_DXT_ROWS)) )
|
||||
cvtest::DCT_1D( src, dst, flags );
|
||||
else
|
||||
cvtest::DCT_2D( src, dst, flags );
|
||||
}
|
||||
|
||||
|
||||
////////////////////// MulSpectrums ////////////////////////
|
||||
class CxCore_MulSpectrumsTest : public CxCore_DXTBaseTest
|
||||
{
|
||||
public:
|
||||
CxCore_MulSpectrumsTest();
|
||||
protected:
|
||||
void run_func();
|
||||
void prepare_to_validation( int test_case_idx );
|
||||
};
|
||||
|
||||
|
||||
CxCore_MulSpectrumsTest::CxCore_MulSpectrumsTest() : CxCore_DXTBaseTest( true, true, true )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CxCore_MulSpectrumsTest::run_func()
|
||||
{
|
||||
Mat& dst = !test_mat[TEMP].empty() && !test_mat[TEMP][0].empty() ?
|
||||
test_mat[TEMP][0] : test_mat[OUTPUT][0];
|
||||
const Mat* src1 = &test_mat[INPUT][0], *src2 = &test_mat[INPUT][1];
|
||||
|
||||
if( inplace )
|
||||
{
|
||||
if( ts->get_current_test_info()->test_case_idx & 1 )
|
||||
src2 = &dst;
|
||||
else
|
||||
src1 = &dst;
|
||||
}
|
||||
|
||||
cv::mulSpectrums( *src1, *src2, dst, flags, (flags & CV_DXT_MUL_CONJ) != 0 );
|
||||
}
|
||||
|
||||
|
||||
void CxCore_MulSpectrumsTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
Mat* src1 = &test_mat[INPUT][0];
|
||||
Mat* src2 = &test_mat[INPUT][1];
|
||||
Mat& dst = test_mat[OUTPUT][0];
|
||||
Mat& dst0 = test_mat[REF_OUTPUT][0];
|
||||
int cn = src1->channels();
|
||||
|
||||
if( cn == 1 )
|
||||
{
|
||||
cvtest::convertFromCCS( *src1, *src1, dst, flags );
|
||||
cvtest::convertFromCCS( *src2, *src2, dst0, flags );
|
||||
src1 = &dst;
|
||||
src2 = &dst0;
|
||||
}
|
||||
|
||||
cvtest::mulComplex( *src1, *src2, dst0, flags );
|
||||
if( cn == 1 )
|
||||
{
|
||||
Mat& temp = test_mat[TEMP][0];
|
||||
cvtest::convertFromCCS( temp, temp, dst, flags );
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_DCT, accuracy) { CxCore_DCTTest test; test.safe_run(); }
|
||||
TEST(Core_DFT, accuracy) { CxCore_DFTTest test; test.safe_run(); }
|
||||
TEST(Core_MulSpectrums, accuracy) { CxCore_MulSpectrumsTest test; test.safe_run(); }
|
||||
|
382
modules/core/test/test_io.cpp
Normal file
382
modules/core/test/test_io.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
static SparseMat cvTsGetRandomSparseMat(int dims, const int* sz, int type,
|
||||
int nzcount, double a, double b, RNG& rng)
|
||||
{
|
||||
SparseMat m(dims, sz, type);
|
||||
int i, j;
|
||||
CV_Assert(CV_MAT_CN(type) == 1);
|
||||
for( i = 0; i < nzcount; i++ )
|
||||
{
|
||||
int idx[CV_MAX_DIM];
|
||||
for( j = 0; j < dims; j++ )
|
||||
idx[j] = cvtest::randInt(rng) % sz[j];
|
||||
double val = cvtest::randReal(rng)*(b - a) + a;
|
||||
uchar* ptr = m.ptr(idx, true, 0);
|
||||
if( type == CV_8U )
|
||||
*(uchar*)ptr = saturate_cast<uchar>(val);
|
||||
else if( type == CV_8S )
|
||||
*(schar*)ptr = saturate_cast<schar>(val);
|
||||
else if( type == CV_16U )
|
||||
*(ushort*)ptr = saturate_cast<ushort>(val);
|
||||
else if( type == CV_16S )
|
||||
*(short*)ptr = saturate_cast<short>(val);
|
||||
else if( type == CV_32S )
|
||||
*(int*)ptr = saturate_cast<int>(val);
|
||||
else if( type == CV_32F )
|
||||
*(float*)ptr = saturate_cast<float>(val);
|
||||
else
|
||||
*(double*)ptr = saturate_cast<double>(val);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
static bool cvTsCheckSparse(const CvSparseMat* m1, const CvSparseMat* m2, double eps)
|
||||
{
|
||||
CvSparseMatIterator it1;
|
||||
CvSparseNode* node1;
|
||||
int depth = CV_MAT_DEPTH(m1->type);
|
||||
|
||||
if( m1->heap->active_count != m2->heap->active_count ||
|
||||
m1->dims != m2->dims || CV_MAT_TYPE(m1->type) != CV_MAT_TYPE(m2->type) )
|
||||
return false;
|
||||
|
||||
for( node1 = cvInitSparseMatIterator( m1, &it1 );
|
||||
node1 != 0; node1 = cvGetNextSparseNode( &it1 ))
|
||||
{
|
||||
uchar* v1 = (uchar*)CV_NODE_VAL(m1,node1);
|
||||
uchar* v2 = cvPtrND( m2, CV_NODE_IDX(m1,node1), 0, 0, &node1->hashval );
|
||||
if( !v2 )
|
||||
return false;
|
||||
if( depth == CV_8U || depth == CV_8S )
|
||||
{
|
||||
if( *v1 != *v2 )
|
||||
return false;
|
||||
}
|
||||
else if( depth == CV_16U || depth == CV_16S )
|
||||
{
|
||||
if( *(ushort*)v1 != *(ushort*)v2 )
|
||||
return false;
|
||||
}
|
||||
else if( depth == CV_32S )
|
||||
{
|
||||
if( *(int*)v1 != *(int*)v2 )
|
||||
return false;
|
||||
}
|
||||
else if( depth == CV_32F )
|
||||
{
|
||||
if( fabs(*(float*)v1 - *(float*)v2) > eps*(fabs(*(float*)v2) + 1) )
|
||||
return false;
|
||||
}
|
||||
else if( fabs(*(double*)v1 - *(double*)v2) > eps*(fabs(*(double*)v2) + 1) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
class Core_IOTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
Core_IOTest() {};
|
||||
protected:
|
||||
void run(int)
|
||||
{
|
||||
double ranges[][2] = {{0, 256}, {-128, 128}, {0, 65536}, {-32768, 32768},
|
||||
{-1000000, 1000000}, {-10, 10}, {-10, 10}};
|
||||
RNG& rng = ts->get_rng();
|
||||
RNG rng0;
|
||||
test_case_count = 2;
|
||||
int progress = 0;
|
||||
MemStorage storage(cvCreateMemStorage(0));
|
||||
|
||||
for( int idx = 0; idx < test_case_count; idx++ )
|
||||
{
|
||||
ts->update_context( this, idx, false );
|
||||
progress = update_progress( progress, idx, test_case_count, 0 );
|
||||
|
||||
cvClearMemStorage(storage);
|
||||
|
||||
char buf[L_tmpnam+16];
|
||||
char* filename = tmpnam(buf);
|
||||
strcat(filename, idx % 2 ? ".yml" : ".xml");
|
||||
if(filename[0] == '\\')
|
||||
filename++;
|
||||
|
||||
FileStorage fs(filename, FileStorage::WRITE);
|
||||
|
||||
int test_int = (int)cvtest::randInt(rng);
|
||||
double test_real = (cvtest::randInt(rng)%2?1:-1)*exp(cvtest::randReal(rng)*18-9);
|
||||
string test_string = "vw wv23424rt\"&<>&'@#$@$%$%&%IJUKYILFD@#$@%$&*&() ";
|
||||
|
||||
int depth = cvtest::randInt(rng) % (CV_64F+1);
|
||||
int cn = cvtest::randInt(rng) % 4 + 1;
|
||||
Mat test_mat(cvtest::randInt(rng)%30+1, cvtest::randInt(rng)%30+1, CV_MAKETYPE(depth, cn));
|
||||
|
||||
rng0.fill(test_mat, CV_RAND_UNI, Scalar::all(ranges[depth][0]), Scalar::all(ranges[depth][1]));
|
||||
if( depth >= CV_32F )
|
||||
{
|
||||
exp(test_mat, test_mat);
|
||||
Mat test_mat_scale(test_mat.size(), test_mat.type());
|
||||
rng0.fill(test_mat_scale, CV_RAND_UNI, Scalar::all(-1), Scalar::all(1));
|
||||
multiply(test_mat, test_mat_scale, test_mat);
|
||||
}
|
||||
|
||||
CvSeq* seq = cvCreateSeq(test_mat.type(), (int)sizeof(CvSeq),
|
||||
(int)test_mat.elemSize(), storage);
|
||||
cvSeqPushMulti(seq, test_mat.data, test_mat.cols*test_mat.rows);
|
||||
|
||||
CvGraph* graph = cvCreateGraph( CV_ORIENTED_GRAPH,
|
||||
sizeof(CvGraph), sizeof(CvGraphVtx),
|
||||
sizeof(CvGraphEdge), storage );
|
||||
int edges[][2] = {{0,1},{1,2},{2,0},{0,3},{3,4},{4,1}};
|
||||
int i, vcount = 5, ecount = 6;
|
||||
for( i = 0; i < vcount; i++ )
|
||||
cvGraphAddVtx(graph);
|
||||
for( i = 0; i < ecount; i++ )
|
||||
{
|
||||
CvGraphEdge* edge;
|
||||
cvGraphAddEdge(graph, edges[i][0], edges[i][1], 0, &edge);
|
||||
edge->weight = (float)(i+1);
|
||||
}
|
||||
|
||||
depth = cvtest::randInt(rng) % (CV_64F+1);
|
||||
cn = cvtest::randInt(rng) % 4 + 1;
|
||||
int sz[] = {cvtest::randInt(rng)%10+1, cvtest::randInt(rng)%10+1, cvtest::randInt(rng)%10+1};
|
||||
MatND test_mat_nd(3, sz, CV_MAKETYPE(depth, cn));
|
||||
|
||||
rng0.fill(test_mat_nd, CV_RAND_UNI, Scalar::all(ranges[depth][0]), Scalar::all(ranges[depth][1]));
|
||||
if( depth >= CV_32F )
|
||||
{
|
||||
exp(test_mat_nd, test_mat_nd);
|
||||
MatND test_mat_scale(test_mat_nd.dims, test_mat_nd.size, test_mat_nd.type());
|
||||
rng0.fill(test_mat_scale, CV_RAND_UNI, Scalar::all(-1), Scalar::all(1));
|
||||
multiply(test_mat_nd, test_mat_scale, test_mat_nd);
|
||||
}
|
||||
|
||||
int ssz[] = {cvtest::randInt(rng)%10+1, cvtest::randInt(rng)%10+1,
|
||||
cvtest::randInt(rng)%10+1,cvtest::randInt(rng)%10+1};
|
||||
SparseMat test_sparse_mat = cvTsGetRandomSparseMat(4, ssz, cvtest::randInt(rng)%(CV_64F+1),
|
||||
cvtest::randInt(rng) % 10000, 0, 100, rng);
|
||||
|
||||
fs << "test_int" << test_int << "test_real" << test_real << "test_string" << test_string;
|
||||
fs << "test_mat" << test_mat;
|
||||
fs << "test_mat_nd" << test_mat_nd;
|
||||
fs << "test_sparse_mat" << test_sparse_mat;
|
||||
|
||||
fs << "test_list" << "[" << 0.0000000000001 << 2 << CV_PI << -3435345 << "2-502 2-029 3egegeg" <<
|
||||
"{:" << "month" << 12 << "day" << 31 << "year" << 1969 << "}" << "]";
|
||||
fs << "test_map" << "{" << "x" << 1 << "y" << 2 << "width" << 100 << "height" << 200 << "lbp" << "[:";
|
||||
|
||||
const uchar arr[] = {0, 1, 1, 0, 1, 1, 0, 1};
|
||||
fs.writeRaw("u", arr, (int)(sizeof(arr)/sizeof(arr[0])));
|
||||
|
||||
fs << "]" << "}";
|
||||
cvWriteComment(*fs, "test comment", 0);
|
||||
|
||||
fs.writeObj("test_seq", seq);
|
||||
fs.writeObj("test_graph",graph);
|
||||
CvGraph* graph2 = (CvGraph*)cvClone(graph);
|
||||
|
||||
fs.release();
|
||||
|
||||
if(!fs.open(filename, FileStorage::READ))
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "filename %s can not be read\n", filename );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISSING_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
int real_int = (int)fs["test_int"];
|
||||
double real_real = (double)fs["test_real"];
|
||||
string real_string = (string)fs["test_string"];
|
||||
|
||||
if( real_int != test_int ||
|
||||
fabs(real_real - test_real) > DBL_EPSILON*(fabs(test_real)+1) ||
|
||||
real_string != test_string )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the read scalars are not correct\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
CvMat* m = (CvMat*)fs["test_mat"].readObj();
|
||||
CvMat _test_mat = test_mat;
|
||||
double max_diff = 0;
|
||||
CvMat stub1, _test_stub1;
|
||||
cvReshape(m, &stub1, 1, 0);
|
||||
cvReshape(&_test_mat, &_test_stub1, 1, 0);
|
||||
vector<int> pt;
|
||||
|
||||
if( !m || !CV_IS_MAT(m) || m->rows != test_mat.rows || m->cols != test_mat.cols ||
|
||||
cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the read matrix is not correct: (%.20g vs %.20g) at (%d,%d)\n",
|
||||
cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[0], pt[1]),
|
||||
pt[0], pt[1] );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
if( m && CV_IS_MAT(m))
|
||||
cvReleaseMat(&m);
|
||||
|
||||
CvMatND* m_nd = (CvMatND*)fs["test_mat_nd"].readObj();
|
||||
CvMatND _test_mat_nd = test_mat_nd;
|
||||
|
||||
if( !m_nd || !CV_IS_MATND(m_nd) )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the read nd-matrix is not correct\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
CvMat stub, _test_stub;
|
||||
cvGetMat(m_nd, &stub, 0, 1);
|
||||
cvGetMat(&_test_mat_nd, &_test_stub, 0, 1);
|
||||
cvReshape(&stub, &stub1, 1, 0);
|
||||
cvReshape(&_test_stub, &_test_stub1, 1, 0);
|
||||
|
||||
if( !CV_ARE_TYPES_EQ(&stub, &_test_stub) ||
|
||||
!CV_ARE_SIZES_EQ(&stub, &_test_stub) ||
|
||||
//cvNorm(&stub, &_test_stub, CV_L2) != 0 )
|
||||
cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "readObj method: the read nd matrix is not correct: (%.20g vs %.20g) vs at (%d,%d)\n",
|
||||
cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[0], pt[1]),
|
||||
pt[0], pt[1] );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
MatND mat_nd2;
|
||||
fs["test_mat_nd"] >> mat_nd2;
|
||||
CvMatND m_nd2 = mat_nd2;
|
||||
cvGetMat(&m_nd2, &stub, 0, 1);
|
||||
cvReshape(&stub, &stub1, 1, 0);
|
||||
|
||||
if( !CV_ARE_TYPES_EQ(&stub, &_test_stub) ||
|
||||
!CV_ARE_SIZES_EQ(&stub, &_test_stub) ||
|
||||
//cvNorm(&stub, &_test_stub, CV_L2) != 0 )
|
||||
cvtest::cmpEps( Mat(&stub1), Mat(&_test_stub1), &max_diff, 0, &pt, true) < 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "C++ method: the read nd matrix is not correct: (%.20g vs %.20g) vs at (%d,%d)\n",
|
||||
cvGetReal2D(&stub1, pt[0], pt[1]), cvGetReal2D(&_test_stub1, pt[1], pt[0]),
|
||||
pt[0], pt[1] );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
cvRelease((void**)&m_nd);
|
||||
|
||||
Ptr<CvSparseMat> m_s = (CvSparseMat*)fs["test_sparse_mat"].readObj();
|
||||
Ptr<CvSparseMat> _test_sparse_ = (CvSparseMat*)test_sparse_mat;
|
||||
Ptr<CvSparseMat> _test_sparse = (CvSparseMat*)cvClone(_test_sparse_);
|
||||
SparseMat m_s2;
|
||||
fs["test_sparse_mat"] >> m_s2;
|
||||
Ptr<CvSparseMat> _m_s2 = (CvSparseMat*)m_s2;
|
||||
|
||||
if( !m_s || !CV_IS_SPARSE_MAT(m_s) ||
|
||||
!cvTsCheckSparse(m_s, _test_sparse,0) ||
|
||||
!cvTsCheckSparse(_m_s2, _test_sparse,0))
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the read sparse matrix is not correct\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
FileNode tl = fs["test_list"];
|
||||
if( tl.type() != FileNode::SEQ || tl.size() != 6 ||
|
||||
fabs((double)tl[0] - 0.0000000000001) >= DBL_EPSILON ||
|
||||
(int)tl[1] != 2 ||
|
||||
fabs((double)tl[2] - CV_PI) >= DBL_EPSILON ||
|
||||
(int)tl[3] != -3435345 ||
|
||||
(string)tl[4] != "2-502 2-029 3egegeg" ||
|
||||
tl[5].type() != FileNode::MAP || tl[5].size() != 3 ||
|
||||
(int)tl[5]["month"] != 12 ||
|
||||
(int)tl[5]["day"] != 31 ||
|
||||
(int)tl[5]["year"] != 1969 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the test list is incorrect\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
FileNode tm = fs["test_map"];
|
||||
FileNode tm_lbp = tm["lbp"];
|
||||
|
||||
int real_x = (int)tm["x"];
|
||||
int real_y = (int)tm["y"];
|
||||
int real_width = (int)tm["width"];
|
||||
int real_height = (int)tm["height"];
|
||||
|
||||
|
||||
int real_lbp_val = 0;
|
||||
FileNodeIterator it;
|
||||
it = tm_lbp.begin();
|
||||
real_lbp_val |= (int)*it << 0;
|
||||
++it;
|
||||
real_lbp_val |= (int)*it << 1;
|
||||
it++;
|
||||
real_lbp_val |= (int)*it << 2;
|
||||
it += 1;
|
||||
real_lbp_val |= (int)*it << 3;
|
||||
FileNodeIterator it2(it);
|
||||
it2 += 4;
|
||||
real_lbp_val |= (int)*it2 << 7;
|
||||
--it2;
|
||||
real_lbp_val |= (int)*it2 << 6;
|
||||
it2--;
|
||||
real_lbp_val |= (int)*it2 << 5;
|
||||
it2 -= 1;
|
||||
real_lbp_val |= (int)*it2 << 4;
|
||||
it2 += -1;
|
||||
CV_Assert( it == it2 );
|
||||
|
||||
if( tm.type() != FileNode::MAP || tm.size() != 5 ||
|
||||
real_x != 1 ||
|
||||
real_y != 2 ||
|
||||
real_width != 100 ||
|
||||
real_height != 200 ||
|
||||
tm_lbp.type() != FileNode::SEQ ||
|
||||
tm_lbp.size() != 8 ||
|
||||
real_lbp_val != 0xb6 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the test map is incorrect\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
CvGraph* graph3 = (CvGraph*)fs["test_graph"].readObj();
|
||||
if(graph2->active_count != vcount || graph3->active_count != vcount ||
|
||||
graph2->edges->active_count != ecount || graph3->edges->active_count != ecount)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the cloned or read graph have wrong number of vertices or edges\n" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
for( i = 0; i < ecount; i++ )
|
||||
{
|
||||
CvGraphEdge* edge2 = cvFindGraphEdge(graph2, edges[i][0], edges[i][1]);
|
||||
CvGraphEdge* edge3 = cvFindGraphEdge(graph3, edges[i][0], edges[i][1]);
|
||||
if( !edge2 || edge2->weight != (float)(i+1) ||
|
||||
!edge3 || edge3->weight != (float)(i+1) )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "the cloned or read graph do not have the edge (%d, %d)\n", edges[i][0], edges[i][1] );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fs.release();
|
||||
remove(filename);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Core_InputOutput, write_read_consistency) { Core_IOTest test; test.safe_run(); }
|
@ -1,2 +1,3 @@
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/gtest/gtest_main.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
||||
|
811
modules/core/test/test_mat.cpp
Normal file
811
modules/core/test/test_mat.cpp
Normal file
@ -0,0 +1,811 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
class Core_ReduceTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
Core_ReduceTest() {};
|
||||
protected:
|
||||
void run( int);
|
||||
int checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim, double eps );
|
||||
int checkCase( int srcType, int dstType, int dim, Size sz );
|
||||
int checkDim( int dim, Size sz );
|
||||
int checkSize( Size sz );
|
||||
};
|
||||
|
||||
template<class Type>
|
||||
void testReduce( const Mat& src, Mat& sum, Mat& avg, Mat& max, Mat& min, int dim )
|
||||
{
|
||||
assert( src.channels() == 1 );
|
||||
if( dim == 0 ) // row
|
||||
{
|
||||
sum.create( 1, src.cols, CV_64FC1 );
|
||||
max.create( 1, src.cols, CV_64FC1 );
|
||||
min.create( 1, src.cols, CV_64FC1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
sum.create( src.rows, 1, CV_64FC1 );
|
||||
max.create( src.rows, 1, CV_64FC1 );
|
||||
min.create( src.rows, 1, CV_64FC1 );
|
||||
}
|
||||
sum.setTo(Scalar(0));
|
||||
max.setTo(Scalar(-DBL_MAX));
|
||||
min.setTo(Scalar(DBL_MAX));
|
||||
|
||||
const Mat_<Type>& src_ = src;
|
||||
Mat_<double>& sum_ = (Mat_<double>&)sum;
|
||||
Mat_<double>& min_ = (Mat_<double>&)min;
|
||||
Mat_<double>& max_ = (Mat_<double>&)max;
|
||||
|
||||
if( dim == 0 )
|
||||
{
|
||||
for( int ri = 0; ri < src.rows; ri++ )
|
||||
{
|
||||
for( int ci = 0; ci < src.cols; ci++ )
|
||||
{
|
||||
sum_(0, ci) += src_(ri, ci);
|
||||
max_(0, ci) = std::max( max_(0, ci), (double)src_(ri, ci) );
|
||||
min_(0, ci) = std::min( min_(0, ci), (double)src_(ri, ci) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int ci = 0; ci < src.cols; ci++ )
|
||||
{
|
||||
for( int ri = 0; ri < src.rows; ri++ )
|
||||
{
|
||||
sum_(ri, 0) += src_(ri, ci);
|
||||
max_(ri, 0) = std::max( max_(ri, 0), (double)src_(ri, ci) );
|
||||
min_(ri, 0) = std::min( min_(ri, 0), (double)src_(ri, ci) );
|
||||
}
|
||||
}
|
||||
}
|
||||
sum.convertTo( avg, CV_64FC1 );
|
||||
avg = avg * (1.0 / (dim==0 ? (double)src.rows : (double)src.cols));
|
||||
}
|
||||
|
||||
void getMatTypeStr( int type, string& str)
|
||||
{
|
||||
str = type == CV_8UC1 ? "CV_8UC1" :
|
||||
type == CV_8SC1 ? "CV_8SC1" :
|
||||
type == CV_16UC1 ? "CV_16UC1" :
|
||||
type == CV_16SC1 ? "CV_16SC1" :
|
||||
type == CV_32SC1 ? "CV_32SC1" :
|
||||
type == CV_32FC1 ? "CV_32FC1" :
|
||||
type == CV_64FC1 ? "CV_64FC1" : "unsupported matrix type";
|
||||
}
|
||||
|
||||
int Core_ReduceTest::checkOp( const Mat& src, int dstType, int opType, const Mat& opRes, int dim, double eps )
|
||||
{
|
||||
int srcType = src.type();
|
||||
bool support = false;
|
||||
if( opType == CV_REDUCE_SUM || opType == CV_REDUCE_AVG )
|
||||
{
|
||||
if( srcType == CV_8U && (dstType == CV_32S || dstType == CV_32F || dstType == CV_64F) )
|
||||
support = true;
|
||||
if( srcType == CV_16U && (dstType == CV_32F || dstType == CV_64F) )
|
||||
support = true;
|
||||
if( srcType == CV_16S && (dstType == CV_32F || dstType == CV_64F) )
|
||||
support = true;
|
||||
if( srcType == CV_32F && (dstType == CV_32F || dstType == CV_64F) )
|
||||
support = true;
|
||||
if( srcType == CV_64F && dstType == CV_64F)
|
||||
support = true;
|
||||
}
|
||||
else if( opType == CV_REDUCE_MAX )
|
||||
{
|
||||
if( srcType == CV_8U && dstType == CV_8U )
|
||||
support = true;
|
||||
if( srcType == CV_32F && dstType == CV_32F )
|
||||
support = true;
|
||||
if( srcType == CV_64F && dstType == CV_64F )
|
||||
support = true;
|
||||
}
|
||||
else if( opType == CV_REDUCE_MIN )
|
||||
{
|
||||
if( srcType == CV_8U && dstType == CV_8U)
|
||||
support = true;
|
||||
if( srcType == CV_32F && dstType == CV_32F)
|
||||
support = true;
|
||||
if( srcType == CV_64F && dstType == CV_64F)
|
||||
support = true;
|
||||
}
|
||||
if( !support )
|
||||
return cvtest::TS::OK;
|
||||
|
||||
assert( opRes.type() == CV_64FC1 );
|
||||
Mat _dst, dst;
|
||||
reduce( src, _dst, dim, opType, dstType );
|
||||
_dst.convertTo( dst, CV_64FC1 );
|
||||
if( norm( opRes, dst, NORM_INF ) > eps )
|
||||
{
|
||||
char msg[100];
|
||||
const char* opTypeStr = opType == CV_REDUCE_SUM ? "CV_REDUCE_SUM" :
|
||||
opType == CV_REDUCE_AVG ? "CV_REDUCE_AVG" :
|
||||
opType == CV_REDUCE_MAX ? "CV_REDUCE_MAX" :
|
||||
opType == CV_REDUCE_MIN ? "CV_REDUCE_MIN" : "unknown operation type";
|
||||
string srcTypeStr, dstTypeStr;
|
||||
getMatTypeStr( src.type(), srcTypeStr );
|
||||
getMatTypeStr( dstType, dstTypeStr );
|
||||
const char* dimStr = dim == 0 ? "ROWS" : "COLS";
|
||||
|
||||
sprintf( msg, "bad accuracy with srcType = %s, dstType = %s, opType = %s, dim = %s",
|
||||
srcTypeStr.c_str(), dstTypeStr.c_str(), opTypeStr, dimStr );
|
||||
ts->printf( cvtest::TS::LOG, msg );
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int Core_ReduceTest::checkCase( int srcType, int dstType, int dim, Size sz )
|
||||
{
|
||||
int code = cvtest::TS::OK, tempCode;
|
||||
Mat src, sum, avg, max, min;
|
||||
|
||||
src.create( sz, srcType );
|
||||
randu( src, Scalar(0), Scalar(100) );
|
||||
|
||||
if( srcType == CV_8UC1 )
|
||||
testReduce<uchar>( src, sum, avg, max, min, dim );
|
||||
else if( srcType == CV_8SC1 )
|
||||
testReduce<char>( src, sum, avg, max, min, dim );
|
||||
else if( srcType == CV_16UC1 )
|
||||
testReduce<unsigned short int>( src, sum, avg, max, min, dim );
|
||||
else if( srcType == CV_16SC1 )
|
||||
testReduce<short int>( src, sum, avg, max, min, dim );
|
||||
else if( srcType == CV_32SC1 )
|
||||
testReduce<int>( src, sum, avg, max, min, dim );
|
||||
else if( srcType == CV_32FC1 )
|
||||
testReduce<float>( src, sum, avg, max, min, dim );
|
||||
else if( srcType == CV_64FC1 )
|
||||
testReduce<double>( src, sum, avg, max, min, dim );
|
||||
else
|
||||
assert( 0 );
|
||||
|
||||
// 1. sum
|
||||
tempCode = checkOp( src, dstType, CV_REDUCE_SUM, sum, dim,
|
||||
srcType == CV_32FC1 && dstType == CV_32FC1 ? 0.05 : FLT_EPSILON );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// 2. avg
|
||||
tempCode = checkOp( src, dstType, CV_REDUCE_AVG, avg, dim,
|
||||
dstType == CV_32SC1 ? 0.6 : 0.00007 );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// 3. max
|
||||
tempCode = checkOp( src, dstType, CV_REDUCE_MAX, max, dim, FLT_EPSILON );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// 4. min
|
||||
tempCode = checkOp( src, dstType, CV_REDUCE_MIN, min, dim, FLT_EPSILON );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int Core_ReduceTest::checkDim( int dim, Size sz )
|
||||
{
|
||||
int code = cvtest::TS::OK, tempCode;
|
||||
|
||||
// CV_8UC1
|
||||
tempCode = checkCase( CV_8UC1, CV_8UC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkCase( CV_8UC1, CV_32SC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkCase( CV_8UC1, CV_32FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkCase( CV_8UC1, CV_64FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// CV_16UC1
|
||||
tempCode = checkCase( CV_16UC1, CV_32FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkCase( CV_16UC1, CV_64FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// CV_16SC1
|
||||
tempCode = checkCase( CV_16SC1, CV_32FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkCase( CV_16SC1, CV_64FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// CV_32FC1
|
||||
tempCode = checkCase( CV_32FC1, CV_32FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkCase( CV_32FC1, CV_64FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
// CV_64FC1
|
||||
tempCode = checkCase( CV_64FC1, CV_64FC1, dim, sz );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int Core_ReduceTest::checkSize( Size sz )
|
||||
{
|
||||
int code = cvtest::TS::OK, tempCode;
|
||||
|
||||
tempCode = checkDim( 0, sz ); // rows
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkDim( 1, sz ); // cols
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void Core_ReduceTest::run( int )
|
||||
{
|
||||
int code = cvtest::TS::OK, tempCode;
|
||||
|
||||
tempCode = checkSize( Size(1,1) );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkSize( Size(1,100) );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkSize( Size(100,1) );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
tempCode = checkSize( Size(1000,500) );
|
||||
code = tempCode != cvtest::TS::OK ? tempCode : code;
|
||||
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_C
|
||||
|
||||
Size sz(200, 500);
|
||||
|
||||
class Core_PCATest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
Core_PCATest() {}
|
||||
protected:
|
||||
void run(int)
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
double diffPrjEps, diffBackPrjEps,
|
||||
prjEps, backPrjEps,
|
||||
evalEps, evecEps;
|
||||
int maxComponents = 100;
|
||||
Mat rPoints(sz, CV_32FC1), rTestPoints(sz, CV_32FC1);
|
||||
RNG& rng = ts->get_rng();
|
||||
|
||||
rng.fill( rPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
|
||||
rng.fill( rTestPoints, RNG::UNIFORM, Scalar::all(0.0), Scalar::all(1.0) );
|
||||
|
||||
PCA rPCA( rPoints, Mat(), CV_PCA_DATA_AS_ROW, maxComponents ), cPCA;
|
||||
|
||||
// 1. check C++ PCA & ROW
|
||||
Mat rPrjTestPoints = rPCA.project( rTestPoints );
|
||||
Mat rBackPrjTestPoints = rPCA.backProject( rPrjTestPoints );
|
||||
|
||||
Mat avg(1, sz.width, CV_32FC1 );
|
||||
reduce( rPoints, avg, 0, CV_REDUCE_AVG );
|
||||
Mat Q = rPoints - repeat( avg, rPoints.rows, 1 ), Qt = Q.t(), eval, evec;
|
||||
Q = Qt * Q;
|
||||
Q = Q /(float)rPoints.rows;
|
||||
|
||||
eigen( Q, eval, evec );
|
||||
/*SVD svd(Q);
|
||||
evec = svd.vt;
|
||||
eval = svd.w;*/
|
||||
|
||||
Mat subEval( maxComponents, 1, eval.type(), eval.data ),
|
||||
subEvec( maxComponents, evec.cols, evec.type(), evec.data );
|
||||
|
||||
#ifdef CHECK_C
|
||||
Mat prjTestPoints, backPrjTestPoints, cPoints = rPoints.t(), cTestPoints = rTestPoints.t();
|
||||
CvMat _points, _testPoints, _avg, _eval, _evec, _prjTestPoints, _backPrjTestPoints;
|
||||
#endif
|
||||
|
||||
// check eigen()
|
||||
double eigenEps = 1e-6;
|
||||
double err;
|
||||
for(int i = 0; i < Q.rows; i++ )
|
||||
{
|
||||
Mat v = evec.row(i).t();
|
||||
Mat Qv = Q * v;
|
||||
|
||||
Mat lv = eval.at<float>(i,0) * v;
|
||||
err = norm( Qv, lv );
|
||||
if( err > eigenEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of eigen(); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
}
|
||||
// check pca eigenvalues
|
||||
evalEps = 1e-6, evecEps = 1;
|
||||
err = norm( rPCA.eigenvalues, subEval );
|
||||
if( err > evalEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "pca.eigenvalues is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
// check pca eigenvectors
|
||||
err = norm( rPCA.eigenvectors, subEvec, CV_RELATIVE_L2 );
|
||||
if( err > evecEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "pca.eigenvectors is incorrect (CV_PCA_DATA_AS_ROW); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
prjEps = 1.265, backPrjEps = 1.265;
|
||||
for( int i = 0; i < rTestPoints.rows; i++ )
|
||||
{
|
||||
// check pca project
|
||||
Mat subEvec_t = subEvec.t();
|
||||
Mat prj = rTestPoints.row(i) - avg; prj *= subEvec_t;
|
||||
err = norm(rPrjTestPoints.row(i), prj, CV_RELATIVE_L2);
|
||||
if( err > prjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
// check pca backProject
|
||||
Mat backPrj = rPrjTestPoints.row(i) * subEvec + avg;
|
||||
err = norm( rBackPrjTestPoints.row(i), backPrj, CV_RELATIVE_L2 );
|
||||
if( err > backPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. check C++ PCA & COL
|
||||
cPCA( rPoints.t(), Mat(), CV_PCA_DATA_AS_COL, maxComponents );
|
||||
diffPrjEps = 1, diffBackPrjEps = 1;
|
||||
err = norm(cPCA.project(rTestPoints.t()), rPrjTestPoints.t(), CV_RELATIVE_L2 );
|
||||
if( err > diffPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of project() (CV_PCA_DATA_AS_COL); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
err = norm(cPCA.backProject(rPrjTestPoints.t()), rBackPrjTestPoints.t(), CV_RELATIVE_L2 );
|
||||
if( err > diffBackPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of backProject() (CV_PCA_DATA_AS_COL); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
#ifdef CHECK_C
|
||||
// 3. check C PCA & ROW
|
||||
_points = rPoints;
|
||||
_testPoints = rTestPoints;
|
||||
_avg = avg;
|
||||
_eval = eval;
|
||||
_evec = evec;
|
||||
prjTestPoints.create(rTestPoints.rows, maxComponents, rTestPoints.type() );
|
||||
backPrjTestPoints.create(rPoints.size(), rPoints.type() );
|
||||
_prjTestPoints = prjTestPoints;
|
||||
_backPrjTestPoints = backPrjTestPoints;
|
||||
|
||||
cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_ROW );
|
||||
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
|
||||
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
|
||||
|
||||
err = norm(prjTestPoints, rPrjTestPoints, CV_RELATIVE_L2);
|
||||
if( err > diffPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
err = norm(backPrjTestPoints, rBackPrjTestPoints, CV_RELATIVE_L2);
|
||||
if( err > diffBackPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_ROW); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
// 3. check C PCA & COL
|
||||
_points = cPoints;
|
||||
_testPoints = cTestPoints;
|
||||
avg = avg.t(); _avg = avg;
|
||||
eval = eval.t(); _eval = eval;
|
||||
evec = evec.t(); _evec = evec;
|
||||
prjTestPoints = prjTestPoints.t(); _prjTestPoints = prjTestPoints;
|
||||
backPrjTestPoints = backPrjTestPoints.t(); _backPrjTestPoints = backPrjTestPoints;
|
||||
|
||||
cvCalcPCA( &_points, &_avg, &_eval, &_evec, CV_PCA_DATA_AS_COL );
|
||||
cvProjectPCA( &_testPoints, &_avg, &_evec, &_prjTestPoints );
|
||||
cvBackProjectPCA( &_prjTestPoints, &_avg, &_evec, &_backPrjTestPoints );
|
||||
|
||||
err = norm(prjTestPoints, rPrjTestPoints.t(), CV_RELATIVE_L2 );
|
||||
if( err > diffPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of cvProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
err = norm(backPrjTestPoints, rBackPrjTestPoints.t(), CV_RELATIVE_L2);
|
||||
if( err > diffBackPrjEps )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of cvBackProjectPCA() (CV_PCA_DATA_AS_COL); err = %f\n", err );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto exit_func;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit_func:
|
||||
|
||||
RNG& _rng = ts->get_rng();
|
||||
_rng = rng;
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
};
|
||||
|
||||
class Core_ArrayOpTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
Core_ArrayOpTest();
|
||||
~Core_ArrayOpTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
Core_ArrayOpTest::Core_ArrayOpTest()
|
||||
{
|
||||
}
|
||||
Core_ArrayOpTest::~Core_ArrayOpTest() {}
|
||||
|
||||
static string idx2string(const int* idx, int dims)
|
||||
{
|
||||
char buf[256];
|
||||
char* ptr = buf;
|
||||
for( int k = 0; k < dims; k++ )
|
||||
{
|
||||
sprintf(ptr, "%4d ", idx[k]);
|
||||
ptr += strlen(ptr);
|
||||
}
|
||||
ptr[-1] = '\0';
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
static const int* string2idx(const string& s, int* idx, int dims)
|
||||
{
|
||||
const char* ptr = s.c_str();
|
||||
for( int k = 0; k < dims; k++ )
|
||||
{
|
||||
int n = 0;
|
||||
sscanf(ptr, "%d%n", idx + k, &n);
|
||||
ptr += n;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
static double getValue(SparseMat& M, const int* idx, RNG& rng)
|
||||
{
|
||||
int d = M.dims();
|
||||
size_t hv = 0, *phv = 0;
|
||||
if( (unsigned)rng % 2 )
|
||||
{
|
||||
hv = d == 2 ? M.hash(idx[0], idx[1]) :
|
||||
d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
|
||||
phv = &hv;
|
||||
}
|
||||
|
||||
const uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], false, phv) :
|
||||
d == 3 ? M.ptr(idx[0], idx[1], idx[2], false, phv) :
|
||||
M.ptr(idx, false, phv);
|
||||
return !ptr ? 0 : M.type() == CV_32F ? *(float*)ptr : M.type() == CV_64F ? *(double*)ptr : 0;
|
||||
}
|
||||
|
||||
static double getValue(const CvSparseMat* M, const int* idx)
|
||||
{
|
||||
int type = 0;
|
||||
const uchar* ptr = cvPtrND(M, idx, &type, 0);
|
||||
return !ptr ? 0 : type == CV_32F ? *(float*)ptr : type == CV_64F ? *(double*)ptr : 0;
|
||||
}
|
||||
|
||||
static void eraseValue(SparseMat& M, const int* idx, RNG& rng)
|
||||
{
|
||||
int d = M.dims();
|
||||
size_t hv = 0, *phv = 0;
|
||||
if( (unsigned)rng % 2 )
|
||||
{
|
||||
hv = d == 2 ? M.hash(idx[0], idx[1]) :
|
||||
d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
|
||||
phv = &hv;
|
||||
}
|
||||
|
||||
if( d == 2 )
|
||||
M.erase(idx[0], idx[1], phv);
|
||||
else if( d == 3 )
|
||||
M.erase(idx[0], idx[1], idx[2], phv);
|
||||
else
|
||||
M.erase(idx, phv);
|
||||
}
|
||||
|
||||
static void eraseValue(CvSparseMat* M, const int* idx)
|
||||
{
|
||||
cvClearND(M, idx);
|
||||
}
|
||||
|
||||
static void setValue(SparseMat& M, const int* idx, double value, RNG& rng)
|
||||
{
|
||||
int d = M.dims();
|
||||
size_t hv = 0, *phv = 0;
|
||||
if( (unsigned)rng % 2 )
|
||||
{
|
||||
hv = d == 2 ? M.hash(idx[0], idx[1]) :
|
||||
d == 3 ? M.hash(idx[0], idx[1], idx[2]) : M.hash(idx);
|
||||
phv = &hv;
|
||||
}
|
||||
|
||||
uchar* ptr = d == 2 ? M.ptr(idx[0], idx[1], true, phv) :
|
||||
d == 3 ? M.ptr(idx[0], idx[1], idx[2], true, phv) :
|
||||
M.ptr(idx, true, phv);
|
||||
if( M.type() == CV_32F )
|
||||
*(float*)ptr = (float)value;
|
||||
else if( M.type() == CV_64F )
|
||||
*(double*)ptr = value;
|
||||
else
|
||||
CV_Error(CV_StsUnsupportedFormat, "");
|
||||
}
|
||||
|
||||
void Core_ArrayOpTest::run( int /* start_from */)
|
||||
{
|
||||
int errcount = 0;
|
||||
|
||||
// dense matrix operations
|
||||
{
|
||||
int sz3[] = {5, 10, 15};
|
||||
MatND A(3, sz3, CV_32F), B(3, sz3, CV_16SC4);
|
||||
CvMatND matA = A, matB = B;
|
||||
RNG rng;
|
||||
rng.fill(A, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
|
||||
rng.fill(B, CV_RAND_UNI, Scalar::all(-10), Scalar::all(10));
|
||||
|
||||
int idx0[] = {3,4,5}, idx1[] = {0, 9, 7};
|
||||
float val0 = 130;
|
||||
Scalar val1(-1000, 30, 3, 8);
|
||||
cvSetRealND(&matA, idx0, val0);
|
||||
cvSetReal3D(&matA, idx1[0], idx1[1], idx1[2], -val0);
|
||||
cvSetND(&matB, idx0, val1);
|
||||
cvSet3D(&matB, idx1[0], idx1[1], idx1[2], -val1);
|
||||
Ptr<CvMatND> matC = cvCloneMatND(&matB);
|
||||
|
||||
if( A.at<float>(idx0[0], idx0[1], idx0[2]) != val0 ||
|
||||
A.at<float>(idx1[0], idx1[1], idx1[2]) != -val0 ||
|
||||
cvGetReal3D(&matA, idx0[0], idx0[1], idx0[2]) != val0 ||
|
||||
cvGetRealND(&matA, idx1) != -val0 ||
|
||||
|
||||
Scalar(B.at<Vec4s>(idx0[0], idx0[1], idx0[2])) != val1 ||
|
||||
Scalar(B.at<Vec4s>(idx1[0], idx1[1], idx1[2])) != -val1 ||
|
||||
Scalar(cvGet3D(matC, idx0[0], idx0[1], idx0[2])) != val1 ||
|
||||
Scalar(cvGetND(matC, idx1)) != -val1 )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "one of cvSetReal3D, cvSetRealND, cvSet3D, cvSetND "
|
||||
"or the corresponding *Get* functions is not correct\n");
|
||||
errcount++;
|
||||
}
|
||||
}
|
||||
|
||||
RNG rng;
|
||||
const int MAX_DIM = 5, MAX_DIM_SZ = 10;
|
||||
// sparse matrix operations
|
||||
for( int si = 0; si < 10; si++ )
|
||||
{
|
||||
int depth = (unsigned)rng % 2 == 0 ? CV_32F : CV_64F;
|
||||
int dims = ((unsigned)rng % MAX_DIM) + 1;
|
||||
int i, k, size[MAX_DIM]={0}, idx[MAX_DIM]={0};
|
||||
vector<string> all_idxs;
|
||||
vector<double> all_vals;
|
||||
vector<double> all_vals2;
|
||||
string sidx, min_sidx, max_sidx;
|
||||
double min_val=0, max_val=0;
|
||||
|
||||
int p = 1;
|
||||
for( k = 0; k < dims; k++ )
|
||||
{
|
||||
size[k] = ((unsigned)rng % MAX_DIM_SZ) + 1;
|
||||
p *= size[k];
|
||||
}
|
||||
SparseMat M( dims, size, depth );
|
||||
map<string, double> M0;
|
||||
|
||||
int nz0 = (unsigned)rng % max(p/5,10);
|
||||
nz0 = min(max(nz0, 1), p);
|
||||
all_vals.resize(nz0);
|
||||
all_vals2.resize(nz0);
|
||||
Mat_<double> _all_vals(all_vals), _all_vals2(all_vals2);
|
||||
rng.fill(_all_vals, CV_RAND_UNI, Scalar(-1000), Scalar(1000));
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
Mat _all_vals_f;
|
||||
_all_vals.convertTo(_all_vals_f, CV_32F);
|
||||
_all_vals_f.convertTo(_all_vals, CV_64F);
|
||||
}
|
||||
_all_vals.convertTo(_all_vals2, _all_vals2.type(), 2);
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
Mat _all_vals2_f;
|
||||
_all_vals2.convertTo(_all_vals2_f, CV_32F);
|
||||
_all_vals2_f.convertTo(_all_vals2, CV_64F);
|
||||
}
|
||||
|
||||
minMaxLoc(_all_vals, &min_val, &max_val);
|
||||
double _norm0 = norm(_all_vals, CV_C);
|
||||
double _norm1 = norm(_all_vals, CV_L1);
|
||||
double _norm2 = norm(_all_vals, CV_L2);
|
||||
|
||||
for( i = 0; i < nz0; i++ )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
for( k = 0; k < dims; k++ )
|
||||
idx[k] = (unsigned)rng % size[k];
|
||||
sidx = idx2string(idx, dims);
|
||||
if( M0.count(sidx) == 0 )
|
||||
break;
|
||||
}
|
||||
all_idxs.push_back(sidx);
|
||||
M0[sidx] = all_vals[i];
|
||||
if( all_vals[i] == min_val )
|
||||
min_sidx = sidx;
|
||||
if( all_vals[i] == max_val )
|
||||
max_sidx = sidx;
|
||||
setValue(M, idx, all_vals[i], rng);
|
||||
double v = getValue(M, idx, rng);
|
||||
if( v != all_vals[i] )
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "%d. immediately after SparseMat[%s]=%.20g the current value is %.20g\n",
|
||||
i, sidx.c_str(), all_vals[i], v);
|
||||
errcount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<CvSparseMat> M2 = (CvSparseMat*)M;
|
||||
MatND Md;
|
||||
M.copyTo(Md);
|
||||
SparseMat M3; SparseMat(Md).convertTo(M3, Md.type(), 2);
|
||||
|
||||
int nz1 = (int)M.nzcount(), nz2 = (int)M3.nzcount();
|
||||
double norm0 = norm(M, CV_C);
|
||||
double norm1 = norm(M, CV_L1);
|
||||
double norm2 = norm(M, CV_L2);
|
||||
double eps = depth == CV_32F ? FLT_EPSILON*100 : DBL_EPSILON*1000;
|
||||
|
||||
if( nz1 != nz0 || nz2 != nz0)
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "%d: The number of non-zero elements before/after converting to/from dense matrix is not correct: %d/%d (while it should be %d)\n",
|
||||
si, nz1, nz2, nz0 );
|
||||
break;
|
||||
}
|
||||
|
||||
if( fabs(norm0 - _norm0) > fabs(_norm0)*eps ||
|
||||
fabs(norm1 - _norm1) > fabs(_norm1)*eps ||
|
||||
fabs(norm2 - _norm2) > fabs(_norm2)*eps )
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "%d: The norms are different: %.20g/%.20g/%.20g vs %.20g/%.20g/%.20g\n",
|
||||
si, norm0, norm1, norm2, _norm0, _norm1, _norm2 );
|
||||
break;
|
||||
}
|
||||
|
||||
int n = (unsigned)rng % max(p/5,10);
|
||||
n = min(max(n, 1), p) + nz0;
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
double val1, val2, val3, val0;
|
||||
if(i < nz0)
|
||||
{
|
||||
sidx = all_idxs[i];
|
||||
string2idx(sidx, idx, dims);
|
||||
val0 = all_vals[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for( k = 0; k < dims; k++ )
|
||||
idx[k] = (unsigned)rng % size[k];
|
||||
sidx = idx2string(idx, dims);
|
||||
val0 = M0[sidx];
|
||||
}
|
||||
val1 = getValue(M, idx, rng);
|
||||
val2 = getValue(M2, idx);
|
||||
val3 = getValue(M3, idx, rng);
|
||||
|
||||
if( val1 != val0 || val2 != val0 || fabs(val3 - val0*2) > fabs(val0*2)*FLT_EPSILON )
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "SparseMat M[%s] = %g/%g/%g (while it should be %g)\n", sidx.c_str(), val1, val2, val3, val0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
{
|
||||
double val1, val2;
|
||||
if(i < nz0)
|
||||
{
|
||||
sidx = all_idxs[i];
|
||||
string2idx(sidx, idx, dims);
|
||||
}
|
||||
else
|
||||
{
|
||||
for( k = 0; k < dims; k++ )
|
||||
idx[k] = (unsigned)rng % size[k];
|
||||
sidx = idx2string(idx, dims);
|
||||
}
|
||||
eraseValue(M, idx, rng);
|
||||
eraseValue(M2, idx);
|
||||
val1 = getValue(M, idx, rng);
|
||||
val2 = getValue(M2, idx);
|
||||
if( val1 != 0 || val2 != 0 )
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "SparseMat: after deleting M[%s], it is =%g/%g (while it should be 0)\n", sidx.c_str(), val1, val2 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int nz = (int)M.nzcount();
|
||||
if( nz != 0 )
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "The number of non-zero elements after removing all the elements = %d (while it should be 0)\n", nz );
|
||||
break;
|
||||
}
|
||||
|
||||
int idx1[MAX_DIM], idx2[MAX_DIM];
|
||||
double val1 = 0, val2 = 0;
|
||||
M3 = SparseMat(Md);
|
||||
minMaxLoc(M3, &val1, &val2, idx1, idx2);
|
||||
string s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
|
||||
if( val1 != min_val || val2 != max_val || s1 != min_sidx || s2 != max_sidx )
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "%d. Sparse: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t"
|
||||
"(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
|
||||
min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
minMaxLoc(Md, &val1, &val2, idx1, idx2);
|
||||
s1 = idx2string(idx1, dims), s2 = idx2string(idx2, dims);
|
||||
if( (min_val < 0 && (val1 != min_val || s1 != min_sidx)) ||
|
||||
(max_val > 0 && (val2 != max_val || s2 != max_sidx)) )
|
||||
{
|
||||
errcount++;
|
||||
ts->printf(cvtest::TS::LOG, "%d. Dense: The value and positions of minimum/maximum elements are different from the reference values and positions:\n\t"
|
||||
"(%g, %g, %s, %s) vs (%g, %g, %s, %s)\n", si, val1, val2, s1.c_str(), s2.c_str(),
|
||||
min_val, max_val, min_sidx.c_str(), max_sidx.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ts->set_failed_test_info(errcount == 0 ? cvtest::TS::OK : cvtest::TS::FAIL_INVALID_OUTPUT);
|
||||
}
|
||||
|
||||
TEST(Core_PCA, accuracy) { Core_PCATest test; test.safe_run(); }
|
||||
TEST(Core_Reduce, accuracy) { Core_ReduceTest test; test.safe_run(); }
|
||||
TEST(Core_Array, basic_operations) { Core_ArrayOpTest test; test.safe_run(); }
|
2372
modules/core/test/test_math.cpp
Normal file
2372
modules/core/test/test_math.cpp
Normal file
File diff suppressed because it is too large
Load Diff
829
modules/core/test/test_operations.cpp
Normal file
829
modules/core/test/test_operations.cpp
Normal file
@ -0,0 +1,829 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
class CV_OperationsTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_OperationsTest();
|
||||
~CV_OperationsTest();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
struct test_excep
|
||||
{
|
||||
test_excep(const string& _s=string("")) : s(_s) {};
|
||||
string s;
|
||||
};
|
||||
|
||||
bool SomeMatFunctions();
|
||||
bool TestMat();
|
||||
bool TestTemplateMat();
|
||||
bool TestMatND();
|
||||
bool TestSparseMat();
|
||||
bool operations1();
|
||||
|
||||
void checkDiff(const Mat& m1, const Mat& m2, const string& s) { if (norm(m1, m2, NORM_INF) != 0) throw test_excep(s); }
|
||||
void checkDiffF(const Mat& m1, const Mat& m2, const string& s) { if (norm(m1, m2, NORM_INF) > 1e-5) throw test_excep(s); }
|
||||
|
||||
};
|
||||
|
||||
CV_OperationsTest::CV_OperationsTest()
|
||||
{
|
||||
}
|
||||
|
||||
CV_OperationsTest::~CV_OperationsTest() {}
|
||||
|
||||
#define STR(a) STR2(a)
|
||||
#define STR2(a) #a
|
||||
|
||||
#define CHECK_DIFF(a, b) checkDiff(a, b, "(" #a ") != (" #b ") at l." STR(__LINE__))
|
||||
#define CHECK_DIFF_FLT(a, b) checkDiffF(a, b, "(" #a ") !=(eps) (" #b ") at l." STR(__LINE__))
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER < 1400
|
||||
#define MSVC_OLD 1
|
||||
#else
|
||||
#define MSVC_OLD 0
|
||||
#endif
|
||||
|
||||
bool CV_OperationsTest::TestMat()
|
||||
{
|
||||
try
|
||||
{
|
||||
Mat one_3x1(3, 1, CV_32F, Scalar(1.0));
|
||||
Mat shi_3x1(3, 1, CV_32F, Scalar(1.2));
|
||||
Mat shi_2x1(2, 1, CV_32F, Scalar(-1));
|
||||
Scalar shift = Scalar::all(15);
|
||||
|
||||
float data[] = { sqrt(2.f)/2, -sqrt(2.f)/2, 1.f, sqrt(2.f)/2, sqrt(2.f)/2, 10.f };
|
||||
Mat rot_2x3(2, 3, CV_32F, data);
|
||||
|
||||
Mat res = one_3x1 + shi_3x1 + shi_3x1 + shi_3x1;
|
||||
res = Mat(Mat(2 * rot_2x3) * res - shi_2x1) + shift;
|
||||
|
||||
Mat tmp, res2;
|
||||
add(one_3x1, shi_3x1, tmp);
|
||||
add(tmp, shi_3x1, tmp);
|
||||
add(tmp, shi_3x1, tmp);
|
||||
gemm(rot_2x3, tmp, 2, shi_2x1, -1, res2, 0);
|
||||
add(res2, Mat(2, 1, CV_32F, shift), res2);
|
||||
|
||||
CHECK_DIFF(res, res2);
|
||||
|
||||
Mat mat4x4(4, 4, CV_32F);
|
||||
randu(mat4x4, Scalar(0), Scalar(10));
|
||||
|
||||
Mat roi1 = mat4x4(Rect(Point(1, 1), Size(2, 2)));
|
||||
Mat roi2 = mat4x4(Range(1, 3), Range(1, 3));
|
||||
|
||||
CHECK_DIFF(roi1, roi2);
|
||||
CHECK_DIFF(mat4x4, mat4x4(Rect(Point(0,0), mat4x4.size())));
|
||||
|
||||
Mat intMat10(3, 3, CV_32S, Scalar(10));
|
||||
Mat intMat11(3, 3, CV_32S, Scalar(11));
|
||||
Mat resMat(3, 3, CV_8U, Scalar(255));
|
||||
|
||||
CHECK_DIFF(resMat, intMat10 == intMat10);
|
||||
CHECK_DIFF(resMat, intMat10 < intMat11);
|
||||
CHECK_DIFF(resMat, intMat11 > intMat10);
|
||||
CHECK_DIFF(resMat, intMat10 <= intMat11);
|
||||
CHECK_DIFF(resMat, intMat11 >= intMat10);
|
||||
CHECK_DIFF(resMat, intMat11 != intMat10);
|
||||
|
||||
CHECK_DIFF(resMat, intMat10 == 10.0);
|
||||
CHECK_DIFF(resMat, 10.0 == intMat10);
|
||||
CHECK_DIFF(resMat, intMat10 < 11.0);
|
||||
CHECK_DIFF(resMat, 11.0 > intMat10);
|
||||
CHECK_DIFF(resMat, 10.0 < intMat11);
|
||||
CHECK_DIFF(resMat, 11.0 >= intMat10);
|
||||
CHECK_DIFF(resMat, 10.0 <= intMat11);
|
||||
CHECK_DIFF(resMat, 10.0 != intMat11);
|
||||
CHECK_DIFF(resMat, intMat11 != 10.0);
|
||||
|
||||
Mat eye = Mat::eye(3, 3, CV_16S);
|
||||
Mat maskMat4(3, 3, CV_16S, Scalar(4));
|
||||
Mat maskMat1(3, 3, CV_16S, Scalar(1));
|
||||
Mat maskMat5(3, 3, CV_16S, Scalar(5));
|
||||
Mat maskMat0(3, 3, CV_16S, Scalar(0));
|
||||
|
||||
CHECK_DIFF(maskMat0, maskMat4 & maskMat1);
|
||||
CHECK_DIFF(maskMat0, Scalar(1) & maskMat4);
|
||||
CHECK_DIFF(maskMat0, maskMat4 & Scalar(1));
|
||||
|
||||
Mat m;
|
||||
m = maskMat4.clone(); m &= maskMat1; CHECK_DIFF(maskMat0, m);
|
||||
m = maskMat4.clone(); m &= maskMat1 | maskMat1; CHECK_DIFF(maskMat0, m);
|
||||
m = maskMat4.clone(); m &= (2* maskMat1 - maskMat1); CHECK_DIFF(maskMat0, m);
|
||||
|
||||
m = maskMat4.clone(); m &= Scalar(1); CHECK_DIFF(maskMat0, m);
|
||||
m = maskMat4.clone(); m |= maskMat1; CHECK_DIFF(maskMat5, m);
|
||||
m = maskMat5.clone(); m ^= maskMat1; CHECK_DIFF(maskMat4, m);
|
||||
m = maskMat4.clone(); m |= (2* maskMat1 - maskMat1); CHECK_DIFF(maskMat5, m);
|
||||
m = maskMat5.clone(); m ^= (2* maskMat1 - maskMat1); CHECK_DIFF(maskMat4, m);
|
||||
|
||||
m = maskMat4.clone(); m |= Scalar(1); CHECK_DIFF(maskMat5, m);
|
||||
m = maskMat5.clone(); m ^= Scalar(1); CHECK_DIFF(maskMat4, m);
|
||||
|
||||
|
||||
|
||||
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & (maskMat1 | maskMat1));
|
||||
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & maskMat1);
|
||||
CHECK_DIFF(maskMat0, maskMat4 & (maskMat1 | maskMat1));
|
||||
CHECK_DIFF(maskMat0, (maskMat1 | maskMat1) & Scalar(4));
|
||||
CHECK_DIFF(maskMat0, Scalar(4) & (maskMat1 | maskMat1));
|
||||
|
||||
CHECK_DIFF(maskMat0, maskMat5 ^ (maskMat4 | maskMat1));
|
||||
CHECK_DIFF(maskMat0, (maskMat4 | maskMat1) ^ maskMat5);
|
||||
CHECK_DIFF(maskMat0, (maskMat4 + maskMat1) ^ (maskMat4 + maskMat1));
|
||||
CHECK_DIFF(maskMat0, Scalar(5) ^ (maskMat4 | Scalar(1)));
|
||||
CHECK_DIFF(maskMat1, Scalar(5) ^ maskMat4);
|
||||
CHECK_DIFF(maskMat0, Scalar(5) ^ (maskMat4 + maskMat1));
|
||||
CHECK_DIFF(maskMat5, Scalar(5) | (maskMat4 + maskMat1));
|
||||
CHECK_DIFF(maskMat0, (maskMat4 + maskMat1) ^ Scalar(5));
|
||||
|
||||
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ maskMat1));
|
||||
CHECK_DIFF(maskMat5, (maskMat4 ^ maskMat1) | maskMat5);
|
||||
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ Scalar(1)));
|
||||
CHECK_DIFF(maskMat5, (maskMat4 | maskMat4) | Scalar(1));
|
||||
CHECK_DIFF(maskMat5, Scalar(1) | (maskMat4 | maskMat4));
|
||||
CHECK_DIFF(maskMat5, Scalar(1) | maskMat4);
|
||||
CHECK_DIFF(maskMat5, (maskMat5 | maskMat5) | (maskMat4 ^ maskMat1));
|
||||
|
||||
CHECK_DIFF(maskMat1, min(maskMat1, maskMat5));
|
||||
CHECK_DIFF(maskMat1, min(Mat(maskMat1 | maskMat1), maskMat5 | maskMat5));
|
||||
CHECK_DIFF(maskMat5, max(maskMat1, maskMat5));
|
||||
CHECK_DIFF(maskMat5, max(Mat(maskMat1 | maskMat1), maskMat5 | maskMat5));
|
||||
|
||||
CHECK_DIFF(maskMat1, min(maskMat1, maskMat5 | maskMat5));
|
||||
CHECK_DIFF(maskMat1, min(maskMat1 | maskMat1, maskMat5));
|
||||
CHECK_DIFF(maskMat5, max(maskMat1 | maskMat1, maskMat5));
|
||||
CHECK_DIFF(maskMat5, max(maskMat1, maskMat5 | maskMat5));
|
||||
|
||||
CHECK_DIFF(~maskMat1, maskMat1 ^ -1);
|
||||
CHECK_DIFF(~(maskMat1 | maskMat1), maskMat1 ^ -1);
|
||||
|
||||
CHECK_DIFF(maskMat1, maskMat4/4.0);
|
||||
|
||||
/////////////////////////////
|
||||
|
||||
CHECK_DIFF(1.0 - (maskMat5 | maskMat5), -maskMat4);
|
||||
CHECK_DIFF((maskMat4 | maskMat4) * 1.0 + 1.0, maskMat5);
|
||||
CHECK_DIFF(1.0 + (maskMat4 | maskMat4) * 1.0, maskMat5);
|
||||
CHECK_DIFF((maskMat5 | maskMat5) * 1.0 - 1.0, maskMat4);
|
||||
CHECK_DIFF(5.0 - (maskMat4 | maskMat4) * 1.0, maskMat1);
|
||||
CHECK_DIFF((maskMat4 | maskMat4) * 1.0 + 0.5 + 0.5, maskMat5);
|
||||
CHECK_DIFF(0.5 + ((maskMat4 | maskMat4) * 1.0 + 0.5), maskMat5);
|
||||
CHECK_DIFF(((maskMat4 | maskMat4) * 1.0 + 2.0) - 1.0, maskMat5);
|
||||
CHECK_DIFF(5.0 - ((maskMat1 | maskMat1) * 1.0 + 3.0), maskMat1);
|
||||
CHECK_DIFF( ( (maskMat1 | maskMat1) * 2.0 + 2.0) * 1.25, maskMat5);
|
||||
CHECK_DIFF( 1.25 * ( (maskMat1 | maskMat1) * 2.0 + 2.0), maskMat5);
|
||||
CHECK_DIFF( -( (maskMat1 | maskMat1) * (-2.0) + 1.0), maskMat1);
|
||||
CHECK_DIFF( maskMat1 * 1.0 + maskMat4 * 0.5 + 2.0, maskMat5);
|
||||
CHECK_DIFF( 1.0 + (maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0), maskMat5);
|
||||
CHECK_DIFF( (maskMat1 * 1.0 + maskMat4 * 0.5 + 2.0) - 1.0, maskMat4);
|
||||
CHECK_DIFF(5.0 - (maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0), maskMat1);
|
||||
CHECK_DIFF((maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0)*1.25, maskMat5);
|
||||
CHECK_DIFF(1.25 * (maskMat1 * 1.0 + maskMat4 * 0.5 + 1.0), maskMat5);
|
||||
CHECK_DIFF(-(maskMat1 * 2.0 + maskMat4 * (-1) + 1.0), maskMat1);
|
||||
CHECK_DIFF((maskMat1 * 1.0 + maskMat4), maskMat5);
|
||||
CHECK_DIFF((maskMat4 + maskMat1 * 1.0), maskMat5);
|
||||
CHECK_DIFF((maskMat1 * 3.0 + 1.0) + maskMat1, maskMat5);
|
||||
CHECK_DIFF(maskMat1 + (maskMat1 * 3.0 + 1.0), maskMat5);
|
||||
CHECK_DIFF(maskMat1*4.0 + (maskMat1 | maskMat1), maskMat5);
|
||||
CHECK_DIFF((maskMat1 | maskMat1) + maskMat1*4.0, maskMat5);
|
||||
CHECK_DIFF((maskMat1*3.0 + 1.0) + (maskMat1 | maskMat1), maskMat5);
|
||||
CHECK_DIFF((maskMat1 | maskMat1) + (maskMat1*3.0 + 1.0), maskMat5);
|
||||
CHECK_DIFF(maskMat1*4.0 + maskMat4*2.0, maskMat1 * 12);
|
||||
CHECK_DIFF((maskMat1*3.0 + 1.0) + maskMat4*2.0, maskMat1 * 12);
|
||||
CHECK_DIFF(maskMat4*2.0 + (maskMat1*3.0 + 1.0), maskMat1 * 12);
|
||||
CHECK_DIFF((maskMat1*3.0 + 1.0) + (maskMat1*2.0 + 2.0), maskMat1 * 8);
|
||||
|
||||
CHECK_DIFF(maskMat5*1.0 - maskMat4, maskMat1);
|
||||
CHECK_DIFF(maskMat5 - maskMat1 * 4.0, maskMat1);
|
||||
CHECK_DIFF((maskMat4 * 1.0 + 4.0)- maskMat4, maskMat4);
|
||||
CHECK_DIFF(maskMat5 - (maskMat1 * 2.0 + 2.0), maskMat1);
|
||||
CHECK_DIFF(maskMat5*1.0 - (maskMat4 | maskMat4), maskMat1);
|
||||
CHECK_DIFF((maskMat5 | maskMat5) - maskMat1 * 4.0, maskMat1);
|
||||
CHECK_DIFF((maskMat4 * 1.0 + 4.0)- (maskMat4 | maskMat4), maskMat4);
|
||||
CHECK_DIFF((maskMat5 | maskMat5) - (maskMat1 * 2.0 + 2.0), maskMat1);
|
||||
CHECK_DIFF(maskMat1*5.0 - maskMat4 * 1.0, maskMat1);
|
||||
CHECK_DIFF((maskMat1*5.0 + 3.0)- maskMat4 * 1.0, maskMat4);
|
||||
CHECK_DIFF(maskMat4 * 2.0 - (maskMat1*4.0 + 3.0), maskMat1);
|
||||
CHECK_DIFF((maskMat1 * 2.0 + 3.0) - (maskMat1*3.0 + 1.0), maskMat1);
|
||||
|
||||
CHECK_DIFF((maskMat5 - maskMat4)* 4.0, maskMat4);
|
||||
CHECK_DIFF(4.0 * (maskMat5 - maskMat4), maskMat4);
|
||||
|
||||
CHECK_DIFF(-((maskMat4 | maskMat4) - (maskMat5 | maskMat5)), maskMat1);
|
||||
|
||||
CHECK_DIFF(4.0 * (maskMat1 | maskMat1), maskMat4);
|
||||
CHECK_DIFF((maskMat4 | maskMat4)/4.0, maskMat1);
|
||||
|
||||
#if !MSVC_OLD
|
||||
CHECK_DIFF(2.0 * (maskMat1 * 2.0) , maskMat4);
|
||||
#endif
|
||||
CHECK_DIFF((maskMat4 / 2.0) / 2.0 , maskMat1);
|
||||
CHECK_DIFF(-(maskMat4 - maskMat5) , maskMat1);
|
||||
CHECK_DIFF(-((maskMat4 - maskMat5) * 1.0), maskMat1);
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
CHECK_DIFF(maskMat4 / maskMat4, maskMat1);
|
||||
|
||||
///// Element-wise multiplication
|
||||
|
||||
CHECK_DIFF(maskMat4.mul(maskMat4, 0.25), maskMat4);
|
||||
CHECK_DIFF(maskMat4.mul(maskMat1 * 4, 0.25), maskMat4);
|
||||
CHECK_DIFF(maskMat4.mul(maskMat4 / 4), maskMat4);
|
||||
CHECK_DIFF(maskMat4.mul(maskMat4 / 4), maskMat4);
|
||||
CHECK_DIFF(maskMat4.mul(maskMat4) * 0.25, maskMat4);
|
||||
CHECK_DIFF(0.25 * maskMat4.mul(maskMat4), maskMat4);
|
||||
|
||||
////// Element-wise division
|
||||
|
||||
CHECK_DIFF(maskMat4 / maskMat4, maskMat1);
|
||||
CHECK_DIFF((maskMat4 & maskMat4) / (maskMat1 * 4), maskMat1);
|
||||
|
||||
CHECK_DIFF((maskMat4 & maskMat4) / maskMat4, maskMat1);
|
||||
CHECK_DIFF(maskMat4 / (maskMat4 & maskMat4), maskMat1);
|
||||
CHECK_DIFF((maskMat1 * 4) / maskMat4, maskMat1);
|
||||
|
||||
CHECK_DIFF(maskMat4 / (maskMat1 * 4), maskMat1);
|
||||
CHECK_DIFF((maskMat4 * 0.5 )/ (maskMat1 * 2), maskMat1);
|
||||
|
||||
CHECK_DIFF(maskMat4 / maskMat4.mul(maskMat1), maskMat1);
|
||||
CHECK_DIFF((maskMat4 & maskMat4) / maskMat4.mul(maskMat1), maskMat1);
|
||||
|
||||
CHECK_DIFF(4.0 / maskMat4, maskMat1);
|
||||
CHECK_DIFF(4.0 / (maskMat4 | maskMat4), maskMat1);
|
||||
CHECK_DIFF(4.0 / (maskMat1 * 4.0), maskMat1);
|
||||
CHECK_DIFF(4.0 / (maskMat4 / maskMat1), maskMat1);
|
||||
|
||||
m = maskMat4.clone(); m/=4.0; CHECK_DIFF(m, maskMat1);
|
||||
m = maskMat4.clone(); m/=maskMat4; CHECK_DIFF(m, maskMat1);
|
||||
m = maskMat4.clone(); m/=(maskMat1 * 4.0); CHECK_DIFF(m, maskMat1);
|
||||
m = maskMat4.clone(); m/=(maskMat4 / maskMat1); CHECK_DIFF(m, maskMat1);
|
||||
|
||||
/////////////////////////////
|
||||
float matrix_data[] = { 3, 1, -4, -5, 1, 0, 0, 1.1f, 1.5f};
|
||||
Mat mt(3, 3, CV_32F, matrix_data);
|
||||
Mat mi = mt.inv();
|
||||
Mat d1 = Mat::eye(3, 3, CV_32F);
|
||||
Mat d2 = d1 * 2;
|
||||
MatExpr mt_tr = mt.t();
|
||||
MatExpr mi_tr = mi.t();
|
||||
Mat mi2 = mi * 2;
|
||||
|
||||
|
||||
CHECK_DIFF_FLT( mi2 * mt, d2 );
|
||||
CHECK_DIFF_FLT( mi * mt, d1 );
|
||||
CHECK_DIFF_FLT( mt_tr * mi_tr, d1 );
|
||||
|
||||
m = mi.clone(); m*=mt; CHECK_DIFF_FLT(m, d1);
|
||||
m = mi.clone(); m*= (2 * mt - mt) ; CHECK_DIFF_FLT(m, d1);
|
||||
|
||||
m = maskMat4.clone(); m+=(maskMat1 * 1.0); CHECK_DIFF(m, maskMat5);
|
||||
m = maskMat5.clone(); m-=(maskMat1 * 4.0); CHECK_DIFF(m, maskMat1);
|
||||
|
||||
m = maskMat1.clone(); m+=(maskMat1 * 3.0 + 1.0); CHECK_DIFF(m, maskMat5);
|
||||
m = maskMat5.clone(); m-=(maskMat1 * 3.0 + 1.0); CHECK_DIFF(m, maskMat1);
|
||||
#if !MSVC_OLD
|
||||
m = mi.clone(); m+=(3.0 * mi * mt + d1); CHECK_DIFF_FLT(m, mi + d1 * 4);
|
||||
m = mi.clone(); m-=(3.0 * mi * mt + d1); CHECK_DIFF_FLT(m, mi - d1 * 4);
|
||||
m = mi.clone(); m*=(mt * 1.0); CHECK_DIFF_FLT(m, d1);
|
||||
m = mi.clone(); m*=(mt * 1.0 + Mat::eye(m.size(), m.type())); CHECK_DIFF_FLT(m, d1 + mi);
|
||||
m = mi.clone(); m*=mt_tr.t(); CHECK_DIFF_FLT(m, d1);
|
||||
|
||||
CHECK_DIFF_FLT( (mi * 2) * mt, d2);
|
||||
CHECK_DIFF_FLT( mi * (2 * mt), d2);
|
||||
CHECK_DIFF_FLT( mt.t() * mi_tr, d1 );
|
||||
CHECK_DIFF_FLT( mt_tr * mi.t(), d1 );
|
||||
CHECK_DIFF_FLT( (mi * 0.4) * (mt * 5), d2);
|
||||
|
||||
CHECK_DIFF_FLT( mt.t() * (mi_tr * 2), d2 );
|
||||
CHECK_DIFF_FLT( (mt_tr * 2) * mi.t(), d2 );
|
||||
|
||||
CHECK_DIFF_FLT(mt.t() * mi.t(), d1);
|
||||
CHECK_DIFF_FLT( (mi * mt) * 2.0, d2);
|
||||
CHECK_DIFF_FLT( 2.0 * (mi * mt), d2);
|
||||
CHECK_DIFF_FLT( -(mi * mt), -d1);
|
||||
|
||||
CHECK_DIFF_FLT( (mi * mt) / 2.0, d1 / 2);
|
||||
|
||||
Mat mt_mul_2_plus_1;
|
||||
gemm(mt, d1, 2, Mat::ones(3, 3, CV_32F), 1, mt_mul_2_plus_1);
|
||||
|
||||
CHECK_DIFF( (mt * 2.0 + 1.0) * mi, mt_mul_2_plus_1 * mi); // (A*alpha + beta)*B
|
||||
CHECK_DIFF( mi * (mt * 2.0 + 1.0), mi * mt_mul_2_plus_1); // A*(B*alpha + beta)
|
||||
CHECK_DIFF( (mt * 2.0 + 1.0) * (mi * 2), mt_mul_2_plus_1 * mi2); // (A*alpha + beta)*(B*gamma)
|
||||
CHECK_DIFF( (mi *2)* (mt * 2.0 + 1.0), mi2 * mt_mul_2_plus_1); // (A*gamma)*(B*alpha + beta)
|
||||
CHECK_DIFF_FLT( (mt * 2.0 + 1.0) * mi.t(), mt_mul_2_plus_1 * mi_tr); // (A*alpha + beta)*B^t
|
||||
CHECK_DIFF_FLT( mi.t() * (mt * 2.0 + 1.0), mi_tr * mt_mul_2_plus_1); // A^t*(B*alpha + beta)
|
||||
|
||||
CHECK_DIFF_FLT( (mi * mt + d2)*5, d1 * 3 * 5);
|
||||
CHECK_DIFF_FLT( mi * mt + d2, d1 * 3);
|
||||
CHECK_DIFF_FLT( -(mi * mt) + d2, d1);
|
||||
CHECK_DIFF_FLT( (mi * mt) + d1, d2);
|
||||
CHECK_DIFF_FLT( d1 + (mi * mt), d2);
|
||||
CHECK_DIFF_FLT( (mi * mt) - d2, -d1);
|
||||
CHECK_DIFF_FLT( d2 - (mi * mt), d1);
|
||||
|
||||
CHECK_DIFF_FLT( (mi * mt) + d2 * 0.5, d2);
|
||||
CHECK_DIFF_FLT( d2 * 0.5 + (mi * mt), d2);
|
||||
CHECK_DIFF_FLT( (mi * mt) - d1 * 2, -d1);
|
||||
CHECK_DIFF_FLT( d1 * 2 - (mi * mt), d1);
|
||||
|
||||
CHECK_DIFF_FLT( (mi * mt) + mi.t(), mi_tr + d1);
|
||||
CHECK_DIFF_FLT( mi.t() + (mi * mt), mi_tr + d1);
|
||||
CHECK_DIFF_FLT( (mi * mt) - mi.t(), d1 - mi_tr);
|
||||
CHECK_DIFF_FLT( mi.t() - (mi * mt), mi_tr - d1);
|
||||
|
||||
CHECK_DIFF_FLT( 2.0 *(mi * mt + d2), d1 * 6);
|
||||
CHECK_DIFF_FLT( -(mi * mt + d2), d1 * -3);
|
||||
|
||||
CHECK_DIFF_FLT(mt.inv() * mt, d1);
|
||||
|
||||
CHECK_DIFF_FLT(mt.inv() * (2*mt - mt), d1);
|
||||
#endif
|
||||
}
|
||||
catch (const test_excep& e)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "%s\n", e.s.c_str());
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CV_OperationsTest::SomeMatFunctions()
|
||||
{
|
||||
try
|
||||
{
|
||||
Mat rgba( 10, 10, CV_8UC4, Scalar(1,2,3,4) );
|
||||
Mat bgr( rgba.rows, rgba.cols, CV_8UC3 );
|
||||
Mat alpha( rgba.rows, rgba.cols, CV_8UC1 );
|
||||
Mat out[] = { bgr, alpha };
|
||||
// rgba[0] -> bgr[2], rgba[1] -> bgr[1],
|
||||
// rgba[2] -> bgr[0], rgba[3] -> alpha[0]
|
||||
int from_to[] = { 0,2, 1,1, 2,0, 3,3 };
|
||||
mixChannels( &rgba, 1, out, 2, from_to, 4 );
|
||||
|
||||
Mat bgr_exp( rgba.size(), CV_8UC3, Scalar(3,2,1));
|
||||
Mat alpha_exp( rgba.size(), CV_8UC1, Scalar(4));
|
||||
|
||||
CHECK_DIFF(bgr_exp, bgr);
|
||||
CHECK_DIFF(alpha_exp, alpha);
|
||||
}
|
||||
catch (const test_excep& e)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "%s\n", e.s.c_str());
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool CV_OperationsTest::TestTemplateMat()
|
||||
{
|
||||
try
|
||||
{
|
||||
Mat_<float> one_3x1(3, 1, 1.0f);
|
||||
Mat_<float> shi_3x1(3, 1, 1.2f);
|
||||
Mat_<float> shi_2x1(2, 1, -2);
|
||||
Scalar shift = Scalar::all(15);
|
||||
|
||||
float data[] = { sqrt(2.f)/2, -sqrt(2.f)/2, 1.f, sqrt(2.f)/2, sqrt(2.f)/2, 10.f };
|
||||
Mat_<float> rot_2x3(2, 3, data);
|
||||
|
||||
Mat_<float> res = Mat(Mat(2 * rot_2x3) * Mat(one_3x1 + shi_3x1 + shi_3x1 + shi_3x1) - shi_2x1) + shift;
|
||||
Mat_<float> resS = rot_2x3 * one_3x1;
|
||||
|
||||
Mat_<float> tmp, res2, resS2;
|
||||
add(one_3x1, shi_3x1, tmp);
|
||||
add(tmp, shi_3x1, tmp);
|
||||
add(tmp, shi_3x1, tmp);
|
||||
gemm(rot_2x3, tmp, 2, shi_2x1, -1, res2, 0);
|
||||
add(res2, Mat(2, 1, CV_32F, shift), res2);
|
||||
|
||||
gemm(rot_2x3, one_3x1, 1, shi_2x1, 0, resS2, 0);
|
||||
CHECK_DIFF(res, res2);
|
||||
CHECK_DIFF(resS, resS2);
|
||||
|
||||
|
||||
Mat_<float> mat4x4(4, 4);
|
||||
randu(mat4x4, Scalar(0), Scalar(10));
|
||||
|
||||
Mat_<float> roi1 = mat4x4(Rect(Point(1, 1), Size(2, 2)));
|
||||
Mat_<float> roi2 = mat4x4(Range(1, 3), Range(1, 3));
|
||||
|
||||
CHECK_DIFF(roi1, roi2);
|
||||
CHECK_DIFF(mat4x4, mat4x4(Rect(Point(0,0), mat4x4.size())));
|
||||
|
||||
Mat_<int> intMat10(3, 3, 10);
|
||||
Mat_<int> intMat11(3, 3, 11);
|
||||
Mat_<uchar> resMat(3, 3, 255);
|
||||
|
||||
CHECK_DIFF(resMat, intMat10 == intMat10);
|
||||
CHECK_DIFF(resMat, intMat10 < intMat11);
|
||||
CHECK_DIFF(resMat, intMat11 > intMat10);
|
||||
CHECK_DIFF(resMat, intMat10 <= intMat11);
|
||||
CHECK_DIFF(resMat, intMat11 >= intMat10);
|
||||
|
||||
CHECK_DIFF(resMat, intMat10 == 10.0);
|
||||
CHECK_DIFF(resMat, intMat10 < 11.0);
|
||||
CHECK_DIFF(resMat, intMat11 > 10.0);
|
||||
CHECK_DIFF(resMat, intMat10 <= 11.0);
|
||||
CHECK_DIFF(resMat, intMat11 >= 10.0);
|
||||
|
||||
Mat_<uchar> maskMat4(3, 3, 4);
|
||||
Mat_<uchar> maskMat1(3, 3, 1);
|
||||
Mat_<uchar> maskMat5(3, 3, 5);
|
||||
Mat_<uchar> maskMat0(3, 3, (uchar)0);
|
||||
|
||||
CHECK_DIFF(maskMat0, maskMat4 & maskMat1);
|
||||
CHECK_DIFF(maskMat0, Scalar(1) & maskMat4);
|
||||
CHECK_DIFF(maskMat0, maskMat4 & Scalar(1));
|
||||
|
||||
Mat_<uchar> m;
|
||||
m = maskMat4.clone(); m&=maskMat1; CHECK_DIFF(maskMat0, m);
|
||||
m = maskMat4.clone(); m&=Scalar(1); CHECK_DIFF(maskMat0, m);
|
||||
|
||||
m = maskMat4.clone(); m|=maskMat1; CHECK_DIFF(maskMat5, m);
|
||||
m = maskMat4.clone(); m^=maskMat1; CHECK_DIFF(maskMat5, m);
|
||||
|
||||
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & (maskMat1 | maskMat1));
|
||||
CHECK_DIFF(maskMat0, (maskMat4 | maskMat4) & maskMat1);
|
||||
CHECK_DIFF(maskMat0, maskMat4 & (maskMat1 | maskMat1));
|
||||
|
||||
CHECK_DIFF(maskMat0, maskMat5 ^ (maskMat4 | maskMat1));
|
||||
CHECK_DIFF(maskMat0, Scalar(5) ^ (maskMat4 | Scalar(1)));
|
||||
|
||||
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ maskMat1));
|
||||
CHECK_DIFF(maskMat5, maskMat5 | (maskMat4 ^ Scalar(1)));
|
||||
|
||||
CHECK_DIFF(~maskMat1, maskMat1 ^ 0xFF);
|
||||
CHECK_DIFF(~(maskMat1 | maskMat1), maskMat1 ^ 0xFF);
|
||||
|
||||
CHECK_DIFF(maskMat1 + maskMat4, maskMat5);
|
||||
CHECK_DIFF(maskMat1 + Scalar(4), maskMat5);
|
||||
CHECK_DIFF(Scalar(4) + maskMat1, maskMat5);
|
||||
CHECK_DIFF(Scalar(4) + (maskMat1 & maskMat1), maskMat5);
|
||||
|
||||
CHECK_DIFF(maskMat1 + 4.0, maskMat5);
|
||||
CHECK_DIFF((maskMat1 & 0xFF) + 4.0, maskMat5);
|
||||
CHECK_DIFF(4.0 + maskMat1, maskMat5);
|
||||
|
||||
m = maskMat4.clone(); m+=Scalar(1); CHECK_DIFF(m, maskMat5);
|
||||
m = maskMat4.clone(); m+=maskMat1; CHECK_DIFF(m, maskMat5);
|
||||
m = maskMat4.clone(); m+=(maskMat1 | maskMat1); CHECK_DIFF(m, maskMat5);
|
||||
|
||||
CHECK_DIFF(maskMat5 - maskMat1, maskMat4);
|
||||
CHECK_DIFF(maskMat5 - Scalar(1), maskMat4);
|
||||
CHECK_DIFF((maskMat5 | maskMat5) - Scalar(1), maskMat4);
|
||||
CHECK_DIFF(maskMat5 - 1, maskMat4);
|
||||
CHECK_DIFF((maskMat5 | maskMat5) - 1, maskMat4);
|
||||
CHECK_DIFF((maskMat5 | maskMat5) - (maskMat1 | maskMat1), maskMat4);
|
||||
|
||||
CHECK_DIFF(maskMat1, min(maskMat1, maskMat5));
|
||||
CHECK_DIFF(maskMat5, max(maskMat1, maskMat5));
|
||||
|
||||
m = maskMat5.clone(); m-=Scalar(1); CHECK_DIFF(m, maskMat4);
|
||||
m = maskMat5.clone(); m-=maskMat1; CHECK_DIFF(m, maskMat4);
|
||||
m = maskMat5.clone(); m-=(maskMat1 | maskMat1); CHECK_DIFF(m, maskMat4);
|
||||
|
||||
m = maskMat4.clone(); m |= Scalar(1); CHECK_DIFF(maskMat5, m);
|
||||
m = maskMat5.clone(); m ^= Scalar(1); CHECK_DIFF(maskMat4, m);
|
||||
|
||||
CHECK_DIFF(maskMat1, maskMat4/4.0);
|
||||
|
||||
Mat_<float> negf(3, 3, -3.0);
|
||||
Mat_<float> posf = -negf;
|
||||
Mat_<float> posf2 = posf * 2;
|
||||
Mat_<int> negi(3, 3, -3);
|
||||
|
||||
CHECK_DIFF(abs(negf), -negf);
|
||||
CHECK_DIFF(abs(posf - posf2), -negf);
|
||||
CHECK_DIFF(abs(negi), -(negi & negi));
|
||||
|
||||
CHECK_DIFF(5.0 - maskMat4, maskMat1);
|
||||
|
||||
|
||||
CHECK_DIFF(maskMat4.mul(maskMat4, 0.25), maskMat4);
|
||||
CHECK_DIFF(maskMat4.mul(maskMat1 * 4, 0.25), maskMat4);
|
||||
CHECK_DIFF(maskMat4.mul(maskMat4 / 4), maskMat4);
|
||||
|
||||
|
||||
////// Element-wise division
|
||||
|
||||
CHECK_DIFF(maskMat4 / maskMat4, maskMat1);
|
||||
CHECK_DIFF(4.0 / maskMat4, maskMat1);
|
||||
m = maskMat4.clone(); m/=4.0; CHECK_DIFF(m, maskMat1);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef Mat_<int> TestMat_t;
|
||||
|
||||
const TestMat_t cnegi = negi.clone();
|
||||
|
||||
TestMat_t::iterator beg = negi.begin();
|
||||
TestMat_t::iterator end = negi.end();
|
||||
|
||||
TestMat_t::const_iterator cbeg = cnegi.begin();
|
||||
TestMat_t::const_iterator cend = cnegi.end();
|
||||
|
||||
int sum = 0;
|
||||
for(; beg!=end; ++beg)
|
||||
sum+=*beg;
|
||||
|
||||
for(; cbeg!=cend; ++cbeg)
|
||||
sum-=*cbeg;
|
||||
|
||||
if (sum != 0) throw test_excep();
|
||||
|
||||
CHECK_DIFF(negi.col(1), negi.col(2));
|
||||
CHECK_DIFF(negi.row(1), negi.row(2));
|
||||
CHECK_DIFF(negi.col(1), negi.diag());
|
||||
|
||||
if (Mat_<Point2f>(1, 1).elemSize1() != sizeof(float)) throw test_excep();
|
||||
if (Mat_<Point2f>(1, 1).elemSize() != 2 * sizeof(float)) throw test_excep();
|
||||
if (Mat_<Point2f>(1, 1).depth() != CV_32F) throw test_excep();
|
||||
if (Mat_<float>(1, 1).depth() != CV_32F) throw test_excep();
|
||||
if (Mat_<int>(1, 1).depth() != CV_32S) throw test_excep();
|
||||
if (Mat_<double>(1, 1).depth() != CV_64F) throw test_excep();
|
||||
if (Mat_<Point3d>(1, 1).depth() != CV_64F) throw test_excep();
|
||||
if (Mat_<signed char>(1, 1).depth() != CV_8S) throw test_excep();
|
||||
if (Mat_<unsigned short>(1, 1).depth() != CV_16U) throw test_excep();
|
||||
if (Mat_<unsigned short>(1, 1).channels() != 1) throw test_excep();
|
||||
if (Mat_<Point2f>(1, 1).channels() != 2) throw test_excep();
|
||||
if (Mat_<Point3f>(1, 1).channels() != 3) throw test_excep();
|
||||
if (Mat_<Point3d>(1, 1).channels() != 3) throw test_excep();
|
||||
|
||||
Mat_<uchar> eye = Mat_<uchar>::zeros(2, 2); CHECK_DIFF(Mat_<uchar>::zeros(Size(2, 2)), eye);
|
||||
eye.at<uchar>(Point(0,0)) = 1; eye.at<uchar>(1, 1) = 1;
|
||||
|
||||
CHECK_DIFF(Mat_<uchar>::eye(2, 2), eye);
|
||||
CHECK_DIFF(eye, Mat_<uchar>::eye(Size(2,2)));
|
||||
|
||||
Mat_<uchar> ones(2, 2, (uchar)1);
|
||||
CHECK_DIFF(ones, Mat_<uchar>::ones(Size(2,2)));
|
||||
CHECK_DIFF(Mat_<uchar>::ones(2, 2), ones);
|
||||
|
||||
Mat_<Point2f> pntMat(2, 2, Point2f(1, 0));
|
||||
if(pntMat.stepT() != 2) throw test_excep();
|
||||
|
||||
uchar uchar_data[] = {1, 0, 0, 1};
|
||||
|
||||
Mat_<uchar> matFromData(1, 4, uchar_data);
|
||||
const Mat_<uchar> mat2 = matFromData.clone();
|
||||
CHECK_DIFF(matFromData, eye.reshape(1));
|
||||
if (matFromData(Point(0,0)) != uchar_data[0])throw test_excep();
|
||||
if (mat2(Point(0,0)) != uchar_data[0]) throw test_excep();
|
||||
|
||||
if (matFromData(0,0) != uchar_data[0])throw test_excep();
|
||||
if (mat2(0,0) != uchar_data[0]) throw test_excep();
|
||||
|
||||
Mat_<uchar> rect(eye, Rect(0, 0, 1, 1));
|
||||
if (rect.cols != 1 || rect.rows != 1 || rect(0,0) != uchar_data[0]) throw test_excep();
|
||||
|
||||
//cv::Mat_<_Tp>::adjustROI(int,int,int,int)
|
||||
//cv::Mat_<_Tp>::cross(const Mat_&) const
|
||||
//cv::Mat_<_Tp>::Mat_(const vector<_Tp>&,bool)
|
||||
//cv::Mat_<_Tp>::Mat_(int,int,_Tp*,size_t)
|
||||
//cv::Mat_<_Tp>::Mat_(int,int,const _Tp&)
|
||||
//cv::Mat_<_Tp>::Mat_(Size,const _Tp&)
|
||||
//cv::Mat_<_Tp>::mul(const Mat_<_Tp>&,double) const
|
||||
//cv::Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat_<_Tp>,double,Mat_<_Tp>,MatOp_DivRS_<Mat> >,Mat_<_Tp> >&,double) const
|
||||
//cv::Mat_<_Tp>::mul(const MatExpr_<MatExpr_Op2_<Mat_<_Tp>,double,Mat_<_Tp>,MatOp_Scale_<Mat> >,Mat_<_Tp> >&,double) const
|
||||
//cv::Mat_<_Tp>::operator Mat_<T2>() const
|
||||
//cv::Mat_<_Tp>::operator MatExpr_<Mat_<_Tp>,Mat_<_Tp> >() const
|
||||
//cv::Mat_<_Tp>::operator()(const Range&,const Range&) const
|
||||
//cv::Mat_<_Tp>::operator()(const Rect&) const
|
||||
|
||||
//cv::Mat_<_Tp>::operator=(const MatExpr_Base&)
|
||||
//cv::Mat_<_Tp>::operator[](int) const
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
|
||||
float matrix_data[] = { 3, 1, -4, -5, 1, 0, 0, 1.1f, 1.5f};
|
||||
Mat_<float> mt(3, 3, matrix_data);
|
||||
Mat_<float> mi = mt.inv();
|
||||
Mat_<float> d1 = Mat_<float>::eye(3, 3);
|
||||
Mat_<float> d2 = d1 * 2;
|
||||
Mat_<float> mt_tr = mt.t();
|
||||
Mat_<float> mi_tr = mi.t();
|
||||
Mat_<float> mi2 = mi * 2;
|
||||
|
||||
CHECK_DIFF_FLT( mi2 * mt, d2 );
|
||||
CHECK_DIFF_FLT( mi * mt, d1 );
|
||||
CHECK_DIFF_FLT( mt_tr * mi_tr, d1 );
|
||||
|
||||
Mat_<float> mf;
|
||||
mf = mi.clone(); mf*=mt; CHECK_DIFF_FLT(mf, d1);
|
||||
|
||||
////// typedefs //////
|
||||
|
||||
if (Mat1b(1, 1).elemSize() != sizeof(uchar)) throw test_excep();
|
||||
if (Mat2b(1, 1).elemSize() != 2 * sizeof(uchar)) throw test_excep();
|
||||
if (Mat3b(1, 1).elemSize() != 3 * sizeof(uchar)) throw test_excep();
|
||||
if (Mat1f(1, 1).elemSize() != sizeof(float)) throw test_excep();
|
||||
if (Mat2f(1, 1).elemSize() != 2 * sizeof(float)) throw test_excep();
|
||||
if (Mat3f(1, 1).elemSize() != 3 * sizeof(float)) throw test_excep();
|
||||
if (Mat1f(1, 1).depth() != CV_32F) throw test_excep();
|
||||
if (Mat3f(1, 1).depth() != CV_32F) throw test_excep();
|
||||
if (Mat3f(1, 1).type() != CV_32FC3) throw test_excep();
|
||||
if (Mat1i(1, 1).depth() != CV_32S) throw test_excep();
|
||||
if (Mat1d(1, 1).depth() != CV_64F) throw test_excep();
|
||||
if (Mat1b(1, 1).depth() != CV_8U) throw test_excep();
|
||||
if (Mat3b(1, 1).type() != CV_8UC3) throw test_excep();
|
||||
if (Mat1w(1, 1).depth() != CV_16U) throw test_excep();
|
||||
if (Mat1s(1, 1).depth() != CV_16S) throw test_excep();
|
||||
if (Mat1f(1, 1).channels() != 1) throw test_excep();
|
||||
if (Mat1b(1, 1).channels() != 1) throw test_excep();
|
||||
if (Mat1i(1, 1).channels() != 1) throw test_excep();
|
||||
if (Mat1w(1, 1).channels() != 1) throw test_excep();
|
||||
if (Mat1s(1, 1).channels() != 1) throw test_excep();
|
||||
if (Mat2f(1, 1).channels() != 2) throw test_excep();
|
||||
if (Mat2b(1, 1).channels() != 2) throw test_excep();
|
||||
if (Mat2i(1, 1).channels() != 2) throw test_excep();
|
||||
if (Mat2w(1, 1).channels() != 2) throw test_excep();
|
||||
if (Mat2s(1, 1).channels() != 2) throw test_excep();
|
||||
if (Mat3f(1, 1).channels() != 3) throw test_excep();
|
||||
if (Mat3b(1, 1).channels() != 3) throw test_excep();
|
||||
if (Mat3i(1, 1).channels() != 3) throw test_excep();
|
||||
if (Mat3w(1, 1).channels() != 3) throw test_excep();
|
||||
if (Mat3s(1, 1).channels() != 3) throw test_excep();
|
||||
|
||||
}
|
||||
catch (const test_excep& e)
|
||||
{
|
||||
ts->printf(cvtest::TS::LOG, "%s\n", e.s.c_str());
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CV_OperationsTest::TestMatND()
|
||||
{
|
||||
int sizes[] = { 3, 3, 3};
|
||||
cv::MatND nd(3, sizes, CV_32F);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CV_OperationsTest::TestSparseMat()
|
||||
{
|
||||
try
|
||||
{
|
||||
int sizes[] = { 10, 10, 10};
|
||||
int dims = sizeof(sizes)/sizeof(sizes[0]);
|
||||
SparseMat mat(dims, sizes, CV_32FC2);
|
||||
|
||||
if (mat.dims() != dims) throw test_excep();
|
||||
if (mat.channels() != 2) throw test_excep();
|
||||
if (mat.depth() != CV_32F) throw test_excep();
|
||||
|
||||
SparseMat mat2 = mat.clone();
|
||||
}
|
||||
catch (const test_excep&)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CV_OperationsTest::operations1()
|
||||
{
|
||||
try
|
||||
{
|
||||
Point3d p1(1, 1, 1), p2(2, 2, 2), p4(4, 4, 4);
|
||||
p1*=2;
|
||||
if (!(p1 == p2)) throw test_excep();
|
||||
if (!(p2 * 2 == p4)) throw test_excep();
|
||||
if (!(p2 * 2.f == p4)) throw test_excep();
|
||||
if (!(p2 * 2.f == p4)) throw test_excep();
|
||||
|
||||
Point2d pi1(1, 1), pi2(2, 2), pi4(4, 4);
|
||||
pi1*=2;
|
||||
if (!(pi1 == pi2)) throw test_excep();
|
||||
if (!(pi2 * 2 == pi4)) throw test_excep();
|
||||
if (!(pi2 * 2.f == pi4)) throw test_excep();
|
||||
if (!(pi2 * 2.f == pi4)) throw test_excep();
|
||||
|
||||
Vec2d v12(1, 1), v22(2, 2);
|
||||
v12*=2.0;
|
||||
if (!(v12 == v22)) throw test_excep();
|
||||
|
||||
Vec3d v13(1, 1, 1), v23(2, 2, 2);
|
||||
v13*=2.0;
|
||||
if (!(v13 == v23)) throw test_excep();
|
||||
|
||||
Vec4d v14(1, 1, 1, 1), v24(2, 2, 2, 2);
|
||||
v14*=2.0;
|
||||
if (!(v14 == v24)) throw test_excep();
|
||||
|
||||
Size sz(10, 20);
|
||||
if (sz.area() != 200) throw test_excep();
|
||||
if (sz.width != 10 || sz.height != 20) throw test_excep();
|
||||
if (((CvSize)sz).width != 10 || ((CvSize)sz).height != 20) throw test_excep();
|
||||
|
||||
Vec<double, 5> v5d(1, 1, 1, 1, 1);
|
||||
Vec<double, 6> v6d(1, 1, 1, 1, 1, 1);
|
||||
Vec<double, 7> v7d(1, 1, 1, 1, 1, 1, 1);
|
||||
Vec<double, 8> v8d(1, 1, 1, 1, 1, 1, 1, 1);
|
||||
Vec<double, 9> v9d(1, 1, 1, 1, 1, 1, 1, 1, 1);
|
||||
Vec<double,10> v10d(1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
|
||||
|
||||
Vec<double,10> v10dzero;
|
||||
for (int ii = 0; ii < 10; ++ii) {
|
||||
if (!v10dzero[ii] == 0.0)
|
||||
throw test_excep();
|
||||
}
|
||||
}
|
||||
catch(const test_excep&)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CV_OperationsTest::run( int /* start_from */)
|
||||
{
|
||||
if (!TestMat())
|
||||
return;
|
||||
|
||||
if (!SomeMatFunctions())
|
||||
return;
|
||||
|
||||
if (!TestTemplateMat())
|
||||
return;
|
||||
|
||||
/* if (!TestMatND())
|
||||
return;*/
|
||||
|
||||
if (!TestSparseMat())
|
||||
return;
|
||||
|
||||
if (!operations1())
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Core_Array, expressions) { CV_OperationsTest test; test.safe_run(); }
|
@ -1,2 +1,8 @@
|
||||
#include "opencv2/gtest/gtestcv.hpp"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts/ts.hpp"
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include <iostream>
|
||||
|
||||
#endif
|
||||
|
303
modules/core/test/test_rand.cpp
Normal file
303
modules/core/test/test_rand.cpp
Normal file
@ -0,0 +1,303 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class Core_RandTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
Core_RandTest();
|
||||
protected:
|
||||
void run(int);
|
||||
bool check_pdf(const Mat& hist, double scale, int dist_type,
|
||||
double& refval, double& realval);
|
||||
};
|
||||
|
||||
|
||||
Core_RandTest::Core_RandTest()
|
||||
{
|
||||
}
|
||||
|
||||
static double chi2_p95(int n)
|
||||
{
|
||||
static float chi2_tab95[] = {
|
||||
3.841f, 5.991f, 7.815f, 9.488f, 11.07f, 12.59f, 14.07f, 15.51f,
|
||||
16.92f, 18.31f, 19.68f, 21.03f, 21.03f, 22.36f, 23.69f, 25.00f,
|
||||
26.30f, 27.59f, 28.87f, 30.14f, 31.41f, 32.67f, 33.92f, 35.17f,
|
||||
36.42f, 37.65f, 38.89f, 40.11f, 41.34f, 42.56f, 43.77f };
|
||||
static const double xp = 1.64;
|
||||
CV_Assert(n >= 1);
|
||||
|
||||
if( n <= 30 )
|
||||
return chi2_tab95[n-1];
|
||||
return n + sqrt((double)2*n)*xp + 0.6666666666666*(xp*xp - 1);
|
||||
}
|
||||
|
||||
bool Core_RandTest::check_pdf(const Mat& hist, double scale,
|
||||
int dist_type, double& refval, double& realval)
|
||||
{
|
||||
Mat hist0(hist.size(), CV_32F);
|
||||
const int* H = (const int*)hist.data;
|
||||
float* H0 = ((float*)hist0.data);
|
||||
int i, hsz = hist.cols;
|
||||
|
||||
double sum = 0;
|
||||
for( i = 0; i < hsz; i++ )
|
||||
sum += H[i];
|
||||
CV_Assert( fabs(1./sum - scale) < FLT_EPSILON );
|
||||
|
||||
if( dist_type == CV_RAND_UNI )
|
||||
{
|
||||
float scale0 = (float)(1./hsz);
|
||||
for( i = 0; i < hsz; i++ )
|
||||
H0[i] = scale0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double sum = 0, r = (hsz-1.)/2;
|
||||
double alpha = 2*sqrt(2.)/r, beta = -alpha*r;
|
||||
for( i = 0; i < hsz; i++ )
|
||||
{
|
||||
double x = i*alpha + beta;
|
||||
H0[i] = (float)exp(-x*x);
|
||||
sum += H0[i];
|
||||
}
|
||||
sum = 1./sum;
|
||||
for( i = 0; i < hsz; i++ )
|
||||
H0[i] = (float)(H0[i]*sum);
|
||||
}
|
||||
|
||||
double chi2 = 0;
|
||||
for( i = 0; i < hsz; i++ )
|
||||
{
|
||||
double a = H0[i];
|
||||
double b = H[i]*scale;
|
||||
if( a > DBL_EPSILON )
|
||||
chi2 += (a - b)*(a - b)/(a + b);
|
||||
}
|
||||
realval = chi2;
|
||||
|
||||
double chi2_pval = chi2_p95(hsz - 1 - (dist_type == CV_RAND_NORMAL ? 2 : 0));
|
||||
refval = chi2_pval*0.01;
|
||||
return realval <= refval;
|
||||
}
|
||||
|
||||
void Core_RandTest::run( int )
|
||||
{
|
||||
static int _ranges[][2] =
|
||||
{{ 0, 256 }, { -128, 128 }, { 0, 65536 }, { -32768, 32768 },
|
||||
{ -1000000, 1000000 }, { -1000, 1000 }, { -1000, 1000 }};
|
||||
|
||||
const int MAX_SDIM = 10;
|
||||
const int N = 2000000;
|
||||
const int maxSlice = 1000;
|
||||
const int MAX_HIST_SIZE = 1000;
|
||||
int progress = 0;
|
||||
|
||||
RNG& rng = ts->get_rng();
|
||||
RNG tested_rng = theRNG();
|
||||
test_case_count = 200;
|
||||
|
||||
for( int idx = 0; idx < test_case_count; idx++ )
|
||||
{
|
||||
progress = update_progress( progress, idx, test_case_count, 0 );
|
||||
ts->update_context( this, idx, false );
|
||||
|
||||
int depth = cvtest::randInt(rng) % (CV_64F+1);
|
||||
int c, cn = (cvtest::randInt(rng) % 4) + 1;
|
||||
int type = CV_MAKETYPE(depth, cn);
|
||||
int dist_type = cvtest::randInt(rng) % (CV_RAND_NORMAL+1);
|
||||
int i, k, SZ = N/cn;
|
||||
Scalar A, B;
|
||||
|
||||
bool do_sphere_test = dist_type == CV_RAND_UNI;
|
||||
Mat arr[2], hist[4];
|
||||
int W[] = {0,0,0,0};
|
||||
|
||||
arr[0].create(1, SZ, type);
|
||||
arr[1].create(1, SZ, type);
|
||||
bool fast_algo = dist_type == CV_RAND_UNI && depth < CV_32F;
|
||||
|
||||
for( c = 0; c < cn; c++ )
|
||||
{
|
||||
int a, b, hsz;
|
||||
if( dist_type == CV_RAND_UNI )
|
||||
{
|
||||
a = (int)(cvtest::randInt(rng) % (_ranges[depth][1] -
|
||||
_ranges[depth][0])) + _ranges[depth][0];
|
||||
do
|
||||
{
|
||||
b = (int)(cvtest::randInt(rng) % (_ranges[depth][1] -
|
||||
_ranges[depth][0])) + _ranges[depth][0];
|
||||
}
|
||||
while( abs(a-b) <= 1 );
|
||||
if( a > b )
|
||||
std::swap(a, b);
|
||||
|
||||
unsigned r = (unsigned)(b - a);
|
||||
fast_algo = fast_algo && r <= 256 && (r & (r-1)) == 0;
|
||||
hsz = min((unsigned)(b - a), (unsigned)MAX_HIST_SIZE);
|
||||
do_sphere_test = do_sphere_test && b - a >= 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
int vrange = _ranges[depth][1] - _ranges[depth][0];
|
||||
int meanrange = vrange/16;
|
||||
int mindiv = MAX(vrange/20, 5);
|
||||
int maxdiv = MIN(vrange/8, 10000);
|
||||
|
||||
a = cvtest::randInt(rng) % meanrange - meanrange/2 +
|
||||
(_ranges[depth][0] + _ranges[depth][1])/2;
|
||||
b = cvtest::randInt(rng) % (maxdiv - mindiv) + mindiv;
|
||||
hsz = min((unsigned)b*9, (unsigned)MAX_HIST_SIZE);
|
||||
}
|
||||
A[c] = a;
|
||||
B[c] = b;
|
||||
hist[c].create(1, hsz, CV_32S);
|
||||
}
|
||||
|
||||
cv::RNG saved_rng = tested_rng;
|
||||
int maxk = fast_algo ? 0 : 1;
|
||||
for( k = 0; k <= maxk; k++ )
|
||||
{
|
||||
tested_rng = saved_rng;
|
||||
int sz = 0, dsz = 0, slice;
|
||||
for( slice = 0; slice < maxSlice; slice++, sz += dsz )
|
||||
{
|
||||
dsz = slice+1 < maxSlice ? cvtest::randInt(rng) % (SZ - sz + 1) : SZ - sz;
|
||||
Mat aslice = arr[k].colRange(sz, sz + dsz);
|
||||
tested_rng.fill(aslice, dist_type, A, B);
|
||||
}
|
||||
}
|
||||
|
||||
if( maxk >= 1 && norm(arr[0], arr[1], NORM_INF) != 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "RNG output depends on the array lengths (some generated numbers get lost?)" );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
|
||||
for( c = 0; c < cn; c++ )
|
||||
{
|
||||
const uchar* data = arr[0].data;
|
||||
int* H = hist[c].ptr<int>();
|
||||
int HSZ = hist[c].cols;
|
||||
double minVal = dist_type == CV_RAND_UNI ? A[c] : A[c] - B[c]*4;
|
||||
double maxVal = dist_type == CV_RAND_UNI ? B[c] : A[c] + B[c]*4;
|
||||
double scale = HSZ/(maxVal - minVal);
|
||||
double delta = -minVal*scale;
|
||||
|
||||
hist[c] = Scalar::all(0);
|
||||
|
||||
for( i = c; i < SZ*cn; i += cn )
|
||||
{
|
||||
double val = depth == CV_8U ? ((const uchar*)data)[i] :
|
||||
depth == CV_8S ? ((const schar*)data)[i] :
|
||||
depth == CV_16U ? ((const ushort*)data)[i] :
|
||||
depth == CV_16S ? ((const short*)data)[i] :
|
||||
depth == CV_32S ? ((const int*)data)[i] :
|
||||
depth == CV_32F ? ((const float*)data)[i] :
|
||||
((const double*)data)[i];
|
||||
int ival = cvFloor(val*scale + delta);
|
||||
if( (unsigned)ival < (unsigned)HSZ )
|
||||
{
|
||||
H[ival]++;
|
||||
W[c]++;
|
||||
}
|
||||
else if( dist_type == CV_RAND_UNI )
|
||||
{
|
||||
if( (minVal <= val && val < maxVal) || (depth >= CV_32F && val == maxVal) )
|
||||
{
|
||||
H[ival < 0 ? 0 : HSZ-1]++;
|
||||
W[c]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
putchar('^');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( dist_type == CV_RAND_UNI && W[c] != SZ )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Uniform RNG gave values out of the range [%g,%g) on channel %d/%d\n",
|
||||
A[c], B[c], c, cn);
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
if( dist_type == CV_RAND_NORMAL && W[c] < SZ*.90)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Normal RNG gave too many values out of the range (%g+4*%g,%g+4*%g) on channel %d/%d\n",
|
||||
A[c], B[c], A[c], B[c], c, cn);
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
double refval = 0, realval = 0;
|
||||
|
||||
if( !check_pdf(hist[c], 1./W[c], dist_type, refval, realval) )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "RNG failed Chi-square test "
|
||||
"(got %g vs probable maximum %g) on channel %d/%d\n",
|
||||
realval, refval, c, cn);
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Monte-Carlo test. Compute volume of SDIM-dimensional sphere
|
||||
// inscribed in [-1,1]^SDIM cube.
|
||||
if( do_sphere_test )
|
||||
{
|
||||
int SDIM = cvtest::randInt(rng) % (MAX_SDIM-1) + 2;
|
||||
int N0 = (SZ*cn/SDIM), N = 0;
|
||||
double r2 = 0;
|
||||
const uchar* data = arr[0].data;
|
||||
double scale[4], delta[4];
|
||||
for( c = 0; c < cn; c++ )
|
||||
{
|
||||
scale[c] = 2./(B[c] - A[c]);
|
||||
delta[c] = -A[c]*scale[c] - 1;
|
||||
}
|
||||
|
||||
for( i = k = c = 0; i <= SZ*cn - SDIM; i++, k++, c++ )
|
||||
{
|
||||
double val = depth == CV_8U ? ((const uchar*)data)[i] :
|
||||
depth == CV_8S ? ((const schar*)data)[i] :
|
||||
depth == CV_16U ? ((const ushort*)data)[i] :
|
||||
depth == CV_16S ? ((const short*)data)[i] :
|
||||
depth == CV_32S ? ((const int*)data)[i] :
|
||||
depth == CV_32F ? ((const float*)data)[i] : ((const double*)data)[i];
|
||||
c &= c < cn ? -1 : 0;
|
||||
val = val*scale[c] + delta[c];
|
||||
r2 += val*val;
|
||||
if( k == SDIM-1 )
|
||||
{
|
||||
N += r2 <= 1;
|
||||
r2 = 0;
|
||||
k = -1;
|
||||
}
|
||||
}
|
||||
|
||||
double V = ((double)N/N0)*(1 << SDIM);
|
||||
|
||||
// the theoretically computed volume
|
||||
int sdim = SDIM % 2;
|
||||
double V0 = sdim + 1;
|
||||
for( sdim += 2; sdim <= SDIM; sdim += 2 )
|
||||
V0 *= 2*CV_PI/sdim;
|
||||
|
||||
if( fabs(V - V0) > 0.3*fabs(V0) )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "RNG failed %d-dim sphere volume test (got %g instead of %g)\n",
|
||||
SDIM, V, V0);
|
||||
ts->printf( cvtest::TS::LOG, "depth = %d, N0 = %d\n", depth, N0);
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Core_Rand, quality) { Core_RandTest test; test.safe_run(); }
|
||||
|
||||
|
122
modules/features2d/test/test_bruteforcematcher.cpp
Normal file
122
modules/features2d/test/test_bruteforcematcher.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#if 0
|
||||
using namespace cv;
|
||||
|
||||
class BruteForceMatcherTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
BruteForceMatcherTest();
|
||||
protected:
|
||||
void run( int );
|
||||
};
|
||||
|
||||
struct CV_EXPORTS L2Fake : public L2<float>
|
||||
{
|
||||
};
|
||||
|
||||
BruteForceMatcherTest::BruteForceMatcherTest() : cvtest::BaseTest( "BruteForceMatcher", "BruteForceMatcher::matchImpl")
|
||||
{
|
||||
support_testing_modes = cvtest::TS::TIMING_MODE;
|
||||
}
|
||||
|
||||
void BruteForceMatcherTest::run( int )
|
||||
{
|
||||
const int dimensions = 64;
|
||||
const int descriptorsNumber = 5000;
|
||||
|
||||
Mat train = Mat( descriptorsNumber, dimensions, CV_32FC1);
|
||||
Mat query = Mat( descriptorsNumber, dimensions, CV_32FC1);
|
||||
|
||||
Mat permutation( 1, descriptorsNumber, CV_32SC1 );
|
||||
for( int i=0;i<descriptorsNumber;i++ )
|
||||
permutation.at<int>( 0, i ) = i;
|
||||
|
||||
//RNG rng = RNG( cvGetTickCount() );
|
||||
RNG rng = RNG( *ts->get_rng() );
|
||||
randShuffle( permutation, 1, &rng );
|
||||
|
||||
float boundary = 500.f;
|
||||
for( int row=0;row<descriptorsNumber;row++ )
|
||||
{
|
||||
for( int col=0;col<dimensions;col++ )
|
||||
{
|
||||
int bit = rng( 2 );
|
||||
train.at<float>( permutation.at<int>( 0, row ), col ) = bit*boundary + rng.uniform( 0.f, boundary );
|
||||
query.at<float>( row, col ) = bit*boundary + rng.uniform( 0.f, boundary );
|
||||
}
|
||||
}
|
||||
|
||||
vector<DMatch> specMatches, genericMatches;
|
||||
BruteForceMatcher<L2<float> > specMatcher;
|
||||
BruteForceMatcher<L2Fake > genericMatcher;
|
||||
|
||||
int64 time0 = cvGetTickCount();
|
||||
specMatcher.match( query, train, specMatches );
|
||||
int64 time1 = cvGetTickCount();
|
||||
genericMatcher.match( query, train, genericMatches );
|
||||
int64 time2 = cvGetTickCount();
|
||||
|
||||
float specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
|
||||
ts->printf( cvtest::TS::LOG, "Matching by matrix multiplication time s: %f, us per pair: %f\n",
|
||||
specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
|
||||
|
||||
float genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
|
||||
ts->printf( cvtest::TS::LOG, "Matching without matrix multiplication time s: %f, us per pair: %f\n",
|
||||
genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
|
||||
|
||||
if( (int)specMatches.size() != descriptorsNumber || (int)genericMatches.size() != descriptorsNumber )
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
for( int i=0;i<descriptorsNumber;i++ )
|
||||
{
|
||||
float epsilon = 0.01f;
|
||||
bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon &&
|
||||
specMatches[i].queryIdx == genericMatches[i].queryIdx &&
|
||||
specMatches[i].trainIdx == genericMatches[i].trainIdx;
|
||||
if( !isEquiv || specMatches[i].trainIdx != permutation.at<int>( 0, i ) )
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Test mask
|
||||
Mat mask( query.rows, train.rows, CV_8UC1 );
|
||||
rng.fill( mask, RNG::UNIFORM, 0, 2 );
|
||||
|
||||
|
||||
time0 = cvGetTickCount();
|
||||
specMatcher.match( query, train, specMatches, mask );
|
||||
time1 = cvGetTickCount();
|
||||
genericMatcher.match( query, train, genericMatches, mask );
|
||||
time2 = cvGetTickCount();
|
||||
|
||||
specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
|
||||
ts->printf( cvtest::TS::LOG, "Matching by matrix multiplication time with mask s: %f, us per pair: %f\n",
|
||||
specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
|
||||
|
||||
genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
|
||||
ts->printf( cvtest::TS::LOG, "Matching without matrix multiplication time with mask s: %f, us per pair: %f\n",
|
||||
genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
|
||||
|
||||
if( specMatches.size() != genericMatches.size() )
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
|
||||
for( size_t i=0;i<specMatches.size();i++ )
|
||||
{
|
||||
//float epsilon = 1e-2;
|
||||
float epsilon = 10000000;
|
||||
bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon &&
|
||||
specMatches[i].queryIdx == genericMatches[i].queryIdx &&
|
||||
specMatches[i].trainIdx == genericMatches[i].trainIdx;
|
||||
if( !isEquiv )
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BruteForceMatcherTest taBruteForceMatcherTest;
|
||||
#endif
|
1186
modules/features2d/test/test_detectordescriptor_evaluation.cpp
Normal file
1186
modules/features2d/test/test_detectordescriptor_evaluation.cpp
Normal file
File diff suppressed because it is too large
Load Diff
317
modules/features2d/test/test_detectors.cpp
Normal file
317
modules/features2d/test/test_detectors.cpp
Normal file
@ -0,0 +1,317 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_DetectorsTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_DetectorsTest();
|
||||
~CV_DetectorsTest();
|
||||
protected:
|
||||
void run(int);
|
||||
template <class T> bool testDetector(const Mat& img, const T& detector, vector<KeyPoint>& expected);
|
||||
|
||||
void LoadExpected(const string& file, vector<KeyPoint>& out);
|
||||
};
|
||||
|
||||
CV_DetectorsTest::CV_DetectorsTest()
|
||||
{
|
||||
}
|
||||
CV_DetectorsTest::~CV_DetectorsTest() {}
|
||||
|
||||
void getRotation(const Mat& img, Mat& aff, Mat& out)
|
||||
{
|
||||
Point center(img.cols/2, img.rows/2);
|
||||
aff = getRotationMatrix2D(center, 30, 1);
|
||||
warpAffine( img, out, aff, img.size());
|
||||
}
|
||||
|
||||
void getZoom(const Mat& img, Mat& aff, Mat& out)
|
||||
{
|
||||
const double mult = 1.2;
|
||||
|
||||
aff.create(2, 3, CV_64F);
|
||||
double *data = aff.ptr<double>();
|
||||
data[0] = mult; data[1] = 0; data[2] = 0;
|
||||
data[3] = 0; data[4] = mult; data[5] = 0;
|
||||
|
||||
warpAffine( img, out, aff, img.size());
|
||||
}
|
||||
|
||||
void getBlur(const Mat& img, Mat& aff, Mat& out)
|
||||
{
|
||||
aff.create(2, 3, CV_64F);
|
||||
double *data = aff.ptr<double>();
|
||||
data[0] = 1; data[1] = 0; data[2] = 0;
|
||||
data[3] = 0; data[4] = 1; data[5] = 0;
|
||||
|
||||
GaussianBlur(img, out, Size(5, 5), 2);
|
||||
}
|
||||
|
||||
void getBrightness(const Mat& img, Mat& aff, Mat& out)
|
||||
{
|
||||
aff.create(2, 3, CV_64F);
|
||||
double *data = aff.ptr<double>();
|
||||
data[0] = 1; data[1] = 0; data[2] = 0;
|
||||
data[3] = 0; data[4] = 1; data[5] = 0;
|
||||
|
||||
add(img, Mat(img.size(), img.type(), Scalar(15)), out);
|
||||
}
|
||||
|
||||
void showOrig(const Mat& img, const vector<KeyPoint>& orig_pts)
|
||||
{
|
||||
|
||||
Mat img_color;
|
||||
cvtColor(img, img_color, CV_GRAY2BGR);
|
||||
|
||||
for(size_t i = 0; i < orig_pts.size(); ++i)
|
||||
circle(img_color, orig_pts[i].pt, (int)orig_pts[i].size/2, CV_RGB(0, 255, 0));
|
||||
|
||||
namedWindow("O"); imshow("O", img_color);
|
||||
}
|
||||
|
||||
void show(const string& name, const Mat& new_img, const vector<KeyPoint>& new_pts, const vector<KeyPoint>& transf_pts)
|
||||
{
|
||||
|
||||
Mat new_img_color;
|
||||
cvtColor(new_img, new_img_color, CV_GRAY2BGR);
|
||||
|
||||
for(size_t i = 0; i < transf_pts.size(); ++i)
|
||||
circle(new_img_color, transf_pts[i].pt, (int)transf_pts[i].size/2, CV_RGB(255, 0, 0));
|
||||
|
||||
for(size_t i = 0; i < new_pts.size(); ++i)
|
||||
circle(new_img_color, new_pts[i].pt, (int)new_pts[i].size/2, CV_RGB(0, 0, 255));
|
||||
|
||||
namedWindow(name + "_T"); imshow(name + "_T", new_img_color);
|
||||
}
|
||||
|
||||
struct WrapPoint
|
||||
{
|
||||
const double* R;
|
||||
WrapPoint(const Mat& rmat) : R(rmat.ptr<double>()) { };
|
||||
|
||||
KeyPoint operator()(const KeyPoint& kp) const
|
||||
{
|
||||
KeyPoint res = kp;
|
||||
res.pt.x = static_cast<float>(kp.pt.x * R[0] + kp.pt.y * R[1] + R[2]);
|
||||
res.pt.y = static_cast<float>(kp.pt.x * R[3] + kp.pt.y * R[4] + R[5]);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
struct sortByR { bool operator()(const KeyPoint& kp1, const KeyPoint& kp2) { return norm(kp1.pt) < norm(kp2.pt); } };
|
||||
|
||||
template <class T> bool CV_DetectorsTest::testDetector(const Mat& img, const T& detector, vector<KeyPoint>& exp)
|
||||
{
|
||||
vector<KeyPoint> orig_kpts;
|
||||
detector(img, orig_kpts);
|
||||
|
||||
typedef void (*TransfFunc )(const Mat&, Mat&, Mat& FransfFunc);
|
||||
const TransfFunc transfFunc[] = { getRotation, getZoom, getBlur, getBrightness };
|
||||
//const string names[] = { "Rotation", "Zoom", "Blur", "Brightness" };
|
||||
const size_t case_num = sizeof(transfFunc)/sizeof(transfFunc[0]);
|
||||
|
||||
vector<Mat> affs(case_num);
|
||||
vector<Mat> new_imgs(case_num);
|
||||
|
||||
vector< vector<KeyPoint> > new_kpts(case_num);
|
||||
vector< vector<KeyPoint> > transf_kpts(case_num);
|
||||
|
||||
//showOrig(img, orig_kpts);
|
||||
for(size_t i = 0; i < case_num; ++i)
|
||||
{
|
||||
transfFunc[i](img, affs[i], new_imgs[i]);
|
||||
detector(new_imgs[i], new_kpts[i]);
|
||||
transform(orig_kpts.begin(), orig_kpts.end(), back_inserter(transf_kpts[i]), WrapPoint(affs[i]));
|
||||
//show(names[i], new_imgs[i], new_kpts[i], transf_kpts[i]);
|
||||
}
|
||||
|
||||
const float thres = 3;
|
||||
const float nthres = 3;
|
||||
|
||||
vector<KeyPoint> result;
|
||||
for(size_t i = 0; i < orig_kpts.size(); ++i)
|
||||
{
|
||||
const KeyPoint& okp = orig_kpts[i];
|
||||
int foundCounter = 0;
|
||||
for(size_t j = 0; j < case_num; ++j)
|
||||
{
|
||||
const KeyPoint& tkp = transf_kpts[j][i];
|
||||
|
||||
size_t k = 0;
|
||||
|
||||
for(; k < new_kpts[j].size(); ++k)
|
||||
if (norm(new_kpts[j][k].pt - tkp.pt) < nthres && fabs(new_kpts[j][k].size - tkp.size) < thres)
|
||||
break;
|
||||
|
||||
if (k != new_kpts[j].size())
|
||||
++foundCounter;
|
||||
|
||||
}
|
||||
if (foundCounter == (int)case_num)
|
||||
result.push_back(okp);
|
||||
}
|
||||
|
||||
sort(result.begin(), result.end(), sortByR());
|
||||
sort(exp.begin(), exp.end(), sortByR());
|
||||
|
||||
if (result.size() != exp.size())
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
|
||||
int foundCounter1 = 0;
|
||||
for(size_t i = 0; i < exp.size(); ++i)
|
||||
{
|
||||
const KeyPoint& e = exp[i];
|
||||
size_t j = 0;
|
||||
for(; j < result.size(); ++j)
|
||||
{
|
||||
const KeyPoint& r = result[i];
|
||||
if (norm(r.pt-e.pt) < nthres && fabs(r.size - e.size) < thres)
|
||||
break;
|
||||
}
|
||||
if (j != result.size())
|
||||
++foundCounter1;
|
||||
}
|
||||
|
||||
int foundCounter2 = 0;
|
||||
for(size_t i = 0; i < result.size(); ++i)
|
||||
{
|
||||
const KeyPoint& r = result[i];
|
||||
size_t j = 0;
|
||||
for(; j < exp.size(); ++j)
|
||||
{
|
||||
const KeyPoint& e = exp[i];
|
||||
if (norm(r.pt-e.pt) < nthres && fabs(r.size - e.size) < thres)
|
||||
break;
|
||||
}
|
||||
if (j != exp.size())
|
||||
++foundCounter2;
|
||||
}
|
||||
//showOrig(img, result); waitKey();
|
||||
|
||||
const float errorRate = 0.9f;
|
||||
if (float(foundCounter1)/exp.size() < errorRate || float(foundCounter2)/result.size() < errorRate)
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct SurfNoMaskWrap
|
||||
{
|
||||
const SURF& detector;
|
||||
SurfNoMaskWrap(const SURF& surf) : detector(surf) {}
|
||||
SurfNoMaskWrap& operator=(const SurfNoMaskWrap&);
|
||||
void operator()(const Mat& img, vector<KeyPoint>& kpts) const { detector(img, Mat(), kpts); }
|
||||
};
|
||||
|
||||
void CV_DetectorsTest::LoadExpected(const string& file, vector<KeyPoint>& out)
|
||||
{
|
||||
Mat mat_exp;
|
||||
FileStorage fs(file, FileStorage::READ);
|
||||
if (fs.isOpened())
|
||||
{
|
||||
read( fs["ResultVectorData"], mat_exp, Mat() );
|
||||
out.resize(mat_exp.cols / sizeof(KeyPoint));
|
||||
copy(mat_exp.ptr<KeyPoint>(), mat_exp.ptr<KeyPoint>() + out.size(), out.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA);
|
||||
out.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CV_DetectorsTest::run( int /*start_from*/ )
|
||||
{
|
||||
Mat img = imread(string(ts->get_data_path()) + "shared/graffiti.png", 0);
|
||||
|
||||
if (img.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat to_test(img.size() * 2, img.type(), Scalar(0));
|
||||
Mat roi = to_test(Rect(img.rows/2, img.cols/2, img.cols, img.rows));
|
||||
img.copyTo(roi);
|
||||
GaussianBlur(to_test, to_test, Size(3, 3), 1.5);
|
||||
|
||||
vector<KeyPoint> exp;
|
||||
LoadExpected(string(ts->get_data_path()) + "detectors/surf.xml", exp);
|
||||
if (exp.empty())
|
||||
return;
|
||||
|
||||
if (!testDetector(to_test, SurfNoMaskWrap(SURF(1536+512+512, 2)), exp))
|
||||
return;
|
||||
|
||||
LoadExpected(string(ts->get_data_path()) + "detectors/star.xml", exp);
|
||||
if (exp.empty())
|
||||
return;
|
||||
|
||||
if (!testDetector(to_test, StarDetector(45, 30, 10, 8, 5), exp))
|
||||
return;
|
||||
|
||||
ts->set_failed_test_info( cvtest::TS::OK);
|
||||
}
|
||||
|
||||
|
||||
TEST(Features2d_Detectors, regression) { CV_DetectorsTest test; test.safe_run(); }
|
||||
|
||||
|
||||
|
126
modules/features2d/test/test_fast.cpp
Normal file
126
modules/features2d/test/test_fast.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class CV_FastTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_FastTest();
|
||||
~CV_FastTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_FastTest::CV_FastTest() {}
|
||||
CV_FastTest::~CV_FastTest() {}
|
||||
|
||||
void CV_FastTest::run( int )
|
||||
{
|
||||
Mat image1 = imread(string(ts->get_data_path()) + "inpaint/orig.jpg");
|
||||
Mat image2 = imread(string(ts->get_data_path()) + "cameracalibration/chess9.jpg");
|
||||
string xml = string(ts->get_data_path()) + "fast/result.xml";
|
||||
|
||||
if (image1.empty() || image2.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat gray1, gray2;
|
||||
cvtColor(image1, gray1, CV_BGR2GRAY);
|
||||
cvtColor(image2, gray2, CV_BGR2GRAY);
|
||||
|
||||
vector<KeyPoint> keypoints1;
|
||||
vector<KeyPoint> keypoints2;
|
||||
FAST(gray1, keypoints1, 30);
|
||||
FAST(gray2, keypoints2, 30);
|
||||
|
||||
for(size_t i = 0; i < keypoints1.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints1[i];
|
||||
cv::circle(image1, kp.pt, cvRound(kp.size/2), CV_RGB(255, 0, 0));
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < keypoints2.size(); ++i)
|
||||
{
|
||||
const KeyPoint& kp = keypoints2[i];
|
||||
cv::circle(image2, kp.pt, cvRound(kp.size/2), CV_RGB(255, 0, 0));
|
||||
}
|
||||
|
||||
Mat kps1(1, (int)(keypoints1.size() * sizeof(KeyPoint)), CV_8U, &keypoints1[0]);
|
||||
Mat kps2(1, (int)(keypoints2.size() * sizeof(KeyPoint)), CV_8U, &keypoints2[0]);
|
||||
|
||||
FileStorage fs(xml, FileStorage::READ);
|
||||
if (!fs.isOpened())
|
||||
{
|
||||
fs.open(xml, FileStorage::WRITE);
|
||||
fs << "exp_kps1" << kps1;
|
||||
fs << "exp_kps2" << kps2;
|
||||
fs.release();
|
||||
}
|
||||
|
||||
if (!fs.isOpened())
|
||||
fs.open(xml, FileStorage::READ);
|
||||
|
||||
Mat exp_kps1, exp_kps2;
|
||||
read( fs["exp_kps1"], exp_kps1, Mat() );
|
||||
read( fs["exp_kps2"], exp_kps2, Mat() );
|
||||
fs.release();
|
||||
|
||||
if ( 0 != norm(exp_kps1, kps1, NORM_L2) || 0 != norm(exp_kps2, kps2, NORM_L2))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
/* cv::namedWindow("Img1"); cv::imshow("Img1", image1);
|
||||
cv::namedWindow("Img2"); cv::imshow("Img2", image2);
|
||||
cv::waitKey(0);*/
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Features2d_FAST, regression) { CV_FastTest test; test.safe_run(); }
|
||||
|
1038
modules/features2d/test/test_features2d.cpp
Normal file
1038
modules/features2d/test/test_features2d.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3
modules/features2d/test/test_main.cpp
Normal file
3
modules/features2d/test/test_main.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
203
modules/features2d/test/test_mser.cpp
Normal file
203
modules/features2d/test/test_mser.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class CV_MserTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_MserTest();
|
||||
protected:
|
||||
void run(int);
|
||||
int LoadBoxes(const char* path, vector<CvBox2D>& boxes);
|
||||
int SaveBoxes(const char* path, const vector<CvBox2D>& boxes);
|
||||
int CompareBoxes(const vector<CvBox2D>& boxes1,const vector<CvBox2D>& boxes2, float max_rel_diff = 0.01f);
|
||||
};
|
||||
|
||||
CV_MserTest::CV_MserTest()
|
||||
{
|
||||
}
|
||||
|
||||
int CV_MserTest::LoadBoxes(const char* path, vector<CvBox2D>& boxes)
|
||||
{
|
||||
boxes.clear();
|
||||
FILE* f = fopen(path,"r");
|
||||
|
||||
if (f==NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!feof(f))
|
||||
{
|
||||
CvBox2D box;
|
||||
fscanf(f,"%f,%f,%f,%f,%f\n",&box.angle,&box.center.x,&box.center.y,&box.size.width,&box.size.height);
|
||||
boxes.push_back(box);
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CV_MserTest::SaveBoxes(const char* path, const vector<CvBox2D>& boxes)
|
||||
{
|
||||
FILE* f = fopen(path,"w");
|
||||
if (f==NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for (int i=0;i<(int)boxes.size();i++)
|
||||
{
|
||||
fprintf(f,"%f,%f,%f,%f,%f\n",boxes[i].angle,boxes[i].center.x,boxes[i].center.y,boxes[i].size.width,boxes[i].size.height);
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CV_MserTest::CompareBoxes(const vector<CvBox2D>& boxes1,const vector<CvBox2D>& boxes2, float max_rel_diff)
|
||||
{
|
||||
if (boxes1.size() != boxes2.size())
|
||||
return 0;
|
||||
|
||||
for (int i=0; i<(int)boxes1.size();i++)
|
||||
{
|
||||
float rel_diff;
|
||||
if (!((boxes1[i].angle == 0.0f) && (abs(boxes2[i].angle) < max_rel_diff)))
|
||||
{
|
||||
rel_diff = abs(boxes1[i].angle-boxes2[i].angle)/abs(boxes1[i].angle);
|
||||
if (rel_diff > max_rel_diff)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (!((boxes1[i].center.x == 0.0f) && (abs(boxes2[i].center.x) < max_rel_diff)))
|
||||
{
|
||||
rel_diff = abs(boxes1[i].center.x-boxes2[i].center.x)/abs(boxes1[i].center.x);
|
||||
if (rel_diff > max_rel_diff)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (!((boxes1[i].center.y == 0.0f) && (abs(boxes2[i].center.y) < max_rel_diff)))
|
||||
{
|
||||
rel_diff = abs(boxes1[i].center.y-boxes2[i].center.y)/abs(boxes1[i].center.y);
|
||||
if (rel_diff > max_rel_diff)
|
||||
return i;
|
||||
}
|
||||
if (!((boxes1[i].size.width == 0.0f) && (abs(boxes2[i].size.width) < max_rel_diff)))
|
||||
{
|
||||
rel_diff = abs(boxes1[i].size.width-boxes2[i].size.width)/abs(boxes1[i].size.width);
|
||||
if (rel_diff > max_rel_diff)
|
||||
return i;
|
||||
}
|
||||
|
||||
if (!((boxes1[i].size.height == 0.0f) && (abs(boxes2[i].size.height) < max_rel_diff)))
|
||||
{
|
||||
rel_diff = abs(boxes1[i].size.height-boxes2[i].size.height)/abs(boxes1[i].size.height);
|
||||
if (rel_diff > max_rel_diff)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CV_MserTest::run(int)
|
||||
{
|
||||
string image_path = string(ts->get_data_path()) + "mser/puzzle.png";
|
||||
|
||||
IplImage* img = cvLoadImage( image_path.c_str());
|
||||
if (!img)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Unable to open image mser/puzzle.png\n");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
CvSeq* contours;
|
||||
CvMemStorage* storage= cvCreateMemStorage();
|
||||
IplImage* hsv = cvCreateImage( cvGetSize( img ), IPL_DEPTH_8U, 3 );
|
||||
cvCvtColor( img, hsv, CV_BGR2YCrCb );
|
||||
CvMSERParams params = cvMSERParams();//cvMSERParams( 5, 60, cvRound(.2*img->width*img->height), .25, .2 );
|
||||
cvExtractMSER( hsv, NULL, &contours, storage, params );
|
||||
|
||||
vector<CvBox2D> boxes;
|
||||
vector<CvBox2D> boxes_orig;
|
||||
for ( int i = 0; i < contours->total; i++ )
|
||||
{
|
||||
CvContour* r = *(CvContour**)cvGetSeqElem( contours, i );
|
||||
CvBox2D box = cvFitEllipse2( r );
|
||||
box.angle=(float)CV_PI/2-box.angle;
|
||||
boxes.push_back(box);
|
||||
}
|
||||
|
||||
string boxes_path = string(ts->get_data_path()) + "mser/boxes.txt";
|
||||
|
||||
if (!LoadBoxes(boxes_path.c_str(),boxes_orig))
|
||||
{
|
||||
SaveBoxes(boxes_path.c_str(),boxes);
|
||||
ts->printf( cvtest::TS::LOG, "Unable to open data file mser/boxes.txt\n");
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
const float dissimularity = 0.01f;
|
||||
int n_box = CompareBoxes(boxes_orig,boxes,dissimularity);
|
||||
if (n_box < 0)
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
|
||||
ts->printf( cvtest::TS::LOG, "Incorrect correspondence in %d box\n",n_box);
|
||||
}
|
||||
|
||||
cvReleaseMemStorage(&storage);
|
||||
cvReleaseImage(&hsv);
|
||||
cvReleaseImage(&img);
|
||||
}
|
||||
|
||||
TEST(Features2d_MSER, regression) { CV_MserTest test; test.safe_run(); }
|
||||
|
523
modules/features2d/test/test_nearestneighbors.cpp
Normal file
523
modules/features2d/test/test_nearestneighbors.cpp
Normal file
@ -0,0 +1,523 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::flann;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
class NearestNeighborTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
NearestNeighborTest() {}
|
||||
protected:
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 1;
|
||||
static const int dims = 30;
|
||||
static const int featuresCount = 2000;
|
||||
static const int K = 1; // * should also test 2nd nn etc.?
|
||||
|
||||
|
||||
virtual void run( int start_from );
|
||||
virtual void createModel( const Mat& data ) = 0;
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) = 0;
|
||||
virtual int checkGetPoins( const Mat& data );
|
||||
virtual int checkFindBoxed();
|
||||
virtual int checkFind( const Mat& data );
|
||||
virtual void releaseModel() = 0;
|
||||
};
|
||||
|
||||
int NearestNeighborTest::checkGetPoins( const Mat& )
|
||||
{
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int NearestNeighborTest::checkFindBoxed()
|
||||
{
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int NearestNeighborTest::checkFind( const Mat& data )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
int pointsCount = 1000;
|
||||
float noise = 0.2f;
|
||||
|
||||
RNG rng;
|
||||
Mat points( pointsCount, dims, CV_32FC1 );
|
||||
Mat results( pointsCount, K, CV_32SC1 );
|
||||
|
||||
std::vector<int> fmap( pointsCount );
|
||||
for( int pi = 0; pi < pointsCount; pi++ )
|
||||
{
|
||||
int fi = rng.next() % featuresCount;
|
||||
fmap[pi] = fi;
|
||||
for( int d = 0; d < dims; d++ )
|
||||
points.at<float>(pi, d) = data.at<float>(fi, d) + rng.uniform(0.0f, 1.0f) * noise;
|
||||
}
|
||||
|
||||
code = findNeighbors( points, results );
|
||||
|
||||
if( code == cvtest::TS::OK )
|
||||
{
|
||||
int correctMatches = 0;
|
||||
for( int pi = 0; pi < pointsCount; pi++ )
|
||||
{
|
||||
if( fmap[pi] == results.at<int>(pi, 0) )
|
||||
correctMatches++;
|
||||
}
|
||||
|
||||
double correctPerc = correctMatches / (double)pointsCount;
|
||||
if (correctPerc < .75)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "correct_perc = %d\n", correctPerc );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
void NearestNeighborTest::run( int /*start_from*/ ) {
|
||||
int code = cvtest::TS::OK, tempCode;
|
||||
Mat desc( featuresCount, dims, CV_32FC1 );
|
||||
randu( desc, Scalar(minValue), Scalar(maxValue) );
|
||||
|
||||
createModel( desc );
|
||||
|
||||
tempCode = checkGetPoins( desc );
|
||||
if( tempCode != cvtest::TS::OK )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of GetPoints \n" );
|
||||
code = tempCode;
|
||||
}
|
||||
|
||||
tempCode = checkFindBoxed();
|
||||
if( tempCode != cvtest::TS::OK )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of FindBoxed \n" );
|
||||
code = tempCode;
|
||||
}
|
||||
|
||||
tempCode = checkFind( desc );
|
||||
if( tempCode != cvtest::TS::OK )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy of Find \n" );
|
||||
code = tempCode;
|
||||
}
|
||||
|
||||
releaseModel();
|
||||
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
class CV_LSHTest : public NearestNeighborTest
|
||||
{
|
||||
public:
|
||||
CV_LSHTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data );
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors );
|
||||
virtual void releaseModel();
|
||||
struct CvLSH* lsh;
|
||||
CvMat desc;
|
||||
};
|
||||
|
||||
void CV_LSHTest::createModel( const Mat& data )
|
||||
{
|
||||
desc = data;
|
||||
lsh = cvCreateMemoryLSH( data.cols, data.rows, 70, 20, CV_32FC1 );
|
||||
cvLSHAdd( lsh, &desc );
|
||||
}
|
||||
|
||||
int CV_LSHTest::findNeighbors( Mat& points, Mat& neighbors )
|
||||
{
|
||||
const int emax = 20;
|
||||
Mat dist( points.rows, neighbors.cols, CV_64FC1);
|
||||
CvMat _dist = dist, _points = points, _neighbors = neighbors;
|
||||
cvLSHQuery( lsh, &_points, &_neighbors, &_dist, neighbors.cols, emax );
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
void CV_LSHTest::releaseModel()
|
||||
{
|
||||
cvReleaseLSH( &lsh );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
class CV_FeatureTreeTest_C : public NearestNeighborTest
|
||||
{
|
||||
public:
|
||||
CV_FeatureTreeTest_C() {}
|
||||
protected:
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors );
|
||||
virtual void releaseModel();
|
||||
CvFeatureTree* tr;
|
||||
CvMat desc;
|
||||
};
|
||||
|
||||
int CV_FeatureTreeTest_C::findNeighbors( Mat& points, Mat& neighbors )
|
||||
{
|
||||
const int emax = 20;
|
||||
Mat dist( points.rows, neighbors.cols, CV_64FC1);
|
||||
CvMat _dist = dist, _points = points, _neighbors = neighbors;
|
||||
cvFindFeatures( tr, &_points, &_neighbors, &_dist, neighbors.cols, emax );
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
void CV_FeatureTreeTest_C::releaseModel()
|
||||
{
|
||||
cvReleaseFeatureTree( tr );
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
class CV_SpillTreeTest_C : public CV_FeatureTreeTest_C
|
||||
{
|
||||
public:
|
||||
CV_SpillTreeTest_C() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data );
|
||||
};
|
||||
|
||||
void CV_SpillTreeTest_C::createModel( const Mat& data )
|
||||
{
|
||||
desc = data;
|
||||
tr = cvCreateSpillTree( &desc );
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
class CV_KDTreeTest_C : public CV_FeatureTreeTest_C
|
||||
{
|
||||
public:
|
||||
CV_KDTreeTest_C() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data );
|
||||
virtual int checkFindBoxed();
|
||||
};
|
||||
|
||||
void CV_KDTreeTest_C::createModel( const Mat& data )
|
||||
{
|
||||
desc = data;
|
||||
tr = cvCreateKDTree( &desc );
|
||||
}
|
||||
|
||||
int CV_KDTreeTest_C::checkFindBoxed()
|
||||
{
|
||||
Mat min(1, dims, CV_32FC1 ), max(1, dims, CV_32FC1 ), indices( 1, 1, CV_32SC1 );
|
||||
float l = minValue, r = maxValue;
|
||||
min.setTo(Scalar(l)), max.setTo(Scalar(r));
|
||||
CvMat _min = min, _max = max, _indices = indices;
|
||||
// TODO check indices
|
||||
if( cvFindFeaturesBoxed( tr, &_min, &_max, &_indices ) != featuresCount )
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
class CV_KDTreeTest_CPP : public NearestNeighborTest
|
||||
{
|
||||
public:
|
||||
CV_KDTreeTest_CPP() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data );
|
||||
virtual int checkGetPoins( const Mat& data );
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors );
|
||||
virtual int checkFindBoxed();
|
||||
virtual void releaseModel();
|
||||
KDTree* tr;
|
||||
};
|
||||
|
||||
|
||||
void CV_KDTreeTest_CPP::createModel( const Mat& data )
|
||||
{
|
||||
tr = new KDTree( data, false );
|
||||
}
|
||||
|
||||
int CV_KDTreeTest_CPP::checkGetPoins( const Mat& data )
|
||||
{
|
||||
Mat res1( data.size(), data.type() ),
|
||||
res2( data.size(), data.type() ),
|
||||
res3( data.size(), data.type() );
|
||||
Mat idxs( 1, data.rows, CV_32SC1 );
|
||||
for( int pi = 0; pi < data.rows; pi++ )
|
||||
{
|
||||
idxs.at<int>(0, pi) = pi;
|
||||
// 1st way
|
||||
const float* point = tr->getPoint(pi);
|
||||
for( int di = 0; di < data.cols; di++ )
|
||||
res1.at<float>(pi, di) = point[di];
|
||||
}
|
||||
// 2nd way
|
||||
tr->getPoints( idxs.ptr<int>(0), data.rows, res2 );
|
||||
|
||||
// 3d way
|
||||
tr->getPoints( idxs, res3 );
|
||||
|
||||
if( norm( res1, data, NORM_L1) != 0 ||
|
||||
norm( res2, data, NORM_L1) != 0 ||
|
||||
norm( res3, data, NORM_L1) != 0)
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int CV_KDTreeTest_CPP::checkFindBoxed()
|
||||
{
|
||||
vector<float> min( dims, minValue), max(dims, maxValue);
|
||||
vector<int> indices;
|
||||
tr->findOrthoRange( &min[0], &max[0], &indices );
|
||||
// TODO check indices
|
||||
if( (int)indices.size() != featuresCount)
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int CV_KDTreeTest_CPP::findNeighbors( Mat& points, Mat& neighbors )
|
||||
{
|
||||
const int emax = 20;
|
||||
Mat neighbors2( neighbors.size(), CV_32SC1 );
|
||||
int j;
|
||||
vector<float> min(points.cols, minValue);
|
||||
vector<float> max(points.cols, maxValue);
|
||||
for( int pi = 0; pi < points.rows; pi++ )
|
||||
{
|
||||
// 1st way
|
||||
tr->findNearest( points.ptr<float>(pi), neighbors.cols, emax, neighbors.ptr<int>(pi) );
|
||||
|
||||
// 2nd way
|
||||
vector<int> neighborsIdx2( neighbors2.cols, 0 );
|
||||
tr->findNearest( points.ptr<float>(pi), neighbors2.cols, emax, &neighborsIdx2 );
|
||||
vector<int>::const_iterator it2 = neighborsIdx2.begin();
|
||||
for( j = 0; it2 != neighborsIdx2.end(); ++it2, j++ )
|
||||
neighbors2.at<int>(pi,j) = *it2;
|
||||
}
|
||||
|
||||
// compare results
|
||||
if( norm( neighbors, neighbors2, NORM_L1 ) != 0 )
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
void CV_KDTreeTest_CPP::releaseModel()
|
||||
{
|
||||
delete tr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
class CV_FlannTest : public NearestNeighborTest
|
||||
{
|
||||
public:
|
||||
CV_FlannTest() {}
|
||||
protected:
|
||||
void createIndex( const Mat& data, const IndexParams& params );
|
||||
int knnSearch( Mat& points, Mat& neighbors );
|
||||
int radiusSearch( Mat& points, Mat& neighbors );
|
||||
virtual void releaseModel();
|
||||
Index* index;
|
||||
};
|
||||
|
||||
void CV_FlannTest::createIndex( const Mat& data, const IndexParams& params )
|
||||
{
|
||||
index = new Index( data, params );
|
||||
}
|
||||
|
||||
int CV_FlannTest::knnSearch( Mat& points, Mat& neighbors )
|
||||
{
|
||||
Mat dist( points.rows, neighbors.cols, CV_32FC1);
|
||||
int knn = 1, j;
|
||||
|
||||
// 1st way
|
||||
index->knnSearch( points, neighbors, dist, knn, SearchParams() );
|
||||
|
||||
// 2nd way
|
||||
Mat neighbors1( neighbors.size(), CV_32SC1 );
|
||||
for( int i = 0; i < points.rows; i++ )
|
||||
{
|
||||
float* fltPtr = points.ptr<float>(i);
|
||||
vector<float> query( fltPtr, fltPtr + points.cols );
|
||||
vector<int> indices( neighbors1.cols, 0 );
|
||||
vector<float> dists( dist.cols, 0 );
|
||||
index->knnSearch( query, indices, dists, knn, SearchParams() );
|
||||
vector<int>::const_iterator it = indices.begin();
|
||||
for( j = 0; it != indices.end(); ++it, j++ )
|
||||
neighbors1.at<int>(i,j) = *it;
|
||||
}
|
||||
|
||||
// compare results
|
||||
if( norm( neighbors, neighbors1, NORM_L1 ) != 0 )
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
int CV_FlannTest::radiusSearch( Mat& points, Mat& neighbors )
|
||||
{
|
||||
Mat dist( 1, neighbors.cols, CV_32FC1);
|
||||
Mat neighbors1( neighbors.size(), CV_32SC1 );
|
||||
float radius = 10.0f;
|
||||
int j;
|
||||
|
||||
// radiusSearch can only search one feature at a time for range search
|
||||
for( int i = 0; i < points.rows; i++ )
|
||||
{
|
||||
// 1st way
|
||||
Mat p( 1, points.cols, CV_32FC1, points.ptr<float>(i) ),
|
||||
n( 1, neighbors.cols, CV_32SC1, neighbors.ptr<int>(i) );
|
||||
index->radiusSearch( p, n, dist, radius, SearchParams() );
|
||||
|
||||
// 2nd way
|
||||
float* fltPtr = points.ptr<float>(i);
|
||||
vector<float> query( fltPtr, fltPtr + points.cols );
|
||||
vector<int> indices( neighbors1.cols, 0 );
|
||||
vector<float> dists( dist.cols, 0 );
|
||||
index->radiusSearch( query, indices, dists, radius, SearchParams() );
|
||||
vector<int>::const_iterator it = indices.begin();
|
||||
for( j = 0; it != indices.end(); ++it, j++ )
|
||||
neighbors1.at<int>(i,j) = *it;
|
||||
}
|
||||
// compare results
|
||||
if( norm( neighbors, neighbors1, NORM_L1 ) != 0 )
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
void CV_FlannTest::releaseModel()
|
||||
{
|
||||
delete index;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
class CV_FlannLinearIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannLinearIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, LinearIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//---------------------------------------
|
||||
class CV_FlannKMeansIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannKMeansIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, KMeansIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return radiusSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//---------------------------------------
|
||||
class CV_FlannKDTreeIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannKDTreeIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, KDTreeIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return radiusSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
class CV_FlannCompositeIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannCompositeIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, CompositeIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
class CV_FlannAutotunedIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannAutotunedIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data ) { createIndex( data, AutotunedIndexParams() ); }
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
//----------------------------------------
|
||||
class CV_FlannSavedIndexTest : public CV_FlannTest
|
||||
{
|
||||
public:
|
||||
CV_FlannSavedIndexTest() {}
|
||||
protected:
|
||||
virtual void createModel( const Mat& data );
|
||||
virtual int findNeighbors( Mat& points, Mat& neighbors ) { return knnSearch( points, neighbors ); }
|
||||
};
|
||||
|
||||
void CV_FlannSavedIndexTest::createModel(const cv::Mat &data)
|
||||
{
|
||||
switch ( cvtest::randInt(ts->get_rng()) % 2 )
|
||||
{
|
||||
//case 0: createIndex( data, LinearIndexParams() ); break; // nothing to save for linear search
|
||||
case 0: createIndex( data, KMeansIndexParams() ); break;
|
||||
case 1: createIndex( data, KDTreeIndexParams() ); break;
|
||||
//case 2: createIndex( data, CompositeIndexParams() ); break; // nothing to save for linear search
|
||||
//case 2: createIndex( data, AutotunedIndexParams() ); break; // possible linear index !
|
||||
default: assert(0);
|
||||
}
|
||||
char filename[50];
|
||||
tmpnam( filename );
|
||||
if(filename[0] == '\\') filename[0] = '_';
|
||||
index->save( filename );
|
||||
|
||||
createIndex( data, SavedIndexParams(filename));
|
||||
remove( filename );
|
||||
}
|
||||
|
||||
TEST(Features2d_LSH, regression) { CV_LSHTest test; test.safe_run(); }
|
||||
TEST(Features2d_SpillTree, regression) { CV_SpillTreeTest_C test; test.safe_run(); }
|
||||
TEST(Features2d_KDTree_C, regression) { CV_KDTreeTest_C test; test.safe_run(); }
|
||||
TEST(Features2d_KDTree_CPP, regression) { CV_KDTreeTest_CPP test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Linear, regression) { CV_FlannLinearIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_KMeans, regression) { CV_FlannKMeansIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_KDTree, regression) { CV_FlannKDTreeIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Composite, regression) { CV_FlannCompositeIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Auto, regression) { CV_FlannAutotunedIndexTest test; test.safe_run(); }
|
||||
TEST(Features2d_FLANN_Saved, regression) { CV_FlannSavedIndexTest test; test.safe_run(); }
|
1
modules/features2d/test/test_precomp.cpp
Normal file
1
modules/features2d/test/test_precomp.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "test_precomp.hpp"
|
11
modules/features2d/test/test_precomp.hpp
Normal file
11
modules/features2d/test/test_precomp.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts/ts.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#endif
|
@ -1,4 +0,0 @@
|
||||
if(BUILD_SHARED_LIBS)
|
||||
add_definitions(-DGTEST_CREATE_SHARED_LIBRARY=1)
|
||||
endif()
|
||||
define_opencv_module(gtest opencv_core)
|
@ -1,422 +0,0 @@
|
||||
The new OpenCV test engine is based
|
||||
on the Google C++ Testing Framework (GTest).
|
||||
Below is the original GTest README.
|
||||
-----------------------------------
|
||||
|
||||
Google C++ Testing Framework
|
||||
============================
|
||||
|
||||
http://code.google.com/p/googletest/
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Google's framework for writing C++ tests on a variety of platforms
|
||||
(Linux, Mac OS X, Windows, Windows CE, Symbian, etc). Based on the
|
||||
xUnit architecture. Supports automatic test discovery, a rich set of
|
||||
assertions, user-defined assertions, death tests, fatal and non-fatal
|
||||
failures, various options for running the tests, and XML test report
|
||||
generation.
|
||||
|
||||
Please see the project page above for more information as well as the
|
||||
mailing list for questions, discussions, and development. There is
|
||||
also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please
|
||||
join us!
|
||||
|
||||
Requirements for End Users
|
||||
--------------------------
|
||||
|
||||
Google Test is designed to have fairly minimal requirements to build
|
||||
and use with your projects, but there are some. Currently, we support
|
||||
Linux, Windows, Mac OS X, and Cygwin. We will also make our best
|
||||
effort to support other platforms (e.g. Solaris, AIX, and z/OS).
|
||||
However, since core members of the Google Test project have no access
|
||||
to these platforms, Google Test may have outstanding issues there. If
|
||||
you notice any problems on your platform, please notify
|
||||
googletestframework@googlegroups.com. Patches for fixing them are
|
||||
even more welcome!
|
||||
|
||||
### Linux Requirements ###
|
||||
|
||||
These are the base requirements to build and use Google Test from a source
|
||||
package (as described below):
|
||||
* GNU-compatible Make or gmake
|
||||
* POSIX-standard shell
|
||||
* POSIX(-2) Regular Expressions (regex.h)
|
||||
* A C++98-standard-compliant compiler
|
||||
|
||||
### Windows Requirements ###
|
||||
|
||||
* Microsoft Visual C++ 7.1 or newer
|
||||
|
||||
### Cygwin Requirements ###
|
||||
|
||||
* Cygwin 1.5.25-14 or newer
|
||||
|
||||
### Mac OS X Requirements ###
|
||||
|
||||
* Mac OS X 10.4 Tiger or newer
|
||||
* Developer Tools Installed
|
||||
|
||||
Also, you'll need CMake 2.6.4 or higher if you want to build the
|
||||
samples using the provided CMake script, regardless of the platform.
|
||||
|
||||
Requirements for Contributors
|
||||
-----------------------------
|
||||
|
||||
We welcome patches. If you plan to contribute a patch, you need to
|
||||
build Google Test and its own tests from an SVN checkout (described
|
||||
below), which has further requirements:
|
||||
|
||||
* Python version 2.3 or newer (for running some of the tests and
|
||||
re-generating certain source files from templates)
|
||||
* CMake 2.6.4 or newer
|
||||
|
||||
Getting the Source
|
||||
------------------
|
||||
|
||||
There are two primary ways of getting Google Test's source code: you
|
||||
can download a stable source release in your preferred archive format,
|
||||
or directly check out the source from our Subversion (SVN) repositary.
|
||||
The SVN checkout requires a few extra steps and some extra software
|
||||
packages on your system, but lets you track the latest development and
|
||||
make patches much more easily, so we highly encourage it.
|
||||
|
||||
### Source Package ###
|
||||
|
||||
Google Test is released in versioned source packages which can be
|
||||
downloaded from the download page [1]. Several different archive
|
||||
formats are provided, but the only difference is the tools used to
|
||||
manipulate them, and the size of the resulting file. Download
|
||||
whichever you are most comfortable with.
|
||||
|
||||
[1] http://code.google.com/p/googletest/downloads/list
|
||||
|
||||
Once the package is downloaded, expand it using whichever tools you
|
||||
prefer for that type. This will result in a new directory with the
|
||||
name "gtest-X.Y.Z" which contains all of the source code. Here are
|
||||
some examples on Linux:
|
||||
|
||||
tar -xvzf gtest-X.Y.Z.tar.gz
|
||||
tar -xvjf gtest-X.Y.Z.tar.bz2
|
||||
unzip gtest-X.Y.Z.zip
|
||||
|
||||
### SVN Checkout ###
|
||||
|
||||
To check out the main branch (also known as the "trunk") of Google
|
||||
Test, run the following Subversion command:
|
||||
|
||||
svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
|
||||
|
||||
Setting up the Build
|
||||
--------------------
|
||||
|
||||
To build Google Test and your tests that use it, you need to tell your
|
||||
build system where to find its headers and source files. The exact
|
||||
way to do it depends on which build system you use, and is usually
|
||||
straightforward.
|
||||
|
||||
### Generic Build Instructions ###
|
||||
|
||||
Suppose you put Google Test in directory ${GTEST_DIR}. To build it,
|
||||
create a library build target (or a project as called by Visual Studio
|
||||
and Xcode) to compile
|
||||
|
||||
${GTEST_DIR}/src/gtest-all.cc
|
||||
|
||||
with
|
||||
|
||||
${GTEST_DIR}/include and ${GTEST_DIR}
|
||||
|
||||
in the header search path. Assuming a Linux-like system and gcc,
|
||||
something like the following will do:
|
||||
|
||||
g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
|
||||
ar -rv libgtest.a gtest-all.o
|
||||
|
||||
Next, you should compile your test source file with
|
||||
${GTEST_DIR}/include in the header search path, and link it with gtest
|
||||
and any other necessary libraries:
|
||||
|
||||
g++ -I${GTEST_DIR}/include path/to/your_test.cc libgtest.a -o your_test
|
||||
|
||||
As an example, the make/ directory contains a Makefile that you can
|
||||
use to build Google Test on systems where GNU make is available
|
||||
(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google
|
||||
Test's own tests. Instead, it just builds the Google Test library and
|
||||
a sample test. You can use it as a starting point for your own build
|
||||
script.
|
||||
|
||||
If the default settings are correct for your environment, the
|
||||
following commands should succeed:
|
||||
|
||||
cd ${GTEST_DIR}/make
|
||||
make
|
||||
./sample1_unittest
|
||||
|
||||
If you see errors, try to tweak the contents of make/Makefile to make
|
||||
them go away. There are instructions in make/Makefile on how to do
|
||||
it.
|
||||
|
||||
### Using CMake ###
|
||||
|
||||
Google Test comes with a CMake build script (CMakeLists.txt) that can
|
||||
be used on a wide range of platforms ("C" stands for cross-platofrm.).
|
||||
If you don't have CMake installed already, you can download it for
|
||||
free from http://www.cmake.org/.
|
||||
|
||||
CMake works by generating native makefiles or build projects that can
|
||||
be used in the compiler environment of your choice. The typical
|
||||
workflow starts with:
|
||||
|
||||
mkdir mybuild # Create a directory to hold the build output.
|
||||
cd mybuild
|
||||
cmake ${GTEST_DIR} # Generate native build scripts.
|
||||
|
||||
If you want to build Google Test's samples, you should replace the
|
||||
last command with
|
||||
|
||||
cmake -Dbuild_gtest_samples=ON ${GTEST_DIR}
|
||||
|
||||
If you are on a *nix system, you should now see a Makefile in the
|
||||
current directory. Just type 'make' to build gtest.
|
||||
|
||||
If you use Windows and have Vistual Studio installed, a gtest.sln file
|
||||
and several .vcproj files will be created. You can then build them
|
||||
using Visual Studio.
|
||||
|
||||
On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
|
||||
|
||||
### Legacy Build Scripts ###
|
||||
|
||||
Before settling on CMake, we have been providing hand-maintained build
|
||||
projects/scripts for Visual Studio, Xcode, and Autotools. While we
|
||||
continue to provide them for convenience, they are not actively
|
||||
maintained any more. We highly recommend that you follow the
|
||||
instructions in the previous two sections to integrate Google Test
|
||||
with your existing build system.
|
||||
|
||||
If you still need to use the legacy build scripts, here's how:
|
||||
|
||||
The msvc\ folder contains two solutions with Visual C++ projects.
|
||||
Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
|
||||
are ready to build Google Test the same way you build any Visual
|
||||
Studio project. Files that have names ending with -md use DLL
|
||||
versions of Microsoft runtime libraries (the /MD or the /MDd compiler
|
||||
option). Files without that suffix use static versions of the runtime
|
||||
libraries (the /MT or the /MTd option). Please note that one must use
|
||||
the same option to compile both gtest and the test code. If you use
|
||||
Visual Studio 2005 or above, we recommend the -md version as /MD is
|
||||
the default for new projects in these versions of Visual Studio.
|
||||
|
||||
On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
|
||||
Xcode. Build the "gtest" target. The universal binary framework will
|
||||
end up in your selected build directory (selected in the Xcode
|
||||
"Preferences..." -> "Building" pane and defaults to xcode/build).
|
||||
Alternatively, at the command line, enter:
|
||||
|
||||
xcodebuild
|
||||
|
||||
This will build the "Release" configuration of gtest.framework in your
|
||||
default build location. See the "xcodebuild" man page for more
|
||||
information about building different configurations and building in
|
||||
different locations.
|
||||
|
||||
Tweaking Google Test
|
||||
--------------------
|
||||
|
||||
Google Test can be used in diverse environments. The default
|
||||
configuration may not work (or may not work well) out of the box in
|
||||
some environments. However, you can easily tweak Google Test by
|
||||
defining control macros on the compiler command line. Generally,
|
||||
these macros are named like GTEST_XYZ and you define them to either 1
|
||||
or 0 to enable or disable a certain feature.
|
||||
|
||||
We list the most frequently used macros below. For a complete list,
|
||||
see file include/gtest/internal/gtest-port.h.
|
||||
|
||||
### Choosing a TR1 Tuple Library ###
|
||||
|
||||
Some Google Test features require the C++ Technical Report 1 (TR1)
|
||||
tuple library, which is not yet available with all compilers. The
|
||||
good news is that Google Test implements a subset of TR1 tuple that's
|
||||
enough for its own need, and will automatically use this when the
|
||||
compiler doesn't provide TR1 tuple.
|
||||
|
||||
Usually you don't need to care about which tuple library Google Test
|
||||
uses. However, if your project already uses TR1 tuple, you need to
|
||||
tell Google Test to use the same TR1 tuple library the rest of your
|
||||
project uses, or the two tuple implementations will clash. To do
|
||||
that, add
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=0
|
||||
|
||||
to the compiler flags while compiling Google Test and your tests. If
|
||||
you want to force Google Test to use its own tuple library, just add
|
||||
|
||||
-DGTEST_USE_OWN_TR1_TUPLE=1
|
||||
|
||||
to the compiler flags instead.
|
||||
|
||||
If you don't want Google Test to use tuple at all, add
|
||||
|
||||
-DGTEST_HAS_TR1_TUPLE=0
|
||||
|
||||
and all features using tuple will be disabled.
|
||||
|
||||
### Multi-threaded Tests ###
|
||||
|
||||
Google Test is thread-safe where the pthread library is available.
|
||||
After #include <gtest/gtest.h>, you can check the GTEST_IS_THREADSAFE
|
||||
macro to see whether this is the case (yes if the macro is #defined to
|
||||
1, no if it's undefined.).
|
||||
|
||||
If Google Test doesn't correctly detect whether pthread is available
|
||||
in your environment, you can force it with
|
||||
|
||||
-DGTEST_HAS_PTHREAD=1
|
||||
|
||||
or
|
||||
|
||||
-DGTEST_HAS_PTHREAD=0
|
||||
|
||||
When Google Test uses pthread, you may need to add flags to your
|
||||
compiler and/or linker to select the pthread library, or you'll get
|
||||
link errors. If you use the CMake script or the deprecated Autotools
|
||||
script, this is taken care of for you. If you use your own build
|
||||
script, you'll need to read your compiler and linker's manual to
|
||||
figure out what flags to add.
|
||||
|
||||
### As a Shared Library (DLL) ###
|
||||
|
||||
Google Test is compact, so most users can build and link it as a
|
||||
static library for the simplicity. You can choose to use Google Test
|
||||
as a shared library (known as a DLL on Windows) if you prefer.
|
||||
|
||||
To compile gtest as a shared library, add
|
||||
|
||||
-DGTEST_CREATE_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags. You'll also need to tell the linker to produce
|
||||
a shared library instead - consult your linker's manual for how to do
|
||||
it.
|
||||
|
||||
To compile your tests that use the gtest shared library, add
|
||||
|
||||
-DGTEST_LINKED_AS_SHARED_LIBRARY=1
|
||||
|
||||
to the compiler flags.
|
||||
|
||||
### Avoiding Macro Name Clashes ###
|
||||
|
||||
In C++, macros don't obey namespaces. Therefore two libraries that
|
||||
both define a macro of the same name will clash if you #include both
|
||||
definitions. In case a Google Test macro clashes with another
|
||||
library, you can force Google Test to rename its macro to avoid the
|
||||
conflict.
|
||||
|
||||
Specifically, if both Google Test and some other code define macro
|
||||
FOO, you can add
|
||||
|
||||
-DGTEST_DONT_DEFINE_FOO=1
|
||||
|
||||
to the compiler flags to tell Google Test to change the macro's name
|
||||
from FOO to GTEST_FOO. Currently FOO can be FAIL, SUCCEED, or TEST.
|
||||
For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
|
||||
|
||||
GTEST_TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
instead of
|
||||
|
||||
TEST(SomeTest, DoesThis) { ... }
|
||||
|
||||
in order to define a test.
|
||||
|
||||
Upgrating from an Earlier Version
|
||||
---------------------------------
|
||||
|
||||
We strive to keep Google Test releases backward compatible.
|
||||
Sometimes, though, we have to make some breaking changes for the
|
||||
users' long-term benefits. This section describes what you'll need to
|
||||
do if you are upgrading from an earlier version of Google Test.
|
||||
|
||||
### Upgrading from 1.3.0 or Earlier ###
|
||||
|
||||
You may need to explicitly enable or disable Google Test's own TR1
|
||||
tuple library. See the instructions in section "Choosing a TR1 Tuple
|
||||
Library".
|
||||
|
||||
### Upgrading from 1.4.0 or Earlier ###
|
||||
|
||||
The Autotools build script (configure + make) is no longer officially
|
||||
supportted. You are encouraged to migrate to your own build system or
|
||||
use CMake. If you still need to use Autotools, you can find
|
||||
instructions in the README file from Google Test 1.4.0.
|
||||
|
||||
On platforms where the pthread library is available, Google Test uses
|
||||
it in order to be thread-safe. See the "Multi-threaded Tests" section
|
||||
for what this means to your build script.
|
||||
|
||||
If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
|
||||
Test will no longer compile. This should affect very few people, as a
|
||||
large portion of STL (including <string>) doesn't compile in this mode
|
||||
anyway. We decided to stop supporting it in order to greatly simplify
|
||||
Google Test's implementation.
|
||||
|
||||
Developing Google Test
|
||||
----------------------
|
||||
|
||||
This section discusses how to make your own changes to Google Test.
|
||||
|
||||
### Testing Google Test Itself ###
|
||||
|
||||
To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test's own tests.
|
||||
For that you can use CMake:
|
||||
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dbuild_all_gtest_tests=ON ${GTEST_DIR}
|
||||
|
||||
Make sure you have Python installed, as some of Google Test's tests
|
||||
are written in Python. If the cmake command complains about not being
|
||||
able to find Python ("Could NOT find PythonInterp (missing:
|
||||
PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
|
||||
executable can be found:
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python -Dbuild_all_gtest_tests=ON \
|
||||
${GTEST_DIR}
|
||||
|
||||
Next, you can build Google Test and all of its own tests. On *nix,
|
||||
this is usually done by 'make'. To run the tests, do
|
||||
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
### Regenerating Source Files ###
|
||||
|
||||
Some of Google Test's source files are generated from templates (not
|
||||
in the C++ sense) using a script. A template file is named FOO.pump,
|
||||
where FOO is the name of the file it will generate. For example, the
|
||||
file include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||
gtest-type-util.h in the same directory.
|
||||
|
||||
Normally you don't need to worry about regenerating the source files,
|
||||
unless you need to modify them. In that case, you should modify the
|
||||
corresponding .pump files instead and run the pump.py Python script to
|
||||
regenerate them. You can find pump.py in the scripts/ directory.
|
||||
Read the Pump manual [2] for how to use it.
|
||||
|
||||
[2] http://code.google.com/p/googletest/wiki/PumpManual
|
||||
|
||||
### Contributing a Patch ###
|
||||
|
||||
We welcome patches. Please read the Google Test developer's guide [3]
|
||||
for how you can contribute. In particular, make sure you have signed
|
||||
the Contributor License Agreement, or we won't be able to accept the
|
||||
patch.
|
||||
|
||||
[3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
|
||||
|
||||
Happy testing!
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
#ifndef __OPENCV_GTESTCV_HPP__
|
||||
#define __OPENCV_GTESTCV_HPP__
|
||||
|
||||
#include "opencv2/gtest/gtest.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
namespace cvtest
|
||||
{
|
||||
|
||||
using std::vector;
|
||||
using cv::RNG;
|
||||
using cv::Mat;
|
||||
using cv::Scalar;
|
||||
using cv::Size;
|
||||
using cv::Point;
|
||||
using cv::Rect;
|
||||
|
||||
enum
|
||||
{
|
||||
TYPE_MASK_8U = 1 << CV_8U,
|
||||
TYPE_MASK_8S = 1 << CV_8S,
|
||||
TYPE_MASK_16U = 1 << CV_16U,
|
||||
TYPE_MASK_16S = 1 << CV_16S,
|
||||
TYPE_MASK_32S = 1 << CV_32S,
|
||||
TYPE_MASK_32F = 1 << CV_32F,
|
||||
TYPE_MASK_64F = 1 << CV_64F,
|
||||
TYPE_MASK_ALL = (TYPE_MASK_64F<<1)-1,
|
||||
TYPE_MASK_ALL_BUT_8S = TYPE_MASK_ALL & ~TYPE_MASK_8S
|
||||
};
|
||||
|
||||
CV_EXPORTS double getMinVal(int depth);
|
||||
CV_EXPORTS double getMaxVal(int depth);
|
||||
|
||||
CV_EXPORTS Size randomSize(RNG& rng, double maxSizeLog);
|
||||
CV_EXPORTS void randomSize(RNG& rng, int minDims, int maxDims, double maxSizeLog, vector<int>& sz);
|
||||
CV_EXPORTS int randomType(RNG& rng, int typeMask, int minChannels, int maxChannels);
|
||||
CV_EXPORTS Mat randomMat(RNG& rng, Size size, int type, double minVal, double maxVal, bool useRoi);
|
||||
CV_EXPORTS Mat randomMat(RNG& rng, const vector<int>& size, int type, double minVal, double maxVal, bool useRoi);
|
||||
CV_EXPORTS void add(const Mat& a, double alpha, const Mat& b, double beta,
|
||||
Scalar gamma, Mat& c, int ctype, bool calcAbs=false);
|
||||
CV_EXPORTS void convert(const Mat& src, Mat& dst, int dtype, double alpha=1, double beta=0);
|
||||
CV_EXPORTS void copy(const Mat& src, Mat& dst, const Mat& mask=Mat(), bool invertMask=false);
|
||||
CV_EXPORTS void set(Mat& dst, const Scalar& gamma, const Mat& mask=Mat());
|
||||
CV_EXPORTS void erode(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
|
||||
int borderType=IPL_BORDER_CONSTANT, const Scalar& borderValue=Scalar());
|
||||
CV_EXPORTS void dilate(const Mat& src, Mat& dst, const Mat& _kernel, Point anchor=Point(-1,-1),
|
||||
int borderType=IPL_BORDER_CONSTANT, const Scalar& borderValue=Scalar());
|
||||
CV_EXPORTS void filter2D(const Mat& src, Mat& dst, int ddepth, const Mat& kernel,
|
||||
Point anchor, double delta, int borderType,
|
||||
const Scalar& borderValue=Scalar());
|
||||
CV_EXPORTS void copyMakeBorder(const Mat& src, Mat& dst, int top, int bottom, int left, int right,
|
||||
int borderType, const Scalar& borderValue=Scalar());
|
||||
CV_EXPORTS void minMaxLoc(const Mat& src, double* maxval, double* minval,
|
||||
vector<int>* maxloc, vector<int>* minloc, const Mat& mask=Mat());
|
||||
CV_EXPORTS double norm(const Mat& src, int normType, const Mat& mask=Mat());
|
||||
CV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType, const Mat& mask=Mat());
|
||||
CV_EXPORTS bool cmpEps(const Mat& src1, const Mat& src2, int maxDiff, vector<int>* loc);
|
||||
CV_EXPORTS void logicOp(const Mat& src1, const Mat& src2, Mat& dst, char c);
|
||||
CV_EXPORTS void logicOp(const Mat& src, const Scalar& s, Mat& dst, char c);
|
||||
CV_EXPORTS void compare(const Mat& src1, const Mat& src2, Mat& dst, int cmpop);
|
||||
CV_EXPORTS void compare(const Mat& src, double s, Mat& dst, int cmpop);
|
||||
CV_EXPORTS void gemm(const Mat& src1, const Mat& src2, double alpha,
|
||||
const Mat& src3, double beta, Mat& dst, int flags);
|
||||
CV_EXPORTS void crosscorr(const Mat& src1, const Mat& src2, Mat& dst, int dtype);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
#include "precomp.hpp"
|
@ -1 +0,0 @@
|
||||
#include "opencv2/gtest/gtestcv.hpp"
|
410
modules/highgui/test/test_drawing.cpp
Normal file
410
modules/highgui/test/test_drawing.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
//#define DRAW_TEST_IMAGE
|
||||
|
||||
class CV_DrawingTest : public CvTest
|
||||
{
|
||||
public:
|
||||
CV_DrawingTest( const char* testName ) : CvTest( testName, "drawing funcs" ) {}
|
||||
protected:
|
||||
void run( int );
|
||||
virtual void draw( Mat& img ) = 0;
|
||||
virtual int checkLineIterator( Mat& img) = 0;
|
||||
};
|
||||
|
||||
void CV_DrawingTest::run( int )
|
||||
{
|
||||
int code = CvTS::OK;
|
||||
Mat testImg, valImg;
|
||||
const string name = "drawing/image.jpg";
|
||||
string path = ts->get_data_path(), filename;
|
||||
filename = path + name;
|
||||
|
||||
draw( testImg );
|
||||
|
||||
#ifdef DRAW_TEST_IMAGE
|
||||
imwrite( filename, testImg );
|
||||
#else
|
||||
valImg = imread( filename );
|
||||
if( valImg.empty() )
|
||||
{
|
||||
ts->printf( CvTS::LOG, "test image can not be read");
|
||||
code = CvTS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
float err = (float)norm( testImg, valImg, CV_RELATIVE_L1 );
|
||||
float Eps = 0.9f;
|
||||
if( err > Eps)
|
||||
{
|
||||
ts->printf( CvTS::LOG, "CV_RELATIVE_L1 between testImg and valImg is equal %f (larger than %f)\n", err, Eps );
|
||||
code = CvTS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = checkLineIterator( testImg );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
class CV_DrawingTest_CPP : public CV_DrawingTest
|
||||
{
|
||||
public:
|
||||
CV_DrawingTest_CPP() : CV_DrawingTest( "drawing_cpp" ) {}
|
||||
protected:
|
||||
virtual void draw( Mat& img );
|
||||
virtual int checkLineIterator( Mat& img);
|
||||
};
|
||||
|
||||
void CV_DrawingTest_CPP::draw( Mat& img )
|
||||
{
|
||||
Size imgSize( 600, 400 );
|
||||
img.create( imgSize, CV_8UC3 );
|
||||
|
||||
vector<Point> polyline(4);
|
||||
polyline[0] = Point(0, 0);
|
||||
polyline[1] = Point(imgSize.width, 0);
|
||||
polyline[2] = Point(imgSize.width, imgSize.height);
|
||||
polyline[3] = Point(0, imgSize.height);
|
||||
const Point* pts = &polyline[0];
|
||||
int n = (int)polyline.size();
|
||||
fillPoly( img, &pts, &n, 1, Scalar::all(255) );
|
||||
|
||||
Point p1(1,1), p2(3,3);
|
||||
if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
|
||||
circle( img, Point(300,100), 40, Scalar(0,0,255), 3 ); // draw
|
||||
|
||||
p2 = Point(3,imgSize.height+1000);
|
||||
if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
|
||||
circle( img, Point(500,300), 50, cvColorToScalar(255,CV_8UC3), 5, 8, 1 ); // draw
|
||||
|
||||
p1 = Point(imgSize.width,1), p2 = Point(imgSize.width,3);
|
||||
if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
|
||||
circle( img, Point(390,100), 10, Scalar(0,0,255), 3 ); // not draw
|
||||
|
||||
p1 = Point(imgSize.width-1,1), p2 = Point(imgSize.width,3);
|
||||
if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
|
||||
ellipse( img, Point(390,100), Size(20,30), 60, 0, 220.0, Scalar(0,200,0), 4 ); //draw
|
||||
|
||||
ellipse( img, RotatedRect(Point(100,200),Size(200,100),160), Scalar(200,200,255), 5 );
|
||||
|
||||
polyline.clear();
|
||||
ellipse2Poly( Point(430,180), Size(100,150), 30, 0, 150, 20, polyline );
|
||||
pts = &polyline[0];
|
||||
n = (int)polyline.size();
|
||||
polylines( img, &pts, &n, 1, false, Scalar(0,0,150), 4, CV_AA );
|
||||
n = 0;
|
||||
for( vector<Point>::const_iterator it = polyline.begin(); n < (int)polyline.size()-1; ++it, n++ )
|
||||
{
|
||||
line( img, *it, *(it+1), Scalar(50,250,100));
|
||||
}
|
||||
|
||||
polyline.clear();
|
||||
ellipse2Poly( Point(500,300), Size(50,80), 0, 0, 180, 10, polyline );
|
||||
pts = &polyline[0];
|
||||
n = (int)polyline.size();
|
||||
polylines( img, &pts, &n, 1, true, Scalar(100,200,100), 20 );
|
||||
fillConvexPoly( img, pts, n, Scalar(0, 80, 0) );
|
||||
|
||||
polyline.resize(8);
|
||||
// external rectengular
|
||||
polyline[0] = Point(0, 0);
|
||||
polyline[1] = Point(80, 0);
|
||||
polyline[2] = Point(80, 80);
|
||||
polyline[3] = Point(0, 80);
|
||||
// internal rectangular
|
||||
polyline[4] = Point(20, 20);
|
||||
polyline[5] = Point(60, 20);
|
||||
polyline[6] = Point(60, 60);
|
||||
polyline[7] = Point(20, 60);
|
||||
const Point* ppts[] = {&polyline[0], &polyline[0]+4};
|
||||
int pn[] = {4, 4};
|
||||
fillPoly( img, ppts, pn, 2, Scalar(100, 100, 0), 8, 0, Point(500, 20) );
|
||||
|
||||
rectangle( img, Point(0, 300), Point(50, 398), Scalar(0,0,255) );
|
||||
|
||||
string text1 = "OpenCV";
|
||||
int baseline = 0, thickness = 3, fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
|
||||
float fontScale = 2;
|
||||
Size textSize = getTextSize( text1, fontFace, fontScale, thickness, &baseline);
|
||||
baseline += thickness;
|
||||
Point textOrg((img.cols - textSize.width)/2, (img.rows + textSize.height)/2);
|
||||
rectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0,0,255));
|
||||
line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255));
|
||||
putText(img, text1, textOrg, fontFace, fontScale, Scalar(150,0,150), thickness, 8);
|
||||
|
||||
string text2 = "abcdefghijklmnopqrstuvwxyz1234567890";
|
||||
Scalar color(200,0,0);
|
||||
fontScale = 0.5, thickness = 1;
|
||||
int dist = 5;
|
||||
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_SIMPLEX, fontScale, thickness, &baseline);
|
||||
textOrg = Point(5,5)+Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_SIMPLEX, fontScale, color, thickness, CV_AA);
|
||||
|
||||
fontScale = 1;
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_PLAIN, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_PLAIN, fontScale, color, thickness, CV_AA);
|
||||
|
||||
fontScale = 0.5;
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_DUPLEX, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_DUPLEX, fontScale, color, thickness, CV_AA);
|
||||
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_COMPLEX, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX, fontScale, color, thickness, CV_AA);
|
||||
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_TRIPLEX, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_TRIPLEX, fontScale, color, thickness, CV_AA);
|
||||
|
||||
fontScale = 1;
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_COMPLEX_SMALL, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,180) + Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX_SMALL, fontScale, color, thickness, CV_AA);
|
||||
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, color, thickness, CV_AA);
|
||||
|
||||
textSize = getTextSize( text2, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, color, thickness, CV_AA);
|
||||
|
||||
dist = 15, fontScale = 0.5;
|
||||
textSize = getTextSize( text2, FONT_ITALIC, fontScale, thickness, &baseline);
|
||||
textOrg += Point(0,textSize.height+dist);
|
||||
putText(img, text2, textOrg, FONT_ITALIC, fontScale, color, thickness, CV_AA);
|
||||
}
|
||||
|
||||
int CV_DrawingTest_CPP::checkLineIterator( Mat& img )
|
||||
{
|
||||
LineIterator it( img, Point(0,300), Point(1000, 300) );
|
||||
for(int i = 0; i < it.count; ++it, i++ )
|
||||
{
|
||||
Vec3b v = (Vec3b)(*(*it)) - img.at<Vec3b>(300,i);
|
||||
float err = (float)norm( v );
|
||||
if( err != 0 )
|
||||
{
|
||||
ts->printf( CvTS::LOG, "LineIterator works incorrect" );
|
||||
return CvTS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
}
|
||||
return CvTS::OK;
|
||||
}
|
||||
|
||||
class CV_DrawingTest_C : public CV_DrawingTest
|
||||
{
|
||||
public:
|
||||
CV_DrawingTest_C() : CV_DrawingTest( "drawing_c" ) {}
|
||||
protected:
|
||||
virtual void draw( Mat& img );
|
||||
virtual int checkLineIterator( Mat& img);
|
||||
};
|
||||
|
||||
void CV_DrawingTest_C::draw( Mat& _img )
|
||||
{
|
||||
CvSize imgSize = cvSize(600, 400);
|
||||
_img.create( imgSize, CV_8UC3 );
|
||||
CvMat img = _img;
|
||||
|
||||
vector<CvPoint> polyline(4);
|
||||
polyline[0] = cvPoint(0, 0);
|
||||
polyline[1] = cvPoint(imgSize.width, 0);
|
||||
polyline[2] = cvPoint(imgSize.width, imgSize.height);
|
||||
polyline[3] = cvPoint(0, imgSize.height);
|
||||
CvPoint* pts = &polyline[0];
|
||||
int n = (int)polyline.size();
|
||||
cvFillPoly( &img, &pts, &n, 1, cvScalar(255,255,255) );
|
||||
|
||||
CvPoint p1 = cvPoint(1,1), p2 = cvPoint(3,3);
|
||||
if( cvClipLine(imgSize, &p1, &p2) )
|
||||
cvCircle( &img, cvPoint(300,100), 40, cvScalar(0,0,255), 3 ); // draw
|
||||
|
||||
p1 = cvPoint(1,1), p2 = cvPoint(3,imgSize.height+1000);
|
||||
if( cvClipLine(imgSize, &p1, &p2) )
|
||||
cvCircle( &img, cvPoint(500,300), 50, cvScalar(255,0,0), 5, 8, 1 ); // draw
|
||||
|
||||
p1 = cvPoint(imgSize.width,1), p2 = cvPoint(imgSize.width,3);
|
||||
if( cvClipLine(imgSize, &p1, &p2) )
|
||||
cvCircle( &img, cvPoint(390,100), 10, cvScalar(0,0,255), 3 ); // not draw
|
||||
|
||||
p1 = Point(imgSize.width-1,1), p2 = Point(imgSize.width,3);
|
||||
if( cvClipLine(imgSize, &p1, &p2) )
|
||||
cvEllipse( &img, cvPoint(390,100), cvSize(20,30), 60, 0, 220.0, cvScalar(0,200,0), 4 ); //draw
|
||||
|
||||
CvBox2D box;
|
||||
box.center.x = 100;
|
||||
box.center.y = 200;
|
||||
box.size.width = 200;
|
||||
box.size.height = 100;
|
||||
box.angle = 160;
|
||||
cvEllipseBox( &img, box, Scalar(200,200,255), 5 );
|
||||
|
||||
polyline.resize(9);
|
||||
pts = &polyline[0];
|
||||
n = (int)polyline.size();
|
||||
assert( cvEllipse2Poly( cvPoint(430,180), cvSize(100,150), 30, 0, 150, &polyline[0], 20 ) == n );
|
||||
cvPolyLine( &img, &pts, &n, 1, false, cvScalar(0,0,150), 4, CV_AA );
|
||||
n = 0;
|
||||
for( vector<CvPoint>::const_iterator it = polyline.begin(); n < (int)polyline.size()-1; ++it, n++ )
|
||||
{
|
||||
cvLine( &img, *it, *(it+1), cvScalar(50,250,100) );
|
||||
}
|
||||
|
||||
polyline.resize(19);
|
||||
pts = &polyline[0];
|
||||
n = (int)polyline.size();
|
||||
assert( cvEllipse2Poly( cvPoint(500,300), cvSize(50,80), 0, 0, 180, &polyline[0], 10 ) == n );
|
||||
cvPolyLine( &img, &pts, &n, 1, true, Scalar(100,200,100), 20 );
|
||||
cvFillConvexPoly( &img, pts, n, cvScalar(0, 80, 0) );
|
||||
|
||||
polyline.resize(8);
|
||||
// external rectengular
|
||||
polyline[0] = cvPoint(500, 20);
|
||||
polyline[1] = cvPoint(580, 20);
|
||||
polyline[2] = cvPoint(580, 100);
|
||||
polyline[3] = cvPoint(500, 100);
|
||||
// internal rectangular
|
||||
polyline[4] = cvPoint(520, 40);
|
||||
polyline[5] = cvPoint(560, 40);
|
||||
polyline[6] = cvPoint(560, 80);
|
||||
polyline[7] = cvPoint(520, 80);
|
||||
CvPoint* ppts[] = {&polyline[0], &polyline[0]+4};
|
||||
int pn[] = {4, 4};
|
||||
cvFillPoly( &img, ppts, pn, 2, cvScalar(100, 100, 0), 8, 0 );
|
||||
|
||||
cvRectangle( &img, cvPoint(0, 300), cvPoint(50, 398), cvScalar(0,0,255) );
|
||||
|
||||
string text1 = "OpenCV";
|
||||
CvFont font;
|
||||
cvInitFont( &font, FONT_HERSHEY_SCRIPT_SIMPLEX, 2, 2, 0, 3 );
|
||||
int baseline = 0;
|
||||
CvSize textSize;
|
||||
cvGetTextSize( text1.c_str(), &font, &textSize, &baseline );
|
||||
baseline += font.thickness;
|
||||
CvPoint textOrg = cvPoint((imgSize.width - textSize.width)/2, (imgSize.height + textSize.height)/2);
|
||||
cvRectangle( &img, cvPoint( textOrg.x, textOrg.y + baseline),
|
||||
cvPoint(textOrg.x + textSize.width, textOrg.y - textSize.height), cvScalar(0,0,255));
|
||||
cvLine( &img, cvPoint(textOrg.x, textOrg.y + font.thickness),
|
||||
cvPoint(textOrg.x + textSize.width, textOrg.y + font.thickness), cvScalar(0, 0, 255));
|
||||
cvPutText( &img, text1.c_str(), textOrg, &font, cvScalar(150,0,150) );
|
||||
|
||||
int dist = 5;
|
||||
string text2 = "abcdefghijklmnopqrstuvwxyz1234567890";
|
||||
CvScalar color = cvScalar(200,0,0);
|
||||
cvInitFont( &font, FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(5, 5+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_PLAIN, 1, 1, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_DUPLEX, 0.5, 0.5, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_COMPLEX, 0.5, 0.5, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_TRIPLEX, 0.5, 0.5, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_COMPLEX_SMALL, 1, 1, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist + 180);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_SCRIPT_SIMPLEX, 1, 1, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
cvInitFont( &font, FONT_HERSHEY_SCRIPT_COMPLEX, 1, 1, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
|
||||
dist = 15;
|
||||
cvInitFont( &font, FONT_ITALIC, 0.5, 0.5, 0, 1, CV_AA );
|
||||
cvGetTextSize( text2.c_str(), &font, &textSize, &baseline );
|
||||
textOrg = cvPoint(textOrg.x,textOrg.y+textSize.height+dist);
|
||||
cvPutText(&img, text2.c_str(), textOrg, &font, color );
|
||||
}
|
||||
|
||||
int CV_DrawingTest_C::checkLineIterator( Mat& _img )
|
||||
{
|
||||
CvLineIterator it;
|
||||
CvMat img = _img;
|
||||
int count = cvInitLineIterator( &img, cvPoint(0,300), cvPoint(1000, 300), &it );
|
||||
for(int i = 0; i < count; i++ )
|
||||
{
|
||||
Vec3b v = (Vec3b)(*(it.ptr)) - _img.at<Vec3b>(300,i);
|
||||
float err = (float)norm( v );
|
||||
if( err != 0 )
|
||||
{
|
||||
ts->printf( CvTS::LOG, "CvLineIterator works incorrect" );
|
||||
return CvTS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
CV_NEXT_LINE_POINT(it);
|
||||
}
|
||||
return CvTS::OK;
|
||||
}
|
||||
|
||||
CV_DrawingTest_CPP drawing_test_cpp;
|
||||
CV_DrawingTest_C drawing_test_c;
|
107
modules/highgui/test/test_gui.cpp
Normal file
107
modules/highgui/test/test_gui.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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 "cvtest.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <iostream>
|
||||
#include "cvaux.h"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
//#if defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64
|
||||
#define MARKERS
|
||||
|
||||
#ifdef MARKERS
|
||||
#define marker(x) cout << (x) << endl
|
||||
#else
|
||||
#define marker(x)
|
||||
#endif
|
||||
|
||||
|
||||
class CV_HighGuiOnlyGuiTest : public CvTest
|
||||
{
|
||||
public:
|
||||
CV_HighGuiOnlyGuiTest();
|
||||
~CV_HighGuiOnlyGuiTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_HighGuiOnlyGuiTest::CV_HighGuiOnlyGuiTest(): CvTest( "z-highgui-gui-only", "?" )
|
||||
{
|
||||
support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
|
||||
}
|
||||
CV_HighGuiOnlyGuiTest::~CV_HighGuiOnlyGuiTest() {}
|
||||
|
||||
void Foo(int /*k*/, void* /*z*/) {}
|
||||
|
||||
void CV_HighGuiOnlyGuiTest::run( int /*start_from */)
|
||||
{
|
||||
cout << "GUI 1" << endl;
|
||||
namedWindow("Win");
|
||||
cout << "GUI 2" << endl;
|
||||
Mat m(30, 30, CV_8U);
|
||||
m = Scalar(128);
|
||||
cout << "GUI 3" << endl;
|
||||
imshow("Win", m);
|
||||
cout << "GUI 4" << endl;
|
||||
int value = 50;
|
||||
cout << "GUI 5" << endl;
|
||||
createTrackbar( "trackbar", "Win", &value, 100, Foo, &value);
|
||||
cout << "GUI 6" << endl;
|
||||
getTrackbarPos( "trackbar", "Win" );
|
||||
cout << "GUI 7" << endl;
|
||||
waitKey(500);
|
||||
cout << "GUI 8" << endl;
|
||||
cvDestroyAllWindows();
|
||||
cout << "GUI 9" << endl;
|
||||
|
||||
ts->set_failed_test_info(CvTS::OK);
|
||||
}
|
||||
|
||||
CV_HighGuiOnlyGuiTest highGuiOnlyGui_test;
|
||||
|
||||
|
2
modules/highgui/test/test_main.cpp
Normal file
2
modules/highgui/test/test_main.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/ts/ts_main.hpp"
|
1
modules/highgui/test/test_precomp.cpp
Normal file
1
modules/highgui/test/test_precomp.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "test_precomp.hpp"
|
9
modules/highgui/test/test_precomp.hpp
Normal file
9
modules/highgui/test/test_precomp.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts/ts.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/core/imgproc_c.h"
|
||||
#include <iostream>
|
||||
|
||||
#endif
|
314
modules/highgui/test/test_video_io.cpp
Normal file
314
modules/highgui/test/test_video_io.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
#if defined WIN32 || defined _WIN32
|
||||
//#if 0
|
||||
|
||||
#else
|
||||
|
||||
#define MARKERS1
|
||||
|
||||
#ifdef MARKERS
|
||||
#define marker(x) cout << (x) << endl
|
||||
#else
|
||||
#define marker(x)
|
||||
#endif
|
||||
|
||||
struct TempDirHolder
|
||||
{
|
||||
string temp_folder;
|
||||
TempDirHolder()
|
||||
{
|
||||
char* p = tmpnam(0);
|
||||
if(p[0] == '\\') p++;
|
||||
temp_folder = string(p);
|
||||
exec_cmd("mkdir " + temp_folder);
|
||||
}
|
||||
~TempDirHolder() { exec_cmd("rm -rf " + temp_folder); }
|
||||
static void exec_cmd(const string& cmd) { marker(cmd); int res = system( cmd.c_str() ); (void)res; }
|
||||
|
||||
TempDirHolder& operator=(const TempDirHolder&);
|
||||
};
|
||||
|
||||
|
||||
class CV_HighGuiTest : public CvTest
|
||||
{
|
||||
public:
|
||||
CV_HighGuiTest();
|
||||
~CV_HighGuiTest();
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
bool ImagesTest(const string& dir, const string& tmp);
|
||||
bool VideoTest(const string& dir, const string& tmp, int fourcc);
|
||||
|
||||
bool GuiTest(const string& dir, const string& tmp);
|
||||
};
|
||||
|
||||
CV_HighGuiTest::CV_HighGuiTest(): CvTest( "z-highgui", "?" )
|
||||
{
|
||||
support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
|
||||
}
|
||||
CV_HighGuiTest::~CV_HighGuiTest() {}
|
||||
|
||||
double PSNR(const Mat& m1, const Mat& m2)
|
||||
{
|
||||
Mat tmp;
|
||||
absdiff( m1.reshape(1), m2.reshape(1), tmp);
|
||||
multiply(tmp, tmp, tmp);
|
||||
|
||||
double MSE = 1.0/(tmp.cols * tmp.rows) * sum(tmp)[0];
|
||||
|
||||
return 20 * log10(255.0 / sqrt(MSE));
|
||||
}
|
||||
|
||||
bool CV_HighGuiTest::ImagesTest(const string& dir, const string& tmp)
|
||||
{
|
||||
int code = CvTS::OK;
|
||||
Mat image = imread(dir + "shared/baboon.jpg");
|
||||
|
||||
if (image.empty())
|
||||
{
|
||||
ts->set_failed_test_info(CvTS::FAIL_MISSING_TEST_DATA);
|
||||
return false;
|
||||
}
|
||||
|
||||
const string exts[] = {"png", "bmp", "tiff", "jpg", "jp2", "ppm", "ras"};
|
||||
const size_t ext_num = sizeof(exts)/sizeof(exts[0]);
|
||||
|
||||
for(size_t i = 0; i < ext_num; ++i)
|
||||
{
|
||||
ts->printf(CvTS::LOG, "ext=%s\n", exts[i].c_str());
|
||||
string ext = exts[i];
|
||||
string full_name = tmp + "/img." + ext;
|
||||
marker(exts[i]);
|
||||
|
||||
imwrite(full_name, image);
|
||||
Mat loaded = imread(full_name);
|
||||
if (loaded.empty())
|
||||
{
|
||||
ts->printf(CvTS::LOG, "Reading failed at fmt=%s\n", ext.c_str());
|
||||
code = CvTS::FAIL_MISMATCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
const double thresDbell = 20;
|
||||
double psnr = PSNR(loaded, image);
|
||||
if (psnr < thresDbell)
|
||||
{
|
||||
ts->printf(CvTS::LOG, "Reading image from file: too big difference (=%g) with fmt=%s\n", psnr, ext.c_str());
|
||||
code = CvTS::FAIL_BAD_ACCURACY;
|
||||
continue;
|
||||
}
|
||||
|
||||
FILE *f = fopen(full_name.c_str(), "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
vector<uchar> from_file(len);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
size_t read = fread(&from_file[0], len, sizeof(vector<uchar>::value_type), f); (void)read;
|
||||
fclose(f);
|
||||
|
||||
|
||||
vector<uchar> buf;
|
||||
imencode("." + exts[i], image, buf);
|
||||
|
||||
if (buf != from_file)
|
||||
{
|
||||
ts->printf(CvTS::LOG, "Encoding failed with fmt=%s\n", ext.c_str());
|
||||
code = CvTS::FAIL_MISMATCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
Mat buf_loaded = imdecode(Mat(buf), 1);
|
||||
if (buf_loaded.empty())
|
||||
{
|
||||
ts->printf(CvTS::LOG, "Decoding failed with fmt=%s\n", ext.c_str());
|
||||
code = CvTS::FAIL_MISMATCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
psnr = PSNR(buf_loaded, image);
|
||||
if (psnr < thresDbell)
|
||||
{
|
||||
ts->printf(CvTS::LOG, "Decoding image from memory: too small PSNR (=%gdb) with fmt=%s\n", psnr, ext.c_str());
|
||||
code = CvTS::FAIL_MISMATCH;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ts->set_failed_test_info(code);
|
||||
return code == CvTS::OK;
|
||||
}
|
||||
|
||||
bool CV_HighGuiTest::VideoTest(const string& dir, const string& tmp, int fourcc)
|
||||
{
|
||||
string src_file = dir + "shared/video_for_test.avi";
|
||||
string tmp_name = tmp + "/video.avi";
|
||||
|
||||
CvCapture* cap = cvCaptureFromFile(src_file.c_str());
|
||||
|
||||
if (!cap)
|
||||
{
|
||||
ts->set_failed_test_info(CvTS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
|
||||
CvVideoWriter* writer = 0;
|
||||
|
||||
int counter = 0;
|
||||
for(;;)
|
||||
{
|
||||
IplImage* img = cvQueryFrame( cap );
|
||||
|
||||
if (!img)
|
||||
break;
|
||||
|
||||
if (writer == 0)
|
||||
{
|
||||
writer = cvCreateVideoWriter(tmp_name.c_str(), fourcc, 24, cvGetSize(img));
|
||||
if (writer == 0)
|
||||
{
|
||||
marker("can't craete writer");
|
||||
cvReleaseCapture( &cap );
|
||||
ts->set_failed_test_info(CvTS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cvWriteFrame(writer, img);
|
||||
}
|
||||
|
||||
|
||||
cvReleaseVideoWriter( &writer );
|
||||
cvReleaseCapture( &cap );
|
||||
|
||||
marker("mid++");
|
||||
|
||||
cap = cvCaptureFromFile(src_file.c_str());
|
||||
marker("mid1");
|
||||
CvCapture *saved = cvCaptureFromFile(tmp_name.c_str());
|
||||
if (!saved)
|
||||
{
|
||||
ts->set_failed_test_info(CvTS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const double thresDbell = 20;
|
||||
|
||||
bool error = false;
|
||||
counter = 0;
|
||||
for(;;)
|
||||
{
|
||||
|
||||
IplImage* ipl = cvQueryFrame( cap );
|
||||
IplImage* ipl1 = cvQueryFrame( saved );
|
||||
|
||||
|
||||
if (!ipl || !ipl1)
|
||||
break;
|
||||
|
||||
Mat img(ipl);
|
||||
Mat img1(ipl1);
|
||||
|
||||
if (PSNR(img1, img) < thresDbell)
|
||||
{
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cvReleaseCapture( &cap );
|
||||
cvReleaseCapture( &saved );
|
||||
|
||||
if (error)
|
||||
{
|
||||
ts->set_failed_test_info(CvTS::FAIL_MISMATCH);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CV_HighGuiTest::run( int /*start_from */)
|
||||
{
|
||||
TempDirHolder th;
|
||||
|
||||
if (!ImagesTest(ts->get_data_path(), th.temp_folder))
|
||||
return;
|
||||
|
||||
#if defined WIN32 || defined __linux__
|
||||
|
||||
#if !defined HAVE_GSTREAMER || defined HAVE_GSTREAMER_APP
|
||||
if (!VideoTest(ts->get_data_path(), th.temp_folder, CV_FOURCC_DEFAULT))
|
||||
return;
|
||||
|
||||
|
||||
if (!VideoTest(ts->get_data_path(), th.temp_folder, CV_FOURCC('M', 'J', 'P', 'G')))
|
||||
return;
|
||||
|
||||
|
||||
if (!VideoTest(ts->get_data_path(), th.temp_folder, CV_FOURCC('M', 'P', 'G', '2')))
|
||||
return;
|
||||
|
||||
#endif
|
||||
//if (!VideoTest(ts->get_data_path(), th.temp_folder, CV_FOURCC('D', 'X', '5', '0'))) return;
|
||||
#endif
|
||||
ts->set_failed_test_info(CvTS::OK);
|
||||
}
|
||||
CV_HighGuiTest HighGui_test;
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -666,6 +666,10 @@ CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int met
|
||||
|
||||
//! normalizes the grayscale image brightness and contrast by normalizing its histogram
|
||||
CV_EXPORTS_W void equalizeHist( const Mat& src, CV_OUT Mat& dst );
|
||||
|
||||
CV_EXPORTS float EMD( const Mat& signature1, const Mat& signature2,
|
||||
int distType, const Mat& cost=Mat(),
|
||||
float* lowerBound=0, Mat* flow=0 );
|
||||
|
||||
//! segments the image using watershed algorithm
|
||||
CV_EXPORTS_W void watershed( const Mat& image, Mat& markers );
|
||||
|
@ -1137,5 +1137,23 @@ icvDistC( const float *x, const float *y, void *user_param )
|
||||
return (float)s;
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
float EMD( const Mat& signature1, const Mat& signature2,
|
||||
int distType, const Mat& cost, float* lowerBound, Mat* flow )
|
||||
{
|
||||
CvMat _signature1 = signature1;
|
||||
CvMat _signature2 = signature2;
|
||||
CvMat _cost = cost, _flow;
|
||||
if( flow )
|
||||
_flow = *flow;
|
||||
|
||||
return cvCalcEMD2( &_signature1, &_signature2, distType, 0, cost.empty() ? 0 : &_cost,
|
||||
flow ? &_flow : 0, lowerBound, 0 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* End of file. */
|
||||
|
@ -3025,8 +3025,8 @@ void sepFilter2D( const Mat& src, Mat& dst, int ddepth,
|
||||
dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
|
||||
|
||||
Ptr<FilterEngine> f = createSeparableLinearFilter(src.type(),
|
||||
dst.type(), kernelX, kernelY, anchor, delta, borderType );
|
||||
f->apply(src, dst);
|
||||
dst.type(), kernelX, kernelY, anchor, delta, borderType & ~BORDER_ISOLATED );
|
||||
f->apply(src, dst, Rect(0,0,-1,-1), Point(), (borderType & BORDER_ISOLATED) != 0 );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,8 +45,6 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
//#undef CV_SSE2
|
||||
|
||||
template<typename T, int shift> struct FixPtCast
|
||||
{
|
||||
typedef int type1;
|
||||
|
@ -380,7 +380,7 @@ void undistortPoints( const Mat& src, Mat& dst,
|
||||
const Mat& cameraMatrix, const Mat& distCoeffs,
|
||||
const Mat& R, const Mat& P )
|
||||
{
|
||||
CV_Assert( src.isContinuous() && src.depth() == CV_32F &&
|
||||
CV_Assert( src.isContinuous() && (src.depth() == CV_32F || src.depth() == CV_64F) &&
|
||||
((src.rows == 1 && src.channels() == 2) || src.cols*src.channels() == 2));
|
||||
|
||||
dst.create(src.size(), src.type());
|
||||
|
359
modules/imgproc/test/test_approxpoly.cpp
Normal file
359
modules/imgproc/test/test_approxpoly.cpp
Normal file
@ -0,0 +1,359 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
#include <limits.h>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// TODO!!!:
|
||||
// check_slice (and/or check) seem(s) to be broken, or this is a bug in function
|
||||
// (or its inability to handle possible self-intersections in the generated contours).
|
||||
//
|
||||
// At least, if // return TotalErrors;
|
||||
// is uncommented in check_slice, the test fails easily.
|
||||
// So, now (and it looks like since 0.9.6)
|
||||
// we only check that the set of vertices of the approximated polygon is
|
||||
// a subset of vertices of the original contour.
|
||||
//
|
||||
|
||||
class CV_ApproxPolyTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_ApproxPolyTest();
|
||||
~CV_ApproxPolyTest();
|
||||
void clear();
|
||||
//int write_default_params(CvFileStorage* fs);
|
||||
|
||||
protected:
|
||||
//int read_params( CvFileStorage* fs );
|
||||
|
||||
int check_slice( CvPoint StartPt, CvPoint EndPt,
|
||||
CvSeqReader* SrcReader, float Eps,
|
||||
int* j, int Count );
|
||||
int check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps );
|
||||
|
||||
bool get_contour( int /*type*/, CvSeq** Seq, int* d,
|
||||
CvMemStorage* storage );
|
||||
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
CV_ApproxPolyTest::CV_ApproxPolyTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CV_ApproxPolyTest::~CV_ApproxPolyTest()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void CV_ApproxPolyTest::clear()
|
||||
{
|
||||
cvtest::BaseTest::clear();
|
||||
}
|
||||
|
||||
|
||||
/*int CV_ApproxPolyTest::write_default_params( CvFileStorage* fs )
|
||||
{
|
||||
cvtest::BaseTest::write_default_params( fs );
|
||||
if( ts->get_testing_mode() != cvtest::TS::TIMING_MODE )
|
||||
{
|
||||
write_param( fs, "test_case_count", test_case_count );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CV_ApproxPolyTest::read_params( CvFileStorage* fs )
|
||||
{
|
||||
int code = cvtest::BaseTest::read_params( fs );
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );
|
||||
min_log_size = cvtest::clipInt( min_log_size, 1, 10 );
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
|
||||
bool CV_ApproxPolyTest::get_contour( int /*type*/, CvSeq** Seq, int* d,
|
||||
CvMemStorage* storage )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int max_x = INT_MIN, max_y = INT_MIN, min_x = INT_MAX, min_y = INT_MAX;
|
||||
int i;
|
||||
CvSeq* seq;
|
||||
int total = cvtest::randInt(rng) % 1000 + 1;
|
||||
CvPoint center;
|
||||
int radius, angle;
|
||||
double deg_to_rad = CV_PI/180.;
|
||||
CvPoint pt;
|
||||
|
||||
center.x = cvtest::randInt( rng ) % 1000;
|
||||
center.y = cvtest::randInt( rng ) % 1000;
|
||||
radius = cvtest::randInt( rng ) % 1000;
|
||||
angle = cvtest::randInt( rng ) % 360;
|
||||
|
||||
seq = cvCreateSeq( CV_SEQ_POLYGON, sizeof(CvContour), sizeof(CvPoint), storage );
|
||||
|
||||
for( i = 0; i < total; i++ )
|
||||
{
|
||||
int d_radius = cvtest::randInt( rng ) % 10 - 5;
|
||||
int d_angle = 360/total;//cvtest::randInt( rng ) % 10 - 5;
|
||||
pt.x = cvRound( center.x + radius*cos(angle*deg_to_rad));
|
||||
pt.y = cvRound( center.x - radius*sin(angle*deg_to_rad));
|
||||
radius += d_radius;
|
||||
angle += d_angle;
|
||||
cvSeqPush( seq, &pt );
|
||||
|
||||
max_x = MAX( max_x, pt.x );
|
||||
max_y = MAX( max_y, pt.y );
|
||||
|
||||
min_x = MIN( min_x, pt.x );
|
||||
min_y = MIN( min_y, pt.y );
|
||||
}
|
||||
|
||||
*d = (max_x - min_x)*(max_x - min_x) + (max_y - min_y)*(max_y - min_y);
|
||||
*Seq = seq;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int CV_ApproxPolyTest::check_slice( CvPoint StartPt, CvPoint EndPt,
|
||||
CvSeqReader* SrcReader, float Eps,
|
||||
int* _j, int Count )
|
||||
{
|
||||
///////////
|
||||
CvPoint Pt;
|
||||
///////////
|
||||
bool flag;
|
||||
double dy,dx;
|
||||
double A,B,C;
|
||||
double Sq;
|
||||
double sin_a = 0;
|
||||
double cos_a = 0;
|
||||
double d = 0;
|
||||
double dist;
|
||||
///////////
|
||||
int j, TotalErrors = 0;
|
||||
|
||||
////////////////////////////////
|
||||
if( SrcReader == NULL )
|
||||
{
|
||||
assert( false );
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////// init line ////////////
|
||||
flag = true;
|
||||
|
||||
dx = (double)StartPt.x - (double)EndPt.x;
|
||||
dy = (double)StartPt.y - (double)EndPt.y;
|
||||
|
||||
if( ( dx == 0 ) && ( dy == 0 ) ) flag = false;
|
||||
else
|
||||
{
|
||||
A = -dy;
|
||||
B = dx;
|
||||
C = dy * (double)StartPt.x - dx * (double)StartPt.y;
|
||||
Sq = sqrt( A*A + B*B );
|
||||
|
||||
sin_a = B/Sq;
|
||||
cos_a = A/Sq;
|
||||
d = C/Sq;
|
||||
}
|
||||
|
||||
/////// find start point and check distance ////////
|
||||
for( j = *_j; j < Count; j++ )
|
||||
{
|
||||
CV_READ_SEQ_ELEM( Pt, *SrcReader );
|
||||
if( StartPt.x == Pt.x && StartPt.y == Pt.y ) break;
|
||||
else
|
||||
{
|
||||
if( flag ) dist = sin_a * Pt.y + cos_a * Pt.x - d;
|
||||
else dist = sqrt( (double)(EndPt.y - Pt.y)*(EndPt.y - Pt.y) + (EndPt.x - Pt.x)*(EndPt.x - Pt.x) );
|
||||
if( dist > Eps ) TotalErrors++;
|
||||
}
|
||||
}
|
||||
|
||||
*_j = j;
|
||||
|
||||
//return TotalErrors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CV_ApproxPolyTest::check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps )
|
||||
{
|
||||
//////////
|
||||
CvSeqReader DstReader;
|
||||
CvSeqReader SrcReader;
|
||||
CvPoint StartPt, EndPt;
|
||||
///////////
|
||||
int TotalErrors = 0;
|
||||
///////////
|
||||
int Count;
|
||||
int i,j;
|
||||
|
||||
assert( SrcSeq && DstSeq );
|
||||
|
||||
////////// init ////////////////////
|
||||
Count = SrcSeq->total;
|
||||
|
||||
cvStartReadSeq( DstSeq, &DstReader, 0 );
|
||||
cvStartReadSeq( SrcSeq, &SrcReader, 0 );
|
||||
|
||||
CV_READ_SEQ_ELEM( StartPt, DstReader );
|
||||
for( i = 0 ; i < Count ; )
|
||||
{
|
||||
CV_READ_SEQ_ELEM( EndPt, SrcReader );
|
||||
i++;
|
||||
if( StartPt.x == EndPt.x && StartPt.y == EndPt.y ) break;
|
||||
}
|
||||
|
||||
///////// start ////////////////
|
||||
for( i = 1, j = 0 ; i <= DstSeq->total ; )
|
||||
{
|
||||
///////// read slice ////////////
|
||||
EndPt.x = StartPt.x;
|
||||
EndPt.y = StartPt.y;
|
||||
CV_READ_SEQ_ELEM( StartPt, DstReader );
|
||||
i++;
|
||||
|
||||
TotalErrors += check_slice( StartPt, EndPt, &SrcReader, Eps, &j, Count );
|
||||
|
||||
if( j > Count )
|
||||
{
|
||||
TotalErrors++;
|
||||
return TotalErrors;
|
||||
} //if( !flag )
|
||||
|
||||
} // for( int i = 0 ; i < DstSeq->total ; i++ )
|
||||
|
||||
return TotalErrors;
|
||||
}
|
||||
|
||||
|
||||
//extern CvTestContourGenerator cvTsTestContours[];
|
||||
|
||||
void CV_ApproxPolyTest::run( int /*start_from*/ )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
CvMemStorage* storage = 0;
|
||||
////////////// Variables ////////////////
|
||||
int IntervalsCount = 10;
|
||||
///////////
|
||||
//CvTestContourGenerator Cont;
|
||||
CvSeq* SrcSeq = NULL;
|
||||
CvSeq* DstSeq;
|
||||
int iDiam;
|
||||
float dDiam, Eps, EpsStep;
|
||||
|
||||
for( int i = 0; i < 30; i++ )
|
||||
{
|
||||
CvMemStoragePos pos;
|
||||
|
||||
ts->update_context( this, i, false );
|
||||
|
||||
///////////////////// init contour /////////
|
||||
dDiam = 0;
|
||||
while( sqrt(dDiam) / IntervalsCount == 0 )
|
||||
{
|
||||
if( storage != 0 )
|
||||
cvReleaseMemStorage(&storage);
|
||||
|
||||
storage = cvCreateMemStorage( 0 );
|
||||
if( get_contour( 0, &SrcSeq, &iDiam, storage ) )
|
||||
dDiam = (float)iDiam;
|
||||
}
|
||||
dDiam = (float)sqrt( dDiam );
|
||||
|
||||
storage = SrcSeq->storage;
|
||||
|
||||
////////////////// test /////////////
|
||||
EpsStep = dDiam / IntervalsCount ;
|
||||
for( Eps = EpsStep ; Eps < dDiam ; Eps += EpsStep )
|
||||
{
|
||||
cvSaveMemStoragePos( storage, &pos );
|
||||
|
||||
////////// call function ////////////
|
||||
DstSeq = cvApproxPoly( SrcSeq, SrcSeq->header_size, storage,
|
||||
CV_POLY_APPROX_DP, Eps );
|
||||
|
||||
if( DstSeq == NULL )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"cvApproxPoly returned NULL for contour #%d, espilon = %g\n", i, Eps );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
} // if( DstSeq == NULL )
|
||||
|
||||
code = check( SrcSeq, DstSeq, Eps );
|
||||
if( code != 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"Incorrect result for the contour #%d approximated with epsilon=%g\n", i, Eps );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
cvRestoreMemStoragePos( storage, &pos );
|
||||
} // for( Eps = EpsStep ; Eps <= Diam ; Eps += EpsStep )
|
||||
|
||||
///////////// free memory ///////////////////
|
||||
cvReleaseMemStorage(&storage);
|
||||
} // for( int i = 0; NULL != ( Cont = Contours[i] ) ; i++ )
|
||||
|
||||
_exit_:
|
||||
cvReleaseMemStorage(&storage);
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(Imgproc_ApproxPoly, accuracy) { CV_ApproxPolyTest test; test.safe_run(); }
|
||||
|
287
modules/imgproc/test/test_canny.cpp
Normal file
287
modules/imgproc/test/test_canny.cpp
Normal file
@ -0,0 +1,287 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_CannyTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_CannyTest();
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
int prepare_test_case( int test_case_idx );
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
int validate_test_results( int /*test_case_idx*/ );
|
||||
|
||||
int aperture_size;
|
||||
bool use_true_gradient;
|
||||
double threshold1, threshold2;
|
||||
bool test_cpp;
|
||||
};
|
||||
|
||||
|
||||
CV_CannyTest::CV_CannyTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
element_wise_relative_error = true;
|
||||
aperture_size = 0;
|
||||
use_true_gradient = false;
|
||||
threshold1 = threshold2 = 0;
|
||||
|
||||
test_cpp = false;
|
||||
}
|
||||
|
||||
|
||||
void CV_CannyTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes,
|
||||
vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
double thresh_range;
|
||||
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_8U;
|
||||
|
||||
aperture_size = cvtest::randInt(rng) % 2 ? 5 : 3;
|
||||
thresh_range = aperture_size == 3 ? 300 : 1000;
|
||||
|
||||
threshold1 = cvtest::randReal(rng)*thresh_range;
|
||||
threshold2 = cvtest::randReal(rng)*thresh_range*0.3;
|
||||
|
||||
if( cvtest::randInt(rng) % 2 )
|
||||
CV_SWAP( threshold1, threshold2, thresh_range );
|
||||
|
||||
use_true_gradient = cvtest::randInt(rng) % 2 != 0;
|
||||
test_cpp = (cvtest::randInt(rng) & 256) == 0;
|
||||
}
|
||||
|
||||
|
||||
int CV_CannyTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
if( code > 0 )
|
||||
{
|
||||
Mat& src = test_mat[INPUT][0];
|
||||
GaussianBlur(src, src, Size(11, 11), 5, 5);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
double CV_CannyTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CV_CannyTest::run_func()
|
||||
{
|
||||
if(!test_cpp)
|
||||
cvCanny( test_array[INPUT][0], test_array[OUTPUT][0], threshold1, threshold2,
|
||||
aperture_size + (use_true_gradient ? CV_CANNY_L2_GRADIENT : 0));
|
||||
else
|
||||
{
|
||||
cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]);
|
||||
cv::Canny(cv::cvarrToMat(test_array[INPUT][0]), _out, threshold1, threshold2,
|
||||
aperture_size + (use_true_gradient ? CV_CANNY_L2_GRADIENT : 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cannyFollow( int x, int y, float lowThreshold, const Mat& mag, Mat& dst )
|
||||
{
|
||||
static const int ofs[][2] = {{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1}};
|
||||
int i;
|
||||
|
||||
dst.at<uchar>(y, x) = (uchar)255;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
int x1 = x + ofs[i][0];
|
||||
int y1 = y + ofs[i][1];
|
||||
if( (unsigned)x1 < (unsigned)mag.cols &&
|
||||
(unsigned)y1 < (unsigned)mag.rows &&
|
||||
mag.at<float>(y1, x1) > lowThreshold &&
|
||||
!dst.at<uchar>(y1, x1) )
|
||||
cannyFollow( x1, y1, lowThreshold, mag, dst );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_Canny( const Mat& src, Mat& dst,
|
||||
double threshold1, double threshold2,
|
||||
int aperture_size, bool use_true_gradient )
|
||||
{
|
||||
int m = aperture_size;
|
||||
Point anchor(m/2, m/2);
|
||||
const double tan_pi_8 = tan(CV_PI/8.);
|
||||
const double tan_3pi_8 = tan(CV_PI*3/8);
|
||||
float lowThreshold = (float)MIN(threshold1, threshold2);
|
||||
float highThreshold = (float)MAX(threshold1, threshold2);
|
||||
|
||||
int x, y, width = src.cols, height = src.rows;
|
||||
|
||||
Mat dxkernel = cvtest::calcSobelKernel2D( 1, 0, m, 0 );
|
||||
Mat dykernel = cvtest::calcSobelKernel2D( 0, 1, m, 0 );
|
||||
Mat dx, dy, mag(height, width, CV_32F);
|
||||
cvtest::filter2D(src, dx, CV_16S, dxkernel, anchor, 0, BORDER_REPLICATE);
|
||||
cvtest::filter2D(src, dy, CV_16S, dykernel, anchor, 0, BORDER_REPLICATE);
|
||||
|
||||
// calc gradient magnitude
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < width; x++ )
|
||||
{
|
||||
int dxval = dx.at<short>(y, x), dyval = dy.at<short>(y, x);
|
||||
mag.at<float>(y, x) = use_true_gradient ?
|
||||
(float)sqrt((double)(dxval*dxval + dyval*dyval)) :
|
||||
(float)(fabs(dxval) + fabs(dyval));
|
||||
}
|
||||
}
|
||||
|
||||
// calc gradient direction, do nonmaxima suppression
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < width; x++ )
|
||||
{
|
||||
|
||||
float a = mag.at<float>(y, x), b = 0, c = 0;
|
||||
int y1 = 0, y2 = 0, x1 = 0, x2 = 0;
|
||||
|
||||
if( a <= lowThreshold )
|
||||
continue;
|
||||
|
||||
int dxval = dx.at<short>(y, x);
|
||||
int dyval = dy.at<short>(y, x);
|
||||
|
||||
double tg = dxval ? (double)dyval/dxval : DBL_MAX*CV_SIGN(dyval);
|
||||
|
||||
if( fabs(tg) < tan_pi_8 )
|
||||
{
|
||||
y1 = y2 = y; x1 = x + 1; x2 = x - 1;
|
||||
}
|
||||
else if( tan_pi_8 <= tg && tg <= tan_3pi_8 )
|
||||
{
|
||||
y1 = y + 1; y2 = y - 1; x1 = x + 1; x2 = x - 1;
|
||||
}
|
||||
else if( -tan_3pi_8 <= tg && tg <= -tan_pi_8 )
|
||||
{
|
||||
y1 = y - 1; y2 = y + 1; x1 = x + 1; x2 = x - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( fabs(tg) > tan_3pi_8 );
|
||||
x1 = x2 = x; y1 = y + 1; y2 = y - 1;
|
||||
}
|
||||
|
||||
if( (unsigned)y1 < (unsigned)height && (unsigned)x1 < (unsigned)width )
|
||||
b = (float)fabs(mag.at<float>(y1, x1));
|
||||
|
||||
if( (unsigned)y2 < (unsigned)height && (unsigned)x2 < (unsigned)width )
|
||||
c = (float)fabs(mag.at<float>(y2, x2));
|
||||
|
||||
if( (a > b || (a == b && ((x1 == x+1 && y1 == y) || (x1 == x && y1 == y+1)))) && a > c )
|
||||
;
|
||||
else
|
||||
mag.at<float>(y, x) = -a;
|
||||
}
|
||||
}
|
||||
|
||||
dst = Scalar::all(0);
|
||||
|
||||
// hysteresis threshold
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
for( x = 0; x < width; x++ )
|
||||
if( mag.at<float>(y, x) > highThreshold && !dst.at<uchar>(y, x) )
|
||||
cannyFollow( x, y, lowThreshold, mag, dst );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_CannyTest::prepare_to_validation( int )
|
||||
{
|
||||
Mat src = test_mat[INPUT][0], dst = test_mat[REF_OUTPUT][0];
|
||||
test_Canny( src, dst, threshold1, threshold2, aperture_size, use_true_gradient );
|
||||
}
|
||||
|
||||
|
||||
int CV_CannyTest::validate_test_results( int test_case_idx )
|
||||
{
|
||||
int code = cvtest::TS::OK, nz0;
|
||||
prepare_to_validation(test_case_idx);
|
||||
|
||||
double err = cvtest::norm(test_mat[OUTPUT][0], test_mat[REF_OUTPUT][0], CV_L1);
|
||||
if( err == 0 )
|
||||
return code;
|
||||
|
||||
if( err != cvRound(err) || cvRound(err)%255 != 0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Some of the pixels, produced by Canny, are not 0's or 255's; the difference is %g\n", err );
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
|
||||
return code;
|
||||
}
|
||||
|
||||
nz0 = cvRound(cvtest::norm(test_mat[REF_OUTPUT][0], CV_L1)/255);
|
||||
err = (err/255/MAX(nz0,100))*100;
|
||||
if( err > 1 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Too high percentage of non-matching edge pixels = %g%%\n", err);
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
TEST(Imgproc_Canny, accuracy) { CV_CannyTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
1645
modules/imgproc/test/test_color.cpp
Normal file
1645
modules/imgproc/test/test_color.cpp
Normal file
File diff suppressed because it is too large
Load Diff
393
modules/imgproc/test/test_contours.cpp
Normal file
393
modules/imgproc/test/test_contours.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_FindContourTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
enum { NUM_IMG = 4 };
|
||||
|
||||
CV_FindContourTest();
|
||||
~CV_FindContourTest();
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
int read_params( CvFileStorage* fs );
|
||||
int prepare_test_case( int test_case_idx );
|
||||
int validate_test_results( int test_case_idx );
|
||||
void run_func();
|
||||
|
||||
int min_blob_size, max_blob_size;
|
||||
int blob_count, max_log_blob_count;
|
||||
int retr_mode, approx_method;
|
||||
|
||||
int min_log_img_size, max_log_img_size;
|
||||
CvSize img_size;
|
||||
int count, count2;
|
||||
|
||||
IplImage* img[NUM_IMG];
|
||||
CvMemStorage* storage;
|
||||
CvSeq *contours, *contours2, *chain;
|
||||
};
|
||||
|
||||
|
||||
CV_FindContourTest::CV_FindContourTest()
|
||||
{
|
||||
int i;
|
||||
|
||||
test_case_count = 300;
|
||||
min_blob_size = 1;
|
||||
max_blob_size = 50;
|
||||
max_log_blob_count = 10;
|
||||
|
||||
min_log_img_size = 3;
|
||||
max_log_img_size = 10;
|
||||
|
||||
for( i = 0; i < NUM_IMG; i++ )
|
||||
img[i] = 0;
|
||||
|
||||
storage = 0;
|
||||
}
|
||||
|
||||
|
||||
CV_FindContourTest::~CV_FindContourTest()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void CV_FindContourTest::clear()
|
||||
{
|
||||
int i;
|
||||
|
||||
cvtest::BaseTest::clear();
|
||||
|
||||
for( i = 0; i < NUM_IMG; i++ )
|
||||
cvReleaseImage( &img[i] );
|
||||
|
||||
cvReleaseMemStorage( &storage );
|
||||
}
|
||||
|
||||
|
||||
int CV_FindContourTest::read_params( CvFileStorage* fs )
|
||||
{
|
||||
int t;
|
||||
int code = cvtest::BaseTest::read_params( fs );
|
||||
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
min_blob_size = cvReadInt( find_param( fs, "min_blob_size" ), min_blob_size );
|
||||
max_blob_size = cvReadInt( find_param( fs, "max_blob_size" ), max_blob_size );
|
||||
max_log_blob_count = cvReadInt( find_param( fs, "max_log_blob_count" ), max_log_blob_count );
|
||||
min_log_img_size = cvReadInt( find_param( fs, "min_log_img_size" ), min_log_img_size );
|
||||
max_log_img_size = cvReadInt( find_param( fs, "max_log_img_size" ), max_log_img_size );
|
||||
|
||||
min_blob_size = cvtest::clipInt( min_blob_size, 1, 100 );
|
||||
max_blob_size = cvtest::clipInt( max_blob_size, 1, 100 );
|
||||
|
||||
if( min_blob_size > max_blob_size )
|
||||
CV_SWAP( min_blob_size, max_blob_size, t );
|
||||
|
||||
max_log_blob_count = cvtest::clipInt( max_log_blob_count, 1, 10 );
|
||||
|
||||
min_log_img_size = cvtest::clipInt( min_log_img_size, 1, 10 );
|
||||
max_log_img_size = cvtest::clipInt( max_log_img_size, 1, 10 );
|
||||
|
||||
if( min_log_img_size > max_log_img_size )
|
||||
CV_SWAP( min_log_img_size, max_log_img_size, t );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cvTsGenerateBlobImage( IplImage* img, int min_blob_size, int max_blob_size,
|
||||
int blob_count, int min_brightness, int max_brightness,
|
||||
RNG& rng )
|
||||
{
|
||||
int i;
|
||||
CvSize size;
|
||||
|
||||
assert( img->depth == IPL_DEPTH_8U && img->nChannels == 1 );
|
||||
|
||||
cvZero( img );
|
||||
|
||||
// keep the border clear
|
||||
cvSetImageROI( img, cvRect(1,1,img->width-2,img->height-2) );
|
||||
size = cvGetSize( img );
|
||||
|
||||
for( i = 0; i < blob_count; i++ )
|
||||
{
|
||||
CvPoint center;
|
||||
CvSize axes;
|
||||
int angle = cvtest::randInt(rng) % 180;
|
||||
int brightness = cvtest::randInt(rng) %
|
||||
(max_brightness - min_brightness) + min_brightness;
|
||||
center.x = cvtest::randInt(rng) % size.width;
|
||||
center.y = cvtest::randInt(rng) % size.height;
|
||||
|
||||
axes.width = (cvtest::randInt(rng) %
|
||||
(max_blob_size - min_blob_size) + min_blob_size + 1)/2;
|
||||
axes.height = (cvtest::randInt(rng) %
|
||||
(max_blob_size - min_blob_size) + min_blob_size + 1)/2;
|
||||
|
||||
cvEllipse( img, center, axes, angle, 0, 360, cvScalar(brightness), CV_FILLED );
|
||||
}
|
||||
|
||||
cvResetImageROI( img );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cvTsMarkContours( IplImage* img, int val )
|
||||
{
|
||||
int i, j;
|
||||
int step = img->widthStep;
|
||||
|
||||
assert( img->depth == IPL_DEPTH_8U && img->nChannels == 1 && (val&1) != 0);
|
||||
|
||||
for( i = 1; i < img->height - 1; i++ )
|
||||
for( j = 1; j < img->width - 1; j++ )
|
||||
{
|
||||
uchar* t = (uchar*)(img->imageData + img->widthStep*i + j);
|
||||
if( *t == 1 && (t[-step] == 0 || t[-1] == 0 || t[1] == 0 || t[step] == 0))
|
||||
*t = (uchar)val;
|
||||
}
|
||||
|
||||
cvThreshold( img, img, val - 2, val, CV_THRESH_BINARY );
|
||||
}
|
||||
|
||||
|
||||
int CV_FindContourTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
const int min_brightness = 0, max_brightness = 2;
|
||||
int i, code = cvtest::BaseTest::prepare_test_case( test_case_idx );
|
||||
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
clear();
|
||||
|
||||
blob_count = cvRound(exp(cvtest::randReal(rng)*max_log_blob_count*CV_LOG2));
|
||||
|
||||
img_size.width = cvRound(exp((cvtest::randReal(rng)*
|
||||
(max_log_img_size - min_log_img_size) + min_log_img_size)*CV_LOG2));
|
||||
img_size.height = cvRound(exp((cvtest::randReal(rng)*
|
||||
(max_log_img_size - min_log_img_size) + min_log_img_size)*CV_LOG2));
|
||||
|
||||
approx_method = cvtest::randInt( rng ) % 4 + 1;
|
||||
retr_mode = cvtest::randInt( rng ) % 4;
|
||||
|
||||
storage = cvCreateMemStorage( 1 << 10 );
|
||||
|
||||
for( i = 0; i < NUM_IMG; i++ )
|
||||
img[i] = cvCreateImage( img_size, 8, 1 );
|
||||
|
||||
cvTsGenerateBlobImage( img[0], min_blob_size, max_blob_size,
|
||||
blob_count, min_brightness, max_brightness, rng );
|
||||
|
||||
cvCopy( img[0], img[1] );
|
||||
cvCopy( img[0], img[2] );
|
||||
|
||||
cvTsMarkContours( img[1], 255 );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CV_FindContourTest::run_func()
|
||||
{
|
||||
contours = contours2 = chain = 0;
|
||||
count = cvFindContours( img[2], storage, &contours, sizeof(CvContour), retr_mode, approx_method );
|
||||
|
||||
cvZero( img[3] );
|
||||
|
||||
if( contours && retr_mode != CV_RETR_EXTERNAL && approx_method < CV_CHAIN_APPROX_TC89_L1 )
|
||||
cvDrawContours( img[3], contours, cvScalar(255), cvScalar(255), INT_MAX, -1 );
|
||||
|
||||
cvCopy( img[0], img[2] );
|
||||
|
||||
count2 = cvFindContours( img[2], storage, &chain, sizeof(CvChain), retr_mode, CV_CHAIN_CODE );
|
||||
|
||||
if( chain )
|
||||
contours2 = cvApproxChains( chain, storage, approx_method, 0, 0, 1 );
|
||||
|
||||
cvZero( img[2] );
|
||||
|
||||
if( contours && retr_mode != CV_RETR_EXTERNAL && approx_method < CV_CHAIN_APPROX_TC89_L1 )
|
||||
cvDrawContours( img[2], contours2, cvScalar(255), cvScalar(255), INT_MAX );
|
||||
}
|
||||
|
||||
|
||||
// the whole testing is done here, run_func() is not utilized in this test
|
||||
int CV_FindContourTest::validate_test_results( int /*test_case_idx*/ )
|
||||
{
|
||||
int i, code = cvtest::TS::OK;
|
||||
|
||||
cvCmpS( img[0], 0, img[0], CV_CMP_GT );
|
||||
|
||||
if( count != count2 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "The number of contours retrieved with different "
|
||||
"approximation methods is not the same\n"
|
||||
"(%d contour(s) for method %d vs %d contour(s) for method %d)\n",
|
||||
count, approx_method, count2, CV_CHAIN_CODE );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
|
||||
if( retr_mode != CV_RETR_EXTERNAL && approx_method < CV_CHAIN_APPROX_TC89_L1 )
|
||||
{
|
||||
Mat _img[4];
|
||||
for( int i = 0; i < 4; i++ )
|
||||
_img[i] = cvarrToMat(img[i]);
|
||||
|
||||
code = cvtest::cmpEps2(ts, _img[0], _img[3], 0, true, "Comparing original image with the map of filled contours" );
|
||||
|
||||
if( code < 0 )
|
||||
goto _exit_;
|
||||
|
||||
code = cvtest::cmpEps2( ts, _img[1], _img[2], 0, true,
|
||||
"Comparing contour outline vs manually produced edge map" );
|
||||
|
||||
if( code < 0 )
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
if( contours )
|
||||
{
|
||||
CvTreeNodeIterator iterator1;
|
||||
CvTreeNodeIterator iterator2;
|
||||
int count3;
|
||||
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
CvTreeNodeIterator iterator;
|
||||
cvInitTreeNodeIterator( &iterator, i == 0 ? contours : contours2, INT_MAX );
|
||||
|
||||
for( count3 = 0; cvNextTreeNode( &iterator ) != 0; count3++ )
|
||||
;
|
||||
|
||||
if( count3 != count )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"The returned number of retrieved contours (using the approx_method = %d) does not match\n"
|
||||
"to the actual number of contours in the tree/list (returned %d, actual %d)\n",
|
||||
i == 0 ? approx_method : 0, count, count3 );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
}
|
||||
|
||||
cvInitTreeNodeIterator( &iterator1, contours, INT_MAX );
|
||||
cvInitTreeNodeIterator( &iterator2, contours2, INT_MAX );
|
||||
|
||||
for( count3 = 0; count3 < count; count3++ )
|
||||
{
|
||||
CvSeq* seq1 = (CvSeq*)cvNextTreeNode( &iterator1 );
|
||||
CvSeq* seq2 = (CvSeq*)cvNextTreeNode( &iterator2 );
|
||||
CvSeqReader reader1;
|
||||
CvSeqReader reader2;
|
||||
|
||||
if( !seq1 || !seq2 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"There are NULL pointers in the original contour tree or the "
|
||||
"tree produced by cvApproxChains\n" );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
cvStartReadSeq( seq1, &reader1 );
|
||||
cvStartReadSeq( seq2, &reader2 );
|
||||
|
||||
if( seq1->total != seq2->total )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"The original contour #%d has %d points, while the corresponding contour has %d point\n",
|
||||
count3, seq1->total, seq2->total );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
for( i = 0; i < seq1->total; i++ )
|
||||
{
|
||||
CvPoint pt1;
|
||||
CvPoint pt2;
|
||||
|
||||
CV_READ_SEQ_ELEM( pt1, reader1 );
|
||||
CV_READ_SEQ_ELEM( pt2, reader2 );
|
||||
|
||||
if( pt1.x != pt2.x || pt1.y != pt2.y )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"The point #%d in the contour #%d is different from the corresponding point "
|
||||
"in the approximated chain ((%d,%d) vs (%d,%d)", count3, i, pt1.x, pt1.y, pt2.x, pt2.y );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_exit_:
|
||||
if( code < 0 )
|
||||
{
|
||||
#if 0
|
||||
cvNamedWindow( "test", 0 );
|
||||
cvShowImage( "test", img[0] );
|
||||
cvWaitKey();
|
||||
#endif
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_FindContours, accuracy) { CV_FindContourTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
1583
modules/imgproc/test/test_convhull.cpp
Normal file
1583
modules/imgproc/test/test_convhull.cpp
Normal file
File diff suppressed because it is too large
Load Diff
297
modules/imgproc/test/test_distancetransform.cpp
Normal file
297
modules/imgproc/test/test_distancetransform.cpp
Normal file
@ -0,0 +1,297 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_DisTransTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_DisTransTest();
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
|
||||
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
|
||||
int prepare_test_case( int test_case_idx );
|
||||
|
||||
int mask_size;
|
||||
int dist_type;
|
||||
int fill_labels;
|
||||
float mask[3];
|
||||
};
|
||||
|
||||
|
||||
CV_DisTransTest::CV_DisTransTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
optional_mask = false;
|
||||
element_wise_relative_error = true;
|
||||
}
|
||||
|
||||
|
||||
void CV_DisTransTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
|
||||
types[INPUT][0] = CV_8UC1;
|
||||
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1;
|
||||
types[OUTPUT][1] = types[REF_OUTPUT][1] = CV_32SC1;
|
||||
|
||||
if( cvtest::randInt(rng) & 1 )
|
||||
{
|
||||
mask_size = 3;
|
||||
dist_type = cvtest::randInt(rng) % 4;
|
||||
dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 :
|
||||
dist_type == 2 ? CV_DIST_L2 : CV_DIST_USER;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask_size = 5;
|
||||
dist_type = cvtest::randInt(rng) % 10;
|
||||
dist_type = dist_type == 0 ? CV_DIST_C : dist_type == 1 ? CV_DIST_L1 :
|
||||
dist_type < 6 ? CV_DIST_L2 : CV_DIST_USER;
|
||||
}
|
||||
|
||||
// for now, check only the "labeled" distance transform mode
|
||||
fill_labels = 0;
|
||||
|
||||
if( !fill_labels )
|
||||
sizes[OUTPUT][1] = sizes[REF_OUTPUT][1] = cvSize(0,0);
|
||||
|
||||
if( dist_type == CV_DIST_USER )
|
||||
{
|
||||
mask[0] = (float)(1.1 - cvtest::randReal(rng)*0.2);
|
||||
mask[1] = (float)(1.9 - cvtest::randReal(rng)*0.8);
|
||||
mask[2] = (float)(3. - cvtest::randReal(rng));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double CV_DisTransTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
Size sz = test_mat[INPUT][0].size();
|
||||
return dist_type == CV_DIST_C || dist_type == CV_DIST_L1 ? 0 : 0.01*MAX(sz.width, sz.height);
|
||||
}
|
||||
|
||||
|
||||
void CV_DisTransTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
|
||||
{
|
||||
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
|
||||
if( i == INPUT && CV_MAT_DEPTH(type) == CV_8U )
|
||||
{
|
||||
low = Scalar::all(0);
|
||||
high = Scalar::all(10);
|
||||
}
|
||||
}
|
||||
|
||||
int CV_DisTransTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
if( code > 0 )
|
||||
{
|
||||
// the function's response to an "all-nonzeros" image is not determined,
|
||||
// so put at least one zero point
|
||||
Mat& mat = test_mat[INPUT][0];
|
||||
RNG& rng = ts->get_rng();
|
||||
int i = cvtest::randInt(rng) % mat.rows;
|
||||
int j = cvtest::randInt(rng) % mat.cols;
|
||||
mat.at<uchar>(i,j) = 0;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void CV_DisTransTest::run_func()
|
||||
{
|
||||
cvDistTransform( test_array[INPUT][0], test_array[OUTPUT][0], dist_type, mask_size,
|
||||
dist_type == CV_DIST_USER ? mask : 0, test_array[OUTPUT][1] );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cvTsDistTransform( const CvMat* _src, CvMat* _dst, int dist_type,
|
||||
int mask_size, float* _mask, CvMat* /*_labels*/ )
|
||||
{
|
||||
int i, j, k;
|
||||
int width = _src->cols, height = _src->rows;
|
||||
const float init_val = 1e6;
|
||||
float mask[3];
|
||||
CvMat* temp;
|
||||
int ofs[16];
|
||||
float delta[16];
|
||||
int tstep, count;
|
||||
|
||||
assert( mask_size == 3 || mask_size == 5 );
|
||||
|
||||
if( dist_type == CV_DIST_USER )
|
||||
memcpy( mask, _mask, sizeof(mask) );
|
||||
else if( dist_type == CV_DIST_C )
|
||||
{
|
||||
mask_size = 3;
|
||||
mask[0] = mask[1] = 1.f;
|
||||
}
|
||||
else if( dist_type == CV_DIST_L1 )
|
||||
{
|
||||
mask_size = 3;
|
||||
mask[0] = 1.f;
|
||||
mask[1] = 2.f;
|
||||
}
|
||||
else if( mask_size == 3 )
|
||||
{
|
||||
mask[0] = 0.955f;
|
||||
mask[1] = 1.3693f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask[0] = 1.0f;
|
||||
mask[1] = 1.4f;
|
||||
mask[2] = 2.1969f;
|
||||
}
|
||||
|
||||
temp = cvCreateMat( height + mask_size-1, width + mask_size-1, CV_32F );
|
||||
tstep = temp->step / sizeof(float);
|
||||
|
||||
if( mask_size == 3 )
|
||||
{
|
||||
count = 4;
|
||||
ofs[0] = -1; delta[0] = mask[0];
|
||||
ofs[1] = -tstep-1; delta[1] = mask[1];
|
||||
ofs[2] = -tstep; delta[2] = mask[0];
|
||||
ofs[3] = -tstep+1; delta[3] = mask[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 8;
|
||||
ofs[0] = -1; delta[0] = mask[0];
|
||||
ofs[1] = -tstep-2; delta[1] = mask[2];
|
||||
ofs[2] = -tstep-1; delta[2] = mask[1];
|
||||
ofs[3] = -tstep; delta[3] = mask[0];
|
||||
ofs[4] = -tstep+1; delta[4] = mask[1];
|
||||
ofs[5] = -tstep+2; delta[5] = mask[2];
|
||||
ofs[6] = -tstep*2-1; delta[6] = mask[2];
|
||||
ofs[7] = -tstep*2+1; delta[7] = mask[2];
|
||||
}
|
||||
|
||||
for( i = 0; i < mask_size/2; i++ )
|
||||
{
|
||||
float* t0 = (float*)(temp->data.ptr + i*temp->step);
|
||||
float* t1 = (float*)(temp->data.ptr + (temp->rows - i - 1)*temp->step);
|
||||
|
||||
for( j = 0; j < width + mask_size - 1; j++ )
|
||||
t0[j] = t1[j] = init_val;
|
||||
}
|
||||
|
||||
for( i = 0; i < height; i++ )
|
||||
{
|
||||
uchar* s = _src->data.ptr + i*_src->step;
|
||||
float* tmp = (float*)(temp->data.ptr + temp->step*(i + (mask_size/2))) + (mask_size/2);
|
||||
|
||||
for( j = 0; j < mask_size/2; j++ )
|
||||
tmp[-j-1] = tmp[j + width] = init_val;
|
||||
|
||||
for( j = 0; j < width; j++ )
|
||||
{
|
||||
if( s[j] == 0 )
|
||||
tmp[j] = 0;
|
||||
else
|
||||
{
|
||||
float min_dist = init_val;
|
||||
for( k = 0; k < count; k++ )
|
||||
{
|
||||
float t = tmp[j+ofs[k]] + delta[k];
|
||||
if( min_dist > t )
|
||||
min_dist = t;
|
||||
}
|
||||
tmp[j] = min_dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( i = height - 1; i >= 0; i-- )
|
||||
{
|
||||
float* d = (float*)(_dst->data.ptr + i*_dst->step);
|
||||
float* tmp = (float*)(temp->data.ptr + temp->step*(i + (mask_size/2))) + (mask_size/2);
|
||||
|
||||
for( j = width - 1; j >= 0; j-- )
|
||||
{
|
||||
float min_dist = tmp[j];
|
||||
if( min_dist > mask[0] )
|
||||
{
|
||||
for( k = 0; k < count; k++ )
|
||||
{
|
||||
float t = tmp[j-ofs[k]] + delta[k];
|
||||
if( min_dist > t )
|
||||
min_dist = t;
|
||||
}
|
||||
tmp[j] = min_dist;
|
||||
}
|
||||
d[j] = min_dist;
|
||||
}
|
||||
}
|
||||
|
||||
cvReleaseMat( &temp );
|
||||
}
|
||||
|
||||
|
||||
void CV_DisTransTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
CvMat _input = test_mat[INPUT][0], _output = test_mat[REF_OUTPUT][0];
|
||||
|
||||
cvTsDistTransform( &_input, &_output, dist_type, mask_size, mask, 0 );
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_DistanceTransform, accuracy) { CV_DisTransTest test; test.safe_run(); }
|
||||
|
||||
|
95
modules/imgproc/test/test_emd.cpp
Normal file
95
modules/imgproc/test/test_emd.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
/*////////////////////// emd_test /////////////////////////*/
|
||||
|
||||
class CV_EMDTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_EMDTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
|
||||
CV_EMDTest::CV_EMDTest()
|
||||
{
|
||||
}
|
||||
|
||||
void CV_EMDTest::run( int )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
const double success_error_level = 1e-6;
|
||||
#define M 10000
|
||||
double emd0 = 2460./210;
|
||||
static float cost[] =
|
||||
{
|
||||
16, 16, 13, 22, 17,
|
||||
14, 14, 13, 19, 15,
|
||||
19, 19, 20, 23, M,
|
||||
M , 0, M, 0, 0
|
||||
};
|
||||
static float w1[] = { 50, 60, 50, 50 },
|
||||
w2[] = { 30, 20, 70, 30, 60 };
|
||||
Mat _w1(4, 1, CV_32F, w1);
|
||||
Mat _w2(5, 1, CV_32F, w2);
|
||||
Mat _cost(_w1.rows, _w2.rows, CV_32F, cost);
|
||||
|
||||
float emd = EMD( _w1, _w2, -1, _cost );
|
||||
if( fabs( emd - emd0 ) > success_error_level*emd0 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"The computed distance is %.2f, while it should be %.2f\n", emd, emd0 );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(Imgproc_EMD, regression) { CV_EMDTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
1776
modules/imgproc/test/test_filter.cpp
Normal file
1776
modules/imgproc/test/test_filter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
533
modules/imgproc/test/test_floodfill.cpp
Normal file
533
modules/imgproc/test/test_floodfill.cpp
Normal file
@ -0,0 +1,533 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_FloodFillTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_FloodFillTest();
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
|
||||
void fill_array( int test_case_idx, int i, int j, Mat& arr );
|
||||
|
||||
/*int write_default_params(CvFileStorage* fs);
|
||||
void get_timing_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types
|
||||
CvSize** whole_sizes, bool *are_images );
|
||||
void print_timing_params( int test_case_idx, char* ptr, int params_left );*/
|
||||
CvPoint seed_pt;
|
||||
CvScalar new_val;
|
||||
CvScalar l_diff, u_diff;
|
||||
int connectivity;
|
||||
bool use_mask, mask_only;
|
||||
int range_type;
|
||||
int new_mask_val;
|
||||
bool test_cpp;
|
||||
};
|
||||
|
||||
|
||||
CV_FloodFillTest::CV_FloodFillTest()
|
||||
{
|
||||
test_array[INPUT_OUTPUT].push_back(NULL);
|
||||
test_array[INPUT_OUTPUT].push_back(NULL);
|
||||
test_array[REF_INPUT_OUTPUT].push_back(NULL);
|
||||
test_array[REF_INPUT_OUTPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
optional_mask = false;
|
||||
element_wise_relative_error = true;
|
||||
|
||||
test_cpp = false;
|
||||
}
|
||||
|
||||
|
||||
void CV_FloodFillTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes,
|
||||
vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int depth, cn;
|
||||
int i;
|
||||
double buf[8];
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
|
||||
depth = cvtest::randInt(rng) % 2;
|
||||
depth = depth == 0 ? CV_8U : CV_32F;
|
||||
cn = cvtest::randInt(rng) & 1 ? 3 : 1;
|
||||
|
||||
use_mask = (cvtest::randInt(rng) & 1) != 0;
|
||||
connectivity = (cvtest::randInt(rng) & 1) ? 4 : 8;
|
||||
mask_only = use_mask && (cvtest::randInt(rng) & 1) != 0;
|
||||
new_mask_val = cvtest::randInt(rng) & 255;
|
||||
range_type = cvtest::randInt(rng) % 3;
|
||||
|
||||
types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
|
||||
types[INPUT_OUTPUT][1] = types[REF_INPUT_OUTPUT][1] = CV_8UC1;
|
||||
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
|
||||
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(9,1);
|
||||
|
||||
if( !use_mask )
|
||||
sizes[INPUT_OUTPUT][1] = sizes[REF_INPUT_OUTPUT][1] = cvSize(0,0);
|
||||
else
|
||||
{
|
||||
CvSize sz = sizes[INPUT_OUTPUT][0];
|
||||
sizes[INPUT_OUTPUT][1] = sizes[REF_INPUT_OUTPUT][1] = cvSize(sz.width+2,sz.height+2);
|
||||
}
|
||||
|
||||
seed_pt.x = cvtest::randInt(rng) % sizes[INPUT_OUTPUT][0].width;
|
||||
seed_pt.y = cvtest::randInt(rng) % sizes[INPUT_OUTPUT][0].height;
|
||||
|
||||
if( range_type == 0 )
|
||||
l_diff = u_diff = Scalar::all(0.);
|
||||
else
|
||||
{
|
||||
Mat m( 1, 8, CV_16S, buf );
|
||||
rng.fill( m, RNG::NORMAL, Scalar::all(0), Scalar::all(32) );
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
l_diff.val[i] = fabs(m.at<short>(i)/16.);
|
||||
u_diff.val[i] = fabs(m.at<short>(i+4)/16.);
|
||||
}
|
||||
}
|
||||
|
||||
new_val = Scalar::all(0.);
|
||||
for( i = 0; i < cn; i++ )
|
||||
new_val.val[i] = cvtest::randReal(rng)*255;
|
||||
|
||||
test_cpp = (cvtest::randInt(rng) & 256) == 0;
|
||||
}
|
||||
|
||||
|
||||
double CV_FloodFillTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
|
||||
{
|
||||
return i == OUTPUT ? FLT_EPSILON : j == 0 ? FLT_EPSILON : 0;
|
||||
}
|
||||
|
||||
|
||||
void CV_FloodFillTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
|
||||
if( i != INPUT && i != INPUT_OUTPUT )
|
||||
{
|
||||
cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
|
||||
return;
|
||||
}
|
||||
|
||||
if( j == 0 )
|
||||
{
|
||||
Mat tmp = arr;
|
||||
Scalar m = Scalar::all(128);
|
||||
Scalar s = Scalar::all(10);
|
||||
|
||||
if( arr.depth() == CV_32FC1 )
|
||||
tmp.create(arr.size(), CV_MAKETYPE(CV_8U, arr.channels()));
|
||||
|
||||
if( range_type == 0 )
|
||||
s = Scalar::all(2);
|
||||
|
||||
rng.fill(tmp, RNG::NORMAL, m, s );
|
||||
if( arr.data != tmp.data )
|
||||
cvtest::convert(tmp, arr, arr.type());
|
||||
}
|
||||
else
|
||||
{
|
||||
Scalar l = Scalar::all(-2);
|
||||
Scalar u = Scalar::all(2);
|
||||
cvtest::randUni(rng, arr, l, u );
|
||||
rectangle( arr, Point(0,0), Point(arr.cols-1,arr.rows-1), Scalar::all(1), 1, 8, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_FloodFillTest::run_func()
|
||||
{
|
||||
int flags = connectivity + (mask_only ? CV_FLOODFILL_MASK_ONLY : 0) +
|
||||
(range_type == 1 ? CV_FLOODFILL_FIXED_RANGE : 0) + (new_mask_val << 8);
|
||||
double* odata = test_mat[OUTPUT][0].ptr<double>();
|
||||
|
||||
if(!test_cpp)
|
||||
{
|
||||
CvConnectedComp comp;
|
||||
cvFloodFill( test_array[INPUT_OUTPUT][0], seed_pt, new_val, l_diff, u_diff, &comp,
|
||||
flags, test_array[INPUT_OUTPUT][1] );
|
||||
odata[0] = comp.area;
|
||||
odata[1] = comp.rect.x;
|
||||
odata[2] = comp.rect.y;
|
||||
odata[3] = comp.rect.width;
|
||||
odata[4] = comp.rect.height;
|
||||
odata[5] = comp.value.val[0];
|
||||
odata[6] = comp.value.val[1];
|
||||
odata[7] = comp.value.val[2];
|
||||
odata[8] = comp.value.val[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat img = cv::cvarrToMat(test_array[INPUT_OUTPUT][0]),
|
||||
mask = test_array[INPUT_OUTPUT][1] ? cv::cvarrToMat(test_array[INPUT_OUTPUT][1]) : cv::Mat();
|
||||
cv::Rect rect;
|
||||
int area;
|
||||
if( !mask.data )
|
||||
area = cv::floodFill( img, seed_pt, new_val, &rect, l_diff, u_diff, flags );
|
||||
else
|
||||
area = cv::floodFill( img, mask, seed_pt, new_val, &rect, l_diff, u_diff, flags );
|
||||
odata[0] = area;
|
||||
odata[1] = rect.x;
|
||||
odata[2] = rect.y;
|
||||
odata[3] = rect.width;
|
||||
odata[4] = rect.height;
|
||||
odata[5] = odata[6] = odata[7] = odata[8] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct ff_offset_pair_t
|
||||
{
|
||||
int mofs, iofs;
|
||||
}
|
||||
ff_offset_pair_t;
|
||||
|
||||
static void
|
||||
cvTsFloodFill( CvMat* _img, CvPoint seed_pt, CvScalar new_val,
|
||||
CvScalar l_diff, CvScalar u_diff, CvMat* _mask,
|
||||
double* comp, int connectivity, int range_type,
|
||||
int new_mask_val, bool mask_only )
|
||||
{
|
||||
CvMemStorage* st = cvCreateMemStorage();
|
||||
ff_offset_pair_t p0, p;
|
||||
CvSeq* seq = cvCreateSeq( 0, sizeof(CvSeq), sizeof(p0), st );
|
||||
CvMat* tmp = _img;
|
||||
CvMat* mask;
|
||||
CvRect r = cvRect( 0, 0, -1, -1 );
|
||||
int area = 0;
|
||||
int i, j;
|
||||
ushort* m;
|
||||
float* img;
|
||||
int mstep, step;
|
||||
int cn = CV_MAT_CN(_img->type);
|
||||
int mdelta[8], idelta[8], ncount;
|
||||
int cols = _img->cols, rows = _img->rows;
|
||||
int u0 = 0, u1 = 0, u2 = 0;
|
||||
double s0 = 0, s1 = 0, s2 = 0;
|
||||
|
||||
if( CV_MAT_DEPTH(_img->type) == CV_8U )
|
||||
{
|
||||
tmp = cvCreateMat( rows, cols, CV_MAKETYPE(CV_32F,CV_MAT_CN(_img->type)) );
|
||||
cvTsConvert(_img, tmp);
|
||||
}
|
||||
|
||||
mask = cvCreateMat( rows + 2, cols + 2, CV_16UC1 );
|
||||
|
||||
if( _mask )
|
||||
cvTsConvert( _mask, mask );
|
||||
else
|
||||
{
|
||||
cvTsZero( mask );
|
||||
cvRectangle( mask, cvPoint(0,0), cvPoint(mask->cols-1,mask->rows-1), Scalar::all(1.), 1, 8, 0 );
|
||||
}
|
||||
|
||||
new_mask_val = (new_mask_val != 0 ? new_mask_val : 1) << 8;
|
||||
|
||||
m = (ushort*)(mask->data.ptr + mask->step) + 1;
|
||||
mstep = mask->step / sizeof(m[0]);
|
||||
img = tmp->data.fl;
|
||||
step = tmp->step / sizeof(img[0]);
|
||||
|
||||
p0.mofs = seed_pt.y*mstep + seed_pt.x;
|
||||
p0.iofs = seed_pt.y*step + seed_pt.x*cn;
|
||||
|
||||
if( m[p0.mofs] )
|
||||
goto _exit_;
|
||||
|
||||
cvSeqPush( seq, &p0 );
|
||||
m[p0.mofs] = (ushort)new_mask_val;
|
||||
|
||||
if( connectivity == 4 )
|
||||
{
|
||||
ncount = 4;
|
||||
mdelta[0] = -mstep; idelta[0] = -step;
|
||||
mdelta[1] = -1; idelta[1] = -cn;
|
||||
mdelta[2] = 1; idelta[2] = cn;
|
||||
mdelta[3] = mstep; idelta[3] = step;
|
||||
}
|
||||
else
|
||||
{
|
||||
ncount = 8;
|
||||
mdelta[0] = -mstep-1; mdelta[1] = -mstep; mdelta[2] = -mstep+1;
|
||||
idelta[0] = -step-cn; idelta[1] = -step; idelta[2] = -step+cn;
|
||||
|
||||
mdelta[3] = -1; mdelta[4] = 1;
|
||||
idelta[3] = -cn; idelta[4] = cn;
|
||||
|
||||
mdelta[5] = mstep-1; mdelta[6] = mstep; mdelta[7] = mstep+1;
|
||||
idelta[5] = step-cn; idelta[6] = step; idelta[7] = step+cn;
|
||||
}
|
||||
|
||||
if( cn == 1 )
|
||||
{
|
||||
float a0 = (float)-l_diff.val[0];
|
||||
float b0 = (float)u_diff.val[0];
|
||||
|
||||
s0 = img[p0.iofs];
|
||||
|
||||
if( range_type < 2 )
|
||||
{
|
||||
a0 += (float)s0; b0 += (float)s0;
|
||||
}
|
||||
|
||||
while( seq->total )
|
||||
{
|
||||
cvSeqPop( seq, &p0 );
|
||||
float a = a0, b = b0;
|
||||
float* ptr = img + p0.iofs;
|
||||
ushort* mptr = m + p0.mofs;
|
||||
|
||||
if( range_type == 2 )
|
||||
a += ptr[0], b += ptr[0];
|
||||
|
||||
for( i = 0; i < ncount; i++ )
|
||||
{
|
||||
int md = mdelta[i], id = idelta[i];
|
||||
float v;
|
||||
if( !mptr[md] && a <= (v = ptr[id]) && v <= b )
|
||||
{
|
||||
mptr[md] = (ushort)new_mask_val;
|
||||
p.mofs = p0.mofs + md;
|
||||
p.iofs = p0.iofs + id;
|
||||
cvSeqPush( seq, &p );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float a0 = (float)-l_diff.val[0];
|
||||
float a1 = (float)-l_diff.val[1];
|
||||
float a2 = (float)-l_diff.val[2];
|
||||
float b0 = (float)u_diff.val[0];
|
||||
float b1 = (float)u_diff.val[1];
|
||||
float b2 = (float)u_diff.val[2];
|
||||
|
||||
s0 = img[p0.iofs];
|
||||
s1 = img[p0.iofs + 1];
|
||||
s2 = img[p0.iofs + 2];
|
||||
|
||||
if( range_type < 2 )
|
||||
{
|
||||
a0 += (float)s0; b0 += (float)s0;
|
||||
a1 += (float)s1; b1 += (float)s1;
|
||||
a2 += (float)s2; b2 += (float)s2;
|
||||
}
|
||||
|
||||
while( seq->total )
|
||||
{
|
||||
cvSeqPop( seq, &p0 );
|
||||
float _a0 = a0, _a1 = a1, _a2 = a2;
|
||||
float _b0 = b0, _b1 = b1, _b2 = b2;
|
||||
float* ptr = img + p0.iofs;
|
||||
ushort* mptr = m + p0.mofs;
|
||||
|
||||
if( range_type == 2 )
|
||||
{
|
||||
_a0 += ptr[0]; _b0 += ptr[0];
|
||||
_a1 += ptr[1]; _b1 += ptr[1];
|
||||
_a2 += ptr[2]; _b2 += ptr[2];
|
||||
}
|
||||
|
||||
for( i = 0; i < ncount; i++ )
|
||||
{
|
||||
int md = mdelta[i], id = idelta[i];
|
||||
float v;
|
||||
if( !mptr[md] &&
|
||||
_a0 <= (v = ptr[id]) && v <= _b0 &&
|
||||
_a1 <= (v = ptr[id+1]) && v <= _b1 &&
|
||||
_a2 <= (v = ptr[id+2]) && v <= _b2 )
|
||||
{
|
||||
mptr[md] = (ushort)new_mask_val;
|
||||
p.mofs = p0.mofs + md;
|
||||
p.iofs = p0.iofs + id;
|
||||
cvSeqPush( seq, &p );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.x = r.width = seed_pt.x;
|
||||
r.y = r.height = seed_pt.y;
|
||||
|
||||
if( !mask_only )
|
||||
{
|
||||
s0 = new_val.val[0];
|
||||
s1 = new_val.val[1];
|
||||
s2 = new_val.val[2];
|
||||
|
||||
if( tmp != _img )
|
||||
{
|
||||
u0 = saturate_cast<uchar>(s0);
|
||||
u1 = saturate_cast<uchar>(s1);
|
||||
u2 = saturate_cast<uchar>(s2);
|
||||
|
||||
s0 = u0;
|
||||
s1 = u1;
|
||||
s2 = u2;
|
||||
}
|
||||
}
|
||||
else
|
||||
s0 = s1 = s2 = 0;
|
||||
|
||||
new_mask_val >>= 8;
|
||||
|
||||
for( i = 0; i < rows; i++ )
|
||||
{
|
||||
float* ptr = img + i*step;
|
||||
ushort* mptr = m + i*mstep;
|
||||
uchar* dmptr = _mask ? _mask->data.ptr + (i+1)*_mask->step + 1 : 0;
|
||||
uchar* dptr = tmp != _img ? _img->data.ptr + i*_img->step : 0;
|
||||
double area0 = area;
|
||||
|
||||
for( j = 0; j < cols; j++ )
|
||||
{
|
||||
if( mptr[j] > 255 )
|
||||
{
|
||||
if( dmptr )
|
||||
dmptr[j] = (uchar)new_mask_val;
|
||||
if( !mask_only )
|
||||
{
|
||||
if( cn == 1 )
|
||||
{
|
||||
if( dptr )
|
||||
dptr[j] = (uchar)u0;
|
||||
else
|
||||
ptr[j] = (float)s0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dptr )
|
||||
{
|
||||
dptr[j*3] = (uchar)u0;
|
||||
dptr[j*3+1] = (uchar)u1;
|
||||
dptr[j*3+2] = (uchar)u2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr[j*3] = (float)s0;
|
||||
ptr[j*3+1] = (float)s1;
|
||||
ptr[j*3+2] = (float)s2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( cn == 1 )
|
||||
s0 += ptr[j];
|
||||
else
|
||||
{
|
||||
s0 += ptr[j*3];
|
||||
s1 += ptr[j*3+1];
|
||||
s2 += ptr[j*3+2];
|
||||
}
|
||||
}
|
||||
|
||||
area++;
|
||||
if( r.x > j )
|
||||
r.x = j;
|
||||
if( r.width < j )
|
||||
r.width = j;
|
||||
}
|
||||
}
|
||||
|
||||
if( area != area0 )
|
||||
{
|
||||
if( r.y > i )
|
||||
r.y = i;
|
||||
if( r.height < i )
|
||||
r.height = i;
|
||||
}
|
||||
}
|
||||
|
||||
_exit_:
|
||||
cvReleaseMat( &mask );
|
||||
if( tmp != _img )
|
||||
cvReleaseMat( &tmp );
|
||||
|
||||
comp[0] = area;
|
||||
comp[1] = r.x;
|
||||
comp[2] = r.y;
|
||||
comp[3] = r.width - r.x + 1;
|
||||
comp[4] = r.height - r.y + 1;
|
||||
if( mask_only )
|
||||
{
|
||||
double t = area ? 1./area : 0;
|
||||
s0 *= t;
|
||||
s1 *= t;
|
||||
s2 *= t;
|
||||
}
|
||||
comp[5] = s0;
|
||||
comp[6] = s1;
|
||||
comp[7] = s2;
|
||||
comp[8] = 0;
|
||||
}
|
||||
|
||||
|
||||
void CV_FloodFillTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
double* comp = test_mat[REF_OUTPUT][0].ptr<double>();
|
||||
CvMat _input = test_mat[REF_INPUT_OUTPUT][0];
|
||||
CvMat _mask = test_mat[REF_INPUT_OUTPUT][1];
|
||||
cvTsFloodFill( &_input, seed_pt, new_val, l_diff, u_diff,
|
||||
_mask.data.ptr ? &_mask : 0,
|
||||
comp, connectivity, range_type,
|
||||
new_mask_val, mask_only );
|
||||
if(test_cpp)
|
||||
comp[5] = comp[6] = comp[7] = comp[8] = 0;
|
||||
}
|
||||
|
||||
TEST(Imgproc_FloodFill, accuracy) { CV_FloodFillTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
141
modules/imgproc/test/test_grabcut.cpp
Normal file
141
modules/imgproc/test/test_grabcut.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class CV_GrabcutTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_GrabcutTest();
|
||||
~CV_GrabcutTest();
|
||||
protected:
|
||||
bool verify(const Mat& mask, const Mat& exp);
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_GrabcutTest::CV_GrabcutTest() {}
|
||||
CV_GrabcutTest::~CV_GrabcutTest() {}
|
||||
|
||||
bool CV_GrabcutTest::verify(const Mat& mask, const Mat& exp)
|
||||
{
|
||||
const float maxDiffRatio = 0.005f;
|
||||
int expArea = countNonZero( exp );
|
||||
int nonIntersectArea = countNonZero( mask != exp );
|
||||
|
||||
float curRatio = (float)nonIntersectArea / (float)expArea;
|
||||
ts->printf( cvtest::TS::LOG, "nonIntersectArea/expArea = %f\n", curRatio );
|
||||
return curRatio < maxDiffRatio;
|
||||
}
|
||||
|
||||
void CV_GrabcutTest::run( int /* start_from */)
|
||||
{
|
||||
cvtest::DefaultRngAuto defRng;
|
||||
|
||||
Mat img = imread(string(ts->get_data_path()) + "shared/airplane.jpg");
|
||||
Mat mask_prob = imread(string(ts->get_data_path()) + "grabcut/mask_prob.png", 0);
|
||||
Mat exp_mask1 = imread(string(ts->get_data_path()) + "grabcut/exp_mask1.png", 0);
|
||||
Mat exp_mask2 = imread(string(ts->get_data_path()) + "grabcut/exp_mask2.png", 0);
|
||||
|
||||
if (img.empty() || (!mask_prob.empty() && img.size() != mask_prob.size()) ||
|
||||
(!exp_mask1.empty() && img.size() != exp_mask1.size()) ||
|
||||
(!exp_mask2.empty() && img.size() != exp_mask2.size()) )
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
|
||||
return;
|
||||
}
|
||||
|
||||
Rect rect(Point(24, 126), Point(483, 294));
|
||||
Mat exp_bgdModel, exp_fgdModel;
|
||||
|
||||
Mat mask;
|
||||
mask = Scalar(0);
|
||||
Mat bgdModel, fgdModel;
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_RECT );
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 2, GC_EVAL );
|
||||
|
||||
// Multiply images by 255 for more visuality of test data.
|
||||
if( mask_prob.empty() )
|
||||
{
|
||||
mask.copyTo( mask_prob );
|
||||
imwrite(string(ts->get_data_path()) + "grabcut/mask_prob.png", mask_prob);
|
||||
}
|
||||
if( exp_mask1.empty() )
|
||||
{
|
||||
exp_mask1 = (mask & 1) * 255;
|
||||
imwrite(string(ts->get_data_path()) + "grabcut/exp_mask1.png", exp_mask1);
|
||||
}
|
||||
|
||||
if (!verify((mask & 1) * 255, exp_mask1))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = mask_prob;
|
||||
bgdModel.release();
|
||||
fgdModel.release();
|
||||
rect = Rect();
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_MASK );
|
||||
grabCut( img, mask, rect, bgdModel, fgdModel, 1, GC_EVAL );
|
||||
|
||||
if( exp_mask2.empty() )
|
||||
{
|
||||
exp_mask2 = (mask & 1) * 255;
|
||||
imwrite(string(ts->get_data_path()) + "grabcut/exp_mask2.png", exp_mask2);
|
||||
}
|
||||
|
||||
if (!verify((mask & 1) * 255, exp_mask2))
|
||||
{
|
||||
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
|
||||
return;
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Imgproc_GrabCut, regression) { CV_GrabcutTest test; test.safe_run(); }
|
||||
|
1842
modules/imgproc/test/test_histograms.cpp
Normal file
1842
modules/imgproc/test/test_histograms.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1387
modules/imgproc/test/test_imgwarp.cpp
Normal file
1387
modules/imgproc/test/test_imgwarp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
121
modules/imgproc/test/test_inpaint.cpp
Normal file
121
modules/imgproc/test/test_inpaint.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class CV_InpaintTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_InpaintTest();
|
||||
~CV_InpaintTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_InpaintTest::CV_InpaintTest()
|
||||
{
|
||||
}
|
||||
CV_InpaintTest::~CV_InpaintTest() {}
|
||||
|
||||
void CV_InpaintTest::run( int )
|
||||
{
|
||||
string folder = string(ts->get_data_path()) + "inpaint/";
|
||||
Mat orig = imread(folder + "orig.jpg");
|
||||
Mat exp1 = imread(folder + "exp1.png");
|
||||
Mat exp2 = imread(folder + "exp2.png");
|
||||
Mat mask = imread(folder + "mask.png");
|
||||
|
||||
if (orig.empty() || exp1.empty() || exp2.empty() || mask.empty())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
Mat inv_mask;
|
||||
mask.convertTo(inv_mask, CV_8UC3, -1.0, 255.0);
|
||||
|
||||
Mat mask1ch;
|
||||
cv::cvtColor(mask, mask1ch, CV_BGR2GRAY);
|
||||
|
||||
Mat test = orig.clone();
|
||||
test.setTo(Scalar::all(255), mask1ch);
|
||||
|
||||
Mat res1, res2;
|
||||
inpaint( test, mask1ch, res1, 5, CV_INPAINT_NS );
|
||||
inpaint( test, mask1ch, res2, 5, CV_INPAINT_TELEA );
|
||||
|
||||
imwrite("d:/exp1.png", res1);
|
||||
imwrite("d:/exp2.png", res2);
|
||||
|
||||
Mat diff1, diff2;
|
||||
absdiff( orig, res1, diff1 );
|
||||
absdiff( orig, res2, diff2 );
|
||||
|
||||
double n1 = norm(diff1.reshape(1), NORM_INF, inv_mask.reshape(1));
|
||||
double n2 = norm(diff2.reshape(1), NORM_INF, inv_mask.reshape(1));
|
||||
|
||||
if (n1 != 0 || n2 != 0)
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
|
||||
return;
|
||||
}
|
||||
|
||||
absdiff( exp1, res1, diff1 );
|
||||
absdiff( exp2, res2, diff2 );
|
||||
|
||||
n1 = norm(diff1.reshape(1), NORM_INF, mask.reshape(1));
|
||||
n2 = norm(diff2.reshape(1), NORM_INF, mask.reshape(1));
|
||||
|
||||
const int jpeg_thres = 3;
|
||||
if (n1 > jpeg_thres || n2 > jpeg_thres)
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
|
||||
return;
|
||||
}
|
||||
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Imgproc_Inpaint, regression) { CV_InpaintTest test; test.safe_run(); }
|
4
modules/imgproc/test/test_main.cpp
Normal file
4
modules/imgproc/test/test_main.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
||||
|
393
modules/imgproc/test/test_moments.cpp
Normal file
393
modules/imgproc/test/test_moments.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
// image moments
|
||||
class CV_MomentsTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_MomentsTest();
|
||||
|
||||
protected:
|
||||
|
||||
enum { MOMENT_COUNT = 25 };
|
||||
int prepare_test_case( int test_case_idx );
|
||||
void prepare_to_validation( int /*test_case_idx*/ );
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
int coi;
|
||||
bool is_binary;
|
||||
};
|
||||
|
||||
|
||||
CV_MomentsTest::CV_MomentsTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
coi = -1;
|
||||
is_binary = false;
|
||||
//element_wise_relative_error = false;
|
||||
}
|
||||
|
||||
|
||||
void CV_MomentsTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
|
||||
{
|
||||
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
|
||||
if( depth == CV_16U )
|
||||
{
|
||||
low = Scalar::all(0);
|
||||
high = Scalar::all(1000);
|
||||
}
|
||||
else if( depth == CV_16S )
|
||||
{
|
||||
low = Scalar::all(-1000);
|
||||
high = Scalar::all(1000);
|
||||
}
|
||||
else if( depth == CV_32F )
|
||||
{
|
||||
low = Scalar::all(-1);
|
||||
high = Scalar::all(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_MomentsTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
int cn = cvtest::randInt(rng) % 4 + 1;
|
||||
int depth = cvtest::randInt(rng) % 4;
|
||||
depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F;
|
||||
if( cn == 2 )
|
||||
cn = 1;
|
||||
|
||||
types[INPUT][0] = CV_MAKETYPE(depth, cn);
|
||||
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
|
||||
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(MOMENT_COUNT,1);
|
||||
|
||||
is_binary = cvtest::randInt(rng) % 2 != 0;
|
||||
coi = 0;
|
||||
cvmat_allowed = true;
|
||||
if( cn > 1 )
|
||||
{
|
||||
coi = cvtest::randInt(rng) % cn;
|
||||
cvmat_allowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double CV_MomentsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
int depth = test_mat[INPUT][0].depth();
|
||||
return depth != CV_32F ? FLT_EPSILON*10 : FLT_EPSILON*100;
|
||||
}
|
||||
|
||||
int CV_MomentsTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
if( code > 0 )
|
||||
{
|
||||
int cn = test_mat[INPUT][0].channels();
|
||||
if( cn > 1 )
|
||||
cvSetImageCOI( (IplImage*)test_array[INPUT][0], coi + 1 );
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void CV_MomentsTest::run_func()
|
||||
{
|
||||
CvMoments* m = (CvMoments*)test_mat[OUTPUT][0].ptr<double>();
|
||||
double* others = (double*)(m + 1);
|
||||
cvMoments( test_array[INPUT][0], m, is_binary );
|
||||
others[0] = cvGetNormalizedCentralMoment( m, 2, 0 );
|
||||
others[1] = cvGetNormalizedCentralMoment( m, 1, 1 );
|
||||
others[2] = cvGetNormalizedCentralMoment( m, 0, 2 );
|
||||
others[3] = cvGetNormalizedCentralMoment( m, 3, 0 );
|
||||
others[4] = cvGetNormalizedCentralMoment( m, 2, 1 );
|
||||
others[5] = cvGetNormalizedCentralMoment( m, 1, 2 );
|
||||
others[6] = cvGetNormalizedCentralMoment( m, 0, 3 );
|
||||
}
|
||||
|
||||
|
||||
void CV_MomentsTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
Mat& src = test_mat[INPUT][0];
|
||||
CvMoments m;
|
||||
double* mdata = test_mat[REF_OUTPUT][0].ptr<double>();
|
||||
int depth = src.depth();
|
||||
int cn = src.channels();
|
||||
int i, y, x, cols = src.cols;
|
||||
double xc = 0., yc = 0.;
|
||||
|
||||
memset( &m, 0, sizeof(m));
|
||||
|
||||
for( y = 0; y < src.rows; y++ )
|
||||
{
|
||||
double s0 = 0, s1 = 0, s2 = 0, s3 = 0;
|
||||
uchar* ptr = src.ptr(y);
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
double val;
|
||||
if( depth == CV_8U )
|
||||
val = ptr[x*cn + coi];
|
||||
else if( depth == CV_16U )
|
||||
val = ((ushort*)ptr)[x*cn + coi];
|
||||
else if( depth == CV_16S )
|
||||
val = ((short*)ptr)[x*cn + coi];
|
||||
else
|
||||
val = ((float*)ptr)[x*cn + coi];
|
||||
|
||||
if( is_binary )
|
||||
val = val != 0;
|
||||
|
||||
s0 += val;
|
||||
s1 += val*x;
|
||||
s2 += val*x*x;
|
||||
s3 += ((val*x)*x)*x;
|
||||
}
|
||||
|
||||
m.m00 += s0;
|
||||
m.m01 += s0*y;
|
||||
m.m02 += (s0*y)*y;
|
||||
m.m03 += ((s0*y)*y)*y;
|
||||
|
||||
m.m10 += s1;
|
||||
m.m11 += s1*y;
|
||||
m.m12 += (s1*y)*y;
|
||||
|
||||
m.m20 += s2;
|
||||
m.m21 += s2*y;
|
||||
|
||||
m.m30 += s3;
|
||||
}
|
||||
|
||||
if( m.m00 != 0 )
|
||||
{
|
||||
xc = m.m10/m.m00, yc = m.m01/m.m00;
|
||||
m.inv_sqrt_m00 = 1./sqrt(fabs(m.m00));
|
||||
}
|
||||
|
||||
for( y = 0; y < src.rows; y++ )
|
||||
{
|
||||
double s0 = 0, s1 = 0, s2 = 0, s3 = 0, y1 = y - yc;
|
||||
uchar* ptr = src.ptr(y);
|
||||
for( x = 0; x < cols; x++ )
|
||||
{
|
||||
double val, x1 = x - xc;
|
||||
if( depth == CV_8U )
|
||||
val = ptr[x*cn + coi];
|
||||
else if( depth == CV_16U )
|
||||
val = ((ushort*)ptr)[x*cn + coi];
|
||||
else if( depth == CV_16S )
|
||||
val = ((short*)ptr)[x*cn + coi];
|
||||
else
|
||||
val = ((float*)ptr)[x*cn + coi];
|
||||
|
||||
if( is_binary )
|
||||
val = val != 0;
|
||||
|
||||
s0 += val;
|
||||
s1 += val*x1;
|
||||
s2 += val*x1*x1;
|
||||
s3 += ((val*x1)*x1)*x1;
|
||||
}
|
||||
|
||||
m.mu02 += s0*y1*y1;
|
||||
m.mu03 += ((s0*y1)*y1)*y1;
|
||||
|
||||
m.mu11 += s1*y1;
|
||||
m.mu12 += (s1*y1)*y1;
|
||||
|
||||
m.mu20 += s2;
|
||||
m.mu21 += s2*y1;
|
||||
|
||||
m.mu30 += s3;
|
||||
}
|
||||
|
||||
memcpy( mdata, &m, sizeof(m));
|
||||
mdata += sizeof(m)/sizeof(m.m00);
|
||||
|
||||
/* calc normalized moments */
|
||||
{
|
||||
double inv_m00 = m.inv_sqrt_m00*m.inv_sqrt_m00;
|
||||
double s2 = inv_m00*inv_m00; /* 1./(m00 ^ (2/2 + 1)) */
|
||||
double s3 = s2*m.inv_sqrt_m00; /* 1./(m00 ^ (3/2 + 1)) */
|
||||
|
||||
mdata[0] = m.mu20 * s2;
|
||||
mdata[1] = m.mu11 * s2;
|
||||
mdata[2] = m.mu02 * s2;
|
||||
|
||||
mdata[3] = m.mu30 * s3;
|
||||
mdata[4] = m.mu21 * s3;
|
||||
mdata[5] = m.mu12 * s3;
|
||||
mdata[6] = m.mu03 * s3;
|
||||
}
|
||||
|
||||
double* a = test_mat[REF_OUTPUT][0].ptr<double>();
|
||||
double* b = test_mat[OUTPUT][0].ptr<double>();
|
||||
for( i = 0; i < MOMENT_COUNT; i++ )
|
||||
{
|
||||
if( fabs(a[i]) < 1e-3 )
|
||||
a[i] = 0;
|
||||
if( fabs(b[i]) < 1e-3 )
|
||||
b[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Hu invariants
|
||||
class CV_HuMomentsTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_HuMomentsTest();
|
||||
|
||||
protected:
|
||||
|
||||
enum { MOMENT_COUNT = 18, HU_MOMENT_COUNT = 7 };
|
||||
|
||||
int prepare_test_case( int test_case_idx );
|
||||
void prepare_to_validation( int /*test_case_idx*/ );
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
};
|
||||
|
||||
|
||||
CV_HuMomentsTest::CV_HuMomentsTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
}
|
||||
|
||||
|
||||
void CV_HuMomentsTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
|
||||
{
|
||||
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
|
||||
low = Scalar::all(-10000);
|
||||
high = Scalar::all(10000);
|
||||
}
|
||||
|
||||
|
||||
void CV_HuMomentsTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;
|
||||
sizes[INPUT][0] = cvSize(MOMENT_COUNT,1);
|
||||
sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(HU_MOMENT_COUNT,1);
|
||||
}
|
||||
|
||||
|
||||
double CV_HuMomentsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return FLT_EPSILON;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CV_HuMomentsTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
|
||||
if( code > 0 )
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void CV_HuMomentsTest::run_func()
|
||||
{
|
||||
cvGetHuMoments( (CvMoments*)test_mat[INPUT][0].data,
|
||||
(CvHuMoments*)test_mat[OUTPUT][0].data );
|
||||
}
|
||||
|
||||
|
||||
void CV_HuMomentsTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
CvMoments* m = (CvMoments*)test_mat[INPUT][0].data;
|
||||
CvHuMoments* hu = (CvHuMoments*)test_mat[REF_OUTPUT][0].data;
|
||||
|
||||
double inv_m00 = m->inv_sqrt_m00*m->inv_sqrt_m00;
|
||||
double s2 = inv_m00*inv_m00; /* 1./(m00 ^ (2/2 + 1)) */
|
||||
double s3 = s2*m->inv_sqrt_m00; /* 1./(m00 ^ (3/2 + 1)) */
|
||||
|
||||
double nu20 = m->mu20 * s2;
|
||||
double nu11 = m->mu11 * s2;
|
||||
double nu02 = m->mu02 * s2;
|
||||
|
||||
double nu30 = m->mu30 * s3;
|
||||
double nu21 = m->mu21 * s3;
|
||||
double nu12 = m->mu12 * s3;
|
||||
double nu03 = m->mu03 * s3;
|
||||
|
||||
#undef sqr
|
||||
#define sqr(a) ((a)*(a))
|
||||
|
||||
hu->hu1 = nu20 + nu02;
|
||||
hu->hu2 = sqr(nu20 - nu02) + 4*sqr(nu11);
|
||||
hu->hu3 = sqr(nu30 - 3*nu12) + sqr(3*nu21 - nu03);
|
||||
hu->hu4 = sqr(nu30 + nu12) + sqr(nu21 + nu03);
|
||||
hu->hu5 = (nu30 - 3*nu12)*(nu30 + nu12)*(sqr(nu30 + nu12) - 3*sqr(nu21 + nu03)) +
|
||||
(3*nu21 - nu03)*(nu21 + nu03)*(3*sqr(nu30 + nu12) - sqr(nu21 + nu03));
|
||||
hu->hu6 = (nu20 - nu02)*(sqr(nu30 + nu12) - sqr(nu21 + nu03)) +
|
||||
4*nu11*(nu30 + nu12)*(nu21 + nu03);
|
||||
hu->hu7 = (3*nu21 - nu03)*(nu30 + nu12)*(sqr(nu30 + nu12) - 3*sqr(nu21 + nu03)) +
|
||||
(3*nu12 - nu30)*(nu21 + nu03)*(3*sqr(nu30 + nu12) - sqr(nu21 + nu03));
|
||||
}
|
||||
|
||||
|
||||
TEST(Imgproc_Moments, accuracy) { CV_MomentsTest test; test.safe_run(); }
|
||||
TEST(Imgproc_HuMoments, accuracy) { CV_HuMomentsTest test; test.safe_run(); }
|
1
modules/imgproc/test/test_precomp.cpp
Normal file
1
modules/imgproc/test/test_precomp.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "test_precomp.hpp"
|
11
modules/imgproc/test/test_precomp.hpp
Normal file
11
modules/imgproc/test/test_precomp.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts/ts.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/highgui/highgui_c.h"
|
||||
#include <iostream>
|
||||
|
||||
#endif
|
204
modules/imgproc/test/test_pyrsegmentation.cpp
Normal file
204
modules/imgproc/test/test_pyrsegmentation.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_PyrSegmentationTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_PyrSegmentationTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
#define SCAN 0
|
||||
|
||||
CV_PyrSegmentationTest::CV_PyrSegmentationTest()
|
||||
{
|
||||
}
|
||||
|
||||
void CV_PyrSegmentationTest::run( int /*start_from*/ )
|
||||
{
|
||||
Mat _image_f, _image, _image_s;
|
||||
const int level = 5;
|
||||
const double range = 15;
|
||||
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
CvPoint _cp[] ={{33,33}, {43,33}, {43,43}, {33,43}};
|
||||
CvPoint _cp2[] ={{50,50}, {70,50}, {70,70}, {50,70}};
|
||||
CvPoint* cp = _cp;
|
||||
CvPoint* cp2 = _cp2;
|
||||
CvConnectedComp *dst_comp[3];
|
||||
CvRect rect[3] = {{50,50,21,21}, {0,0,128,128}, {33,33,11,11}};
|
||||
double a[3] = {441.0, 15822.0, 121.0};
|
||||
|
||||
/* ippiPoint cp3[] ={130,130, 150,130, 150,150, 130,150}; */
|
||||
/* CvPoint cp[] ={0,0, 5,5, 5,0, 10,5, 10,0, 15,5, 15,0}; */
|
||||
int nPoints = 4;
|
||||
int block_size = 1000;
|
||||
|
||||
CvMemStorage *storage; /* storage for connected component writing */
|
||||
CvSeq *comp;
|
||||
|
||||
RNG& rng = ts->get_rng();
|
||||
int i, j, iter;
|
||||
|
||||
IplImage *image, *image_f, *image_s;
|
||||
CvSize size = {128, 128};
|
||||
const int threshold1 = 50, threshold2 = 50;
|
||||
|
||||
rect[1].width = size.width;
|
||||
rect[1].height = size.height;
|
||||
a[1] = size.width*size.height - a[0] - a[2];
|
||||
|
||||
OPENCV_CALL( storage = cvCreateMemStorage( block_size ) );
|
||||
|
||||
for( iter = 0; iter < 2; iter++ )
|
||||
{
|
||||
int channels = iter == 0 ? 1 : 3;
|
||||
int mask[] = {0,0,0};
|
||||
|
||||
image = cvCreateImage(size, 8, channels );
|
||||
image_s = cvCloneImage( image );
|
||||
image_f = cvCloneImage( image );
|
||||
|
||||
if( channels == 1 )
|
||||
{
|
||||
int color1 = 30, color2 = 110, color3 = 190;
|
||||
|
||||
cvSet( image, cvScalarAll(color1));
|
||||
cvFillPoly( image, &cp, &nPoints, 1, cvScalar(color2));
|
||||
cvFillPoly( image, &cp2, &nPoints, 1, cvScalar(color3));
|
||||
}
|
||||
else
|
||||
{
|
||||
CvScalar color1 = CV_RGB(30,30,30), color2 = CV_RGB(255,0,0), color3 = CV_RGB(0,255,0);
|
||||
|
||||
assert( channels == 3 );
|
||||
cvSet( image, color1 );
|
||||
cvFillPoly( image, &cp, &nPoints, 1, color2);
|
||||
cvFillPoly( image, &cp2, &nPoints, 1, color3);
|
||||
}
|
||||
|
||||
_image_f = cvarrToMat(image_f);
|
||||
cvtest::randUni( rng, _image_f, cvScalarAll(0), cvScalarAll(range*2) );
|
||||
cvAddWeighted( image, 1, image_f, 1, -range, image_f );
|
||||
|
||||
cvPyrSegmentation( image_f, image_s,
|
||||
storage, &comp,
|
||||
level, threshold1, threshold2 );
|
||||
|
||||
if(comp->total != 3)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG,
|
||||
"The segmentation function returned %d (not 3) components\n", comp->total );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
/* read the connected components */
|
||||
dst_comp[0] = (CvConnectedComp*)CV_GET_SEQ_ELEM( CvConnectedComp, comp, 0 );
|
||||
dst_comp[1] = (CvConnectedComp*)CV_GET_SEQ_ELEM( CvConnectedComp, comp, 1 );
|
||||
dst_comp[2] = (CvConnectedComp*)CV_GET_SEQ_ELEM( CvConnectedComp, comp, 2 );
|
||||
|
||||
/*{
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
CvRect r = dst_comp[i]->rect;
|
||||
cvRectangle( image_s, cvPoint(r.x,r.y), cvPoint(r.x+r.width,r.y+r.height),
|
||||
CV_RGB(255,255,255), 3, 8, 0 );
|
||||
}
|
||||
|
||||
cvNamedWindow( "test", 1 );
|
||||
cvShowImage( "test", image_s );
|
||||
cvWaitKey(0);
|
||||
}*/
|
||||
|
||||
_image = cvarrToMat(image);
|
||||
_image_s = cvarrToMat(image_s);
|
||||
code = cvtest::cmpEps2( ts, _image, _image_s, 10, false, "the output image" );
|
||||
if( code < 0 )
|
||||
goto _exit_;
|
||||
|
||||
for( i = 0; i < 3; i++)
|
||||
{
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
if( !mask[j] && dst_comp[i]->area == a[j] &&
|
||||
dst_comp[i]->rect.x == rect[j].x &&
|
||||
dst_comp[i]->rect.y == rect[j].y &&
|
||||
dst_comp[i]->rect.width == rect[j].width &&
|
||||
dst_comp[i]->rect.height == rect[j].height )
|
||||
{
|
||||
mask[j] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( j == 3 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "The component #%d is incorrect\n", i );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
}
|
||||
|
||||
cvReleaseImage(&image_f);
|
||||
cvReleaseImage(&image);
|
||||
cvReleaseImage(&image_s);
|
||||
}
|
||||
|
||||
_exit_:
|
||||
|
||||
cvReleaseMemStorage( &storage );
|
||||
cvReleaseImage(&image_f);
|
||||
cvReleaseImage(&image);
|
||||
cvReleaseImage(&image_s);
|
||||
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(Imgproc_PyrSegmentation, regression) { CV_PyrSegmentationTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
341
modules/imgproc/test/test_subdivisions.cpp
Normal file
341
modules/imgproc/test/test_subdivisions.cpp
Normal file
@ -0,0 +1,341 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_SubdivTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_SubdivTest();
|
||||
~CV_SubdivTest();
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
int read_params( CvFileStorage* fs );
|
||||
int prepare_test_case( int test_case_idx );
|
||||
int validate_test_results( int test_case_idx );
|
||||
void run_func();
|
||||
|
||||
int min_log_img_size, max_log_img_size;
|
||||
CvSize img_size;
|
||||
int min_log_point_count;
|
||||
int max_log_point_count;
|
||||
int point_count;
|
||||
CvSubdiv2D* subdiv;
|
||||
CvMemStorage* storage;
|
||||
};
|
||||
|
||||
|
||||
CV_SubdivTest::CV_SubdivTest()
|
||||
{
|
||||
test_case_count = 100;
|
||||
min_log_point_count = 1;
|
||||
max_log_point_count = 10;
|
||||
min_log_img_size = 1;
|
||||
max_log_img_size = 10;
|
||||
|
||||
storage = 0;
|
||||
}
|
||||
|
||||
|
||||
CV_SubdivTest::~CV_SubdivTest()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void CV_SubdivTest::clear()
|
||||
{
|
||||
cvtest::BaseTest::clear();
|
||||
cvReleaseMemStorage( &storage );
|
||||
}
|
||||
|
||||
|
||||
int CV_SubdivTest::read_params( CvFileStorage* fs )
|
||||
{
|
||||
int code = cvtest::BaseTest::read_params( fs );
|
||||
int t;
|
||||
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );
|
||||
min_log_point_count = cvReadInt( find_param( fs, "min_log_point_count" ), min_log_point_count );
|
||||
max_log_point_count = cvReadInt( find_param( fs, "max_log_point_count" ), max_log_point_count );
|
||||
min_log_img_size = cvReadInt( find_param( fs, "min_log_img_size" ), min_log_img_size );
|
||||
max_log_img_size = cvReadInt( find_param( fs, "max_log_img_size" ), max_log_img_size );
|
||||
|
||||
min_log_point_count = cvtest::clipInt( min_log_point_count, 1, 10 );
|
||||
max_log_point_count = cvtest::clipInt( max_log_point_count, 1, 10 );
|
||||
if( min_log_point_count > max_log_point_count )
|
||||
CV_SWAP( min_log_point_count, max_log_point_count, t );
|
||||
|
||||
min_log_img_size = cvtest::clipInt( min_log_img_size, 1, 10 );
|
||||
max_log_img_size = cvtest::clipInt( max_log_img_size, 1, 10 );
|
||||
if( min_log_img_size > max_log_img_size )
|
||||
CV_SWAP( min_log_img_size, max_log_img_size, t );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CV_SubdivTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int code = cvtest::BaseTest::prepare_test_case( test_case_idx );
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
clear();
|
||||
|
||||
point_count = cvRound(exp((cvtest::randReal(rng)*
|
||||
(max_log_point_count - min_log_point_count) + min_log_point_count)*CV_LOG2));
|
||||
img_size.width = cvRound(exp((cvtest::randReal(rng)*
|
||||
(max_log_img_size - min_log_img_size) + min_log_img_size)*CV_LOG2));
|
||||
img_size.height = cvRound(exp((cvtest::randReal(rng)*
|
||||
(max_log_img_size - min_log_img_size) + min_log_img_size)*CV_LOG2));
|
||||
|
||||
storage = cvCreateMemStorage( 1 << 10 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void CV_SubdivTest::run_func()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static inline double sqdist( CvPoint2D32f pt1, CvPoint2D32f pt2 )
|
||||
{
|
||||
double dx = pt1.x - pt2.x;
|
||||
double dy = pt1.y - pt2.y;
|
||||
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
subdiv2DCheck( CvSubdiv2D* subdiv )
|
||||
{
|
||||
int i, j, total = subdiv->edges->total;
|
||||
CV_Assert( subdiv != 0 );
|
||||
|
||||
for( i = 0; i < total; i++ )
|
||||
{
|
||||
CvQuadEdge2D* edge = (CvQuadEdge2D*)cvGetSetElem(subdiv->edges,i);
|
||||
|
||||
if( edge && CV_IS_SET_ELEM( edge ))
|
||||
{
|
||||
for( j = 0; j < 4; j++ )
|
||||
{
|
||||
CvSubdiv2DEdge e = (CvSubdiv2DEdge)edge + j;
|
||||
CvSubdiv2DEdge o_next = cvSubdiv2DNextEdge(e);
|
||||
CvSubdiv2DEdge o_prev = cvSubdiv2DGetEdge(e, CV_PREV_AROUND_ORG );
|
||||
CvSubdiv2DEdge d_prev = cvSubdiv2DGetEdge(e, CV_PREV_AROUND_DST );
|
||||
CvSubdiv2DEdge d_next = cvSubdiv2DGetEdge(e, CV_NEXT_AROUND_DST );
|
||||
|
||||
// check points
|
||||
if( cvSubdiv2DEdgeOrg(e) != cvSubdiv2DEdgeOrg(o_next))
|
||||
return 0;
|
||||
if( cvSubdiv2DEdgeOrg(e) != cvSubdiv2DEdgeOrg(o_prev))
|
||||
return 0;
|
||||
if( cvSubdiv2DEdgeDst(e) != cvSubdiv2DEdgeDst(d_next))
|
||||
return 0;
|
||||
if( cvSubdiv2DEdgeDst(e) != cvSubdiv2DEdgeDst(d_prev))
|
||||
return 0;
|
||||
if( j % 2 == 0 )
|
||||
{
|
||||
if( cvSubdiv2DEdgeDst(o_next) != cvSubdiv2DEdgeOrg(d_prev))
|
||||
return 0;
|
||||
if( cvSubdiv2DEdgeDst(o_prev) != cvSubdiv2DEdgeOrg(d_next))
|
||||
return 0;
|
||||
if( cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(
|
||||
e,CV_NEXT_AROUND_LEFT),CV_NEXT_AROUND_LEFT),CV_NEXT_AROUND_LEFT) != e )
|
||||
return 0;
|
||||
if( cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(
|
||||
e,CV_NEXT_AROUND_RIGHT),CV_NEXT_AROUND_RIGHT),CV_NEXT_AROUND_RIGHT) != e)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// the whole testing is done here, run_func() is not utilized in this test
|
||||
int CV_SubdivTest::validate_test_results( int /*test_case_idx*/ )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
RNG& rng = ts->get_rng();
|
||||
int j, k, real_count = point_count;
|
||||
double xrange = img_size.width*(1 - FLT_EPSILON);
|
||||
double yrange = img_size.height*(1 - FLT_EPSILON);
|
||||
|
||||
subdiv = subdiv = cvCreateSubdivDelaunay2D(
|
||||
cvRect( 0, 0, img_size.width, img_size.height ), storage );
|
||||
|
||||
CvSeq* seq = cvCreateSeq( 0, sizeof(*seq), sizeof(CvPoint2D32f), storage );
|
||||
CvSeqWriter writer;
|
||||
cvStartAppendToSeq( seq, &writer );
|
||||
|
||||
// insert random points
|
||||
for( j = 0; j < point_count; j++ )
|
||||
{
|
||||
CvPoint2D32f pt;
|
||||
CvSubdiv2DPoint* point;
|
||||
|
||||
pt.x = (float)(cvtest::randReal(rng)*xrange);
|
||||
pt.y = (float)(cvtest::randReal(rng)*yrange);
|
||||
|
||||
CvSubdiv2DPointLocation loc =
|
||||
cvSubdiv2DLocate( subdiv, pt, 0, &point );
|
||||
|
||||
if( loc == CV_PTLOC_VERTEX )
|
||||
{
|
||||
int index = cvSeqElemIdx( (CvSeq*)subdiv, point );
|
||||
CvPoint2D32f* pt1;
|
||||
cvFlushSeqWriter( &writer );
|
||||
pt1 = (CvPoint2D32f*)cvGetSeqElem( seq, index - 3 );
|
||||
|
||||
if( !pt1 ||
|
||||
fabs(pt1->x - pt.x) > FLT_EPSILON ||
|
||||
fabs(pt1->y - pt.y) > FLT_EPSILON )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "The point #%d: (%.1f,%.1f) is said to coinside with a subdivision vertex, "
|
||||
"however it could be found in a sequence of inserted points\n", j, pt.x, pt.y );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
real_count--;
|
||||
}
|
||||
|
||||
point = cvSubdivDelaunay2DInsert( subdiv, pt );
|
||||
if( point->pt.x != pt.x || point->pt.y != pt.y )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "The point #%d: (%.1f,%.1f) has been incorrectly added\n", j, pt.x, pt.y );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
if( (j + 1) % 10 == 0 || j == point_count - 1 )
|
||||
{
|
||||
if( !subdiv2DCheck( subdiv ))
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Subdivision consistency check failed after inserting the point #%d\n", j );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
}
|
||||
|
||||
if( loc != CV_PTLOC_VERTEX )
|
||||
{
|
||||
CV_WRITE_SEQ_ELEM( pt, writer );
|
||||
}
|
||||
}
|
||||
|
||||
if( code < 0 )
|
||||
goto _exit_;
|
||||
|
||||
cvCalcSubdivVoronoi2D( subdiv );
|
||||
seq = cvEndWriteSeq( &writer );
|
||||
|
||||
if( !subdiv2DCheck( subdiv ))
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "The subdivision failed consistency check after building the Voronoi tesselation\n" );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
for( j = 0; j < MAX((point_count - 5)/10 + 5, 10); j++ )
|
||||
{
|
||||
CvPoint2D32f pt;
|
||||
double minDistance;
|
||||
|
||||
pt.x = (float)(cvtest::randReal(rng)*xrange);
|
||||
pt.y = (float)(cvtest::randReal(rng)*yrange);
|
||||
|
||||
CvSubdiv2DPoint* point = cvFindNearestPoint2D( subdiv, pt );
|
||||
CvSeqReader reader;
|
||||
|
||||
if( !point )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "There is no nearest point (?!) for the point (%.1f, %.1f) in the subdivision\n",
|
||||
pt.x, pt.y );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
goto _exit_;
|
||||
}
|
||||
|
||||
cvStartReadSeq( seq, &reader );
|
||||
minDistance = sqdist( pt, point->pt );
|
||||
|
||||
for( k = 0; k < seq->total; k++ )
|
||||
{
|
||||
CvPoint2D32f ptt;
|
||||
CV_READ_SEQ_ELEM( ptt, reader );
|
||||
|
||||
double distance = sqdist( pt, ptt );
|
||||
if( minDistance > distance && sqdist(ptt, point->pt) > FLT_EPSILON*1000 )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "The triangulation vertex (%.3f,%.3f) was said to be nearest to (%.3f,%.3f),\n"
|
||||
"whereas another vertex (%.3f,%.3f) is closer\n",
|
||||
point->pt.x, point->pt.y, pt.x, pt.y, ptt.x, ptt.y );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
goto _exit_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_exit_:
|
||||
if( code < 0 )
|
||||
ts->set_failed_test_info( code );
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
TEST(Imgproc_Subdiv, correctness) { CV_SubdivTest test; test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
||||
|
336
modules/imgproc/test/test_templmatch.cpp
Normal file
336
modules/imgproc/test/test_templmatch.cpp
Normal file
@ -0,0 +1,336 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_TemplMatchTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_TemplMatchTest();
|
||||
|
||||
protected:
|
||||
int read_params( CvFileStorage* fs );
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
|
||||
int max_template_size;
|
||||
int method;
|
||||
bool test_cpp;
|
||||
};
|
||||
|
||||
|
||||
CV_TemplMatchTest::CV_TemplMatchTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
element_wise_relative_error = false;
|
||||
max_template_size = 100;
|
||||
method = 0;
|
||||
test_cpp = false;
|
||||
}
|
||||
|
||||
|
||||
int CV_TemplMatchTest::read_params( CvFileStorage* fs )
|
||||
{
|
||||
int code = cvtest::ArrayTest::read_params( fs );
|
||||
if( code < 0 )
|
||||
return code;
|
||||
|
||||
max_template_size = cvReadInt( find_param( fs, "max_template_size" ), max_template_size );
|
||||
max_template_size = cvtest::clipInt( max_template_size, 1, 100 );
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
void CV_TemplMatchTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
|
||||
{
|
||||
cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
if( depth == CV_32F )
|
||||
{
|
||||
low = Scalar::all(-10.);
|
||||
high = Scalar::all(10.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_TemplMatchTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int depth = cvtest::randInt(rng) % 2, cn = cvtest::randInt(rng) & 1 ? 3 : 1;
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
depth = depth == 0 ? CV_8U : CV_32F;
|
||||
|
||||
types[INPUT][0] = types[INPUT][1] = CV_MAKETYPE(depth,cn);
|
||||
types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_32FC1;
|
||||
|
||||
sizes[INPUT][1].width = cvtest::randInt(rng)%MIN(sizes[INPUT][1].width,max_template_size) + 1;
|
||||
sizes[INPUT][1].height = cvtest::randInt(rng)%MIN(sizes[INPUT][1].height,max_template_size) + 1;
|
||||
sizes[OUTPUT][0].width = sizes[INPUT][0].width - sizes[INPUT][1].width + 1;
|
||||
sizes[OUTPUT][0].height = sizes[INPUT][0].height - sizes[INPUT][1].height + 1;
|
||||
sizes[REF_OUTPUT][0] = sizes[OUTPUT][0];
|
||||
|
||||
method = cvtest::randInt(rng)%6;
|
||||
test_cpp = (cvtest::randInt(rng) & 256) == 0;
|
||||
}
|
||||
|
||||
|
||||
double CV_TemplMatchTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
if( test_mat[INPUT][1].depth() == CV_8U ||
|
||||
(method >= CV_TM_CCOEFF && test_mat[INPUT][1].cols*test_mat[INPUT][1].rows <= 2) )
|
||||
return 1e-2;
|
||||
else
|
||||
return 1e-3;
|
||||
}
|
||||
|
||||
|
||||
void CV_TemplMatchTest::run_func()
|
||||
{
|
||||
if(!test_cpp)
|
||||
cvMatchTemplate( test_array[INPUT][0], test_array[INPUT][1], test_array[OUTPUT][0], method );
|
||||
else
|
||||
{
|
||||
cv::Mat _out = cv::cvarrToMat(test_array[OUTPUT][0]);
|
||||
cv::matchTemplate(cv::cvarrToMat(test_array[INPUT][0]), cv::cvarrToMat(test_array[INPUT][1]), _out, method);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void cvTsMatchTemplate( const CvMat* img, const CvMat* templ, CvMat* result, int method )
|
||||
{
|
||||
int i, j, k, l;
|
||||
int depth = CV_MAT_DEPTH(img->type), cn = CV_MAT_CN(img->type);
|
||||
int width_n = templ->cols*cn, height = templ->rows;
|
||||
int a_step = img->step / CV_ELEM_SIZE(img->type & CV_MAT_DEPTH_MASK);
|
||||
int b_step = templ->step / CV_ELEM_SIZE(templ->type & CV_MAT_DEPTH_MASK);
|
||||
CvScalar b_mean, b_sdv;
|
||||
double b_denom = 1., b_sum2 = 0;
|
||||
int area = templ->rows*templ->cols;
|
||||
|
||||
cvAvgSdv(templ, &b_mean, &b_sdv);
|
||||
|
||||
for( i = 0; i < cn; i++ )
|
||||
b_sum2 += (b_sdv.val[i]*b_sdv.val[i] + b_mean.val[i]*b_mean.val[i])*area;
|
||||
|
||||
if( b_sdv.val[0]*b_sdv.val[0] + b_sdv.val[1]*b_sdv.val[1] +
|
||||
b_sdv.val[2]*b_sdv.val[2] + b_sdv.val[3]*b_sdv.val[3] < DBL_EPSILON &&
|
||||
method == CV_TM_CCOEFF_NORMED )
|
||||
{
|
||||
cvSet( result, cvScalarAll(1.) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( method & 1 )
|
||||
{
|
||||
b_denom = 0;
|
||||
if( method != CV_TM_CCOEFF_NORMED )
|
||||
{
|
||||
b_denom = b_sum2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < cn; i++ )
|
||||
b_denom += b_sdv.val[i]*b_sdv.val[i]*area;
|
||||
}
|
||||
b_denom = sqrt(b_denom);
|
||||
if( b_denom == 0 )
|
||||
b_denom = 1.;
|
||||
}
|
||||
|
||||
assert( CV_TM_SQDIFF <= method && method <= CV_TM_CCOEFF_NORMED );
|
||||
|
||||
for( i = 0; i < result->rows; i++ )
|
||||
{
|
||||
for( j = 0; j < result->cols; j++ )
|
||||
{
|
||||
CvScalar a_sum = {{ 0, 0, 0, 0 }}, a_sum2 = {{ 0, 0, 0, 0 }};
|
||||
CvScalar ccorr = {{ 0, 0, 0, 0 }};
|
||||
double value = 0.;
|
||||
|
||||
if( depth == CV_8U )
|
||||
{
|
||||
const uchar* a = img->data.ptr + i*img->step + j*cn;
|
||||
const uchar* b = templ->data.ptr;
|
||||
|
||||
if( cn == 1 || method < CV_TM_CCOEFF )
|
||||
{
|
||||
for( k = 0; k < height; k++, a += a_step, b += b_step )
|
||||
for( l = 0; l < width_n; l++ )
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( k = 0; k < height; k++, a += a_step, b += b_step )
|
||||
for( l = 0; l < width_n; l += 3 )
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
ccorr.val[1] += a[l+1]*b[l+1];
|
||||
ccorr.val[2] += a[l+2]*b[l+2];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum.val[1] += a[l+1];
|
||||
a_sum.val[2] += a[l+2];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
a_sum2.val[1] += a[l+1]*a[l+1];
|
||||
a_sum2.val[2] += a[l+2]*a[l+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const float* a = (const float*)(img->data.ptr + i*img->step) + j*cn;
|
||||
const float* b = (const float*)templ->data.ptr;
|
||||
|
||||
if( cn == 1 || method < CV_TM_CCOEFF )
|
||||
{
|
||||
for( k = 0; k < height; k++, a += a_step, b += b_step )
|
||||
for( l = 0; l < width_n; l++ )
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( k = 0; k < height; k++, a += a_step, b += b_step )
|
||||
for( l = 0; l < width_n; l += 3 )
|
||||
{
|
||||
ccorr.val[0] += a[l]*b[l];
|
||||
ccorr.val[1] += a[l+1]*b[l+1];
|
||||
ccorr.val[2] += a[l+2]*b[l+2];
|
||||
a_sum.val[0] += a[l];
|
||||
a_sum.val[1] += a[l+1];
|
||||
a_sum.val[2] += a[l+2];
|
||||
a_sum2.val[0] += a[l]*a[l];
|
||||
a_sum2.val[1] += a[l+1]*a[l+1];
|
||||
a_sum2.val[2] += a[l+2]*a[l+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( method )
|
||||
{
|
||||
case CV_TM_CCORR:
|
||||
case CV_TM_CCORR_NORMED:
|
||||
value = ccorr.val[0];
|
||||
break;
|
||||
case CV_TM_SQDIFF:
|
||||
case CV_TM_SQDIFF_NORMED:
|
||||
value = (a_sum2.val[0] + b_sum2 - 2*ccorr.val[0]);
|
||||
break;
|
||||
default:
|
||||
value = (ccorr.val[0] - a_sum.val[0]*b_mean.val[0]+
|
||||
ccorr.val[1] - a_sum.val[1]*b_mean.val[1]+
|
||||
ccorr.val[2] - a_sum.val[2]*b_mean.val[2]);
|
||||
}
|
||||
|
||||
if( method & 1 )
|
||||
{
|
||||
double denom;
|
||||
|
||||
// calc denominator
|
||||
if( method != CV_TM_CCOEFF_NORMED )
|
||||
{
|
||||
denom = a_sum2.val[0] + a_sum2.val[1] + a_sum2.val[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
denom = a_sum2.val[0] - (a_sum.val[0]*a_sum.val[0])/area;
|
||||
denom += a_sum2.val[1] - (a_sum.val[1]*a_sum.val[1])/area;
|
||||
denom += a_sum2.val[2] - (a_sum.val[2]*a_sum.val[2])/area;
|
||||
}
|
||||
denom = sqrt(MAX(denom,0))*b_denom;
|
||||
if( fabs(value) < denom )
|
||||
value /= denom;
|
||||
else if( fabs(value) < denom*1.125 )
|
||||
value = value > 0 ? 1 : -1;
|
||||
else
|
||||
value = method != CV_TM_SQDIFF_NORMED ? 0 : 1;
|
||||
}
|
||||
|
||||
((float*)(result->data.ptr + result->step*i))[j] = (float)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_TemplMatchTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
CvMat _input = test_mat[INPUT][0], _templ = test_mat[INPUT][1];
|
||||
CvMat _output = test_mat[REF_OUTPUT][0];
|
||||
cvTsMatchTemplate( &_input, &_templ, &_output, method );
|
||||
|
||||
//if( ts->get_current_test_info()->test_case_idx == 0 )
|
||||
/*{
|
||||
CvFileStorage* fs = cvOpenFileStorage( "_match_template.yml", 0, CV_STORAGE_WRITE );
|
||||
cvWrite( fs, "image", &test_mat[INPUT][0] );
|
||||
cvWrite( fs, "template", &test_mat[INPUT][1] );
|
||||
cvWrite( fs, "ref", &test_mat[REF_OUTPUT][0] );
|
||||
cvWrite( fs, "opencv", &test_mat[OUTPUT][0] );
|
||||
cvWriteInt( fs, "method", method );
|
||||
cvReleaseFileStorage( &fs );
|
||||
}*/
|
||||
|
||||
if( method >= CV_TM_CCOEFF )
|
||||
{
|
||||
// avoid numerical stability problems in singular cases (when the results are near to 0)
|
||||
const double delta = 10.;
|
||||
test_mat[REF_OUTPUT][0] += Scalar::all(delta);
|
||||
test_mat[OUTPUT][0] += Scalar::all(delta);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Imgproc_MatchTemplate, accuracy) { CV_TemplMatchTest test; test.safe_run(); }
|
217
modules/imgproc/test/test_thresh.cpp
Normal file
217
modules/imgproc/test/test_thresh.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_ThreshTest : public cvtest::ArrayTest
|
||||
{
|
||||
public:
|
||||
CV_ThreshTest();
|
||||
|
||||
protected:
|
||||
void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
|
||||
double get_success_error_level( int test_case_idx, int i, int j );
|
||||
void run_func();
|
||||
void prepare_to_validation( int );
|
||||
|
||||
int thresh_type;
|
||||
float thresh_val;
|
||||
float max_val;
|
||||
};
|
||||
|
||||
|
||||
CV_ThreshTest::CV_ThreshTest()
|
||||
{
|
||||
test_array[INPUT].push_back(NULL);
|
||||
test_array[OUTPUT].push_back(NULL);
|
||||
test_array[REF_OUTPUT].push_back(NULL);
|
||||
optional_mask = false;
|
||||
element_wise_relative_error = true;
|
||||
}
|
||||
|
||||
|
||||
void CV_ThreshTest::get_test_array_types_and_sizes( int test_case_idx,
|
||||
vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||
{
|
||||
RNG& rng = ts->get_rng();
|
||||
int depth = cvtest::randInt(rng) % 2, cn = cvtest::randInt(rng) % 4 + 1;
|
||||
cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
|
||||
depth = depth == 0 ? CV_8U : CV_32F;
|
||||
|
||||
types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_MAKETYPE(depth,cn);
|
||||
thresh_type = cvtest::randInt(rng) % 5;
|
||||
|
||||
if( depth == CV_8U )
|
||||
{
|
||||
thresh_val = (float)(cvtest::randReal(rng)*350. - 50.);
|
||||
max_val = (float)(cvtest::randReal(rng)*350. - 50.);
|
||||
if( cvtest::randInt(rng)%4 == 0 )
|
||||
max_val = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
thresh_val = (float)(cvtest::randReal(rng)*1000. - 500.);
|
||||
max_val = (float)(cvtest::randReal(rng)*1000. - 500.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double CV_ThreshTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
|
||||
{
|
||||
return FLT_EPSILON*10;
|
||||
}
|
||||
|
||||
|
||||
void CV_ThreshTest::run_func()
|
||||
{
|
||||
cvThreshold( test_array[INPUT][0], test_array[OUTPUT][0],
|
||||
thresh_val, max_val, thresh_type );
|
||||
}
|
||||
|
||||
|
||||
static void test_threshold( const Mat& _src, Mat& _dst,
|
||||
float thresh, float maxval, int thresh_type )
|
||||
{
|
||||
int i, j;
|
||||
int depth = _src.depth(), cn = _src.channels();
|
||||
int width_n = _src.cols*cn, height = _src.rows;
|
||||
int ithresh = cvFloor(thresh), ithresh2, imaxval = cvRound(maxval);
|
||||
const uchar* src = _src.data;
|
||||
uchar* dst = _dst.data;
|
||||
size_t srcstep = _src.step, dststep = _dst.step;
|
||||
|
||||
ithresh2 = saturate_cast<uchar>(ithresh);
|
||||
imaxval = saturate_cast<uchar>(imaxval);
|
||||
|
||||
assert( depth == CV_8U || depth == CV_32F );
|
||||
|
||||
switch( thresh_type )
|
||||
{
|
||||
case CV_THRESH_BINARY:
|
||||
for( i = 0; i < height; i++, src += srcstep, dst += dststep )
|
||||
{
|
||||
if( depth == CV_8U )
|
||||
for( j = 0; j < width_n; j++ )
|
||||
dst[j] = (uchar)(src[j] > ithresh ? imaxval : 0);
|
||||
else
|
||||
for( j = 0; j < width_n; j++ )
|
||||
((float*)dst)[j] = ((const float*)src)[j] > thresh ? maxval : 0.f;
|
||||
}
|
||||
break;
|
||||
case CV_THRESH_BINARY_INV:
|
||||
for( i = 0; i < height; i++, src += srcstep, dst += dststep )
|
||||
{
|
||||
if( depth == CV_8U )
|
||||
for( j = 0; j < width_n; j++ )
|
||||
dst[j] = (uchar)(src[j] > ithresh ? 0 : imaxval);
|
||||
else
|
||||
for( j = 0; j < width_n; j++ )
|
||||
((float*)dst)[j] = ((const float*)src)[j] > thresh ? 0.f : maxval;
|
||||
}
|
||||
break;
|
||||
case CV_THRESH_TRUNC:
|
||||
for( i = 0; i < height; i++, src += srcstep, dst += dststep )
|
||||
{
|
||||
if( depth == CV_8U )
|
||||
for( j = 0; j < width_n; j++ )
|
||||
{
|
||||
int s = src[j];
|
||||
dst[j] = (uchar)(s > ithresh ? ithresh2 : s);
|
||||
}
|
||||
else
|
||||
for( j = 0; j < width_n; j++ )
|
||||
{
|
||||
float s = ((const float*)src)[j];
|
||||
((float*)dst)[j] = s > thresh ? thresh : s;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CV_THRESH_TOZERO:
|
||||
for( i = 0; i < height; i++, src += srcstep, dst += dststep )
|
||||
{
|
||||
if( depth == CV_8U )
|
||||
for( j = 0; j < width_n; j++ )
|
||||
{
|
||||
int s = src[j];
|
||||
dst[j] = (uchar)(s > ithresh ? s : 0);
|
||||
}
|
||||
else
|
||||
for( j = 0; j < width_n; j++ )
|
||||
{
|
||||
float s = ((const float*)src)[j];
|
||||
((float*)dst)[j] = s > thresh ? s : 0.f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CV_THRESH_TOZERO_INV:
|
||||
for( i = 0; i < height; i++, src += srcstep, dst += dststep )
|
||||
{
|
||||
if( depth == CV_8U )
|
||||
for( j = 0; j < width_n; j++ )
|
||||
{
|
||||
int s = src[j];
|
||||
dst[j] = (uchar)(s > ithresh ? 0 : s);
|
||||
}
|
||||
else
|
||||
for( j = 0; j < width_n; j++ )
|
||||
{
|
||||
float s = ((const float*)src)[j];
|
||||
((float*)dst)[j] = s > thresh ? 0.f : s;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CV_ThreshTest::prepare_to_validation( int /*test_case_idx*/ )
|
||||
{
|
||||
test_threshold( test_mat[INPUT][0], test_mat[REF_OUTPUT][0],
|
||||
thresh_val, max_val, thresh_type );
|
||||
}
|
||||
|
||||
TEST(Imgproc_Threshold, accuracy) { CV_ThreshTest test; test.safe_run(); }
|
||||
|
133
modules/imgproc/test/test_watershed.cpp
Normal file
133
modules/imgproc/test/test_watershed.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of the copyright holders may not 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 Intel Corporation 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"
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class CV_WatershedTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_WatershedTest();
|
||||
~CV_WatershedTest();
|
||||
protected:
|
||||
void run(int);
|
||||
};
|
||||
|
||||
CV_WatershedTest::CV_WatershedTest() {}
|
||||
CV_WatershedTest::~CV_WatershedTest() {}
|
||||
|
||||
void CV_WatershedTest::run( int /* start_from */)
|
||||
{
|
||||
string exp_path = string(ts->get_data_path()) + "watershed/wshed_exp.png";
|
||||
Mat exp = imread(exp_path, 0);
|
||||
Mat orig = imread(string(ts->get_data_path()) + "inpaint/orig.jpg");
|
||||
FileStorage fs(string(ts->get_data_path()) + "watershed/comp.xml", FileStorage::READ);
|
||||
|
||||
if (orig.empty() || !fs.isOpened())
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
|
||||
return;
|
||||
}
|
||||
|
||||
CvSeq* cnts = (CvSeq*)fs["contours"].readObj();
|
||||
|
||||
Mat markers(orig.size(), CV_32SC1);
|
||||
markers = Scalar(0);
|
||||
IplImage iplmrks = markers;
|
||||
|
||||
vector<unsigned char> colors(1);
|
||||
for(int i = 0; cnts != 0; cnts = cnts->h_next, ++i )
|
||||
{
|
||||
cvDrawContours( &iplmrks, cnts, Scalar::all(i + 1), Scalar::all(i + 1), -1, CV_FILLED);
|
||||
Point* p = (Point*)cvGetSeqElem(cnts, 0);
|
||||
|
||||
//expected image was added with 1 in order to save to png
|
||||
//so now we substract 1 to get real color
|
||||
if(exp.data)
|
||||
colors.push_back(exp.ptr(p->y)[p->x] - 1);
|
||||
}
|
||||
fs.release();
|
||||
const int compNum = (int)(colors.size() - 1);
|
||||
|
||||
watershed(orig, markers);
|
||||
|
||||
for(int j = 0; j < markers.rows; ++j)
|
||||
{
|
||||
int* line = markers.ptr<int>(j);
|
||||
for(int i = 0; i < markers.cols; ++i)
|
||||
{
|
||||
int& pixel = line[i];
|
||||
|
||||
if (pixel == -1) // border
|
||||
continue;
|
||||
|
||||
if (pixel <= 0 || pixel > compNum)
|
||||
continue; // bad result, doing nothing and going to get error latter;
|
||||
|
||||
// repaint in saved color to compare with expected;
|
||||
if(exp.data)
|
||||
pixel = colors[pixel];
|
||||
}
|
||||
}
|
||||
|
||||
Mat markers8U;
|
||||
markers.convertTo(markers8U, CV_8U, 1, 1);
|
||||
|
||||
if( exp.empty() || orig.size() != exp.size() )
|
||||
{
|
||||
imwrite(exp_path, markers8U);
|
||||
exp = markers8U;
|
||||
}
|
||||
|
||||
if (0 != norm(markers8U, exp, NORM_INF))
|
||||
{
|
||||
ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
|
||||
return;
|
||||
}
|
||||
ts->set_failed_test_info(cvtest::TS::OK);
|
||||
}
|
||||
|
||||
TEST(Imgproc_Watershed, regression) { CV_WatershedTest test; test.safe_run(); }
|
||||
|
327
modules/ml/test/test_emknearestkmeans.cpp
Normal file
327
modules/ml/test/test_emknearestkmeans.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void defaultDistribs( vector<Mat>& means, vector<Mat>& covs )
|
||||
{
|
||||
float mp0[] = {0.0f, 0.0f}, cp0[] = {0.67f, 0.0f, 0.0f, 0.67f};
|
||||
float mp1[] = {5.0f, 0.0f}, cp1[] = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||
float mp2[] = {1.0f, 5.0f}, cp2[] = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||
Mat m0( 1, 2, CV_32FC1, mp0 ), c0( 2, 2, CV_32FC1, cp0 );
|
||||
Mat m1( 1, 2, CV_32FC1, mp1 ), c1( 2, 2, CV_32FC1, cp1 );
|
||||
Mat m2( 1, 2, CV_32FC1, mp2 ), c2( 2, 2, CV_32FC1, cp2 );
|
||||
means.resize(3), covs.resize(3);
|
||||
m0.copyTo(means[0]), c0.copyTo(covs[0]);
|
||||
m1.copyTo(means[1]), c1.copyTo(covs[1]);
|
||||
m2.copyTo(means[2]), c2.copyTo(covs[2]);
|
||||
}
|
||||
|
||||
// generate points sets by normal distributions
|
||||
void generateData( Mat& data, Mat& labels, const vector<int>& sizes, const vector<Mat>& means, const vector<Mat>& covs, int labelType )
|
||||
{
|
||||
vector<int>::const_iterator sit = sizes.begin();
|
||||
int total = 0;
|
||||
for( ; sit != sizes.end(); ++sit )
|
||||
total += *sit;
|
||||
assert( means.size() == sizes.size() && covs.size() == sizes.size() );
|
||||
assert( !data.empty() && data.rows == total );
|
||||
assert( data.type() == CV_32FC1 );
|
||||
|
||||
labels.create( data.rows, 1, labelType );
|
||||
|
||||
randn( data, Scalar::all(0.0), Scalar::all(1.0) );
|
||||
vector<Mat>::const_iterator mit = means.begin(), cit = covs.begin();
|
||||
int bi, ei = 0;
|
||||
sit = sizes.begin();
|
||||
for( int p = 0, l = 0; sit != sizes.end(); ++sit, ++mit, ++cit, l++ )
|
||||
{
|
||||
bi = ei;
|
||||
ei = bi + *sit;
|
||||
assert( mit->rows == 1 && mit->cols == data.cols );
|
||||
assert( cit->rows == data.cols && cit->cols == data.cols );
|
||||
for( int i = bi; i < ei; i++, p++ )
|
||||
{
|
||||
Mat r(1, data.cols, CV_32FC1, data.ptr<float>(i));
|
||||
r = r * (*cit) + *mit;
|
||||
if( labelType == CV_32FC1 )
|
||||
labels.at<float>(p, 0) = (float)l;
|
||||
else
|
||||
labels.at<int>(p, 0) = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int maxIdx( const vector<int>& count )
|
||||
{
|
||||
int idx = -1;
|
||||
int maxVal = -1;
|
||||
vector<int>::const_iterator it = count.begin();
|
||||
for( int i = 0; it != count.end(); ++it, i++ )
|
||||
{
|
||||
if( *it > maxVal)
|
||||
{
|
||||
maxVal = *it;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
assert( idx >= 0);
|
||||
return idx;
|
||||
}
|
||||
|
||||
bool getLabelsMap( const Mat& labels, const vector<int>& sizes, vector<int>& labelsMap )
|
||||
{
|
||||
int total = 0, setCount = (int)sizes.size();
|
||||
vector<int>::const_iterator sit = sizes.begin();
|
||||
for( ; sit != sizes.end(); ++sit )
|
||||
total += *sit;
|
||||
assert( !labels.empty() );
|
||||
assert( labels.rows == total && labels.cols == 1 );
|
||||
assert( labels.type() == CV_32SC1 || labels.type() == CV_32FC1 );
|
||||
|
||||
bool isFlt = labels.type() == CV_32FC1;
|
||||
labelsMap.resize(setCount);
|
||||
vector<int>::iterator lmit = labelsMap.begin();
|
||||
vector<bool> buzy(setCount, false);
|
||||
int bi, ei = 0;
|
||||
for( sit = sizes.begin(); sit != sizes.end(); ++sit, ++lmit )
|
||||
{
|
||||
vector<int> count( setCount, 0 );
|
||||
bi = ei;
|
||||
ei = bi + *sit;
|
||||
if( isFlt )
|
||||
{
|
||||
for( int i = bi; i < ei; i++ )
|
||||
count[(int)labels.at<float>(i, 0)]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = bi; i < ei; i++ )
|
||||
count[labels.at<int>(i, 0)]++;
|
||||
}
|
||||
|
||||
*lmit = maxIdx( count );
|
||||
if( buzy[*lmit] )
|
||||
return false;
|
||||
buzy[*lmit] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float calcErr( const Mat& labels, const Mat& origLabels, const vector<int>& sizes, bool labelsEquivalent = true )
|
||||
{
|
||||
int err = 0;
|
||||
assert( !labels.empty() && !origLabels.empty() );
|
||||
assert( labels.cols == 1 && origLabels.cols == 1 );
|
||||
assert( labels.rows == origLabels.rows );
|
||||
assert( labels.type() == origLabels.type() );
|
||||
assert( labels.type() == CV_32SC1 || labels.type() == CV_32FC1 );
|
||||
|
||||
vector<int> labelsMap;
|
||||
bool isFlt = labels.type() == CV_32FC1;
|
||||
if( !labelsEquivalent )
|
||||
{
|
||||
getLabelsMap( labels, sizes, labelsMap );
|
||||
for( int i = 0; i < labels.rows; i++ )
|
||||
if( isFlt )
|
||||
err += labels.at<float>(i, 0) != labelsMap[(int)origLabels.at<float>(i, 0)];
|
||||
else
|
||||
err += labels.at<int>(i, 0) != labelsMap[origLabels.at<int>(i, 0)];
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < labels.rows; i++ )
|
||||
if( isFlt )
|
||||
err += labels.at<float>(i, 0) != origLabels.at<float>(i, 0);
|
||||
else
|
||||
err += labels.at<int>(i, 0) != origLabels.at<int>(i, 0);
|
||||
}
|
||||
return (float)err / (float)labels.rows;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
class CV_KMeansTest : public cvtest::BaseTest {
|
||||
public:
|
||||
CV_KMeansTest() {}
|
||||
protected:
|
||||
virtual void run( int start_from );
|
||||
};
|
||||
|
||||
void CV_KMeansTest::run( int /*start_from*/ )
|
||||
{
|
||||
const int iters = 100;
|
||||
int sizesArr[] = { 5000, 7000, 8000 };
|
||||
int pointsCount = sizesArr[0]+ sizesArr[1] + sizesArr[2];
|
||||
|
||||
Mat data( pointsCount, 2, CV_32FC1 ), labels;
|
||||
vector<int> sizes( sizesArr, sizesArr + sizeof(sizesArr) / sizeof(sizesArr[0]) );
|
||||
vector<Mat> means, covs;
|
||||
defaultDistribs( means, covs );
|
||||
generateData( data, labels, sizes, means, covs, CV_32SC1 );
|
||||
|
||||
int code = cvtest::TS::OK;
|
||||
Mat bestLabels;
|
||||
// 1. flag==KMEANS_PP_CENTERS
|
||||
kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_PP_CENTERS, 0 );
|
||||
if( calcErr( bestLabels, labels, sizes, false ) > 0.01f )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy if flag==KMEANS_PP_CENTERS" );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
// 2. flag==KMEANS_RANDOM_CENTERS
|
||||
kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_RANDOM_CENTERS, 0 );
|
||||
if( calcErr( bestLabels, labels, sizes, false ) > 0.01f )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy if flag==KMEANS_PP_CENTERS" );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
// 3. flag==KMEANS_USE_INITIAL_LABELS
|
||||
labels.copyTo( bestLabels );
|
||||
RNG rng;
|
||||
for( int i = 0; i < 0.5f * pointsCount; i++ )
|
||||
bestLabels.at<int>( rng.next() % pointsCount, 0 ) = rng.next() % 3;
|
||||
kmeans( data, 3, bestLabels, TermCriteria( TermCriteria::COUNT, iters, 0.0), 0, KMEANS_USE_INITIAL_LABELS, 0 );
|
||||
if( calcErr( bestLabels, labels, sizes, false ) > 0.01f )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy if flag==KMEANS_PP_CENTERS" );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
class CV_KNearestTest : public cvtest::BaseTest {
|
||||
public:
|
||||
CV_KNearestTest() {}
|
||||
protected:
|
||||
virtual void run( int start_from );
|
||||
};
|
||||
|
||||
void CV_KNearestTest::run( int /*start_from*/ )
|
||||
{
|
||||
int sizesArr[] = { 500, 700, 800 };
|
||||
int pointsCount = sizesArr[0]+ sizesArr[1] + sizesArr[2];
|
||||
|
||||
// train data
|
||||
Mat trainData( pointsCount, 2, CV_32FC1 ), trainLabels;
|
||||
vector<int> sizes( sizesArr, sizesArr + sizeof(sizesArr) / sizeof(sizesArr[0]) );
|
||||
vector<Mat> means, covs;
|
||||
defaultDistribs( means, covs );
|
||||
generateData( trainData, trainLabels, sizes, means, covs, CV_32FC1 );
|
||||
|
||||
// test data
|
||||
Mat testData( pointsCount, 2, CV_32FC1 ), testLabels, bestLabels;
|
||||
generateData( testData, testLabels, sizes, means, covs, CV_32FC1 );
|
||||
|
||||
int code = cvtest::TS::OK;
|
||||
KNearest knearest;
|
||||
knearest.train( trainData, trainLabels );
|
||||
knearest.find_nearest( testData, 4, &bestLabels );
|
||||
if( calcErr( bestLabels, testLabels, sizes, true ) > 0.01f )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy on test data" );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
class CV_EMTest : public cvtest::BaseTest {
|
||||
public:
|
||||
CV_EMTest() {}
|
||||
protected:
|
||||
virtual void run( int start_from );
|
||||
};
|
||||
|
||||
void CV_EMTest::run( int /*start_from*/ )
|
||||
{
|
||||
int sizesArr[] = { 5000, 7000, 8000 };
|
||||
int pointsCount = sizesArr[0]+ sizesArr[1] + sizesArr[2];
|
||||
|
||||
// train data
|
||||
Mat trainData( pointsCount, 2, CV_32FC1 ), trainLabels;
|
||||
vector<int> sizes( sizesArr, sizesArr + sizeof(sizesArr) / sizeof(sizesArr[0]) );
|
||||
vector<Mat> means, covs;
|
||||
defaultDistribs( means, covs );
|
||||
generateData( trainData, trainLabels, sizes, means, covs, CV_32SC1 );
|
||||
|
||||
// test data
|
||||
Mat testData( pointsCount, 2, CV_32FC1 ), testLabels, bestLabels;
|
||||
generateData( testData, testLabels, sizes, means, covs, CV_32SC1 );
|
||||
|
||||
int code = cvtest::TS::OK;
|
||||
ExpectationMaximization em;
|
||||
CvEMParams params;
|
||||
params.nclusters = 3;
|
||||
em.train( trainData, Mat(), params, &bestLabels );
|
||||
|
||||
// check train error
|
||||
if( calcErr( bestLabels, trainLabels, sizes, true ) > 0.002f )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy on train data" );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
// check test error
|
||||
bestLabels.create( testData.rows, 1, CV_32SC1 );
|
||||
for( int i = 0; i < testData.rows; i++ )
|
||||
{
|
||||
Mat sample( 1, testData.cols, CV_32FC1, testData.ptr<float>(i));
|
||||
bestLabels.at<int>(i,0) = (int)em.predict( sample, 0 );
|
||||
}
|
||||
if( calcErr( bestLabels, testLabels, sizes, true ) > 0.005f )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "bad accuracy on test data" );
|
||||
code = cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
TEST(ML_KMeans, accuracy) { CV_KMeansTest test; test.safe_run(); }
|
||||
TEST(ML_KNearest, accuracy) { CV_KNearestTest test; test.safe_run(); }
|
||||
TEST(ML_EMTest, accuracy) { CV_EMTest test; test.safe_run(); }
|
275
modules/ml/test/test_gbttest.cpp
Normal file
275
modules/ml/test/test_gbttest.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
class CV_GBTreesTest : public cvtest::BaseTest
|
||||
{
|
||||
public:
|
||||
CV_GBTreesTest();
|
||||
~CV_GBTreesTest();
|
||||
|
||||
protected:
|
||||
void run(int);
|
||||
|
||||
int TestTrainPredict(int test_num);
|
||||
int TestSaveLoad();
|
||||
|
||||
int checkPredictError(int test_num);
|
||||
int checkLoadSave();
|
||||
|
||||
//string model_file_name1;
|
||||
//string model_file_name2;
|
||||
char model_file_name1[50];
|
||||
char model_file_name2[50];
|
||||
string* datasets;
|
||||
string data_path;
|
||||
|
||||
CvMLData* data;
|
||||
CvGBTrees* gtb;
|
||||
|
||||
vector<float> test_resps1;
|
||||
vector<float> test_resps2;
|
||||
};
|
||||
|
||||
|
||||
int _get_len(const CvMat* mat)
|
||||
{
|
||||
return (mat->cols > mat->rows) ? mat->cols : mat->rows;
|
||||
}
|
||||
|
||||
|
||||
CV_GBTreesTest::CV_GBTreesTest()
|
||||
{
|
||||
datasets = 0;
|
||||
data = 0;
|
||||
gtb = 0;
|
||||
}
|
||||
|
||||
CV_GBTreesTest::~CV_GBTreesTest()
|
||||
{
|
||||
if (data)
|
||||
delete data;
|
||||
delete[] datasets;
|
||||
}
|
||||
|
||||
|
||||
int CV_GBTreesTest::TestTrainPredict(int test_num)
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
int weak_count = 200;
|
||||
float shrinkage = 0.1f;
|
||||
float subsample_portion = 0.5f;
|
||||
int max_depth = 5;
|
||||
bool use_surrogates = true;
|
||||
int loss_function_type = 0;
|
||||
switch (test_num)
|
||||
{
|
||||
case (1) : loss_function_type = CvGBTrees::SQUARED_LOSS; break;
|
||||
case (2) : loss_function_type = CvGBTrees::ABSOLUTE_LOSS; break;
|
||||
case (3) : loss_function_type = CvGBTrees::HUBER_LOSS; break;
|
||||
case (0) : loss_function_type = CvGBTrees::DEVIANCE_LOSS; break;
|
||||
default :
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Bad test_num value in CV_GBTreesTest::TestTrainPredict(..) function." );
|
||||
return cvtest::TS::FAIL_BAD_ARG_CHECK;
|
||||
}
|
||||
}
|
||||
|
||||
int dataset_num = test_num == 0 ? 0 : 1;
|
||||
if (!data)
|
||||
{
|
||||
data = new CvMLData();
|
||||
data->set_delimiter(',');
|
||||
|
||||
if (data->read_csv(datasets[dataset_num].c_str()))
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "File reading error." );
|
||||
return cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
|
||||
if (test_num == 0)
|
||||
{
|
||||
data->set_response_idx(57);
|
||||
data->set_var_types("ord[0-56],cat[57]");
|
||||
}
|
||||
else
|
||||
{
|
||||
data->set_response_idx(13);
|
||||
data->set_var_types("ord[0-2,4-13],cat[3]");
|
||||
subsample_portion = 0.7f;
|
||||
}
|
||||
|
||||
int train_sample_count = cvFloor(_get_len(data->get_responses())*0.5f);
|
||||
CvTrainTestSplit spl( train_sample_count );
|
||||
data->set_train_test_split( &spl );
|
||||
}
|
||||
|
||||
data->mix_train_and_test_idx();
|
||||
|
||||
|
||||
if (gtb) delete gtb;
|
||||
gtb = new CvGBTrees();
|
||||
bool tmp_code = true;
|
||||
tmp_code = gtb->train(data, CvGBTreesParams(loss_function_type, weak_count,
|
||||
shrinkage, subsample_portion,
|
||||
max_depth, use_surrogates));
|
||||
|
||||
if (!tmp_code)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Model training was failed.");
|
||||
return cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
|
||||
code = checkPredictError(test_num);
|
||||
|
||||
return code;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int CV_GBTreesTest::checkPredictError(int test_num)
|
||||
{
|
||||
if (!gtb)
|
||||
return cvtest::TS::FAIL_GENERIC;
|
||||
|
||||
float mean[] = {5.430247f, 13.5654f, 12.6569f, 13.1661f};
|
||||
float sigma[] = {0.4162694f, 3.21161f, 3.43297f, 3.00624f};
|
||||
|
||||
float current_error = gtb->calc_error(data, CV_TEST_ERROR);
|
||||
|
||||
if ( abs( current_error - mean[test_num]) > 6*sigma[test_num] )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Test error is out of range:\n"
|
||||
"abs(%f/*curEr*/ - %f/*mean*/ > %f/*6*sigma*/",
|
||||
current_error, mean[test_num], 6*sigma[test_num] );
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
|
||||
return cvtest::TS::OK;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int CV_GBTreesTest::TestSaveLoad()
|
||||
{
|
||||
if (!gtb)
|
||||
return cvtest::TS::FAIL_GENERIC;
|
||||
|
||||
tmpnam(model_file_name1);
|
||||
tmpnam(model_file_name2);
|
||||
|
||||
if(model_file_name1[0] == '\\')
|
||||
model_file_name1[0] = '_';
|
||||
if(model_file_name2[0] == '\\')
|
||||
model_file_name2[0] = '_';
|
||||
|
||||
gtb->save(model_file_name1);
|
||||
gtb->calc_error(data, CV_TEST_ERROR, &test_resps1);
|
||||
gtb->load(model_file_name1);
|
||||
gtb->calc_error(data, CV_TEST_ERROR, &test_resps2);
|
||||
gtb->save(model_file_name2);
|
||||
|
||||
return checkLoadSave();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CV_GBTreesTest::checkLoadSave()
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
// 1. compare files
|
||||
ifstream f1( model_file_name1 ), f2( model_file_name2 );
|
||||
string s1, s2;
|
||||
int lineIdx = 0;
|
||||
CV_Assert( f1.is_open() && f2.is_open() );
|
||||
for( ; !f1.eof() && !f2.eof(); lineIdx++ )
|
||||
{
|
||||
getline( f1, s1 );
|
||||
getline( f2, s2 );
|
||||
if( s1.compare(s2) )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "first and second saved files differ in %n-line; first %n line: %s; second %n-line: %s",
|
||||
lineIdx, lineIdx, s1.c_str(), lineIdx, s2.c_str() );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
}
|
||||
if( !f1.eof() || !f2.eof() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "First and second saved files differ in %n-line; first %n line: %s; second %n-line: %s",
|
||||
lineIdx, lineIdx, s1.c_str(), lineIdx, s2.c_str() );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
f1.close();
|
||||
f2.close();
|
||||
// delete temporary files
|
||||
remove( model_file_name1 );
|
||||
remove( model_file_name2 );
|
||||
|
||||
// 2. compare responses
|
||||
CV_Assert( test_resps1.size() == test_resps2.size() );
|
||||
vector<float>::const_iterator it1 = test_resps1.begin(), it2 = test_resps2.begin();
|
||||
for( ; it1 != test_resps1.end(); ++it1, ++it2 )
|
||||
{
|
||||
if( fabs(*it1 - *it2) > FLT_EPSILON )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "Responses predicted before saving and after loading are different" );
|
||||
code = cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CV_GBTreesTest::run(int)
|
||||
{
|
||||
|
||||
string data_path = string(ts->get_data_path());
|
||||
datasets = new string[2];
|
||||
datasets[0] = data_path + string("spambase.data"); /*string("dataset_classification.csv");*/
|
||||
datasets[1] = data_path + string("housing_.data"); /*string("dataset_regression.csv");*/
|
||||
|
||||
int code = cvtest::TS::OK;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
|
||||
int temp_code = TestTrainPredict(i);
|
||||
if (temp_code != cvtest::TS::OK)
|
||||
{
|
||||
code = temp_code;
|
||||
break;
|
||||
}
|
||||
|
||||
else if (i==0)
|
||||
{
|
||||
temp_code = TestSaveLoad();
|
||||
if (temp_code != cvtest::TS::OK)
|
||||
code = temp_code;
|
||||
delete data;
|
||||
data = 0;
|
||||
}
|
||||
|
||||
delete gtb;
|
||||
gtb = 0;
|
||||
}
|
||||
delete data;
|
||||
data = 0;
|
||||
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////// test registration /////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(ML_GBTrees, regression) { CV_GBTreesTest test; test.safe_run(); }
|
3
modules/ml/test/test_main.cpp
Normal file
3
modules/ml/test/test_main.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("ml")
|
130
modules/ml/test/test_mltests.cpp
Normal file
130
modules/ml/test/test_mltests.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
CV_AMLTest::CV_AMLTest( const char* _modelName ) : CV_MLBaseTest( _modelName )
|
||||
{
|
||||
validationFN = "avalidation.xml";
|
||||
}
|
||||
|
||||
int CV_AMLTest::run_test_case( int testCaseIdx )
|
||||
{
|
||||
int code = cvtest::TS::OK;
|
||||
code = prepare_test_case( testCaseIdx );
|
||||
|
||||
if (code == cvtest::TS::OK)
|
||||
{
|
||||
//#define GET_STAT
|
||||
#ifdef GET_STAT
|
||||
const char* data_name = ((CvFileNode*)cvGetSeqElem( dataSetNames, testCaseIdx ))->data.str.ptr;
|
||||
printf("%s, %s ", name, data_name);
|
||||
const int icount = 100;
|
||||
float res[icount];
|
||||
for (int k = 0; k < icount; k++)
|
||||
{
|
||||
#endif
|
||||
data.mix_train_and_test_idx();
|
||||
code = train( testCaseIdx );
|
||||
#ifdef GET_STAT
|
||||
float case_result = get_error();
|
||||
|
||||
res[k] = case_result;
|
||||
}
|
||||
float mean = 0, sigma = 0;
|
||||
for (int k = 0; k < icount; k++)
|
||||
{
|
||||
mean += res[k];
|
||||
}
|
||||
mean = mean /icount;
|
||||
for (int k = 0; k < icount; k++)
|
||||
{
|
||||
sigma += (res[k] - mean)*(res[k] - mean);
|
||||
}
|
||||
sigma = sqrt(sigma/icount);
|
||||
printf("%f, %f\n", mean, sigma);
|
||||
#endif
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int CV_AMLTest::validate_test_results( int testCaseIdx )
|
||||
{
|
||||
int iters;
|
||||
float mean, sigma;
|
||||
// read validation params
|
||||
FileNode resultNode =
|
||||
validationFS.getFirstTopLevelNode()["validation"][modelName][dataSetNames[testCaseIdx]]["result"];
|
||||
resultNode["iter_count"] >> iters;
|
||||
if ( iters > 0)
|
||||
{
|
||||
resultNode["mean"] >> mean;
|
||||
resultNode["sigma"] >> sigma;
|
||||
float curErr = get_error( testCaseIdx, CV_TEST_ERROR );
|
||||
const int coeff = 4;
|
||||
ts->printf( cvtest::TS::LOG, "Test case = %d; test error = %f; mean error = %f (diff=%f), %d*sigma = %f",
|
||||
testCaseIdx, curErr, mean, abs( curErr - mean), coeff, coeff*sigma );
|
||||
if ( abs( curErr - mean) > coeff*sigma )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "abs(%f - %f) > %f - OUT OF RANGE!\n", curErr, mean, coeff*sigma, coeff );
|
||||
return cvtest::TS::FAIL_BAD_ACCURACY;
|
||||
}
|
||||
else
|
||||
ts->printf( cvtest::TS::LOG, ".\n" );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "validation info is not suitable" );
|
||||
return cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
TEST(ML_DTree, regression) { CV_AMLTest test( CV_DTREE ); test.safe_run(); }
|
||||
TEST(ML_Boost, regression) { CV_AMLTest test( CV_BOOST ); test.safe_run(); }
|
||||
TEST(ML_RTrees, regression) { CV_AMLTest test( CV_RTREES ); test.safe_run(); }
|
||||
TEST(ML_ERTrees, regression) { CV_AMLTest test( CV_ERTREES ); test.safe_run(); }
|
||||
|
||||
/* End of file. */
|
796
modules/ml/test/test_mltests2.cpp
Normal file
796
modules/ml/test/test_mltests2.cpp
Normal file
@ -0,0 +1,796 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, 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:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's 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.
|
||||
//
|
||||
// * The name of Intel Corporation may not 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 Intel Corporation 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"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
// auxiliary functions
|
||||
// 1. nbayes
|
||||
void nbayes_check_data( CvMLData* _data )
|
||||
{
|
||||
if( _data->get_missing() )
|
||||
CV_Error( CV_StsBadArg, "missing values are not supported" );
|
||||
const CvMat* var_types = _data->get_var_types();
|
||||
bool is_classifier = var_types->data.ptr[var_types->cols-1] == CV_VAR_CATEGORICAL;
|
||||
if( ( fabs( cvNorm( var_types, 0, CV_L1 ) -
|
||||
(var_types->rows + var_types->cols - 2)*CV_VAR_ORDERED - CV_VAR_CATEGORICAL ) > FLT_EPSILON ) ||
|
||||
!is_classifier )
|
||||
CV_Error( CV_StsBadArg, "incorrect types of predictors or responses" );
|
||||
}
|
||||
bool nbayes_train( CvNormalBayesClassifier* nbayes, CvMLData* _data )
|
||||
{
|
||||
nbayes_check_data( _data );
|
||||
const CvMat* values = _data->get_values();
|
||||
const CvMat* responses = _data->get_responses();
|
||||
const CvMat* train_sidx = _data->get_train_sample_idx();
|
||||
const CvMat* var_idx = _data->get_var_idx();
|
||||
return nbayes->train( values, responses, var_idx, train_sidx );
|
||||
}
|
||||
float nbayes_calc_error( CvNormalBayesClassifier* nbayes, CvMLData* _data, int type, vector<float> *resp )
|
||||
{
|
||||
float err = 0;
|
||||
nbayes_check_data( _data );
|
||||
const CvMat* values = _data->get_values();
|
||||
const CvMat* response = _data->get_responses();
|
||||
const CvMat* sample_idx = (type == CV_TEST_ERROR) ? _data->get_test_sample_idx() : _data->get_train_sample_idx();
|
||||
int* sidx = sample_idx ? sample_idx->data.i : 0;
|
||||
int r_step = CV_IS_MAT_CONT(response->type) ?
|
||||
1 : response->step / CV_ELEM_SIZE(response->type);
|
||||
int sample_count = sample_idx ? sample_idx->cols : 0;
|
||||
sample_count = (type == CV_TRAIN_ERROR && sample_count == 0) ? values->rows : sample_count;
|
||||
float* pred_resp = 0;
|
||||
if( resp && (sample_count > 0) )
|
||||
{
|
||||
resp->resize( sample_count );
|
||||
pred_resp = &((*resp)[0]);
|
||||
}
|
||||
|
||||
for( int i = 0; i < sample_count; i++ )
|
||||
{
|
||||
CvMat sample;
|
||||
int si = sidx ? sidx[i] : i;
|
||||
cvGetRow( values, &sample, si );
|
||||
float r = (float)nbayes->predict( &sample, 0 );
|
||||
if( pred_resp )
|
||||
pred_resp[i] = r;
|
||||
int d = fabs((double)r - response->data.fl[si*r_step]) <= FLT_EPSILON ? 0 : 1;
|
||||
err += d;
|
||||
}
|
||||
err = sample_count ? err / (float)sample_count * 100 : -FLT_MAX;
|
||||
return err;
|
||||
}
|
||||
|
||||
// 2. knearest
|
||||
void knearest_check_data_and_get_predictors( CvMLData* _data, CvMat* _predictors )
|
||||
{
|
||||
const CvMat* values = _data->get_values();
|
||||
const CvMat* var_idx = _data->get_var_idx();
|
||||
if( var_idx->cols + var_idx->rows != values->cols )
|
||||
CV_Error( CV_StsBadArg, "var_idx is not supported" );
|
||||
if( _data->get_missing() )
|
||||
CV_Error( CV_StsBadArg, "missing values are not supported" );
|
||||
int resp_idx = _data->get_response_idx();
|
||||
if( resp_idx == 0)
|
||||
cvGetCols( values, _predictors, 1, values->cols );
|
||||
else if( resp_idx == values->cols - 1 )
|
||||
cvGetCols( values, _predictors, 0, values->cols - 1 );
|
||||
else
|
||||
CV_Error( CV_StsBadArg, "responses must be in the first or last column; other cases are not supported" );
|
||||
}
|
||||
bool knearest_train( CvKNearest* knearest, CvMLData* _data )
|
||||
{
|
||||
const CvMat* responses = _data->get_responses();
|
||||
const CvMat* train_sidx = _data->get_train_sample_idx();
|
||||
bool is_regression = _data->get_var_type( _data->get_response_idx() ) == CV_VAR_ORDERED;
|
||||
CvMat predictors;
|
||||
knearest_check_data_and_get_predictors( _data, &predictors );
|
||||
return knearest->train( &predictors, responses, train_sidx, is_regression );
|
||||
}
|
||||
float knearest_calc_error( CvKNearest* knearest, CvMLData* _data, int k, int type, vector<float> *resp )
|
||||
{
|
||||
float err = 0;
|
||||
const CvMat* response = _data->get_responses();
|
||||
const CvMat* sample_idx = (type == CV_TEST_ERROR) ? _data->get_test_sample_idx() : _data->get_train_sample_idx();
|
||||
int* sidx = sample_idx ? sample_idx->data.i : 0;
|
||||
int r_step = CV_IS_MAT_CONT(response->type) ?
|
||||
1 : response->step / CV_ELEM_SIZE(response->type);
|
||||
bool is_regression = _data->get_var_type( _data->get_response_idx() ) == CV_VAR_ORDERED;
|
||||
CvMat predictors;
|
||||
knearest_check_data_and_get_predictors( _data, &predictors );
|
||||
int sample_count = sample_idx ? sample_idx->cols : 0;
|
||||
sample_count = (type == CV_TRAIN_ERROR && sample_count == 0) ? predictors.rows : sample_count;
|
||||
float* pred_resp = 0;
|
||||
if( resp && (sample_count > 0) )
|
||||
{
|
||||
resp->resize( sample_count );
|
||||
pred_resp = &((*resp)[0]);
|
||||
}
|
||||
if ( !is_regression )
|
||||
{
|
||||
for( int i = 0; i < sample_count; i++ )
|
||||
{
|
||||
CvMat sample;
|
||||
int si = sidx ? sidx[i] : i;
|
||||
cvGetRow( &predictors, &sample, si );
|
||||
float r = knearest->find_nearest( &sample, k );
|
||||
if( pred_resp )
|
||||
pred_resp[i] = r;
|
||||
int d = fabs((double)r - response->data.fl[si*r_step]) <= FLT_EPSILON ? 0 : 1;
|
||||
err += d;
|
||||
}
|
||||
err = sample_count ? err / (float)sample_count * 100 : -FLT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < sample_count; i++ )
|
||||
{
|
||||
CvMat sample;
|
||||
int si = sidx ? sidx[i] : i;
|
||||
cvGetRow( &predictors, &sample, si );
|
||||
float r = knearest->find_nearest( &sample, k );
|
||||
if( pred_resp )
|
||||
pred_resp[i] = r;
|
||||
float d = r - response->data.fl[si*r_step];
|
||||
err += d*d;
|
||||
}
|
||||
err = sample_count ? err / (float)sample_count : -FLT_MAX;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// 3. svm
|
||||
int str_to_svm_type(string& str)
|
||||
{
|
||||
if( !str.compare("C_SVC") )
|
||||
return CvSVM::C_SVC;
|
||||
if( !str.compare("NU_SVC") )
|
||||
return CvSVM::NU_SVC;
|
||||
if( !str.compare("ONE_CLASS") )
|
||||
return CvSVM::ONE_CLASS;
|
||||
if( !str.compare("EPS_SVR") )
|
||||
return CvSVM::EPS_SVR;
|
||||
if( !str.compare("NU_SVR") )
|
||||
return CvSVM::NU_SVR;
|
||||
CV_Error( CV_StsBadArg, "incorrect svm type string" );
|
||||
return -1;
|
||||
}
|
||||
int str_to_svm_kernel_type( string& str )
|
||||
{
|
||||
if( !str.compare("LINEAR") )
|
||||
return CvSVM::LINEAR;
|
||||
if( !str.compare("POLY") )
|
||||
return CvSVM::POLY;
|
||||
if( !str.compare("RBF") )
|
||||
return CvSVM::RBF;
|
||||
if( !str.compare("SIGMOID") )
|
||||
return CvSVM::SIGMOID;
|
||||
CV_Error( CV_StsBadArg, "incorrect svm type string" );
|
||||
return -1;
|
||||
}
|
||||
void svm_check_data( CvMLData* _data )
|
||||
{
|
||||
if( _data->get_missing() )
|
||||
CV_Error( CV_StsBadArg, "missing values are not supported" );
|
||||
const CvMat* var_types = _data->get_var_types();
|
||||
for( int i = 0; i < var_types->cols-1; i++ )
|
||||
if (var_types->data.ptr[i] == CV_VAR_CATEGORICAL)
|
||||
{
|
||||
char msg[50];
|
||||
sprintf( msg, "incorrect type of %d-predictor", i );
|
||||
CV_Error( CV_StsBadArg, msg );
|
||||
}
|
||||
}
|
||||
bool svm_train( CvSVM* svm, CvMLData* _data, CvSVMParams _params )
|
||||
{
|
||||
svm_check_data(_data);
|
||||
const CvMat* _train_data = _data->get_values();
|
||||
const CvMat* _responses = _data->get_responses();
|
||||
const CvMat* _var_idx = _data->get_var_idx();
|
||||
const CvMat* _sample_idx = _data->get_train_sample_idx();
|
||||
return svm->train( _train_data, _responses, _var_idx, _sample_idx, _params );
|
||||
}
|
||||
bool svm_train_auto( CvSVM* svm, CvMLData* _data, CvSVMParams _params,
|
||||
int k_fold, CvParamGrid C_grid, CvParamGrid gamma_grid,
|
||||
CvParamGrid p_grid, CvParamGrid nu_grid, CvParamGrid coef_grid,
|
||||
CvParamGrid degree_grid )
|
||||
{
|
||||
svm_check_data(_data);
|
||||
const CvMat* _train_data = _data->get_values();
|
||||
const CvMat* _responses = _data->get_responses();
|
||||
const CvMat* _var_idx = _data->get_var_idx();
|
||||
const CvMat* _sample_idx = _data->get_train_sample_idx();
|
||||
return svm->train_auto( _train_data, _responses, _var_idx,
|
||||
_sample_idx, _params, k_fold, C_grid, gamma_grid, p_grid, nu_grid, coef_grid, degree_grid );
|
||||
}
|
||||
float svm_calc_error( CvSVM* svm, CvMLData* _data, int type, vector<float> *resp )
|
||||
{
|
||||
svm_check_data(_data);
|
||||
float err = 0;
|
||||
const CvMat* values = _data->get_values();
|
||||
const CvMat* response = _data->get_responses();
|
||||
const CvMat* sample_idx = (type == CV_TEST_ERROR) ? _data->get_test_sample_idx() : _data->get_train_sample_idx();
|
||||
const CvMat* var_types = _data->get_var_types();
|
||||
int* sidx = sample_idx ? sample_idx->data.i : 0;
|
||||
int r_step = CV_IS_MAT_CONT(response->type) ?
|
||||
1 : response->step / CV_ELEM_SIZE(response->type);
|
||||
bool is_classifier = var_types->data.ptr[var_types->cols-1] == CV_VAR_CATEGORICAL;
|
||||
int sample_count = sample_idx ? sample_idx->cols : 0;
|
||||
sample_count = (type == CV_TRAIN_ERROR && sample_count == 0) ? values->rows : sample_count;
|
||||
float* pred_resp = 0;
|
||||
if( resp && (sample_count > 0) )
|
||||
{
|
||||
resp->resize( sample_count );
|
||||
pred_resp = &((*resp)[0]);
|
||||
}
|
||||
if ( is_classifier )
|
||||
{
|
||||
for( int i = 0; i < sample_count; i++ )
|
||||
{
|
||||
CvMat sample;
|
||||
int si = sidx ? sidx[i] : i;
|
||||
cvGetRow( values, &sample, si );
|
||||
float r = svm->predict( &sample );
|
||||
if( pred_resp )
|
||||
pred_resp[i] = r;
|
||||
int d = fabs((double)r - response->data.fl[si*r_step]) <= FLT_EPSILON ? 0 : 1;
|
||||
err += d;
|
||||
}
|
||||
err = sample_count ? err / (float)sample_count * 100 : -FLT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < sample_count; i++ )
|
||||
{
|
||||
CvMat sample;
|
||||
int si = sidx ? sidx[i] : i;
|
||||
cvGetRow( values, &sample, si );
|
||||
float r = svm->predict( &sample );
|
||||
if( pred_resp )
|
||||
pred_resp[i] = r;
|
||||
float d = r - response->data.fl[si*r_step];
|
||||
err += d*d;
|
||||
}
|
||||
err = sample_count ? err / (float)sample_count : -FLT_MAX;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// 4. em
|
||||
// 5. ann
|
||||
int str_to_ann_train_method( string& str )
|
||||
{
|
||||
if( !str.compare("BACKPROP") )
|
||||
return CvANN_MLP_TrainParams::BACKPROP;
|
||||
if( !str.compare("RPROP") )
|
||||
return CvANN_MLP_TrainParams::RPROP;
|
||||
CV_Error( CV_StsBadArg, "incorrect ann train method string" );
|
||||
return -1;
|
||||
}
|
||||
void ann_check_data_and_get_predictors( CvMLData* _data, CvMat* _inputs )
|
||||
{
|
||||
const CvMat* values = _data->get_values();
|
||||
const CvMat* var_idx = _data->get_var_idx();
|
||||
if( var_idx->cols + var_idx->rows != values->cols )
|
||||
CV_Error( CV_StsBadArg, "var_idx is not supported" );
|
||||
if( _data->get_missing() )
|
||||
CV_Error( CV_StsBadArg, "missing values are not supported" );
|
||||
int resp_idx = _data->get_response_idx();
|
||||
if( resp_idx == 0)
|
||||
cvGetCols( values, _inputs, 1, values->cols );
|
||||
else if( resp_idx == values->cols - 1 )
|
||||
cvGetCols( values, _inputs, 0, values->cols - 1 );
|
||||
else
|
||||
CV_Error( CV_StsBadArg, "outputs must be in the first or last column; other cases are not supported" );
|
||||
}
|
||||
void ann_get_new_responses( CvMLData* _data, Mat& new_responses, map<int, int>& cls_map )
|
||||
{
|
||||
const CvMat* train_sidx = _data->get_train_sample_idx();
|
||||
int* train_sidx_ptr = train_sidx->data.i;
|
||||
const CvMat* responses = _data->get_responses();
|
||||
float* responses_ptr = responses->data.fl;
|
||||
int r_step = CV_IS_MAT_CONT(responses->type) ?
|
||||
1 : responses->step / CV_ELEM_SIZE(responses->type);
|
||||
int cls_count = 0;
|
||||
// construct cls_map
|
||||
cls_map.clear();
|
||||
for( int si = 0; si < train_sidx->cols; si++ )
|
||||
{
|
||||
int sidx = train_sidx_ptr[si];
|
||||
int r = cvRound(responses_ptr[sidx*r_step]);
|
||||
CV_DbgAssert( fabs(responses_ptr[sidx*r_step]-r) < FLT_EPSILON );
|
||||
int cls_map_size = (int)cls_map.size();
|
||||
cls_map[r];
|
||||
if ( (int)cls_map.size() > cls_map_size )
|
||||
cls_map[r] = cls_count++;
|
||||
}
|
||||
new_responses.create( responses->rows, cls_count, CV_32F );
|
||||
new_responses.setTo( 0 );
|
||||
for( int si = 0; si < train_sidx->cols; si++ )
|
||||
{
|
||||
int sidx = train_sidx_ptr[si];
|
||||
int r = cvRound(responses_ptr[sidx*r_step]);
|
||||
int cidx = cls_map[r];
|
||||
new_responses.ptr<float>(sidx)[cidx] = 1;
|
||||
}
|
||||
}
|
||||
int ann_train( CvANN_MLP* ann, CvMLData* _data, Mat& new_responses, CvANN_MLP_TrainParams _params, int flags = 0 )
|
||||
{
|
||||
const CvMat* train_sidx = _data->get_train_sample_idx();
|
||||
CvMat predictors;
|
||||
ann_check_data_and_get_predictors( _data, &predictors );
|
||||
CvMat _new_responses = CvMat( new_responses );
|
||||
return ann->train( &predictors, &_new_responses, 0, train_sidx, _params, flags );
|
||||
}
|
||||
float ann_calc_error( CvANN_MLP* ann, CvMLData* _data, map<int, int>& cls_map, int type , vector<float> *resp_labels )
|
||||
{
|
||||
float err = 0;
|
||||
const CvMat* responses = _data->get_responses();
|
||||
const CvMat* sample_idx = (type == CV_TEST_ERROR) ? _data->get_test_sample_idx() : _data->get_train_sample_idx();
|
||||
int* sidx = sample_idx ? sample_idx->data.i : 0;
|
||||
int r_step = CV_IS_MAT_CONT(responses->type) ?
|
||||
1 : responses->step / CV_ELEM_SIZE(responses->type);
|
||||
CvMat predictors;
|
||||
ann_check_data_and_get_predictors( _data, &predictors );
|
||||
int sample_count = sample_idx ? sample_idx->cols : 0;
|
||||
sample_count = (type == CV_TRAIN_ERROR && sample_count == 0) ? predictors.rows : sample_count;
|
||||
float* pred_resp = 0;
|
||||
vector<float> innresp;
|
||||
if( sample_count > 0 )
|
||||
{
|
||||
if( resp_labels )
|
||||
{
|
||||
resp_labels->resize( sample_count );
|
||||
pred_resp = &((*resp_labels)[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
innresp.resize( sample_count );
|
||||
pred_resp = &(innresp[0]);
|
||||
}
|
||||
}
|
||||
int cls_count = (int)cls_map.size();
|
||||
Mat output( 1, cls_count, CV_32FC1 );
|
||||
CvMat _output = CvMat(output);
|
||||
map<int, int>::iterator b_it = cls_map.begin();
|
||||
for( int i = 0; i < sample_count; i++ )
|
||||
{
|
||||
CvMat sample;
|
||||
int si = sidx ? sidx[i] : i;
|
||||
cvGetRow( &predictors, &sample, si );
|
||||
ann->predict( &sample, &_output );
|
||||
CvPoint best_cls = {0,0};
|
||||
cvMinMaxLoc( &_output, 0, 0, 0, &best_cls, 0 );
|
||||
int r = cvRound(responses->data.fl[si*r_step]);
|
||||
CV_DbgAssert( fabs(responses->data.fl[si*r_step]-r) < FLT_EPSILON );
|
||||
r = cls_map[r];
|
||||
int d = best_cls.x == r ? 0 : 1;
|
||||
err += d;
|
||||
pred_resp[i] = (float)best_cls.x;
|
||||
}
|
||||
err = sample_count ? err / (float)sample_count * 100 : -FLT_MAX;
|
||||
return err;
|
||||
}
|
||||
|
||||
// 6. dtree
|
||||
// 7. boost
|
||||
int str_to_boost_type( string& str )
|
||||
{
|
||||
if ( !str.compare("DISCRETE") )
|
||||
return CvBoost::DISCRETE;
|
||||
if ( !str.compare("REAL") )
|
||||
return CvBoost::REAL;
|
||||
if ( !str.compare("LOGIT") )
|
||||
return CvBoost::LOGIT;
|
||||
if ( !str.compare("GENTLE") )
|
||||
return CvBoost::GENTLE;
|
||||
CV_Error( CV_StsBadArg, "incorrect boost type string" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 8. rtrees
|
||||
// 9. ertrees
|
||||
|
||||
// ---------------------------------- MLBaseTest ---------------------------------------------------
|
||||
|
||||
CV_MLBaseTest::CV_MLBaseTest(const char* _modelName)
|
||||
{
|
||||
int64 seeds[] = { CV_BIG_INT(0x00009fff4f9c8d52),
|
||||
CV_BIG_INT(0x0000a17166072c7c),
|
||||
CV_BIG_INT(0x0201b32115cd1f9a),
|
||||
CV_BIG_INT(0x0513cb37abcd1234),
|
||||
CV_BIG_INT(0x0001a2b3c4d5f678)
|
||||
};
|
||||
|
||||
int seedCount = sizeof(seeds)/sizeof(seeds[0]);
|
||||
RNG& rng = theRNG();
|
||||
|
||||
initSeed = rng.state;
|
||||
|
||||
rng.state = seeds[rng(seedCount)];
|
||||
|
||||
modelName = _modelName;
|
||||
nbayes = 0;
|
||||
knearest = 0;
|
||||
svm = 0;
|
||||
em = 0;
|
||||
ann = 0;
|
||||
dtree = 0;
|
||||
boost = 0;
|
||||
rtrees = 0;
|
||||
ertrees = 0;
|
||||
if( !modelName.compare(CV_NBAYES) )
|
||||
nbayes = new CvNormalBayesClassifier;
|
||||
else if( !modelName.compare(CV_KNEAREST) )
|
||||
knearest = new CvKNearest;
|
||||
else if( !modelName.compare(CV_SVM) )
|
||||
svm = new CvSVM;
|
||||
else if( !modelName.compare(CV_EM) )
|
||||
em = new CvEM;
|
||||
else if( !modelName.compare(CV_ANN) )
|
||||
ann = new CvANN_MLP;
|
||||
else if( !modelName.compare(CV_DTREE) )
|
||||
dtree = new CvDTree;
|
||||
else if( !modelName.compare(CV_BOOST) )
|
||||
boost = new CvBoost;
|
||||
else if( !modelName.compare(CV_RTREES) )
|
||||
rtrees = new CvRTrees;
|
||||
else if( !modelName.compare(CV_ERTREES) )
|
||||
ertrees = new CvERTrees;
|
||||
}
|
||||
|
||||
CV_MLBaseTest::~CV_MLBaseTest()
|
||||
{
|
||||
if( validationFS.isOpened() )
|
||||
validationFS.release();
|
||||
if( nbayes )
|
||||
delete nbayes;
|
||||
if( knearest )
|
||||
delete knearest;
|
||||
if( svm )
|
||||
delete svm;
|
||||
if( em )
|
||||
delete em;
|
||||
if( ann )
|
||||
delete ann;
|
||||
if( dtree )
|
||||
delete dtree;
|
||||
if( boost )
|
||||
delete boost;
|
||||
if( rtrees )
|
||||
delete rtrees;
|
||||
if( ertrees )
|
||||
delete ertrees;
|
||||
theRNG().state = initSeed;
|
||||
}
|
||||
|
||||
int CV_MLBaseTest::read_params( CvFileStorage* _fs )
|
||||
{
|
||||
if( !_fs )
|
||||
test_case_count = -1;
|
||||
else
|
||||
{
|
||||
CvFileNode* fn = cvGetRootFileNode( _fs, 0 );
|
||||
fn = (CvFileNode*)cvGetSeqElem( fn->data.seq, 0 );
|
||||
fn = cvGetFileNodeByName( _fs, fn, "run_params" );
|
||||
CvSeq* dataSetNamesSeq = cvGetFileNodeByName( _fs, fn, modelName.c_str() )->data.seq;
|
||||
test_case_count = dataSetNamesSeq ? dataSetNamesSeq->total : -1;
|
||||
if( test_case_count > 0 )
|
||||
{
|
||||
dataSetNames.resize( test_case_count );
|
||||
vector<string>::iterator it = dataSetNames.begin();
|
||||
for( int i = 0; i < test_case_count; i++, it++ )
|
||||
*it = ((CvFileNode*)cvGetSeqElem( dataSetNamesSeq, i ))->data.str.ptr;
|
||||
}
|
||||
}
|
||||
return cvtest::TS::OK;;
|
||||
}
|
||||
|
||||
void CV_MLBaseTest::run( int start_from )
|
||||
{
|
||||
string filename = ts->get_data_path();
|
||||
filename += get_validation_filename();
|
||||
validationFS.open( filename, FileStorage::READ );
|
||||
read_params( *validationFS );
|
||||
|
||||
int code = cvtest::TS::OK;
|
||||
start_from = 0;
|
||||
for (int i = 0; i < test_case_count; i++)
|
||||
{
|
||||
int temp_code = run_test_case( i );
|
||||
if (temp_code == cvtest::TS::OK)
|
||||
temp_code = validate_test_results( i );
|
||||
if (temp_code != cvtest::TS::OK)
|
||||
code = temp_code;
|
||||
}
|
||||
if ( test_case_count <= 0)
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "validation file is not determined or not correct" );
|
||||
code = cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
ts->set_failed_test_info( code );
|
||||
}
|
||||
|
||||
int CV_MLBaseTest::prepare_test_case( int test_case_idx )
|
||||
{
|
||||
int trainSampleCount, respIdx;
|
||||
string varTypes;
|
||||
clear();
|
||||
|
||||
string dataPath = ts->get_data_path();
|
||||
if ( dataPath.empty() )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "data path is empty" );
|
||||
return cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
|
||||
string dataName = dataSetNames[test_case_idx],
|
||||
filename = dataPath + dataName + ".data";
|
||||
if ( data.read_csv( filename.c_str() ) != 0)
|
||||
{
|
||||
char msg[100];
|
||||
sprintf( msg, "file %s can not be read", filename.c_str() );
|
||||
ts->printf( cvtest::TS::LOG, msg );
|
||||
return cvtest::TS::FAIL_INVALID_TEST_DATA;
|
||||
}
|
||||
|
||||
FileNode dataParamsNode = validationFS.getFirstTopLevelNode()["validation"][modelName][dataName]["data_params"];
|
||||
CV_DbgAssert( !dataParamsNode.empty() );
|
||||
|
||||
CV_DbgAssert( !dataParamsNode["LS"].empty() );
|
||||
dataParamsNode["LS"] >> trainSampleCount;
|
||||
CvTrainTestSplit spl( trainSampleCount );
|
||||
data.set_train_test_split( &spl );
|
||||
|
||||
CV_DbgAssert( !dataParamsNode["resp_idx"].empty() );
|
||||
dataParamsNode["resp_idx"] >> respIdx;
|
||||
data.set_response_idx( respIdx );
|
||||
|
||||
CV_DbgAssert( !dataParamsNode["types"].empty() );
|
||||
dataParamsNode["types"] >> varTypes;
|
||||
data.set_var_types( varTypes.c_str() );
|
||||
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
string& CV_MLBaseTest::get_validation_filename()
|
||||
{
|
||||
return validationFN;
|
||||
}
|
||||
|
||||
int CV_MLBaseTest::train( int testCaseIdx )
|
||||
{
|
||||
bool is_trained = false;
|
||||
FileNode modelParamsNode =
|
||||
validationFS.getFirstTopLevelNode()["validation"][modelName][dataSetNames[testCaseIdx]]["model_params"];
|
||||
|
||||
if( !modelName.compare(CV_NBAYES) )
|
||||
is_trained = nbayes_train( nbayes, &data );
|
||||
else if( !modelName.compare(CV_KNEAREST) )
|
||||
{
|
||||
assert( 0 );
|
||||
//is_trained = knearest->train( &data );
|
||||
}
|
||||
else if( !modelName.compare(CV_SVM) )
|
||||
{
|
||||
string svm_type_str, kernel_type_str;
|
||||
modelParamsNode["svm_type"] >> svm_type_str;
|
||||
modelParamsNode["kernel_type"] >> kernel_type_str;
|
||||
CvSVMParams params;
|
||||
params.svm_type = str_to_svm_type( svm_type_str );
|
||||
params.kernel_type = str_to_svm_kernel_type( kernel_type_str );
|
||||
modelParamsNode["degree"] >> params.degree;
|
||||
modelParamsNode["gamma"] >> params.gamma;
|
||||
modelParamsNode["coef0"] >> params.coef0;
|
||||
modelParamsNode["C"] >> params.C;
|
||||
modelParamsNode["nu"] >> params.nu;
|
||||
modelParamsNode["p"] >> params.p;
|
||||
is_trained = svm_train( svm, &data, params );
|
||||
}
|
||||
else if( !modelName.compare(CV_EM) )
|
||||
{
|
||||
assert( 0 );
|
||||
}
|
||||
else if( !modelName.compare(CV_ANN) )
|
||||
{
|
||||
string train_method_str;
|
||||
double param1, param2;
|
||||
modelParamsNode["train_method"] >> train_method_str;
|
||||
modelParamsNode["param1"] >> param1;
|
||||
modelParamsNode["param2"] >> param2;
|
||||
Mat new_responses;
|
||||
ann_get_new_responses( &data, new_responses, cls_map );
|
||||
int layer_sz[] = { data.get_values()->cols - 1, 100, 100, (int)cls_map.size() };
|
||||
CvMat layer_sizes =
|
||||
cvMat( 1, (int)(sizeof(layer_sz)/sizeof(layer_sz[0])), CV_32S, layer_sz );
|
||||
ann->create( &layer_sizes );
|
||||
is_trained = ann_train( ann, &data, new_responses, CvANN_MLP_TrainParams(cvTermCriteria(CV_TERMCRIT_ITER,300,0.01),
|
||||
str_to_ann_train_method(train_method_str), param1, param2) ) >= 0;
|
||||
}
|
||||
else if( !modelName.compare(CV_DTREE) )
|
||||
{
|
||||
int MAX_DEPTH, MIN_SAMPLE_COUNT, MAX_CATEGORIES, CV_FOLDS;
|
||||
float REG_ACCURACY = 0;
|
||||
bool USE_SURROGATE, IS_PRUNED;
|
||||
modelParamsNode["max_depth"] >> MAX_DEPTH;
|
||||
modelParamsNode["min_sample_count"] >> MIN_SAMPLE_COUNT;
|
||||
modelParamsNode["use_surrogate"] >> USE_SURROGATE;
|
||||
modelParamsNode["max_categories"] >> MAX_CATEGORIES;
|
||||
modelParamsNode["cv_folds"] >> CV_FOLDS;
|
||||
modelParamsNode["is_pruned"] >> IS_PRUNED;
|
||||
is_trained = dtree->train( &data,
|
||||
CvDTreeParams(MAX_DEPTH, MIN_SAMPLE_COUNT, REG_ACCURACY, USE_SURROGATE,
|
||||
MAX_CATEGORIES, CV_FOLDS, false, IS_PRUNED, 0 )) != 0;
|
||||
}
|
||||
else if( !modelName.compare(CV_BOOST) )
|
||||
{
|
||||
int BOOST_TYPE, WEAK_COUNT, MAX_DEPTH;
|
||||
float WEIGHT_TRIM_RATE;
|
||||
bool USE_SURROGATE;
|
||||
string typeStr;
|
||||
modelParamsNode["type"] >> typeStr;
|
||||
BOOST_TYPE = str_to_boost_type( typeStr );
|
||||
modelParamsNode["weak_count"] >> WEAK_COUNT;
|
||||
modelParamsNode["weight_trim_rate"] >> WEIGHT_TRIM_RATE;
|
||||
modelParamsNode["max_depth"] >> MAX_DEPTH;
|
||||
modelParamsNode["use_surrogate"] >> USE_SURROGATE;
|
||||
is_trained = boost->train( &data,
|
||||
CvBoostParams(BOOST_TYPE, WEAK_COUNT, WEIGHT_TRIM_RATE, MAX_DEPTH, USE_SURROGATE, 0) ) != 0;
|
||||
}
|
||||
else if( !modelName.compare(CV_RTREES) )
|
||||
{
|
||||
int MAX_DEPTH, MIN_SAMPLE_COUNT, MAX_CATEGORIES, CV_FOLDS, NACTIVE_VARS, MAX_TREES_NUM;
|
||||
float REG_ACCURACY = 0, OOB_EPS = 0.0;
|
||||
bool USE_SURROGATE, IS_PRUNED;
|
||||
modelParamsNode["max_depth"] >> MAX_DEPTH;
|
||||
modelParamsNode["min_sample_count"] >> MIN_SAMPLE_COUNT;
|
||||
modelParamsNode["use_surrogate"] >> USE_SURROGATE;
|
||||
modelParamsNode["max_categories"] >> MAX_CATEGORIES;
|
||||
modelParamsNode["cv_folds"] >> CV_FOLDS;
|
||||
modelParamsNode["is_pruned"] >> IS_PRUNED;
|
||||
modelParamsNode["nactive_vars"] >> NACTIVE_VARS;
|
||||
modelParamsNode["max_trees_num"] >> MAX_TREES_NUM;
|
||||
is_trained = rtrees->train( &data, CvRTParams( MAX_DEPTH, MIN_SAMPLE_COUNT, REG_ACCURACY,
|
||||
USE_SURROGATE, MAX_CATEGORIES, 0, true, // (calc_var_importance == true) <=> RF processes variable importance
|
||||
NACTIVE_VARS, MAX_TREES_NUM, OOB_EPS, CV_TERMCRIT_ITER)) != 0;
|
||||
}
|
||||
else if( !modelName.compare(CV_ERTREES) )
|
||||
{
|
||||
int MAX_DEPTH, MIN_SAMPLE_COUNT, MAX_CATEGORIES, CV_FOLDS, NACTIVE_VARS, MAX_TREES_NUM;
|
||||
float REG_ACCURACY = 0, OOB_EPS = 0.0;
|
||||
bool USE_SURROGATE, IS_PRUNED;
|
||||
modelParamsNode["max_depth"] >> MAX_DEPTH;
|
||||
modelParamsNode["min_sample_count"] >> MIN_SAMPLE_COUNT;
|
||||
modelParamsNode["use_surrogate"] >> USE_SURROGATE;
|
||||
modelParamsNode["max_categories"] >> MAX_CATEGORIES;
|
||||
modelParamsNode["cv_folds"] >> CV_FOLDS;
|
||||
modelParamsNode["is_pruned"] >> IS_PRUNED;
|
||||
modelParamsNode["nactive_vars"] >> NACTIVE_VARS;
|
||||
modelParamsNode["max_trees_num"] >> MAX_TREES_NUM;
|
||||
is_trained = ertrees->train( &data, CvRTParams( MAX_DEPTH, MIN_SAMPLE_COUNT, REG_ACCURACY,
|
||||
USE_SURROGATE, MAX_CATEGORIES, 0, false, // (calc_var_importance == true) <=> RF processes variable importance
|
||||
NACTIVE_VARS, MAX_TREES_NUM, OOB_EPS, CV_TERMCRIT_ITER)) != 0;
|
||||
}
|
||||
|
||||
if( !is_trained )
|
||||
{
|
||||
ts->printf( cvtest::TS::LOG, "in test case %d model training was failed", testCaseIdx );
|
||||
return cvtest::TS::FAIL_INVALID_OUTPUT;
|
||||
}
|
||||
return cvtest::TS::OK;
|
||||
}
|
||||
|
||||
float CV_MLBaseTest::get_error( int testCaseIdx, int type, vector<float> *resp )
|
||||
{
|
||||
float err = 0;
|
||||
if( !modelName.compare(CV_NBAYES) )
|
||||
err = nbayes_calc_error( nbayes, &data, type, resp );
|
||||
else if( !modelName.compare(CV_KNEAREST) )
|
||||
{
|
||||
assert( 0 );
|
||||
testCaseIdx = 0;
|
||||
/*int k = 2;
|
||||
validationFS.getFirstTopLevelNode()["validation"][modelName][dataSetNames[testCaseIdx]]["model_params"]["k"] >> k;
|
||||
err = knearest->calc_error( &data, k, type, resp );*/
|
||||
}
|
||||
else if( !modelName.compare(CV_SVM) )
|
||||
err = svm_calc_error( svm, &data, type, resp );
|
||||
else if( !modelName.compare(CV_EM) )
|
||||
assert( 0 );
|
||||
else if( !modelName.compare(CV_ANN) )
|
||||
err = ann_calc_error( ann, &data, cls_map, type, resp );
|
||||
else if( !modelName.compare(CV_DTREE) )
|
||||
err = dtree->calc_error( &data, type, resp );
|
||||
else if( !modelName.compare(CV_BOOST) )
|
||||
err = boost->calc_error( &data, type, resp );
|
||||
else if( !modelName.compare(CV_RTREES) )
|
||||
err = rtrees->calc_error( &data, type, resp );
|
||||
else if( !modelName.compare(CV_ERTREES) )
|
||||
err = ertrees->calc_error( &data, type, resp );
|
||||
return err;
|
||||
}
|
||||
|
||||
void CV_MLBaseTest::save( const char* filename )
|
||||
{
|
||||
if( !modelName.compare(CV_NBAYES) )
|
||||
nbayes->save( filename );
|
||||
else if( !modelName.compare(CV_KNEAREST) )
|
||||
knearest->save( filename );
|
||||
else if( !modelName.compare(CV_SVM) )
|
||||
svm->save( filename );
|
||||
else if( !modelName.compare(CV_EM) )
|
||||
em->save( filename );
|
||||
else if( !modelName.compare(CV_ANN) )
|
||||
ann->save( filename );
|
||||
else if( !modelName.compare(CV_DTREE) )
|
||||
dtree->save( filename );
|
||||
else if( !modelName.compare(CV_BOOST) )
|
||||
boost->save( filename );
|
||||
else if( !modelName.compare(CV_RTREES) )
|
||||
rtrees->save( filename );
|
||||
else if( !modelName.compare(CV_ERTREES) )
|
||||
ertrees->save( filename );
|
||||
}
|
||||
|
||||
void CV_MLBaseTest::load( const char* filename )
|
||||
{
|
||||
if( !modelName.compare(CV_NBAYES) )
|
||||
nbayes->load( filename );
|
||||
else if( !modelName.compare(CV_KNEAREST) )
|
||||
knearest->load( filename );
|
||||
else if( !modelName.compare(CV_SVM) )
|
||||
svm->load( filename );
|
||||
else if( !modelName.compare(CV_EM) )
|
||||
em->load( filename );
|
||||
else if( !modelName.compare(CV_ANN) )
|
||||
ann->load( filename );
|
||||
else if( !modelName.compare(CV_DTREE) )
|
||||
dtree->load( filename );
|
||||
else if( !modelName.compare(CV_BOOST) )
|
||||
boost->load( filename );
|
||||
else if( !modelName.compare(CV_RTREES) )
|
||||
rtrees->load( filename );
|
||||
else if( !modelName.compare(CV_ERTREES) )
|
||||
ertrees->load( filename );
|
||||
}
|
||||
|
||||
/* End of file. */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user