reworked nearly all of the OpenCV tests (except for opencv_gpu tests) - they now use the Google Test engine.

This commit is contained in:
Vadim Pisarevsky 2011-02-09 20:55:11 +00:00
parent 63806c9ab9
commit 061b49e0b2
122 changed files with 39081 additions and 28854 deletions

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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,

View 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(); }

File diff suppressed because it is too large Load Diff

View 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(); }

View 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(); }

View 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);
}

View 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

View 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. */

View 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. */

View 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. */

View 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(); }

View 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. */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")

View 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. */

View File

@ -0,0 +1 @@
#include "test_precomp.hpp"

View 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

View 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(); }

View 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(); }

View 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(); }

View 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. */

View 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,

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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,
},

View File

@ -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;

View File

@ -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;

View File

@ -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

File diff suppressed because it is too large Load Diff

View 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(); }

View 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\"&amp;&lt;&gt;&amp;&apos;@#$@$%$%&%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(); }

View File

@ -1,2 +1,3 @@
#include "test_precomp.hpp"
#include "opencv2/gtest/gtest_main.hpp"
CV_TEST_MAIN("cv")

View 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(); }

File diff suppressed because it is too large Load Diff

View 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(); }

View File

@ -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

View 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(); }

View 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

File diff suppressed because it is too large Load Diff

View 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(); }

View 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(); }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")

View 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(); }

View 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(); }

View File

@ -0,0 +1 @@
#include "test_precomp.hpp"

View 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

View File

@ -1,4 +0,0 @@
if(BUILD_SHARED_LIBS)
add_definitions(-DGTEST_CREATE_SHARED_LIBRARY=1)
endif()
define_opencv_module(gtest opencv_core)

View File

@ -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

View File

@ -1,5 +0,0 @@
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -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

View File

@ -1 +0,0 @@
#include "precomp.hpp"

View File

@ -1 +0,0 @@
#include "opencv2/gtest/gtestcv.hpp"

View 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;

View 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;

View File

@ -0,0 +1,2 @@
#include "test_precomp.hpp"
#include "opencv2/ts/ts_main.hpp"

View File

@ -0,0 +1 @@
#include "test_precomp.hpp"

View 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

View 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

View File

@ -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 );

View File

@ -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. */

View 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 );
}
}

View File

@ -45,8 +45,6 @@
namespace cv
{
//#undef CV_SSE2
template<typename T, int shift> struct FixPtCast
{
typedef int type1;

View File

@ -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());

View 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(); }

View 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. */

File diff suppressed because it is too large Load Diff

View 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. */

File diff suppressed because it is too large Load Diff

View 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(); }

View 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. */

File diff suppressed because it is too large Load Diff

View 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. */

View 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(); }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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(); }

View File

@ -0,0 +1,4 @@
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")

View 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(); }

View File

@ -0,0 +1 @@
#include "test_precomp.hpp"

View 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

View 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. */

View 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. */

View 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(); }

View 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(); }

View 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(); }

View 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(); }

View 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(); }

View File

@ -0,0 +1,3 @@
#include "test_precomp.hpp"
CV_TEST_MAIN("ml")

View 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. */

View 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