Path: blob/master/modules/imgproc/test/test_moments.cpp
16354 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective owners.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/40#include "test_precomp.hpp"41#include "opencv2/ts/ocl_test.hpp"4243namespace opencv_test { namespace {4445#define OCL_TUNING_MODE 046#if OCL_TUNING_MODE47#define OCL_TUNING_MODE_ONLY(code) code48#else49#define OCL_TUNING_MODE_ONLY(code)50#endif5152// image moments53class CV_MomentsTest : public cvtest::ArrayTest54{55public:56CV_MomentsTest(bool try_umat);5758protected:5960enum { MOMENT_COUNT = 25 };61int prepare_test_case( int test_case_idx );62void prepare_to_validation( int /*test_case_idx*/ );63void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );64void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );65double get_success_error_level( int test_case_idx, int i, int j );66void run_func();67bool is_binary;68bool try_umat_;69};707172CV_MomentsTest::CV_MomentsTest(bool try_umat) :73try_umat_(try_umat)74{75test_array[INPUT].push_back(NULL);76test_array[OUTPUT].push_back(NULL);77test_array[REF_OUTPUT].push_back(NULL);78is_binary = false;79OCL_TUNING_MODE_ONLY(test_case_count = 10);80//element_wise_relative_error = false;81}828384void CV_MomentsTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )85{86cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );87int depth = CV_MAT_DEPTH(type);8889if( depth == CV_16U )90{91low = Scalar::all(0);92high = Scalar::all(1000);93}94else if( depth == CV_16S )95{96low = Scalar::all(-1000);97high = Scalar::all(1000);98}99else if( depth == CV_32F )100{101low = Scalar::all(-1);102high = Scalar::all(1);103}104}105106void CV_MomentsTest::get_test_array_types_and_sizes( int test_case_idx,107vector<vector<Size> >& sizes, vector<vector<int> >& types )108{109RNG& rng = ts->get_rng();110cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );111int depth = cvtest::randInt(rng) % 4;112depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : depth == 2 ? CV_16S : CV_32F;113114is_binary = cvtest::randInt(rng) % 2 != 0;115116OCL_TUNING_MODE_ONLY(117depth = CV_8U;118is_binary = false;119sizes[INPUT][0] = Size(1024,768)120);121122types[INPUT][0] = CV_MAKETYPE(depth, 1);123types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;124sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(MOMENT_COUNT,1);125if(CV_MAT_DEPTH(types[INPUT][0])>=CV_32S)126sizes[INPUT][0].width = MAX(sizes[INPUT][0].width, 3);127128cvmat_allowed = true;129}130131132double CV_MomentsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )133{134int depth = test_mat[INPUT][0].depth();135return depth != CV_32F ? FLT_EPSILON*10 : FLT_EPSILON*100;136}137138int CV_MomentsTest::prepare_test_case( int test_case_idx )139{140int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );141return code;142}143144145void CV_MomentsTest::run_func()146{147CvMoments* m = (CvMoments*)test_mat[OUTPUT][0].ptr<double>();148double* others = (double*)(m + 1);149if (try_umat_)150{151UMat u;152test_mat[INPUT][0].clone().copyTo(u);153OCL_TUNING_MODE_ONLY(154static double ttime = 0;155static int ncalls = 0;156moments(u, is_binary != 0);157double t = (double)getTickCount());158Moments new_m = moments(u, is_binary != 0);159OCL_TUNING_MODE_ONLY(160ttime += (double)getTickCount() - t;161ncalls++;162printf("%g\n", ttime/ncalls/u.total()));163*m = cvMoments(new_m);164}165else166cvMoments( test_array[INPUT][0], m, is_binary );167168others[0] = cvGetNormalizedCentralMoment( m, 2, 0 );169others[1] = cvGetNormalizedCentralMoment( m, 1, 1 );170others[2] = cvGetNormalizedCentralMoment( m, 0, 2 );171others[3] = cvGetNormalizedCentralMoment( m, 3, 0 );172others[4] = cvGetNormalizedCentralMoment( m, 2, 1 );173others[5] = cvGetNormalizedCentralMoment( m, 1, 2 );174others[6] = cvGetNormalizedCentralMoment( m, 0, 3 );175}176177178void CV_MomentsTest::prepare_to_validation( int /*test_case_idx*/ )179{180Mat& src = test_mat[INPUT][0];181CvMoments m = cvMoments();182double* mdata = test_mat[REF_OUTPUT][0].ptr<double>();183int depth = src.depth();184int cn = src.channels();185int i, y, x, cols = src.cols;186double xc = 0., yc = 0.;187188int coi = 0;189for( y = 0; y < src.rows; y++ )190{191double s0 = 0, s1 = 0, s2 = 0, s3 = 0;192uchar* ptr = src.ptr(y);193for( x = 0; x < cols; x++ )194{195double val;196if( depth == CV_8U )197val = ptr[x*cn + coi];198else if( depth == CV_16U )199val = ((ushort*)ptr)[x*cn + coi];200else if( depth == CV_16S )201val = ((short*)ptr)[x*cn + coi];202else203val = ((float*)ptr)[x*cn + coi];204205if( is_binary )206val = val != 0;207208s0 += val;209s1 += val*x;210s2 += val*x*x;211s3 += ((val*x)*x)*x;212}213214m.m00 += s0;215m.m01 += s0*y;216m.m02 += (s0*y)*y;217m.m03 += ((s0*y)*y)*y;218219m.m10 += s1;220m.m11 += s1*y;221m.m12 += (s1*y)*y;222223m.m20 += s2;224m.m21 += s2*y;225226m.m30 += s3;227}228229if( m.m00 != 0 )230{231xc = m.m10/m.m00, yc = m.m01/m.m00;232m.inv_sqrt_m00 = 1./sqrt(fabs(m.m00));233}234235for( y = 0; y < src.rows; y++ )236{237double s0 = 0, s1 = 0, s2 = 0, s3 = 0, y1 = y - yc;238uchar* ptr = src.ptr(y);239for( x = 0; x < cols; x++ )240{241double val, x1 = x - xc;242if( depth == CV_8U )243val = ptr[x*cn + coi];244else if( depth == CV_16U )245val = ((ushort*)ptr)[x*cn + coi];246else if( depth == CV_16S )247val = ((short*)ptr)[x*cn + coi];248else249val = ((float*)ptr)[x*cn + coi];250251if( is_binary )252val = val != 0;253254s0 += val;255s1 += val*x1;256s2 += val*x1*x1;257s3 += ((val*x1)*x1)*x1;258}259260m.mu02 += s0*y1*y1;261m.mu03 += ((s0*y1)*y1)*y1;262263m.mu11 += s1*y1;264m.mu12 += (s1*y1)*y1;265266m.mu20 += s2;267m.mu21 += s2*y1;268269m.mu30 += s3;270}271272memcpy( mdata, &m, sizeof(m));273mdata += sizeof(m)/sizeof(m.m00);274275/* calc normalized moments */276{277double inv_m00 = m.inv_sqrt_m00*m.inv_sqrt_m00;278double s2 = inv_m00*inv_m00; /* 1./(m00 ^ (2/2 + 1)) */279double s3 = s2*m.inv_sqrt_m00; /* 1./(m00 ^ (3/2 + 1)) */280281mdata[0] = m.mu20 * s2;282mdata[1] = m.mu11 * s2;283mdata[2] = m.mu02 * s2;284285mdata[3] = m.mu30 * s3;286mdata[4] = m.mu21 * s3;287mdata[5] = m.mu12 * s3;288mdata[6] = m.mu03 * s3;289}290291double* a = test_mat[REF_OUTPUT][0].ptr<double>();292double* b = test_mat[OUTPUT][0].ptr<double>();293for( i = 0; i < MOMENT_COUNT; i++ )294{295if( fabs(a[i]) < 1e-3 )296a[i] = 0;297if( fabs(b[i]) < 1e-3 )298b[i] = 0;299}300}301302303// Hu invariants304class CV_HuMomentsTest : public cvtest::ArrayTest305{306public:307CV_HuMomentsTest();308309protected:310311enum { MOMENT_COUNT = 18, HU_MOMENT_COUNT = 7 };312313int prepare_test_case( int test_case_idx );314void prepare_to_validation( int /*test_case_idx*/ );315void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );316void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );317double get_success_error_level( int test_case_idx, int i, int j );318void run_func();319};320321322CV_HuMomentsTest::CV_HuMomentsTest()323{324test_array[INPUT].push_back(NULL);325test_array[OUTPUT].push_back(NULL);326test_array[REF_OUTPUT].push_back(NULL);327}328329330void CV_HuMomentsTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )331{332cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );333low = Scalar::all(-10000);334high = Scalar::all(10000);335}336337338void CV_HuMomentsTest::get_test_array_types_and_sizes( int test_case_idx,339vector<vector<Size> >& sizes, vector<vector<int> >& types )340{341cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );342types[INPUT][0] = types[OUTPUT][0] = types[REF_OUTPUT][0] = CV_64FC1;343sizes[INPUT][0] = cvSize(MOMENT_COUNT,1);344sizes[OUTPUT][0] = sizes[REF_OUTPUT][0] = cvSize(HU_MOMENT_COUNT,1);345}346347348double CV_HuMomentsTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )349{350return FLT_EPSILON;351}352353354355int CV_HuMomentsTest::prepare_test_case( int test_case_idx )356{357int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );358if( code > 0 )359{360// ...361}362363return code;364}365366367void CV_HuMomentsTest::run_func()368{369cvGetHuMoments( test_mat[INPUT][0].ptr<CvMoments>(),370test_mat[OUTPUT][0].ptr<CvHuMoments>() );371}372373374void CV_HuMomentsTest::prepare_to_validation( int /*test_case_idx*/ )375{376CvMoments* m = test_mat[INPUT][0].ptr<CvMoments>();377CvHuMoments* hu = test_mat[REF_OUTPUT][0].ptr<CvHuMoments>();378379double inv_m00 = m->inv_sqrt_m00*m->inv_sqrt_m00;380double s2 = inv_m00*inv_m00; /* 1./(m00 ^ (2/2 + 1)) */381double s3 = s2*m->inv_sqrt_m00; /* 1./(m00 ^ (3/2 + 1)) */382383double nu20 = m->mu20 * s2;384double nu11 = m->mu11 * s2;385double nu02 = m->mu02 * s2;386387double nu30 = m->mu30 * s3;388double nu21 = m->mu21 * s3;389double nu12 = m->mu12 * s3;390double nu03 = m->mu03 * s3;391392#undef sqr393#define sqr(a) ((a)*(a))394395hu->hu1 = nu20 + nu02;396hu->hu2 = sqr(nu20 - nu02) + 4*sqr(nu11);397hu->hu3 = sqr(nu30 - 3*nu12) + sqr(3*nu21 - nu03);398hu->hu4 = sqr(nu30 + nu12) + sqr(nu21 + nu03);399hu->hu5 = (nu30 - 3*nu12)*(nu30 + nu12)*(sqr(nu30 + nu12) - 3*sqr(nu21 + nu03)) +400(3*nu21 - nu03)*(nu21 + nu03)*(3*sqr(nu30 + nu12) - sqr(nu21 + nu03));401hu->hu6 = (nu20 - nu02)*(sqr(nu30 + nu12) - sqr(nu21 + nu03)) +4024*nu11*(nu30 + nu12)*(nu21 + nu03);403hu->hu7 = (3*nu21 - nu03)*(nu30 + nu12)*(sqr(nu30 + nu12) - 3*sqr(nu21 + nu03)) +404(3*nu12 - nu30)*(nu21 + nu03)*(3*sqr(nu30 + nu12) - sqr(nu21 + nu03));405}406407408TEST(Imgproc_Moments, accuracy) { CV_MomentsTest test(false); test.safe_run(); }409OCL_TEST(Imgproc_Moments, accuracy) { CV_MomentsTest test(true); test.safe_run(); }410TEST(Imgproc_HuMoments, accuracy) { CV_HuMomentsTest test; test.safe_run(); }411412class CV_SmallContourMomentTest : public cvtest::BaseTest413{414public:415CV_SmallContourMomentTest() {}416~CV_SmallContourMomentTest() {}417protected:418void run(int)419{420try421{422vector<Point> points;423points.push_back(Point(50, 56));424points.push_back(Point(53, 53));425points.push_back(Point(46, 54));426points.push_back(Point(49, 51));427428Moments m = moments(points, false);429double area = contourArea(points);430431CV_Assert( m.m00 == 0 && m.m01 == 0 && m.m10 == 0 && area == 0 );432}433catch(...)434{435ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);436}437}438};439440TEST(Imgproc_ContourMoment, small) { CV_SmallContourMomentTest test; test.safe_run(); }441442}} // namespace443444445