Merge pull request #14827 from YashasSamaga:cuda4dnn-csl-low
[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 typedef testing::TestWithParam<tuple<Backend, Target> > dump;
82 TEST_P(dump, Regression)
83 {
84     const int backend  = get<0>(GetParam());
85     const int target   = get<1>(GetParam());
86     Net net = readNet(findDataFile("dnn/squeezenet_v1.1.prototxt"),
87                       findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
88
89     int size[] = {1, 3, 227, 227};
90     Mat input = cv::Mat::ones(4, size, CV_32F);
91     net.setInput(input);
92     net.setPreferableBackend(backend);
93     net.setPreferableTarget(target);
94     EXPECT_FALSE(net.dump().empty());
95     net.forward();
96     EXPECT_FALSE(net.dump().empty());
97 }
98
99 INSTANTIATE_TEST_CASE_P(/**/, dump, dnnBackendsAndTargets());
100
101 class FirstCustomLayer CV_FINAL : public Layer
102 {
103 public:
104     FirstCustomLayer(const LayerParams &params) : Layer(params) {}
105
106     static Ptr<Layer> create(LayerParams& params)
107     {
108         return Ptr<Layer>(new FirstCustomLayer(params));
109     }
110
111     void forward(InputArrayOfArrays, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
112     {
113         CV_TRACE_FUNCTION();
114         CV_TRACE_ARG_VALUE(name, "name", name.c_str());
115
116         std::vector<Mat> outputs;
117         outputs_arr.getMatVector(outputs);
118         outputs[0].setTo(1);
119     }
120 };
121
122 class SecondCustomLayer CV_FINAL : public Layer
123 {
124 public:
125     SecondCustomLayer(const LayerParams &params) : Layer(params) {}
126
127     static Ptr<Layer> create(LayerParams& params)
128     {
129         return Ptr<Layer>(new SecondCustomLayer(params));
130     }
131
132     void forward(InputArrayOfArrays, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
133     {
134         CV_TRACE_FUNCTION();
135         CV_TRACE_ARG_VALUE(name, "name", name.c_str());
136
137         std::vector<Mat> outputs;
138         outputs_arr.getMatVector(outputs);
139         outputs[0].setTo(2);
140     }
141 };
142
143 TEST(LayerFactory, custom_layers)
144 {
145     LayerParams lp;
146     lp.name = "name";
147     lp.type = "CustomType";
148
149     Mat inp(1, 1, CV_32FC1);
150     for (int i = 0; i < 3; ++i)
151     {
152         if (i == 0)      { CV_DNN_REGISTER_LAYER_CLASS(CustomType, FirstCustomLayer); }
153         else if (i == 1) { CV_DNN_REGISTER_LAYER_CLASS(CustomType, SecondCustomLayer); }
154         else if (i == 2) { LayerFactory::unregisterLayer("CustomType"); }
155
156         Net net;
157         net.addLayerToPrev(lp.name, lp.type, lp);
158
159         net.setInput(inp);
160         net.setPreferableBackend(DNN_BACKEND_OPENCV);
161         Mat output = net.forward();
162
163         if (i == 0)      { EXPECT_EQ(output.at<float>(0), 1); }
164         else if (i == 1) { EXPECT_EQ(output.at<float>(0), 2); }
165         else if (i == 2) { EXPECT_EQ(output.at<float>(0), 1); }
166     }
167     LayerFactory::unregisterLayer("CustomType");
168 }
169
170 typedef testing::TestWithParam<tuple<float, Vec3f, int, tuple<Backend, Target> > > setInput;
171 TEST_P(setInput, normalization)
172 {
173     const float kScale = get<0>(GetParam());
174     const Scalar kMean = get<1>(GetParam());
175     const int dtype    = get<2>(GetParam());
176     const int backend  = get<0>(get<3>(GetParam()));
177     const int target   = get<1>(get<3>(GetParam()));
178     const bool kSwapRB = true;
179
180     if(backend == DNN_BACKEND_CUDA)
181         applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA);
182     if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16 && dtype != CV_32F)
183         applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
184     if (backend == DNN_BACKEND_VKCOM && dtype != CV_32F)
185         throw SkipTestException(CV_TEST_TAG_DNN_SKIP_VULKAN);
186
187     Mat inp(5, 5, CV_8UC3);
188     randu(inp, 0, 255);
189     Mat ref = blobFromImage(inp, kScale, Size(), kMean, kSwapRB, /*crop*/false);
190
191     LayerParams lp;
192     Net net;
193     net.addLayerToPrev("testLayer", "Identity", lp);
194     net.setPreferableBackend(backend);
195     net.setPreferableTarget(target);
196
197     Mat blob = blobFromImage(inp, 1.0, Size(), Scalar(), kSwapRB, /*crop*/false, dtype);
198     ASSERT_EQ(blob.type(), dtype);
199     net.setInput(blob, "", kScale, kMean);
200     Mat out = net.forward();
201     ASSERT_EQ(out.type(), CV_32F);
202     normAssert(ref, out, "", 4e-4, 1e-3);
203 }
204
205 INSTANTIATE_TEST_CASE_P(/**/, setInput, Combine(
206   Values(1.0f, 1.0 / 127.5),
207   Values(Vec3f(), Vec3f(50, 50, 50), Vec3f(10, 50, 140)),
208   Values(CV_32F, CV_8U),
209   dnnBackendsAndTargets()
210 ));
211
212 class CustomLayerWithDeprecatedForward CV_FINAL : public Layer
213 {
214 public:
215     CustomLayerWithDeprecatedForward(const LayerParams &params) : Layer(params) {}
216
217     static Ptr<Layer> create(LayerParams& params)
218     {
219         return Ptr<Layer>(new CustomLayerWithDeprecatedForward(params));
220     }
221
222     virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
223     {
224         CV_Assert_N(inputs[0]->depth() == CV_32F, outputs[0].depth() == CV_32F);
225         cv::add(*inputs[0], 0.5f, outputs[0]);
226     }
227 };
228
229 class CustomLayerWithDeprecatedForwardAndFallback CV_FINAL : public Layer
230 {
231 public:
232     CustomLayerWithDeprecatedForwardAndFallback(const LayerParams &params) : Layer(params) {}
233
234     static Ptr<Layer> create(LayerParams& params)
235     {
236         return Ptr<Layer>(new CustomLayerWithDeprecatedForwardAndFallback(params));
237     }
238
239     void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, OutputArrayOfArrays internals) CV_OVERRIDE
240     {
241         CV_TRACE_FUNCTION();
242         CV_TRACE_ARG_VALUE(name, "name", name.c_str());
243
244         CV_OCL_RUN(preferableTarget == DNN_TARGET_OPENCL || preferableTarget == DNN_TARGET_OPENCL_FP16,
245                    forward_ocl(inputs, outputs, internals));
246
247         Layer::forward_fallback(inputs, outputs, internals);
248     }
249
250     virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
251     {
252         CV_Assert_N(inputs[0]->depth() == CV_32F, outputs[0].depth() == CV_32F);
253         cv::add(*inputs[0], 0.5f, outputs[0]);
254     }
255
256 #ifdef HAVE_OPENCL
257     bool forward_ocl(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
258     {
259         if (inputs_arr.depth() != CV_32F)
260             return false;
261
262         std::vector<UMat> inputs;
263         std::vector<UMat> outputs;
264         inputs_arr.getUMatVector(inputs);
265         outputs_arr.getUMatVector(outputs);
266         cv::add(inputs[0], 0.5f, outputs[0]);
267         return true;
268     }
269 #endif
270 };
271
272 typedef testing::TestWithParam<tuple<Backend, Target> > DeprecatedForward;
273 TEST_P(DeprecatedForward, CustomLayer)
274 {
275     const int backend  = get<0>(GetParam());
276     const int target   = get<1>(GetParam());
277
278     Mat inp(5, 5, CV_32FC1);
279     randu(inp, -1.0f, 1.0f);
280     inp = blobFromImage(inp);
281
282     CV_DNN_REGISTER_LAYER_CLASS(CustomType, CustomLayerWithDeprecatedForward);
283     try
284     {
285         LayerParams lp;
286         Net net;
287         net.addLayerToPrev("testLayer", "CustomType", lp);
288         net.setPreferableBackend(backend);
289         net.setPreferableTarget(target);
290         net.setInput(inp);
291         Mat out = net.forward();
292         normAssert(out, inp + 0.5f, "", 2e-4, 7e-4);
293     }
294     catch (...)
295     {
296         LayerFactory::unregisterLayer("CustomType");
297         throw;
298     }
299     LayerFactory::unregisterLayer("CustomType");
300 }
301
302 TEST_P(DeprecatedForward, CustomLayerWithFallback)
303 {
304     const int backend  = get<0>(GetParam());
305     const int target   = get<1>(GetParam());
306
307     Mat inp(5, 5, CV_32FC1);
308     randu(inp, -1.0f, 1.0f);
309     inp = blobFromImage(inp);
310
311     CV_DNN_REGISTER_LAYER_CLASS(CustomType, CustomLayerWithDeprecatedForwardAndFallback);
312     try
313     {
314         LayerParams lp;
315         Net net;
316         net.addLayerToPrev("testLayer", "CustomType", lp);
317         net.setPreferableBackend(backend);
318         net.setPreferableTarget(target);
319         net.setInput(inp);
320         Mat out = net.forward();
321         normAssert(out, inp + 0.5f, "", 2e-4, 7e-4);
322     }
323     catch (...)
324     {
325         LayerFactory::unregisterLayer("CustomType");
326         throw;
327     }
328     LayerFactory::unregisterLayer("CustomType");
329 }
330
331 INSTANTIATE_TEST_CASE_P(/**/, DeprecatedForward, dnnBackendsAndTargets());
332
333 TEST(Net, forwardAndRetrieve)
334 {
335     std::string prototxt =
336         "input: \"data\"\n"
337         "layer {\n"
338         "  name: \"testLayer\"\n"
339         "  type: \"Slice\"\n"
340         "  bottom: \"data\"\n"
341         "  top: \"firstCopy\"\n"
342         "  top: \"secondCopy\"\n"
343         "  slice_param {\n"
344         "    axis: 0\n"
345         "    slice_point: 2\n"
346         "  }\n"
347         "}";
348     Net net = readNetFromCaffe(&prototxt[0], prototxt.size());
349     net.setPreferableBackend(DNN_BACKEND_OPENCV);
350
351     Mat inp(4, 5, CV_32F);
352     randu(inp, -1, 1);
353     net.setInput(inp);
354
355     std::vector<String> outNames;
356     outNames.push_back("testLayer");
357     std::vector<std::vector<Mat> > outBlobs;
358
359     net.forward(outBlobs, outNames);
360
361     EXPECT_EQ(outBlobs.size(), 1);
362     EXPECT_EQ(outBlobs[0].size(), 2);
363     normAssert(outBlobs[0][0], inp.rowRange(0, 2), "first part");
364     normAssert(outBlobs[0][1], inp.rowRange(2, 4), "second part");
365 }
366
367 #ifdef HAVE_INF_ENGINE
368 static const std::chrono::milliseconds async_timeout(10000);
369
370 // This test runs network in synchronous mode for different inputs and then
371 // runs the same model asynchronously for the same inputs.
372 typedef testing::TestWithParam<tuple<int, Target> > Async;
373 TEST_P(Async, set_and_forward_single)
374 {
375     const int dtype = get<0>(GetParam());
376     const int target = get<1>(GetParam());
377
378     const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : "";
379     const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin");
380     const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml");
381
382     Net netSync = readNet(model, proto);
383     netSync.setPreferableTarget(target);
384
385     Net netAsync = readNet(model, proto);
386     netAsync.setPreferableTarget(target);
387
388     // Generate inputs.
389     const int numInputs = 10;
390     std::vector<Mat> inputs(numInputs);
391     int blobSize[] = {2, 6, 75, 113};
392     for (int i = 0; i < numInputs; ++i)
393     {
394         inputs[i].create(4, &blobSize[0], dtype);
395         randu(inputs[i], 0, 255);
396     }
397
398     // Run synchronously.
399     std::vector<Mat> refs(numInputs);
400     for (int i = 0; i < numInputs; ++i)
401     {
402         netSync.setInput(inputs[i]);
403         refs[i] = netSync.forward().clone();
404     }
405
406     // Run asynchronously. To make test more robust, process inputs in the reversed order.
407     for (int i = numInputs - 1; i >= 0; --i)
408     {
409         netAsync.setInput(inputs[i]);
410
411         AsyncArray out = netAsync.forwardAsync();
412         ASSERT_TRUE(out.valid());
413         Mat result;
414         EXPECT_TRUE(out.get(result, async_timeout));
415         normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
416     }
417 }
418
419 TEST_P(Async, set_and_forward_all)
420 {
421     const int dtype = get<0>(GetParam());
422     const int target = get<1>(GetParam());
423
424     const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : "";
425     const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin");
426     const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml");
427
428
429     Net netSync = readNet(model, proto);
430     netSync.setPreferableTarget(target);
431
432     Net netAsync = readNet(model, proto);
433     netAsync.setPreferableTarget(target);
434
435     // Generate inputs.
436     const int numInputs = 10;
437     std::vector<Mat> inputs(numInputs);
438     int blobSize[] = {2, 6, 75, 113};
439     for (int i = 0; i < numInputs; ++i)
440     {
441         inputs[i].create(4, &blobSize[0], dtype);
442         randu(inputs[i], 0, 255);
443     }
444
445     // Run synchronously.
446     std::vector<Mat> refs(numInputs);
447     for (int i = 0; i < numInputs; ++i)
448     {
449         netSync.setInput(inputs[i]);
450         refs[i] = netSync.forward().clone();
451     }
452
453     // Run asynchronously. To make test more robust, process inputs in the reversed order.
454     std::vector<AsyncArray> outs(numInputs);
455     for (int i = numInputs - 1; i >= 0; --i)
456     {
457         netAsync.setInput(inputs[i]);
458         outs[i] = netAsync.forwardAsync();
459     }
460
461     for (int i = numInputs - 1; i >= 0; --i)
462     {
463         ASSERT_TRUE(outs[i].valid());
464         Mat result;
465         EXPECT_TRUE(outs[i].get(result, async_timeout));
466         normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
467     }
468 }
469
470 INSTANTIATE_TEST_CASE_P(/**/, Async, Combine(
471   Values(CV_32F, CV_8U),
472   testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE))
473 ));
474
475 typedef testing::TestWithParam<Target>  Test_Model_Optimizer;
476 TEST_P(Test_Model_Optimizer, forward_two_nets)
477 {
478     const int target = GetParam();
479
480     const std::string suffix = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? "_fp16" : "";
481     const std::string& model = findDataFile("dnn/layers/layer_convolution" + suffix + ".bin");
482     const std::string& proto = findDataFile("dnn/layers/layer_convolution" + suffix + ".xml");
483
484     Net net0 = readNet(model, proto);
485     net0.setPreferableTarget(target);
486
487     Net net1 = readNet(model, proto);
488     net1.setPreferableTarget(target);
489
490     // Generate inputs.
491     int blobSize[] = {2, 6, 75, 113};
492     Mat input(4, &blobSize[0], CV_32F);
493     randu(input, 0, 255);
494
495     net0.setInput(input);
496     Mat ref0 = net0.forward().clone();
497
498     net1.setInput(input);
499     Mat ref1 = net1.forward();
500
501     net0.setInput(input);
502     Mat ref2 = net0.forward();
503
504     normAssert(ref0, ref2, 0, 0);
505 }
506 INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer,
507   testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE))
508 );
509
510 #endif  // HAVE_INF_ENGINE
511
512 }} // namespace