test_torch_importer.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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) 2013, OpenCV Foundation, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of the copyright holders may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. #include "test_precomp.hpp"
  42. #include "npy_blob.hpp"
  43. #include <opencv2/dnn/shape_utils.hpp>
  44. #include <opencv2/dnn/layer.details.hpp> // CV_DNN_REGISTER_LAYER_CLASS
  45. namespace opencv_test
  46. {
  47. using namespace std;
  48. using namespace testing;
  49. using namespace cv;
  50. using namespace cv::dnn;
  51. template<typename TStr>
  52. static std::string _tf(TStr filename, bool inTorchDir = true, bool required = true)
  53. {
  54. String path = "dnn/";
  55. if (inTorchDir)
  56. path += "torch/";
  57. path += filename;
  58. return findDataFile(path, required);
  59. }
  60. TEST(Torch_Importer, simple_read)
  61. {
  62. Net net;
  63. ASSERT_NO_THROW(net = readNetFromTorch(_tf("net_simple_net.txt"), false));
  64. ASSERT_FALSE(net.empty());
  65. }
  66. class Test_Torch_layers : public DNNTestLayer
  67. {
  68. public:
  69. void runTorchNet(const String& prefix, String outLayerName = "",
  70. bool check2ndBlob = false, bool isBinary = false, bool evaluate = true,
  71. double l1 = 0.0, double lInf = 0.0)
  72. {
  73. String suffix = (isBinary) ? ".dat" : ".txt";
  74. Mat inp, outRef;
  75. ASSERT_NO_THROW( inp = readTorchBlob(_tf(prefix + "_input" + suffix), isBinary) );
  76. ASSERT_NO_THROW( outRef = readTorchBlob(_tf(prefix + "_output" + suffix), isBinary) );
  77. checkBackend(backend, target, &inp, &outRef);
  78. Net net = readNetFromTorch(_tf(prefix + "_net" + suffix), isBinary, evaluate);
  79. ASSERT_FALSE(net.empty());
  80. net.setPreferableBackend(backend);
  81. net.setPreferableTarget(target);
  82. if (outLayerName.empty())
  83. outLayerName = net.getLayerNames().back();
  84. net.setInput(inp);
  85. std::vector<Mat> outBlobs;
  86. net.forward(outBlobs, outLayerName);
  87. l1 = l1 ? l1 : default_l1;
  88. lInf = lInf ? lInf : default_lInf;
  89. normAssert(outRef, outBlobs[0], "", l1, lInf);
  90. if (check2ndBlob && backend == DNN_BACKEND_OPENCV)
  91. {
  92. Mat out2 = outBlobs[1];
  93. Mat ref2 = readTorchBlob(_tf(prefix + "_output_2" + suffix), isBinary);
  94. normAssert(out2, ref2, "", l1, lInf);
  95. }
  96. }
  97. };
  98. TEST_P(Test_Torch_layers, run_convolution)
  99. {
  100. // Output reference values are in range [23.4018, 72.0181]
  101. double l1 = default_l1, lInf = default_lInf;
  102. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
  103. {
  104. l1 = 0.08;
  105. lInf = 0.43;
  106. }
  107. else if (target == DNN_TARGET_CUDA_FP16)
  108. {
  109. l1 = 0.08;
  110. lInf = 0.5;
  111. }
  112. runTorchNet("net_conv", "", false, true, true, l1, lInf);
  113. }
  114. TEST_P(Test_Torch_layers, run_pool_max)
  115. {
  116. if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
  117. applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
  118. if (target == DNN_TARGET_CUDA_FP16)
  119. applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
  120. double l1 = 0.0, lInf = 0.0;
  121. runTorchNet("net_pool_max", "", true, false, true, l1, lInf);
  122. }
  123. TEST_P(Test_Torch_layers, run_pool_ave)
  124. {
  125. runTorchNet("net_pool_ave");
  126. }
  127. TEST_P(Test_Torch_layers, run_reshape_change_batch_size)
  128. {
  129. runTorchNet("net_reshape");
  130. }
  131. TEST_P(Test_Torch_layers, run_reshape)
  132. {
  133. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
  134. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  135. runTorchNet("net_reshape_batch");
  136. runTorchNet("net_reshape_channels", "", false, true);
  137. }
  138. TEST_P(Test_Torch_layers, run_reshape_single_sample)
  139. {
  140. // Reference output values in range [14.4586, 18.4492].
  141. double l1 = default_l1, lInf = default_lInf;
  142. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
  143. {
  144. l1 = 0.033;
  145. lInf = 0.05;
  146. }
  147. else if (target == DNN_TARGET_CUDA_FP16)
  148. {
  149. l1 = 0.02;
  150. lInf = 0.04;
  151. }
  152. runTorchNet("net_reshape_single_sample", "", false, false, true, l1, lInf);
  153. }
  154. TEST_P(Test_Torch_layers, run_linear)
  155. {
  156. if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
  157. applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
  158. runTorchNet("net_linear_2d");
  159. }
  160. TEST_P(Test_Torch_layers, run_concat)
  161. {
  162. runTorchNet("net_concat", "l5_torchMerge");
  163. }
  164. TEST_P(Test_Torch_layers, run_depth_concat)
  165. {
  166. double lInf = 0.0;
  167. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
  168. {
  169. lInf = 0.032;
  170. }
  171. else if (target == DNN_TARGET_CUDA_FP16)
  172. {
  173. lInf = 0.03;
  174. }
  175. runTorchNet("net_depth_concat", "", false, true, true, 0.0, lInf);
  176. }
  177. TEST_P(Test_Torch_layers, run_deconv)
  178. {
  179. runTorchNet("net_deconv");
  180. }
  181. TEST_P(Test_Torch_layers, run_batch_norm)
  182. {
  183. runTorchNet("net_batch_norm", "", false, true);
  184. runTorchNet("net_batch_norm_train", "", false, true, false);
  185. }
  186. TEST_P(Test_Torch_layers, net_prelu)
  187. {
  188. runTorchNet("net_prelu");
  189. }
  190. TEST_P(Test_Torch_layers, net_cadd_table)
  191. {
  192. runTorchNet("net_cadd_table");
  193. }
  194. TEST_P(Test_Torch_layers, net_softmax)
  195. {
  196. runTorchNet("net_softmax");
  197. runTorchNet("net_softmax_spatial");
  198. }
  199. TEST_P(Test_Torch_layers, net_logsoftmax)
  200. {
  201. runTorchNet("net_logsoftmax");
  202. runTorchNet("net_logsoftmax_spatial");
  203. }
  204. TEST_P(Test_Torch_layers, net_lp_pooling_square)
  205. {
  206. runTorchNet("net_lp_pooling_square", "", false, true);
  207. }
  208. TEST_P(Test_Torch_layers, net_lp_pooling_power)
  209. {
  210. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
  211. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  212. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  213. #endif
  214. runTorchNet("net_lp_pooling_power", "", false, true);
  215. }
  216. TEST_P(Test_Torch_layers, net_conv_gemm_lrn)
  217. {
  218. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
  219. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
  220. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  221. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  222. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  223. #endif
  224. double l1 = 0.0, lInf = 0.0;
  225. if (target == DNN_TARGET_OPENCL_FP16)
  226. {
  227. l1 = 0.046;
  228. lInf = 0.023;
  229. }
  230. else if (target == DNN_TARGET_MYRIAD)
  231. {
  232. l1 = 0.02;
  233. lInf = 0.05;
  234. }
  235. else if (target == DNN_TARGET_CUDA_FP16)
  236. {
  237. l1 = 0.0042;
  238. lInf = 0.021;
  239. }
  240. // The OpenCL kernels use the native_ math functions which have
  241. // implementation defined accuracy, so we use relaxed thresholds. See
  242. // https://github.com/opencv/opencv/issues/9821 for more details.
  243. else if (target == DNN_TARGET_OPENCL)
  244. {
  245. l1 = 0.02;
  246. lInf = 0.02;
  247. }
  248. runTorchNet("net_conv_gemm_lrn", "", false, true, true, l1, lInf);
  249. }
  250. TEST_P(Test_Torch_layers, net_inception_block)
  251. {
  252. runTorchNet("net_inception_block", "", false, true);
  253. }
  254. TEST_P(Test_Torch_layers, net_normalize)
  255. {
  256. if(backend == DNN_BACKEND_CUDA)
  257. applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* only L1 and L2 norms are supported */
  258. runTorchNet("net_normalize", "", false, true);
  259. }
  260. TEST_P(Test_Torch_layers, net_padding)
  261. {
  262. runTorchNet("net_padding", "", false, true);
  263. runTorchNet("net_spatial_zero_padding", "", false, true);
  264. runTorchNet("net_spatial_reflection_padding", "", false, true);
  265. }
  266. TEST_P(Test_Torch_layers, net_non_spatial)
  267. {
  268. #if defined(INF_ENGINE_RELEASE) && ( \
  269. INF_ENGINE_VER_MAJOR_EQ(2021030000) || \
  270. INF_ENGINE_VER_MAJOR_EQ(2021040000) \
  271. )
  272. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  273. // 2021.3: crash
  274. // 2021.4: [ GENERAL_ERROR ] AssertionFailed: !out.networkInputs.empty()
  275. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  276. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
  277. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
  278. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
  279. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
  280. #endif
  281. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 &&
  282. (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
  283. applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
  284. CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  285. runTorchNet("net_non_spatial", "", false, true);
  286. }
  287. TEST_P(Test_Torch_layers, run_paralel)
  288. {
  289. if (backend != DNN_BACKEND_OPENCV || target != DNN_TARGET_CPU)
  290. throw SkipTestException(""); // TODO: Check this
  291. runTorchNet("net_parallel", "l5_torchMerge");
  292. }
  293. TEST_P(Test_Torch_layers, net_residual)
  294. {
  295. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE == 2018050000
  296. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL ||
  297. target == DNN_TARGET_OPENCL_FP16))
  298. applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
  299. CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  300. #endif
  301. runTorchNet("net_residual", "", false, true);
  302. }
  303. class Test_Torch_nets : public DNNTestLayer {};
  304. TEST_P(Test_Torch_nets, OpenFace_accuracy)
  305. {
  306. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
  307. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
  308. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  309. #endif
  310. checkBackend();
  311. const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false);
  312. Net net = readNetFromTorch(model);
  313. net.setPreferableBackend(backend);
  314. net.setPreferableTarget(target);
  315. Mat sample = imread(findDataFile("cv/shared/lena.png"));
  316. Mat sampleF32(sample.size(), CV_32FC3);
  317. sample.convertTo(sampleF32, sampleF32.type());
  318. sampleF32 /= 255;
  319. resize(sampleF32, sampleF32, Size(96, 96), 0, 0, INTER_NEAREST);
  320. Mat inputBlob = blobFromImage(sampleF32, 1.0, Size(), Scalar(), /*swapRB*/true);
  321. net.setInput(inputBlob);
  322. Mat out = net.forward();
  323. // Reference output values are in range [-0.17212, 0.263492]
  324. // on Myriad problem layer: l4_Pooling - does not use pads_begin
  325. float l1 = 1e-5, lInf = 1e-3;
  326. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
  327. {
  328. l1 = 2e-3;
  329. lInf = 5e-3;
  330. }
  331. else if (target == DNN_TARGET_CUDA_FP16)
  332. {
  333. l1 = 0.0004;
  334. lInf = 0.0012;
  335. }
  336. Mat outRef = readTorchBlob(_tf("net_openface_output.dat"), true);
  337. normAssert(out, outRef, "", l1, lInf);
  338. }
  339. static Mat getSegmMask(const Mat& scores)
  340. {
  341. const int rows = scores.size[2];
  342. const int cols = scores.size[3];
  343. const int numClasses = scores.size[1];
  344. Mat maxCl = Mat::zeros(rows, cols, CV_8UC1);
  345. Mat maxVal(rows, cols, CV_32FC1, Scalar(0));
  346. for (int ch = 0; ch < numClasses; ch++)
  347. {
  348. for (int row = 0; row < rows; row++)
  349. {
  350. const float *ptrScore = scores.ptr<float>(0, ch, row);
  351. uint8_t *ptrMaxCl = maxCl.ptr<uint8_t>(row);
  352. float *ptrMaxVal = maxVal.ptr<float>(row);
  353. for (int col = 0; col < cols; col++)
  354. {
  355. if (ptrScore[col] > ptrMaxVal[col])
  356. {
  357. ptrMaxVal[col] = ptrScore[col];
  358. ptrMaxCl[col] = (uchar)ch;
  359. }
  360. }
  361. }
  362. }
  363. return maxCl;
  364. }
  365. // Computer per-class intersection over union metric.
  366. static void normAssertSegmentation(const Mat& ref, const Mat& test)
  367. {
  368. CV_Assert_N(ref.dims == 4, test.dims == 4);
  369. const int numClasses = ref.size[1];
  370. CV_Assert(numClasses == test.size[1]);
  371. Mat refMask = getSegmMask(ref);
  372. Mat testMask = getSegmMask(test);
  373. EXPECT_EQ(countNonZero(refMask != testMask), 0);
  374. }
  375. TEST_P(Test_Torch_nets, ENet_accuracy)
  376. {
  377. applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB);
  378. checkBackend();
  379. if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
  380. throw SkipTestException("");
  381. if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16)
  382. applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
  383. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2020010000)
  384. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
  385. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  386. #else
  387. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
  388. {
  389. if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  390. if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  391. if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  392. throw SkipTestException("");
  393. }
  394. #endif
  395. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2021010000)
  396. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
  397. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  398. #endif
  399. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
  400. {
  401. if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  402. if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  403. if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  404. throw SkipTestException("");
  405. }
  406. Net net;
  407. {
  408. const string model = findDataFile("dnn/Enet-model-best.net", false);
  409. net = readNetFromTorch(model, true);
  410. ASSERT_TRUE(!net.empty());
  411. }
  412. net.setPreferableBackend(backend);
  413. net.setPreferableTarget(target);
  414. Mat sample = imread(_tf("street.png", false));
  415. Mat inputBlob = blobFromImage(sample, 1./255, Size(), Scalar(), /*swapRB*/true);
  416. net.setInput(inputBlob, "");
  417. Mat out = net.forward();
  418. Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
  419. // Due to numerical instability in Pooling-Unpooling layers (indexes jittering)
  420. // thresholds for ENet must be changed. Accuracy of results was checked on
  421. // Cityscapes dataset and difference in mIOU with Torch is 10E-4%
  422. normAssert(ref, out, "", 0.00044, /*target == DNN_TARGET_CPU ? 0.453 : */0.552);
  423. normAssertSegmentation(ref, out);
  424. const int N = 3;
  425. for (int i = 0; i < N; i++)
  426. {
  427. net.setInput(inputBlob, "");
  428. Mat out = net.forward();
  429. normAssert(ref, out, "", 0.00044, /*target == DNN_TARGET_CPU ? 0.453 : */0.552);
  430. normAssertSegmentation(ref, out);
  431. }
  432. }
  433. // Check accuracy of style transfer models from https://github.com/jcjohnson/fast-neural-style
  434. // th fast_neural_style.lua \
  435. // -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
  436. // -output_image lena.png \
  437. // -median_filter 0 \
  438. // -image_size 0 \
  439. // -model models/eccv16/starry_night.t7
  440. // th fast_neural_style.lua \
  441. // -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
  442. // -output_image lena.png \
  443. // -median_filter 0 \
  444. // -image_size 0 \
  445. // -model models/instance_norm/feathers.t7
  446. TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy)
  447. {
  448. #if defined INF_ENGINE_RELEASE
  449. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD
  450. && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
  451. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  452. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD
  453. && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
  454. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  455. #endif
  456. checkBackend();
  457. #if defined(INF_ENGINE_RELEASE)
  458. #if INF_ENGINE_RELEASE <= 2018050000
  459. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL)
  460. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  461. #endif
  462. #endif
  463. std::string models[] = {"dnn/fast_neural_style_eccv16_starry_night.t7",
  464. "dnn/fast_neural_style_instance_norm_feathers.t7"};
  465. std::string targets[] = {"dnn/lena_starry_night.png", "dnn/lena_feathers.png"};
  466. for (int i = 0; i < 2; ++i)
  467. {
  468. const string model = findDataFile(models[i], false);
  469. Net net = readNetFromTorch(model);
  470. net.setPreferableBackend(backend);
  471. net.setPreferableTarget(target);
  472. Mat img = imread(findDataFile("dnn/googlenet_1.png"));
  473. Mat inputBlob = blobFromImage(img, 1.0, Size(), Scalar(103.939, 116.779, 123.68), false);
  474. net.setInput(inputBlob);
  475. Mat out = net.forward();
  476. // Deprocessing.
  477. getPlane(out, 0, 0) += 103.939;
  478. getPlane(out, 0, 1) += 116.779;
  479. getPlane(out, 0, 2) += 123.68;
  480. out = cv::min(cv::max(0, out), 255);
  481. Mat ref = imread(findDataFile(targets[i]));
  482. Mat refBlob = blobFromImage(ref, 1.0, Size(), Scalar(), false);
  483. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
  484. {
  485. double normL1 = cvtest::norm(refBlob, out, cv::NORM_L1) / refBlob.total();
  486. if (target == DNN_TARGET_MYRIAD)
  487. EXPECT_LE(normL1, 4.0f);
  488. else
  489. EXPECT_LE(normL1, 0.6f);
  490. }
  491. else if(target == DNN_TARGET_CUDA_FP16)
  492. {
  493. normAssert(out, refBlob, "", 0.6, 25);
  494. }
  495. else
  496. normAssert(out, refBlob, "", 0.5, 1.1);
  497. }
  498. }
  499. INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_nets, dnnBackendsAndTargets());
  500. // Test a custom layer
  501. // https://github.com/torch/nn/blob/master/doc/convolution.md#nn.SpatialUpSamplingNearest
  502. class SpatialUpSamplingNearestLayer CV_FINAL : public Layer
  503. {
  504. public:
  505. SpatialUpSamplingNearestLayer(const LayerParams &params) : Layer(params)
  506. {
  507. scale = params.get<int>("scale_factor");
  508. }
  509. static Ptr<Layer> create(LayerParams& params)
  510. {
  511. return Ptr<Layer>(new SpatialUpSamplingNearestLayer(params));
  512. }
  513. virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,
  514. const int requiredOutputs,
  515. std::vector<std::vector<int> > &outputs,
  516. std::vector<std::vector<int> > &internals) const CV_OVERRIDE
  517. {
  518. std::vector<int> outShape(4);
  519. outShape[0] = inputs[0][0]; // batch size
  520. outShape[1] = inputs[0][1]; // number of channels
  521. outShape[2] = scale * inputs[0][2];
  522. outShape[3] = scale * inputs[0][3];
  523. outputs.assign(1, outShape);
  524. return false;
  525. }
  526. void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
  527. {
  528. CV_TRACE_FUNCTION();
  529. CV_TRACE_ARG_VALUE(name, "name", name.c_str());
  530. std::vector<Mat> inputs, outputs;
  531. inputs_arr.getMatVector(inputs);
  532. outputs_arr.getMatVector(outputs);
  533. Mat& inp = inputs[0];
  534. Mat& out = outputs[0];
  535. const int outHeight = out.size[2];
  536. const int outWidth = out.size[3];
  537. for (size_t n = 0; n < inp.size[0]; ++n)
  538. {
  539. for (size_t ch = 0; ch < inp.size[1]; ++ch)
  540. {
  541. resize(getPlane(inp, n, ch), getPlane(out, n, ch),
  542. Size(outWidth, outHeight), 0, 0, INTER_NEAREST);
  543. }
  544. }
  545. }
  546. private:
  547. int scale;
  548. };
  549. TEST_P(Test_Torch_layers, upsampling_nearest)
  550. {
  551. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
  552. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  553. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // TODO
  554. #endif
  555. // Test a custom layer.
  556. CV_DNN_REGISTER_LAYER_CLASS(SpatialUpSamplingNearest, SpatialUpSamplingNearestLayer);
  557. try
  558. {
  559. runTorchNet("net_spatial_upsampling_nearest", "", false, true);
  560. }
  561. catch (...)
  562. {
  563. LayerFactory::unregisterLayer("SpatialUpSamplingNearest");
  564. throw;
  565. }
  566. LayerFactory::unregisterLayer("SpatialUpSamplingNearest");
  567. // Test an implemented layer.
  568. runTorchNet("net_spatial_upsampling_nearest", "", false, true);
  569. }
  570. INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_layers, dnnBackendsAndTargets());
  571. }