catching OpenCL double not supported exceptions
[profile/ivi/opencv.git] / modules / ocl / test / test_ml.cpp
1 ///////////////////////////////////////////////////////////////////////////////////////
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 // Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
13 // Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // @Authors
17 //    Jin Ma,        jin@multicorewareinc.com
18 //    Xiaopeng Fu,   fuxiaopeng2222@163.com
19 //    Erping Pang,   pang_er_ping@163.com
20 // Redistribution and use in source and binary forms, with or without modification,
21 // are permitted provided that the following conditions are met:
22 //
23 //   * Redistribution's of source code must retain the above copyright notice,
24 //     this list of conditions and the following disclaimer.
25 //
26 //   * Redistribution's in binary form must reproduce the above copyright notice,
27 //     this list of conditions and the following disclaimer in the documentation
28 //     and/or other oclMaterials provided with the distribution.
29 //
30 //   * The name of the copyright holders may not be used to endorse or promote products
31 //     derived from this software without specific prior written permission.
32 //
33 // This software is provided by the copyright holders and contributors "as is" and
34 // any express or implied warranties, including, but not limited to, the implied
35 // warranties of merchantability and fitness for a particular purpose are disclaimed.
36 // In no event shall the Intel Corporation or contributors be liable for any direct,
37 // indirect, incidental, special, exemplary, or consequential damages
38 // (including, but not limited to, procurement of substitute goods or services;
39 // loss of use, data, or profits; or business interruption) however caused
40 // and on any theory of liability, whether in contract, strict liability,
41 // or tort (including negligence or otherwise) arising in any way out of
42 // the use of this software, even if advised of the possibility of such damage.
43 //
44 //M*/
45
46 #include "test_precomp.hpp"
47
48 #ifdef HAVE_OPENCL
49
50 using namespace cv;
51 using namespace cv::ocl;
52 using namespace cvtest;
53 using namespace testing;
54
55 ///////K-NEAREST NEIGHBOR//////////////////////////
56
57 static void genTrainData(cv::RNG& rng, Mat& trainData, int trainDataRow, int trainDataCol,
58                          Mat& trainLabel = Mat().setTo(Scalar::all(0)), int nClasses = 0)
59 {
60     cv::Size size(trainDataCol, trainDataRow);
61     trainData = randomMat(rng, size, CV_32FC1, 1.0, 1000.0, false);
62     if(nClasses != 0)
63     {
64         cv::Size size1(trainDataRow, 1);
65         trainLabel = randomMat(rng, size1, CV_8UC1, 0, nClasses - 1, false);
66         trainLabel.convertTo(trainLabel, CV_32FC1);
67     }
68 }
69
70 PARAM_TEST_CASE(KNN, int, Size, int, bool)
71 {
72     int k;
73     int trainDataCol;
74     int testDataRow;
75     int nClass;
76     bool regression;
77     virtual void SetUp()
78     {
79         k = GET_PARAM(0);
80         nClass = GET_PARAM(2);
81         trainDataCol = GET_PARAM(1).width;
82         testDataRow = GET_PARAM(1).height;
83         regression = GET_PARAM(3);
84     }
85 };
86
87 OCL_TEST_P(KNN, Accuracy)
88 {
89     Mat trainData, trainLabels;
90     const int trainDataRow = 500;
91     genTrainData(rng, trainData, trainDataRow, trainDataCol, trainLabels, nClass);
92
93     Mat testData, testLabels;
94     genTrainData(rng, testData, testDataRow, trainDataCol);
95
96     KNearestNeighbour knn_ocl;
97     CvKNearest knn_cpu;
98     Mat best_label_cpu;
99     oclMat best_label_ocl;
100
101     /*ocl k-Nearest_Neighbor start*/
102     oclMat trainData_ocl;
103     trainData_ocl.upload(trainData);
104     Mat simpleIdx;
105     knn_ocl.train(trainData, trainLabels, simpleIdx, regression);
106
107     oclMat testdata;
108     testdata.upload(testData);
109     knn_ocl.find_nearest(testdata, k, best_label_ocl);
110     /*ocl k-Nearest_Neighbor end*/
111
112     /*cpu k-Nearest_Neighbor start*/
113     knn_cpu.train(trainData, trainLabels, simpleIdx, regression);
114     knn_cpu.find_nearest(testData, k, &best_label_cpu);
115     /*cpu k-Nearest_Neighbor end*/
116     if(regression)
117     {
118         EXPECT_MAT_SIMILAR(Mat(best_label_ocl), best_label_cpu, 1e-5);
119     }
120     else
121     {
122         EXPECT_MAT_NEAR(Mat(best_label_ocl), best_label_cpu, 0.0);
123     }
124 }
125
126 INSTANTIATE_TEST_CASE_P(OCL_ML, KNN, Combine(Values(6, 5), Values(Size(200, 400), Size(300, 600)),
127     Values(4, 3), Values(false, true)));
128
129 ////////////////////////////////SVM/////////////////////////////////////////////////
130
131 #ifdef HAVE_CLAMDBLAS
132
133 PARAM_TEST_CASE(SVM_OCL, int, int, int)
134 {
135     cv::Size size;
136     int kernel_type;
137     int svm_type;
138     Mat src, labels, samples, labels_predict;
139     int K;
140
141     virtual void SetUp()
142     {
143
144         kernel_type = GET_PARAM(0);
145         svm_type = GET_PARAM(1);
146         K = GET_PARAM(2);
147         cv::Size size = cv::Size(MWIDTH, MHEIGHT);
148         src.create(size, CV_32FC1);
149         labels.create(1, size.height, CV_32SC1);
150         int row_idx = 0;
151         const int max_number = size.height / K - 1;
152         CV_Assert(K <= size.height);
153         for(int i = 0; i < K; i++ )
154         {
155             Mat center_row_header = src.row(row_idx);
156             center_row_header.setTo(0);
157             int nchannel = center_row_header.channels();
158             for(int j = 0; j < nchannel; j++)
159             {
160                 center_row_header.at<float>(0, i * nchannel + j) = 500.0;
161             }
162             labels.at<int>(0, row_idx) = i;
163             for(int j = 0; (j < max_number) ||
164                     (i == K - 1 && j < max_number + size.height % K); j ++)
165             {
166                 Mat cur_row_header = src.row(row_idx + 1 + j);
167                 center_row_header.copyTo(cur_row_header);
168                 Mat tmpmat = randomMat(cur_row_header.size(), cur_row_header.type(), 1, 100, false);
169                 cur_row_header += tmpmat;
170                 labels.at<int>(0, row_idx + 1 + j) = i;
171             }
172             row_idx += 1 + max_number;
173         }
174         labels.convertTo(labels, CV_32FC1);
175         cv::Size test_size = cv::Size(MWIDTH, 100);
176         samples.create(test_size, CV_32FC1);
177         labels_predict.create(1, test_size.height, CV_32SC1);
178         const int max_number_test = test_size.height / K - 1;
179         row_idx = 0;
180         for(int i = 0; i < K; i++ )
181         {
182             Mat center_row_header = samples.row(row_idx);
183             center_row_header.setTo(0);
184             int nchannel = center_row_header.channels();
185             for(int j = 0; j < nchannel; j++)
186             {
187                 center_row_header.at<float>(0, i * nchannel + j) = 500.0;
188             }
189             labels_predict.at<int>(0, row_idx) = i;
190             for(int j = 0; (j < max_number_test) ||
191                     (i == K - 1 && j < max_number_test + test_size.height % K); j ++)
192             {
193                 Mat cur_row_header = samples.row(row_idx + 1 + j);
194                 center_row_header.copyTo(cur_row_header);
195                 Mat tmpmat = randomMat(cur_row_header.size(), cur_row_header.type(), 1, 100, false);
196                 cur_row_header += tmpmat;
197                 labels_predict.at<int>(0, row_idx + 1 + j) = i;
198             }
199             row_idx += 1 + max_number_test;
200         }
201         labels_predict.convertTo(labels_predict, CV_32FC1);
202     }
203 };
204
205 OCL_TEST_P(SVM_OCL, Accuracy)
206 {
207     CvSVMParams params;
208     params.degree = 0.4;
209     params.gamma = 1;
210     params.coef0 = 1;
211     params.C = 1;
212     params.nu = 0.5;
213     params.p = 1;
214     params.svm_type = svm_type;
215     params.kernel_type = kernel_type;
216
217     params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 1000, 0.001);
218
219     CvSVM SVM;
220     SVM.train(src, labels, Mat(), Mat(), params);
221
222     cv::ocl::CvSVM_OCL SVM_OCL;
223     SVM_OCL.train(src, labels, Mat(), Mat(), params);
224
225     int c = SVM.get_support_vector_count();
226     int c1 = SVM_OCL.get_support_vector_count();
227
228     Mat sv(c, MHEIGHT, CV_32FC1);
229     Mat sv_ocl(c1, MHEIGHT, CV_32FC1);
230     for(int i = 0; i < c; i++)
231     {
232         const float* v = SVM.get_support_vector(i);
233
234         for(int j = 0; j < MHEIGHT; j++)
235         {
236             sv.at<float>(i, j) = v[j];
237         }
238     }
239     for(int i = 0; i < c1; i++)
240     {
241         const float* v_ocl = SVM_OCL.get_support_vector(i);
242
243         for(int j = 0; j < MHEIGHT; j++)
244         {
245             sv_ocl.at<float>(i, j) = v_ocl[j];
246         }
247     }
248     cv::BFMatcher matcher(cv::NORM_L2);
249     std::vector<cv::DMatch> matches;
250     matcher.match(sv, sv_ocl, matches);
251     int count = 0;
252
253     for(std::vector<cv::DMatch>::iterator itr = matches.begin(); itr != matches.end(); itr++)
254     {
255         if((*itr).distance < 0.1)
256         {
257             count ++;
258         }
259     }
260     if(c != 0)
261     {
262         float matchedRatio = (float)count / c;
263         EXPECT_GT(matchedRatio, 0.95);
264     }
265     if(c != 0)
266     {
267         CvMat *result = cvCreateMat(1, samples.rows, CV_32FC1);
268         CvMat test_samples = samples;
269
270         CvMat *result_ocl = cvCreateMat(1, samples.rows, CV_32FC1);
271
272         SVM.predict(&test_samples, result);
273
274         SVM_OCL.predict(&test_samples, result_ocl);
275
276         int true_resp = 0, true_resp_ocl = 0;
277         for (int i = 0; i < samples.rows; i++)
278         {
279             if (result->data.fl[i] == labels_predict.at<float>(0, i))
280             {
281                 true_resp++;
282             }
283         }
284         float matchedRatio = (float)true_resp / samples.rows;
285
286         for (int i = 0; i < samples.rows; i++)
287         {
288             if (result_ocl->data.fl[i] == labels_predict.at<float>(0, i))
289             {
290                 true_resp_ocl++;
291             }
292         }
293         float matchedRatio_ocl = (float)true_resp_ocl / samples.rows;
294
295         if(matchedRatio != 0 && true_resp_ocl < true_resp)
296         {
297             EXPECT_NEAR(matchedRatio_ocl, matchedRatio, 0.03);
298         }
299     }
300 }
301
302 // TODO FIXIT: CvSVM::EPS_SVR case is crashed inside CPU implementation
303 // Anonymous enums are not supported well so cast them to 'int'
304
305 INSTANTIATE_TEST_CASE_P(OCL_ML, SVM_OCL, testing::Combine(
306                             Values((int)CvSVM::LINEAR, (int)CvSVM::POLY, (int)CvSVM::RBF, (int)CvSVM::SIGMOID),
307                             Values((int)CvSVM::C_SVC, (int)CvSVM::NU_SVC, (int)CvSVM::ONE_CLASS, (int)CvSVM::NU_SVR),
308                             Values(2, 3, 4)
309                         ));
310 #endif // HAVE_CLAMDBLAS
311
312 #endif // HAVE_OPENCL