Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/video/test/test_ecc.cpp
16354 views
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
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistribution's of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistribution's in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * The name of the copyright holders may not be used to endorse or promote products
28
// derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "test_precomp.hpp"
44
45
namespace opencv_test { namespace {
46
47
class CV_ECC_BaseTest : public cvtest::BaseTest
48
{
49
public:
50
CV_ECC_BaseTest();
51
52
protected:
53
54
double computeRMS(const Mat& mat1, const Mat& mat2);
55
bool isMapCorrect(const Mat& mat);
56
57
58
double MAX_RMS_ECC;//upper bound for RMS error
59
int ntests;//number of tests per motion type
60
int ECC_iterations;//number of iterations for ECC
61
double ECC_epsilon; //we choose a negative value, so that
62
// ECC_iterations are always executed
63
};
64
65
CV_ECC_BaseTest::CV_ECC_BaseTest()
66
{
67
MAX_RMS_ECC=0.1;
68
ntests = 3;
69
ECC_iterations = 50;
70
ECC_epsilon = -1; //-> negative value means that ECC_Iterations will be executed
71
}
72
73
74
bool CV_ECC_BaseTest::isMapCorrect(const Mat& map)
75
{
76
bool tr = true;
77
float mapVal;
78
for(int i =0; i<map.rows; i++)
79
for(int j=0; j<map.cols; j++){
80
mapVal = map.at<float>(i, j);
81
tr = tr & (!cvIsNaN(mapVal) && (fabs(mapVal) < 1e9));
82
}
83
84
return tr;
85
}
86
87
double CV_ECC_BaseTest::computeRMS(const Mat& mat1, const Mat& mat2){
88
89
CV_Assert(mat1.rows == mat2.rows);
90
CV_Assert(mat1.cols == mat2.cols);
91
92
Mat errorMat;
93
subtract(mat1, mat2, errorMat);
94
95
return sqrt(errorMat.dot(errorMat)/(mat1.rows*mat1.cols));
96
}
97
98
99
class CV_ECC_Test_Translation : public CV_ECC_BaseTest
100
{
101
public:
102
CV_ECC_Test_Translation();
103
protected:
104
void run(int);
105
106
bool testTranslation(int);
107
};
108
109
CV_ECC_Test_Translation::CV_ECC_Test_Translation(){}
110
111
bool CV_ECC_Test_Translation::testTranslation(int from)
112
{
113
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
114
115
116
if (img.empty())
117
{
118
ts->printf( ts->LOG, "test image can not be read");
119
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
120
return false;
121
}
122
Mat testImg;
123
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
124
125
cv::RNG rng = ts->get_rng();
126
127
int progress=0;
128
129
for (int k=from; k<ntests; k++){
130
131
ts->update_context( this, k, true );
132
progress = update_progress(progress, k, ntests, 0);
133
134
Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
135
0, 1, (rng.uniform(10.f, 20.f)));
136
137
Mat warpedImage;
138
139
warpAffine(testImg, warpedImage, translationGround,
140
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
141
142
Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
143
144
findTransformECC(warpedImage, testImg, mapTranslation, 0,
145
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
146
147
if (!isMapCorrect(mapTranslation)){
148
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
149
return false;
150
}
151
152
if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
153
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
154
ts->printf( ts->LOG, "RMS = %f",
155
computeRMS(mapTranslation, translationGround));
156
return false;
157
}
158
159
}
160
return true;
161
}
162
163
void CV_ECC_Test_Translation::run(int from)
164
{
165
166
if (!testTranslation(from))
167
return;
168
169
ts->set_failed_test_info(cvtest::TS::OK);
170
}
171
172
173
174
class CV_ECC_Test_Euclidean : public CV_ECC_BaseTest
175
{
176
public:
177
CV_ECC_Test_Euclidean();
178
protected:
179
void run(int);
180
181
bool testEuclidean(int);
182
};
183
184
CV_ECC_Test_Euclidean::CV_ECC_Test_Euclidean() { }
185
186
bool CV_ECC_Test_Euclidean::testEuclidean(int from)
187
{
188
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
189
190
191
if (img.empty())
192
{
193
ts->printf( ts->LOG, "test image can not be read");
194
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
195
return false;
196
}
197
Mat testImg;
198
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
199
200
cv::RNG rng = ts->get_rng();
201
202
int progress = 0;
203
for (int k=from; k<ntests; k++){
204
ts->update_context( this, k, true );
205
progress = update_progress(progress, k, ntests, 0);
206
207
double angle = CV_PI/30 + CV_PI*rng.uniform((double)-2.f, (double)2.f)/180;
208
209
Mat euclideanGround = (Mat_<float>(2,3) << cos(angle), -sin(angle), (rng.uniform(10.f, 20.f)),
210
sin(angle), cos(angle), (rng.uniform(10.f, 20.f)));
211
212
Mat warpedImage;
213
214
warpAffine(testImg, warpedImage, euclideanGround,
215
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
216
217
Mat mapEuclidean = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
218
219
findTransformECC(warpedImage, testImg, mapEuclidean, 1,
220
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
221
222
if (!isMapCorrect(mapEuclidean)){
223
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
224
return false;
225
}
226
227
if (computeRMS(mapEuclidean, euclideanGround)>MAX_RMS_ECC){
228
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
229
ts->printf( ts->LOG, "RMS = %f",
230
computeRMS(mapEuclidean, euclideanGround));
231
return false;
232
}
233
234
}
235
return true;
236
}
237
238
239
void CV_ECC_Test_Euclidean::run(int from)
240
{
241
242
if (!testEuclidean(from))
243
return;
244
245
ts->set_failed_test_info(cvtest::TS::OK);
246
}
247
248
class CV_ECC_Test_Affine : public CV_ECC_BaseTest
249
{
250
public:
251
CV_ECC_Test_Affine();
252
protected:
253
void run(int);
254
255
bool testAffine(int);
256
};
257
258
CV_ECC_Test_Affine::CV_ECC_Test_Affine(){}
259
260
261
bool CV_ECC_Test_Affine::testAffine(int from)
262
{
263
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
264
265
if (img.empty())
266
{
267
ts->printf( ts->LOG, "test image can not be read");
268
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
269
return false;
270
}
271
Mat testImg;
272
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
273
274
cv::RNG rng = ts->get_rng();
275
276
int progress = 0;
277
for (int k=from; k<ntests; k++){
278
ts->update_context( this, k, true );
279
progress = update_progress(progress, k, ntests, 0);
280
281
282
Mat affineGround = (Mat_<float>(2,3) << (1-rng.uniform(-0.05f, 0.05f)),
283
(rng.uniform(-0.03f, 0.03f)), (rng.uniform(10.f, 20.f)),
284
(rng.uniform(-0.03f, 0.03f)), (1-rng.uniform(-0.05f, 0.05f)),
285
(rng.uniform(10.f, 20.f)));
286
287
Mat warpedImage;
288
289
warpAffine(testImg, warpedImage, affineGround,
290
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
291
292
Mat mapAffine = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
293
294
findTransformECC(warpedImage, testImg, mapAffine, 2,
295
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
296
297
if (!isMapCorrect(mapAffine)){
298
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
299
return false;
300
}
301
302
if (computeRMS(mapAffine, affineGround)>MAX_RMS_ECC){
303
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
304
ts->printf( ts->LOG, "RMS = %f",
305
computeRMS(mapAffine, affineGround));
306
return false;
307
}
308
309
}
310
311
return true;
312
}
313
314
315
void CV_ECC_Test_Affine::run(int from)
316
{
317
318
if (!testAffine(from))
319
return;
320
321
ts->set_failed_test_info(cvtest::TS::OK);
322
}
323
324
class CV_ECC_Test_Homography : public CV_ECC_BaseTest
325
{
326
public:
327
CV_ECC_Test_Homography();
328
protected:
329
void run(int);
330
331
bool testHomography(int);
332
};
333
334
CV_ECC_Test_Homography::CV_ECC_Test_Homography(){}
335
336
bool CV_ECC_Test_Homography::testHomography(int from)
337
{
338
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
339
340
341
if (img.empty())
342
{
343
ts->printf( ts->LOG, "test image can not be read");
344
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
345
return false;
346
}
347
Mat testImg;
348
resize(img, testImg, Size(216, 216), 0, 0, INTER_LINEAR_EXACT);
349
350
cv::RNG rng = ts->get_rng();
351
352
int progress = 0;
353
for (int k=from; k<ntests; k++){
354
ts->update_context( this, k, true );
355
progress = update_progress(progress, k, ntests, 0);
356
357
Mat homoGround = (Mat_<float>(3,3) << (1-rng.uniform(-0.05f, 0.05f)),
358
(rng.uniform(-0.03f, 0.03f)), (rng.uniform(10.f, 20.f)),
359
(rng.uniform(-0.03f, 0.03f)), (1-rng.uniform(-0.05f, 0.05f)),(rng.uniform(10.f, 20.f)),
360
(rng.uniform(0.0001f, 0.0003f)), (rng.uniform(0.0001f, 0.0003f)), 1.f);
361
362
Mat warpedImage;
363
364
warpPerspective(testImg, warpedImage, homoGround,
365
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
366
367
Mat mapHomography = Mat::eye(3, 3, CV_32F);
368
369
findTransformECC(warpedImage, testImg, mapHomography, 3,
370
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon));
371
372
if (!isMapCorrect(mapHomography)){
373
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
374
return false;
375
}
376
377
if (computeRMS(mapHomography, homoGround)>MAX_RMS_ECC){
378
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
379
ts->printf( ts->LOG, "RMS = %f",
380
computeRMS(mapHomography, homoGround));
381
return false;
382
}
383
384
}
385
return true;
386
}
387
388
void CV_ECC_Test_Homography::run(int from)
389
{
390
if (!testHomography(from))
391
return;
392
393
ts->set_failed_test_info(cvtest::TS::OK);
394
}
395
396
class CV_ECC_Test_Mask : public CV_ECC_BaseTest
397
{
398
public:
399
CV_ECC_Test_Mask();
400
protected:
401
void run(int);
402
403
bool testMask(int);
404
};
405
406
CV_ECC_Test_Mask::CV_ECC_Test_Mask(){}
407
408
bool CV_ECC_Test_Mask::testMask(int from)
409
{
410
Mat img = imread( string(ts->get_data_path()) + "shared/fruits.png", 0);
411
412
413
if (img.empty())
414
{
415
ts->printf( ts->LOG, "test image can not be read");
416
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
417
return false;
418
}
419
Mat scaledImage;
420
resize(img, scaledImage, Size(216, 216), 0, 0, INTER_LINEAR_EXACT );
421
422
Mat_<float> testImg;
423
scaledImage.convertTo(testImg, testImg.type());
424
425
cv::RNG rng = ts->get_rng();
426
427
int progress=0;
428
429
for (int k=from; k<ntests; k++){
430
431
ts->update_context( this, k, true );
432
progress = update_progress(progress, k, ntests, 0);
433
434
Mat translationGround = (Mat_<float>(2,3) << 1, 0, (rng.uniform(10.f, 20.f)),
435
0, 1, (rng.uniform(10.f, 20.f)));
436
437
Mat warpedImage;
438
439
warpAffine(testImg, warpedImage, translationGround,
440
Size(200,200), INTER_LINEAR + WARP_INVERSE_MAP);
441
442
Mat mapTranslation = (Mat_<float>(2,3) << 1, 0, 0, 0, 1, 0);
443
444
Mat_<unsigned char> mask = Mat_<unsigned char>::ones(testImg.rows, testImg.cols);
445
for (int i=testImg.rows*2/3; i<testImg.rows; i++) {
446
for (int j=testImg.cols*2/3; j<testImg.cols; j++) {
447
testImg(i, j) = 0;
448
mask(i, j) = 0;
449
}
450
}
451
452
findTransformECC(warpedImage, testImg, mapTranslation, 0,
453
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, ECC_iterations, ECC_epsilon), mask);
454
455
if (!isMapCorrect(mapTranslation)){
456
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
457
return false;
458
}
459
460
if (computeRMS(mapTranslation, translationGround)>MAX_RMS_ECC){
461
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
462
ts->printf( ts->LOG, "RMS = %f",
463
computeRMS(mapTranslation, translationGround));
464
return false;
465
}
466
467
}
468
return true;
469
}
470
471
void CV_ECC_Test_Mask::run(int from)
472
{
473
if (!testMask(from))
474
return;
475
476
ts->set_failed_test_info(cvtest::TS::OK);
477
}
478
479
TEST(Video_ECC_Translation, accuracy) { CV_ECC_Test_Translation test; test.safe_run();}
480
TEST(Video_ECC_Euclidean, accuracy) { CV_ECC_Test_Euclidean test; test.safe_run(); }
481
TEST(Video_ECC_Affine, accuracy) { CV_ECC_Test_Affine test; test.safe_run(); }
482
TEST(Video_ECC_Homography, accuracy) { CV_ECC_Test_Homography test; test.safe_run(); }
483
TEST(Video_ECC_Mask, accuracy) { CV_ECC_Test_Mask test; test.safe_run(); }
484
485
}} // namespace
486
487