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

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