048f01c1bd44e0788a3891d1a952660745dde7aa
[opencv] / tests / cv / src / achesscorners.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "cvtest.h"
43
44 void show_points( IplImage* gray, CvPoint2D32f* u, int u_cnt, CvPoint2D32f* v, int v_cnt,
45                   CvSize pattern_size, int was_found )
46 {
47     CvSize size;
48     int i;
49
50     cvGetImageRawData( gray, 0, 0, &size );
51     
52     IplImage* rgb = cvCreateImage( size, 8, 3 );
53     cvMerge( gray, gray, gray, 0, rgb );
54
55     if( v )
56     {
57         for( i = 0; i < v_cnt; i++ )
58         {
59             cvCircle( rgb, cvPoint(cvRound(v[i].x), cvRound(v[i].y)), 3, CV_RGB(255,0,0), CV_FILLED);
60         }
61     }
62
63     if( u )
64     {
65         for( i = 0; i < u_cnt; i++ )
66         {
67             cvCircle( rgb, cvPoint(cvRound(u[i].x), cvRound(u[i].y)), 3, CV_RGB(0,255,0), CV_FILLED);
68         }
69     }
70
71     cvDrawChessboardCorners( rgb, pattern_size, v, v_cnt, was_found );
72
73     cvvNamedWindow( "test", 0 );
74     cvvShowImage( "test", rgb );
75
76     cvvWaitKey(0);
77 }
78
79
80 class CV_ChessboardDetectorTest : public CvTest
81 {
82 public:
83     CV_ChessboardDetectorTest();
84 protected:
85     void run(int);
86 };
87
88
89 CV_ChessboardDetectorTest::CV_ChessboardDetectorTest():
90     CvTest( "chessboard-detector", "cvFindChessboardCorners" )
91 {
92     support_testing_modes = CvTS::CORRECTNESS_CHECK_MODE;
93 }
94
95 /* ///////////////////// chess_corner_test ///////////////////////// */
96 void CV_ChessboardDetectorTest::run( int start_from )
97 {
98     int code = CvTS::OK;
99
100 //#define WRITE_POINTS 1
101 #ifndef WRITE_POINTS    
102     const double rough_success_error_level = 2.5;
103     const double precise_success_error_level = 2;
104     double err = 0, max_rough_error = 0, max_precise_error = 0;
105 #endif
106
107     /* test parameters */
108     char   filepath[1000];
109     char   filename[1000];
110
111     CvMat*  _u = 0;
112     CvMat*  _v = 0;
113     CvPoint2D32f* u;
114     CvPoint2D32f* v;
115
116     IplImage* img = 0;
117     IplImage* gray = 0;
118     IplImage* thresh = 0;
119
120     int  k, idx, max_idx;
121     int  progress = 0;
122
123     sprintf( filepath, "%scameracalibration/", ts->get_data_path() );
124     sprintf( filename, "%schessboard_list.dat", filepath );
125     CvFileStorage* fs = cvOpenFileStorage( filename, 0, CV_STORAGE_READ );
126     CvFileNode* board_list = fs ? cvGetFileNodeByName( fs, 0, "boards" ) : 0;
127
128     if( !fs || !board_list || !CV_NODE_IS_SEQ(board_list->tag) ||
129         board_list->data.seq->total % 2 != 0 )
130     {
131         ts->printf( CvTS::LOG, "chessboard_list.dat can not be readed or is not valid" );
132         code = CvTS::FAIL_MISSING_TEST_DATA;
133         goto _exit_;
134     }
135
136     max_idx = board_list->data.seq->total/2;
137
138     for( idx = start_from; idx < max_idx; idx++ )
139     {
140         int count0 = -1;
141         int count = 0;
142         CvSize pattern_size = { -1, -1 };
143         int j, result;
144         
145         ts->update_context( this, idx-1, true );
146
147         /* read the image */
148         sprintf( filename, "%s%s", filepath,
149             cvReadString((CvFileNode*)cvGetSeqElem(board_list->data.seq,idx*2),"dummy.txt"));
150     
151         img = cvLoadImage( filename );
152         
153         if( !img )
154         {
155             ts->printf( CvTS::LOG, "one of chessboard images can't be read: %s", filename );
156             if( max_idx == 1 )
157             {
158                 code = CvTS::FAIL_MISSING_TEST_DATA;
159                 goto _exit_;
160             }
161             continue;
162         }
163
164         gray = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 );
165         thresh = cvCreateImage( cvSize( img->width, img->height ), IPL_DEPTH_8U, 1 );
166         cvCvtColor( img, gray, CV_BGR2GRAY );
167  
168         sprintf( filename, "%s%s", filepath,
169             cvReadString((CvFileNode*)cvGetSeqElem(board_list->data.seq,idx*2+1),"dummy.txt"));
170
171         _u = (CvMat*)cvLoad( filename );
172
173         if( _u == 0 )
174         {
175             if( idx == 0 )
176                 ts->printf( CvTS::LOG, "one of chessboard corner files can't be read: %s", filename ); 
177             if( max_idx == 1 )
178             {
179                 code = CvTS::FAIL_MISSING_TEST_DATA;
180                 goto _exit_;
181             }
182             continue;
183         }
184
185         pattern_size.width = _u->cols;
186         pattern_size.height = _u->rows;
187         count0 = pattern_size.width*pattern_size.height;
188
189         /* allocate additional buffers */
190         _v = cvCloneMat( _u );
191         count = count0;
192
193         u = (CvPoint2D32f*)_u->data.fl;
194         v = (CvPoint2D32f*)_v->data.fl;
195
196         OPENCV_CALL( result = cvFindChessboardCorners(
197                      gray, pattern_size, v, &count, 7 ));
198
199         //show_points( gray, 0, count0, v, count, pattern_size, result );
200         if( !result || count != count0 )
201         {
202             ts->printf( CvTS::LOG, "chess board is not found" );
203             code = CvTS::FAIL_INVALID_OUTPUT;
204             goto _exit_;
205         }
206
207 #ifndef WRITE_POINTS
208         err = DBL_MAX;
209         for( k = 0; k < 2; k++ )
210         {
211             double err1 = 0;
212             for( j = 0; j < count0; j++ )
213             {
214                 int j1 = k == 0 ? j : count0 - j - 1;
215                 double dx = fabs( v[j].x - u[j1].x );
216                 double dy = fabs( v[j].y - u[j1].y );
217
218                 dx = MAX( dx, dy );
219                 if( dx > err1 )
220                     err1 = dx;
221             }
222             err = MIN(err, err1);
223         }
224         if( err > rough_success_error_level )
225         {
226             ts->printf( CvTS::LOG, "bad accuracy of corner guesses" );
227             code = CvTS::FAIL_BAD_ACCURACY;
228             goto _exit_;
229         }
230
231         max_rough_error = MAX( max_rough_error, err );
232 #endif
233         OPENCV_CALL( cvFindCornerSubPix( gray, v, count, cvSize( 5, 5 ), cvSize(-1,-1),
234                             cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,30,0.1)));
235         //show_points( gray, u + 1, count0, v, count, pattern_size, result  );
236
237 #ifndef WRITE_POINTS
238         err = DBL_MAX;
239         for( k = 0; k < 2; k++ )
240         {
241             double err1 = 0;
242             for( j = 0; j < count0; j++ )
243             {
244                 int j1 = k == 0 ? j : count0 - j - 1;
245                 double dx = fabs( v[j].x - u[j1].x );
246                 double dy = fabs( v[j].y - u[j1].y );
247
248                 dx = MAX( dx, dy );
249                 if( dx > err1 )
250                     err1 = dx;
251             }
252             err = MIN(err, err1);
253         }
254         if( err > precise_success_error_level )
255         {
256             ts->printf( CvTS::LOG, "bad accuracy of adjusted corners" ); 
257             code = CvTS::FAIL_BAD_ACCURACY;
258             goto _exit_;
259         }
260         max_precise_error = MAX( max_precise_error, err );
261 #else
262         cvSave( filename, _v );
263 #endif
264         cvReleaseMat( &_u );
265         cvReleaseMat( &_v );
266         cvReleaseImage( &img );
267         cvReleaseImage( &gray );
268         cvReleaseImage( &thresh );
269         progress = update_progress( progress, idx-1, max_idx, 0 );
270     }
271
272 _exit_:
273
274     /* release occupied memory */
275     cvReleaseMat( &_u );
276     cvReleaseMat( &_v );
277     cvReleaseFileStorage( &fs );
278     cvReleaseImage( &img );
279     cvReleaseImage( &gray );
280     cvReleaseImage( &thresh );
281
282     if( code < 0 )
283         ts->set_failed_test_info( code );
284 }
285
286 CV_ChessboardDetectorTest chessboard_detector_test;
287
288 /* End of file. */