Path: blob/master/modules/imgproc/test/test_approxpoly.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*/4041#include "test_precomp.hpp"4243namespace opencv_test { namespace {4445//46// TODO!!!:47// check_slice (and/or check) seem(s) to be broken, or this is a bug in function48// (or its inability to handle possible self-intersections in the generated contours).49//50// At least, if // return TotalErrors;51// is uncommented in check_slice, the test fails easily.52// So, now (and it looks like since 0.9.6)53// we only check that the set of vertices of the approximated polygon is54// a subset of vertices of the original contour.55//5657class CV_ApproxPolyTest : public cvtest::BaseTest58{59public:60CV_ApproxPolyTest();61~CV_ApproxPolyTest();62void clear();63//int write_default_params(CvFileStorage* fs);6465protected:66//int read_params( CvFileStorage* fs );6768int check_slice( CvPoint StartPt, CvPoint EndPt,69CvSeqReader* SrcReader, float Eps,70int* j, int Count );71int check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps );7273bool get_contour( int /*type*/, CvSeq** Seq, int* d,74CvMemStorage* storage );7576void run(int);77};787980CV_ApproxPolyTest::CV_ApproxPolyTest()81{82}838485CV_ApproxPolyTest::~CV_ApproxPolyTest()86{87clear();88}899091void CV_ApproxPolyTest::clear()92{93cvtest::BaseTest::clear();94}959697/*int CV_ApproxPolyTest::write_default_params( CvFileStorage* fs )98{99cvtest::BaseTest::write_default_params( fs );100if( ts->get_testing_mode() != cvtest::TS::TIMING_MODE )101{102write_param( fs, "test_case_count", test_case_count );103}104return 0;105}106107108int CV_ApproxPolyTest::read_params( CvFileStorage* fs )109{110int code = cvtest::BaseTest::read_params( fs );111if( code < 0 )112return code;113114test_case_count = cvReadInt( find_param( fs, "test_case_count" ), test_case_count );115min_log_size = cvtest::clipInt( min_log_size, 1, 10 );116return 0;117}*/118119120bool CV_ApproxPolyTest::get_contour( int /*type*/, CvSeq** Seq, int* d,121CvMemStorage* storage )122{123RNG& rng = ts->get_rng();124int max_x = INT_MIN, max_y = INT_MIN, min_x = INT_MAX, min_y = INT_MAX;125int i;126CvSeq* seq;127int total = cvtest::randInt(rng) % 1000 + 1;128Point center;129int radius, angle;130double deg_to_rad = CV_PI/180.;131Point pt;132133center.x = cvtest::randInt( rng ) % 1000;134center.y = cvtest::randInt( rng ) % 1000;135radius = cvtest::randInt( rng ) % 1000;136angle = cvtest::randInt( rng ) % 360;137138seq = cvCreateSeq( CV_SEQ_POLYGON, sizeof(CvContour), sizeof(CvPoint), storage );139140for( i = 0; i < total; i++ )141{142int d_radius = cvtest::randInt( rng ) % 10 - 5;143int d_angle = 360/total;//cvtest::randInt( rng ) % 10 - 5;144pt.x = cvRound( center.x + radius*cos(angle*deg_to_rad));145pt.y = cvRound( center.x - radius*sin(angle*deg_to_rad));146radius += d_radius;147angle += d_angle;148cvSeqPush( seq, &pt );149150max_x = MAX( max_x, pt.x );151max_y = MAX( max_y, pt.y );152153min_x = MIN( min_x, pt.x );154min_y = MIN( min_y, pt.y );155}156157*d = (max_x - min_x)*(max_x - min_x) + (max_y - min_y)*(max_y - min_y);158*Seq = seq;159return true;160}161162163int CV_ApproxPolyTest::check_slice( CvPoint StartPt, CvPoint EndPt,164CvSeqReader* SrcReader, float Eps,165int* _j, int Count )166{167///////////168Point Pt;169///////////170bool flag;171double dy,dx;172double A,B,C;173double Sq;174double sin_a = 0;175double cos_a = 0;176double d = 0;177double dist;178///////////179int j, TotalErrors = 0;180181////////////////////////////////182if( SrcReader == NULL )183{184assert( false );185return 0;186}187188///////// init line ////////////189flag = true;190191dx = (double)StartPt.x - (double)EndPt.x;192dy = (double)StartPt.y - (double)EndPt.y;193194if( ( dx == 0 ) && ( dy == 0 ) ) flag = false;195else196{197A = -dy;198B = dx;199C = dy * (double)StartPt.x - dx * (double)StartPt.y;200Sq = sqrt( A*A + B*B );201202sin_a = B/Sq;203cos_a = A/Sq;204d = C/Sq;205}206207/////// find start point and check distance ////////208for( j = *_j; j < Count; j++ )209{210{ CvPoint pt_ = CV_STRUCT_INITIALIZER; CV_READ_SEQ_ELEM(pt_, *SrcReader); Pt = pt_; }211if( StartPt.x == Pt.x && StartPt.y == Pt.y ) break;212else213{214if( flag ) dist = sin_a * Pt.y + cos_a * Pt.x - d;215else dist = sqrt( (double)(EndPt.y - Pt.y)*(EndPt.y - Pt.y) + (EndPt.x - Pt.x)*(EndPt.x - Pt.x) );216if( dist > Eps ) TotalErrors++;217}218}219220*_j = j;221222//return TotalErrors;223return 0;224}225226227int CV_ApproxPolyTest::check( CvSeq* SrcSeq, CvSeq* DstSeq, float Eps )228{229//////////230CvSeqReader DstReader;231CvSeqReader SrcReader;232CvPoint StartPt = {0, 0}, EndPt = {0, 0};233///////////234int TotalErrors = 0;235///////////236int Count;237int i,j;238239assert( SrcSeq && DstSeq );240241////////// init ////////////////////242Count = SrcSeq->total;243244cvStartReadSeq( DstSeq, &DstReader, 0 );245cvStartReadSeq( SrcSeq, &SrcReader, 0 );246247CV_READ_SEQ_ELEM( StartPt, DstReader );248for( i = 0 ; i < Count ; )249{250CV_READ_SEQ_ELEM( EndPt, SrcReader );251i++;252if( StartPt.x == EndPt.x && StartPt.y == EndPt.y ) break;253}254255///////// start ////////////////256for( i = 1, j = 0 ; i <= DstSeq->total ; )257{258///////// read slice ////////////259EndPt.x = StartPt.x;260EndPt.y = StartPt.y;261CV_READ_SEQ_ELEM( StartPt, DstReader );262i++;263264TotalErrors += check_slice( StartPt, EndPt, &SrcReader, Eps, &j, Count );265266if( j > Count )267{268TotalErrors++;269return TotalErrors;270} //if( !flag )271272} // for( int i = 0 ; i < DstSeq->total ; i++ )273274return TotalErrors;275}276277278//extern CvTestContourGenerator cvTsTestContours[];279280void CV_ApproxPolyTest::run( int /*start_from*/ )281{282int code = cvtest::TS::OK;283CvMemStorage* storage = 0;284////////////// Variables ////////////////285int IntervalsCount = 10;286///////////287//CvTestContourGenerator Cont;288CvSeq* SrcSeq = NULL;289CvSeq* DstSeq;290int iDiam;291float dDiam, Eps, EpsStep;292293for( int i = 0; i < 30; i++ )294{295CvMemStoragePos pos;296297ts->update_context( this, i, false );298299///////////////////// init contour /////////300dDiam = 0;301while( sqrt(dDiam) / IntervalsCount == 0 )302{303if( storage != 0 )304cvReleaseMemStorage(&storage);305306storage = cvCreateMemStorage( 0 );307if( get_contour( 0, &SrcSeq, &iDiam, storage ) )308dDiam = (float)iDiam;309}310dDiam = (float)sqrt( dDiam );311312storage = SrcSeq->storage;313314////////////////// test /////////////315EpsStep = dDiam / IntervalsCount ;316for( Eps = EpsStep ; Eps < dDiam ; Eps += EpsStep )317{318cvSaveMemStoragePos( storage, &pos );319320////////// call function ////////////321DstSeq = cvApproxPoly( SrcSeq, SrcSeq->header_size, storage,322CV_POLY_APPROX_DP, Eps );323324if( DstSeq == NULL )325{326ts->printf( cvtest::TS::LOG,327"cvApproxPoly returned NULL for contour #%d, espilon = %g\n", i, Eps );328code = cvtest::TS::FAIL_INVALID_OUTPUT;329goto _exit_;330} // if( DstSeq == NULL )331332code = check( SrcSeq, DstSeq, Eps );333if( code != 0 )334{335ts->printf( cvtest::TS::LOG,336"Incorrect result for the contour #%d approximated with epsilon=%g\n", i, Eps );337code = cvtest::TS::FAIL_BAD_ACCURACY;338goto _exit_;339}340341cvRestoreMemStoragePos( storage, &pos );342} // for( Eps = EpsStep ; Eps <= Diam ; Eps += EpsStep )343344///////////// free memory ///////////////////345cvReleaseMemStorage(&storage);346} // for( int i = 0; NULL != ( Cont = Contours[i] ) ; i++ )347348_exit_:349cvReleaseMemStorage(&storage);350351if( code < 0 )352ts->set_failed_test_info( code );353}354355TEST(Imgproc_ApproxPoly, accuracy) { CV_ApproxPolyTest test; test.safe_run(); }356357}} // namespace358359360