dnn(test): replace SkipTestException with tags
[platform/upstream/opencv.git] / modules / dnn / test / test_misc.cpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2017, Intel Corporation, all rights reserved.
6 // Third party copyrights are property of their respective owners.
7
8 #include "test_precomp.hpp"
9 #include <opencv2/core/ocl.hpp>
10 #include <opencv2/core/opencl/ocl_defs.hpp>
11 #include <opencv2/dnn/layer.details.hpp>  // CV_DNN_REGISTER_LAYER_CLASS
12
13 namespace opencv_test { namespace {
14
15 TEST(blobFromImage_4ch, Regression)
16 {
17     Mat ch[4];
18     for(int i = 0; i < 4; i++)
19         ch[i] = Mat::ones(10, 10, CV_8U)*i;
20
21     Mat img;
22     merge(ch, 4, img);
23     Mat blob = dnn::blobFromImage(img, 1., Size(), Scalar(), false, false);
24
25     for(int i = 0; i < 4; i++)
26     {
27         ch[i] = Mat(img.rows, img.cols, CV_32F, blob.ptr(0, i));
28         ASSERT_DOUBLE_EQ(cvtest::norm(ch[i], cv::NORM_INF), i);
29     }
30 }
31
32 TEST(blobFromImage, allocated)
33 {
34     int size[] = {1, 3, 4, 5};
35     Mat img(size[2], size[3], CV_32FC(size[1]));
36     Mat blob(4, size, CV_32F);
37     void* blobData = blob.data;
38     dnn::blobFromImage(img, blob, 1.0 / 255, Size(), Scalar(), false, false);
39     ASSERT_EQ(blobData, blob.data);
40 }
41
42 TEST(imagesFromBlob, Regression)
43 {
44     int nbOfImages = 8;
45
46     std::vector<cv::Mat> inputImgs(nbOfImages);
47     for (int i = 0; i < nbOfImages; i++)
48     {
49         inputImgs[i] = cv::Mat::ones(100, 100, CV_32FC3);
50         cv::randu(inputImgs[i], cv::Scalar::all(0), cv::Scalar::all(1));
51     }
52
53     cv::Mat blob = cv::dnn::blobFromImages(inputImgs, 1., cv::Size(), cv::Scalar(), false, false);
54     std::vector<cv::Mat> outputImgs;
55     cv::dnn::imagesFromBlob(blob, outputImgs);
56
57     for (int i = 0; i < nbOfImages; i++)
58     {
59         ASSERT_EQ(cv::countNonZero(inputImgs[i] != outputImgs[i]), 0);
60     }
61 }
62
63 TEST(readNet, Regression)
64 {
65     Net net = readNet(findDataFile("dnn/squeezenet_v1.1.prototxt"),
66                       findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
67     EXPECT_FALSE(net.empty());
68     net = readNet(findDataFile("dnn/opencv_face_detector.caffemodel", false),
69                   findDataFile("dnn/opencv_face_detector.prototxt"));
70     EXPECT_FALSE(net.empty());
71     net = readNet(findDataFile("dnn/openface_nn4.small2.v1.t7", false));
72     EXPECT_FALSE(net.empty());
73     net = readNet(findDataFile("dnn/tiny-yolo-voc.cfg"),
74                   findDataFile("dnn/tiny-yolo-voc.weights", false));
75     EXPECT_FALSE(net.empty());
76     net = readNet(findDataFile("dnn/ssd_mobilenet_v1_coco.pbtxt"),
77                   findDataFile("dnn/ssd_mobilenet_v1_coco.pb", false));
78     EXPECT_FALSE(net.empty());
79 }
80
81 class FirstCustomLayer CV_FINAL : public Layer
82 {
83 public:
84     FirstCustomLayer(const LayerParams &params) : Layer(params) {}
85
86     static Ptr<Layer> create(LayerParams& params)
87     {
88         return Ptr<Layer>(new FirstCustomLayer(params));
89     }
90
91     void forward(InputArrayOfArrays, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
92     {
93         CV_TRACE_FUNCTION();
94         CV_TRACE_ARG_VALUE(name, "name", name.c_str());
95
96         std::vector<Mat> outputs;
97         outputs_arr.getMatVector(outputs);
98         outputs[0].setTo(1);
99     }
100 };
101
102 class SecondCustomLayer CV_FINAL : public Layer
103 {
104 public:
105     SecondCustomLayer(const LayerParams &params) : Layer(params) {}
106
107     static Ptr<Layer> create(LayerParams& params)
108     {
109         return Ptr<Layer>(new SecondCustomLayer(params));
110     }
111
112     void forward(InputArrayOfArrays, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
113     {
114         CV_TRACE_FUNCTION();
115         CV_TRACE_ARG_VALUE(name, "name", name.c_str());
116
117         std::vector<Mat> outputs;
118         outputs_arr.getMatVector(outputs);
119         outputs[0].setTo(2);
120     }
121 };
122
123 TEST(LayerFactory, custom_layers)
124 {
125     LayerParams lp;
126     lp.name = "name";
127     lp.type = "CustomType";
128
129     Mat inp(1, 1, CV_32FC1);
130     for (int i = 0; i < 3; ++i)
131     {
132         if (i == 0)      { CV_DNN_REGISTER_LAYER_CLASS(CustomType, FirstCustomLayer); }
133         else if (i == 1) { CV_DNN_REGISTER_LAYER_CLASS(CustomType, SecondCustomLayer); }
134         else if (i == 2) { LayerFactory::unregisterLayer("CustomType"); }
135
136         Net net;
137         net.addLayerToPrev(lp.name, lp.type, lp);
138
139         net.setInput(inp);
140         net.setPreferableBackend(DNN_BACKEND_OPENCV);
141         Mat output = net.forward();
142
143         if (i == 0)      { EXPECT_EQ(output.at<float>(0), 1); }
144         else if (i == 1) { EXPECT_EQ(output.at<float>(0), 2); }
145         else if (i == 2) { EXPECT_EQ(output.at<float>(0), 1); }
146     }
147     LayerFactory::unregisterLayer("CustomType");
148 }
149
150 typedef testing::TestWithParam<tuple<float, Vec3f, int, tuple<Backend, Target> > > setInput;
151 TEST_P(setInput, normalization)
152 {
153     const float kScale = get<0>(GetParam());
154     const Scalar kMean = get<1>(GetParam());
155     const int dtype    = get<2>(GetParam());
156     const int backend  = get<0>(get<3>(GetParam()));
157     const int target   = get<1>(get<3>(GetParam()));
158     const bool kSwapRB = true;
159
160     if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16 && dtype != CV_32F)
161         applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
162
163     Mat inp(5, 5, CV_8UC3);
164     randu(inp, 0, 255);
165     Mat ref = blobFromImage(inp, kScale, Size(), kMean, kSwapRB, /*crop*/false);
166
167     LayerParams lp;
168     Net net;
169     net.addLayerToPrev("testLayer", "Identity", lp);
170     net.setPreferableBackend(backend);
171     net.setPreferableTarget(target);
172
173     Mat blob = blobFromImage(inp, 1.0, Size(), Scalar(), kSwapRB, /*crop*/false, dtype);
174     ASSERT_EQ(blob.type(), dtype);
175     net.setInput(blob, "", kScale, kMean);
176     Mat out = net.forward();
177     ASSERT_EQ(out.type(), CV_32F);
178     normAssert(ref, out, "", 4e-4, 1e-3);
179 }
180
181 INSTANTIATE_TEST_CASE_P(/**/, setInput, Combine(
182   Values(1.0f, 1.0 / 127.5),
183   Values(Vec3f(), Vec3f(50, 50, 50), Vec3f(10, 50, 140)),
184   Values(CV_32F, CV_8U),
185   dnnBackendsAndTargets()
186 ));
187
188 class CustomLayerWithDeprecatedForward CV_FINAL : public Layer
189 {
190 public:
191     CustomLayerWithDeprecatedForward(const LayerParams &params) : Layer(params) {}
192
193     static Ptr<Layer> create(LayerParams& params)
194     {
195         return Ptr<Layer>(new CustomLayerWithDeprecatedForward(params));
196     }
197
198     virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
199     {
200         CV_Assert_N(inputs[0]->depth() == CV_32F, outputs[0].depth() == CV_32F);
201         cv::add(*inputs[0], 0.5f, outputs[0]);
202     }
203 };
204
205 class CustomLayerWithDeprecatedForwardAndFallback CV_FINAL : public Layer
206 {
207 public:
208     CustomLayerWithDeprecatedForwardAndFallback(const LayerParams &params) : Layer(params) {}
209
210     static Ptr<Layer> create(LayerParams& params)
211     {
212         return Ptr<Layer>(new CustomLayerWithDeprecatedForwardAndFallback(params));
213     }
214
215     void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, OutputArrayOfArrays internals) CV_OVERRIDE
216     {
217         CV_TRACE_FUNCTION();
218         CV_TRACE_ARG_VALUE(name, "name", name.c_str());
219
220         CV_OCL_RUN(preferableTarget == DNN_TARGET_OPENCL || preferableTarget == DNN_TARGET_OPENCL_FP16,
221                    forward_ocl(inputs, outputs, internals));
222
223         Layer::forward_fallback(inputs, outputs, internals);
224     }
225
226     virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
227     {
228         CV_Assert_N(inputs[0]->depth() == CV_32F, outputs[0].depth() == CV_32F);
229         cv::add(*inputs[0], 0.5f, outputs[0]);
230     }
231
232 #ifdef HAVE_OPENCL
233     bool forward_ocl(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
234     {
235         if (inputs_arr.depth() != CV_32F)
236             return false;
237
238         std::vector<UMat> inputs;
239         std::vector<UMat> outputs;
240         inputs_arr.getUMatVector(inputs);
241         outputs_arr.getUMatVector(outputs);
242         cv::add(inputs[0], 0.5f, outputs[0]);
243         return true;
244     }
245 #endif
246 };
247
248 typedef testing::TestWithParam<tuple<Backend, Target> > DeprecatedForward;
249 TEST_P(DeprecatedForward, CustomLayer)
250 {
251     const int backend  = get<0>(GetParam());
252     const int target   = get<1>(GetParam());
253
254     Mat inp(5, 5, CV_32FC1);
255     randu(inp, -1.0f, 1.0f);
256     inp = blobFromImage(inp);
257
258     CV_DNN_REGISTER_LAYER_CLASS(CustomType, CustomLayerWithDeprecatedForward);
259     try
260     {
261         LayerParams lp;
262         Net net;
263         net.addLayerToPrev("testLayer", "CustomType", lp);
264         net.setPreferableBackend(backend);
265         net.setPreferableTarget(target);
266         net.setInput(inp);
267         Mat out = net.forward();
268         normAssert(out, inp + 0.5f, "", 2e-4, 7e-4);
269     }
270     catch (...)
271     {
272         LayerFactory::unregisterLayer("CustomType");
273         throw;
274     }
275     LayerFactory::unregisterLayer("CustomType");
276 }
277
278 TEST_P(DeprecatedForward, CustomLayerWithFallback)
279 {
280     const int backend  = get<0>(GetParam());
281     const int target   = get<1>(GetParam());
282
283     Mat inp(5, 5, CV_32FC1);
284     randu(inp, -1.0f, 1.0f);
285     inp = blobFromImage(inp);
286
287     CV_DNN_REGISTER_LAYER_CLASS(CustomType, CustomLayerWithDeprecatedForwardAndFallback);
288     try
289     {
290         LayerParams lp;
291         Net net;
292         net.addLayerToPrev("testLayer", "CustomType", lp);
293         net.setPreferableBackend(backend);
294         net.setPreferableTarget(target);
295         net.setInput(inp);
296         Mat out = net.forward();
297         normAssert(out, inp + 0.5f, "", 2e-4, 7e-4);
298     }
299     catch (...)
300     {
301         LayerFactory::unregisterLayer("CustomType");
302         throw;
303     }
304     LayerFactory::unregisterLayer("CustomType");
305 }
306
307 INSTANTIATE_TEST_CASE_P(/**/, DeprecatedForward, dnnBackendsAndTargets());
308
309 TEST(Net, forwardAndRetrieve)
310 {
311     std::string prototxt =
312         "input: \"data\"\n"
313         "layer {\n"
314         "  name: \"testLayer\"\n"
315         "  type: \"Slice\"\n"
316         "  bottom: \"data\"\n"
317         "  top: \"firstCopy\"\n"
318         "  top: \"secondCopy\"\n"
319         "  slice_param {\n"
320         "    axis: 0\n"
321         "    slice_point: 2\n"
322         "  }\n"
323         "}";
324     Net net = readNetFromCaffe(&prototxt[0], prototxt.size());
325     net.setPreferableBackend(DNN_BACKEND_OPENCV);
326
327     Mat inp(4, 5, CV_32F);
328     randu(inp, -1, 1);
329     net.setInput(inp);
330
331     std::vector<String> outNames;
332     outNames.push_back("testLayer");
333     std::vector<std::vector<Mat> > outBlobs;
334
335     net.forward(outBlobs, outNames);
336
337     EXPECT_EQ(outBlobs.size(), 1);
338     EXPECT_EQ(outBlobs[0].size(), 2);
339     normAssert(outBlobs[0][0], inp.rowRange(0, 2), "first part");
340     normAssert(outBlobs[0][1], inp.rowRange(2, 4), "second part");
341 }
342
343 #ifdef HAVE_INF_ENGINE
344 static const std::chrono::milliseconds async_timeout(500);
345
346 // This test runs network in synchronous mode for different inputs and then
347 // runs the same model asynchronously for the same inputs.
348 typedef testing::TestWithParam<tuple<int, Target> > Async;
349 TEST_P(Async, set_and_forward_single)
350 {
351     const int dtype = get<0>(GetParam());
352     const int target = get<1>(GetParam());
353
354     const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : "";
355     const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin");
356     const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml");
357
358     Net netSync = readNet(model, proto);
359     netSync.setPreferableTarget(target);
360
361     Net netAsync = readNet(model, proto);
362     netAsync.setPreferableTarget(target);
363
364     // Generate inputs.
365     const int numInputs = 10;
366     std::vector<Mat> inputs(numInputs);
367     int blobSize[] = {2, 6, 75, 113};
368     for (int i = 0; i < numInputs; ++i)
369     {
370         inputs[i].create(4, &blobSize[0], dtype);
371         randu(inputs[i], 0, 255);
372     }
373
374     // Run synchronously.
375     std::vector<Mat> refs(numInputs);
376     for (int i = 0; i < numInputs; ++i)
377     {
378         netSync.setInput(inputs[i]);
379         refs[i] = netSync.forward().clone();
380     }
381
382     // Run asynchronously. To make test more robust, process inputs in the reversed order.
383     for (int i = numInputs - 1; i >= 0; --i)
384     {
385         netAsync.setInput(inputs[i]);
386
387         AsyncArray out = netAsync.forwardAsync();
388         ASSERT_TRUE(out.valid());
389         Mat result;
390         EXPECT_TRUE(out.get(result, async_timeout));
391         normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
392     }
393 }
394
395 TEST_P(Async, set_and_forward_all)
396 {
397     const int dtype = get<0>(GetParam());
398     const int target = get<1>(GetParam());
399
400     const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : "";
401     const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin");
402     const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml");
403
404
405     Net netSync = readNet(model, proto);
406     netSync.setPreferableTarget(target);
407
408     Net netAsync = readNet(model, proto);
409     netAsync.setPreferableTarget(target);
410
411     // Generate inputs.
412     const int numInputs = 10;
413     std::vector<Mat> inputs(numInputs);
414     int blobSize[] = {2, 6, 75, 113};
415     for (int i = 0; i < numInputs; ++i)
416     {
417         inputs[i].create(4, &blobSize[0], dtype);
418         randu(inputs[i], 0, 255);
419     }
420
421     // Run synchronously.
422     std::vector<Mat> refs(numInputs);
423     for (int i = 0; i < numInputs; ++i)
424     {
425         netSync.setInput(inputs[i]);
426         refs[i] = netSync.forward().clone();
427     }
428
429     // Run asynchronously. To make test more robust, process inputs in the reversed order.
430     std::vector<AsyncArray> outs(numInputs);
431     for (int i = numInputs - 1; i >= 0; --i)
432     {
433         netAsync.setInput(inputs[i]);
434         outs[i] = netAsync.forwardAsync();
435     }
436
437     for (int i = numInputs - 1; i >= 0; --i)
438     {
439         ASSERT_TRUE(outs[i].valid());
440         Mat result;
441         EXPECT_TRUE(outs[i].get(result, async_timeout));
442         normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
443     }
444 }
445
446 INSTANTIATE_TEST_CASE_P(/**/, Async, Combine(
447   Values(CV_32F, CV_8U),
448   testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE))
449 ));
450 #endif  // HAVE_INF_ENGINE
451
452 }} // namespace