Merge pull request #2887 from ilya-lavrenov:ipp_morph_fix
[platform/upstream/opencv.git] / modules / objdetect / test / test_latentsvmdetector.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 //                           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 #include "opencv2/objdetect/objdetect_c.h"
45 #include <string>
46
47 #ifdef HAVE_TBB
48 #include "tbb/task_scheduler_init.h"
49 #endif
50
51 using namespace std;
52 using namespace cv;
53
54 const int num_detections = 3;
55 const float true_scores[3] = {-0.383931f, -0.825876f, -0.959934f};
56 const float score_thr = 0.05f;
57 const CvRect true_bounding_boxes[3] = {cvRect(0, 45, 362, 452), cvRect(304, 0, 64, 80), cvRect(236, 0, 108, 59)};
58
59 class CV_LatentSVMDetectorTest : public cvtest::BaseTest
60 {
61 protected:
62     void run(int);
63     bool isEqual(CvRect r1, CvRect r2, int eps);
64 };
65
66 bool CV_LatentSVMDetectorTest::isEqual(CvRect r1, CvRect r2, int eps)
67 {
68     return (std::abs(r1.x - r2.x) <= eps
69             && std::abs(r1.y - r2.y) <= eps
70             && std::abs(r1.width - r2.width) <= eps
71             && std::abs(r1.height - r2.height) <= eps);
72 }
73
74 void CV_LatentSVMDetectorTest::run( int /* start_from */)
75 {
76     string img_path = string(ts->get_data_path()) + "latentsvmdetector/cat.png";
77     string model_path = string(ts->get_data_path()) + "latentsvmdetector/models_VOC2007/cat.xml";
78     int numThreads = -1;
79
80 #ifdef HAVE_TBB
81     numThreads = 2;
82     tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred);
83     init.initialize(numThreads);
84 #endif
85
86     Mat image2 = cv::imread(img_path.c_str());
87     IplImage image = image2;
88     if (image2.empty())
89     {
90         ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
91         return;
92     }
93
94     CvLatentSvmDetector* detector = cvLoadLatentSvmDetector(model_path.c_str());
95     if (!detector)
96     {
97         ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
98         return;
99     }
100
101     CvMemStorage* storage = cvCreateMemStorage(0);
102     CvSeq* detections = 0;
103     detections = cvLatentSvmDetectObjects(&image, detector, storage, 0.5f, numThreads);
104     if (detections->total != num_detections)
105     {
106         ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
107     }
108     else
109     {
110         ts->set_failed_test_info(cvtest::TS::OK);
111         for (int i = 0; i < detections->total; i++)
112         {
113             CvObjectDetection detection = *(CvObjectDetection*)cvGetSeqElem( detections, i );
114             CvRect bounding_box = detection.rect;
115             float score = detection.score;
116             if ((!isEqual(bounding_box, true_bounding_boxes[i], 1)) || (fabs(score - true_scores[i]) > score_thr))
117             {
118                 ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
119                 break;
120             }
121         }
122     }
123 #ifdef HAVE_TBB
124     init.terminate();
125 #endif
126     cvReleaseMemStorage( &storage );
127     cvReleaseLatentSvmDetector( &detector );
128 }
129
130 // Test for c++ version of Latent SVM
131
132 class LatentSVMDetectorTest : public cvtest::BaseTest
133 {
134 protected:
135     void run(int);
136 };
137
138 static void writeDetections( FileStorage& fs, const string& nodeName, const vector<LatentSvmDetector::ObjectDetection>& detections )
139 {
140     fs << nodeName << "[";
141     for( size_t i = 0; i < detections.size(); i++ )
142     {
143         const LatentSvmDetector::ObjectDetection& d = detections[i];
144         fs << d.rect.x << d.rect.y << d.rect.width << d.rect.height
145            << d.score << d.classID;
146     }
147     fs << "]";
148 }
149
150 static void readDetections( FileStorage fs, const string& nodeName, vector<LatentSvmDetector::ObjectDetection>& detections )
151 {
152     detections.clear();
153
154     FileNode fn = fs.root()[nodeName];
155     FileNodeIterator fni = fn.begin();
156     while( fni != fn.end() )
157     {
158         LatentSvmDetector::ObjectDetection d;
159         fni >> d.rect.x >> d.rect.y >> d.rect.width >> d.rect.height
160             >> d.score >> d.classID;
161         detections.push_back( d );
162     }
163 }
164
165 static inline bool isEqual( const LatentSvmDetector::ObjectDetection& d1, const LatentSvmDetector::ObjectDetection& d2, int eps, float threshold)
166 {
167     return (
168            std::abs(d1.rect.x - d2.rect.x) <= eps
169            && std::abs(d1.rect.y - d2.rect.y) <= eps
170            && std::abs(d1.rect.width - d2.rect.width) <= eps
171            && std::abs(d1.rect.height - d2.rect.height) <= eps
172            && (d1.classID == d2.classID)
173            && std::abs(d1.score - d2.score) <= threshold
174            );
175 }
176
177 std::ostream& operator << (std::ostream& os, const CvRect& r)
178 {
179     return (os << "[x=" << r.x << ", y=" << r.y << ", w=" << r.width << ", h=" << r.height << "]");
180 }
181
182 bool compareResults( const vector<LatentSvmDetector::ObjectDetection>& calc, const vector<LatentSvmDetector::ObjectDetection>& valid, int eps, float threshold)
183 {
184     if( calc.size() != valid.size() )
185         return false;
186
187     for( size_t i = 0; i < calc.size(); i++ )
188     {
189         const LatentSvmDetector::ObjectDetection& c = calc[i];
190         const LatentSvmDetector::ObjectDetection& v = valid[i];
191         if( !isEqual(c, v, eps, threshold) )
192         {
193             std::cerr << "Expected: " << v.rect << " class=" << v.classID << " score=" << v.score << std::endl;
194             std::cerr << "Actual:   " << c.rect << " class=" << c.classID << " score=" << c.score << std::endl;
195             return false;
196         }
197     }
198     return true;
199 }
200
201 void LatentSVMDetectorTest::run( int /* start_from */)
202 {
203     string img_path_cat = string(ts->get_data_path()) + "latentsvmdetector/cat.png";
204     string img_path_cars = string(ts->get_data_path()) + "latentsvmdetector/cars.png";
205
206     string model_path_cat = string(ts->get_data_path()) + "latentsvmdetector/models_VOC2007/cat.xml";
207     string model_path_car = string(ts->get_data_path()) + "latentsvmdetector/models_VOC2007/car.xml";
208
209     string true_res_path = string(ts->get_data_path()) + "latentsvmdetector/results.xml";
210
211     int numThreads = 1;
212
213 #ifdef HAVE_TBB
214     numThreads = 2;
215 #endif
216
217     Mat image_cat = imread( img_path_cat );
218     Mat image_cars = imread( img_path_cars );
219     if( image_cat.empty() || image_cars.empty() )
220     {
221         ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
222         return;
223     }
224
225     // We will test 2 cases:
226     // detector1 - to test case of one class 'cat'
227     // detector12 - to test case of two (several) classes 'cat' and car
228
229     // Load detectors
230     LatentSvmDetector detector1( vector<String>(1,model_path_cat) );
231
232     vector<String> models_pathes(2);
233     models_pathes[0] = model_path_cat;
234     models_pathes[1] = model_path_car;
235     LatentSvmDetector detector12( models_pathes );
236
237     if( detector1.empty() || detector12.empty() || detector12.getClassCount() != 2 )
238     {
239         ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
240         return;
241     }
242
243     // 1. Test method detect
244     // Run detectors
245     vector<LatentSvmDetector::ObjectDetection> detections1_cat, detections12_cat, detections12_cars;
246     detector1.detect( image_cat, detections1_cat, 0.5, numThreads );
247     detector12.detect( image_cat, detections12_cat, 0.5, numThreads );
248     detector12.detect( image_cars, detections12_cars, 0.5, numThreads );
249
250     // Load true results
251     FileStorage fs( true_res_path, FileStorage::READ );
252     if( fs.isOpened() )
253     {
254         vector<LatentSvmDetector::ObjectDetection> true_detections1_cat, true_detections12_cat, true_detections12_cars;
255         readDetections( fs, "detections1_cat", true_detections1_cat );
256         readDetections( fs, "detections12_cat", true_detections12_cat );
257         readDetections( fs, "detections12_cars", true_detections12_cars );
258
259
260         if( !compareResults(detections1_cat, true_detections1_cat, 1, score_thr) )
261         {
262             std::cerr << "Results of detector1 are invalid on image cat.png" << std::endl;
263             ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
264         }
265         if( !compareResults(detections12_cat, true_detections12_cat, 1, score_thr) )
266         {
267             std::cerr << "Results of detector12 are invalid on image cat.png" << std::endl;
268             ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
269         }
270         if( !compareResults(detections12_cars, true_detections12_cars, 1, score_thr) )
271         {
272             std::cerr << "Results of detector12 are invalid on image cars.png" << std::endl;
273             ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
274         }
275     }
276     else
277     {
278         fs.open( true_res_path, FileStorage::WRITE );
279         if( fs.isOpened() )
280         {
281             writeDetections( fs, "detections1_cat", detections1_cat );
282             writeDetections( fs, "detections12_cat", detections12_cat );
283             writeDetections( fs, "detections12_cars", detections12_cars );
284         }
285         else
286             std::cerr << "File " << true_res_path << " cann't be opened to save test results" << std::endl;
287     }
288
289     // 2. Simple tests of other methods
290     if( detector1.getClassCount() != 1 || detector1.getClassNames()[0] != "cat" )
291     {
292         std::cerr << "Incorrect result of method getClassNames() or getClassCount()" << std::endl;
293         ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT);
294     }
295
296     detector1.clear();
297     if( !detector1.empty() )
298     {
299         std::cerr << "There is a bug in method clear() or empty()" << std::endl;
300         ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT);
301     }
302
303     ts->set_failed_test_info( cvtest::TS::OK);
304 }
305
306 TEST(Objdetect_LatentSVMDetector_c, DISABLED_regression) { CV_LatentSVMDetectorTest test; test.safe_run(); }
307 TEST(Objdetect_LatentSVMDetector_cpp, DISABLED_regression) { LatentSVMDetectorTest test; test.safe_run(); }