test_torch_importer.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  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 || target == DNN_TARGET_CPU_FP16)
  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. if (target == DNN_TARGET_CPU_FP16)
  121. applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
  122. double l1 = 0.0, lInf = 0.0;
  123. runTorchNet("net_pool_max", "", true, false, true, l1, lInf);
  124. }
  125. TEST_P(Test_Torch_layers, run_pool_ave)
  126. {
  127. runTorchNet("net_pool_ave");
  128. }
  129. TEST_P(Test_Torch_layers, run_reshape_change_batch_size)
  130. {
  131. runTorchNet("net_reshape");
  132. }
  133. TEST_P(Test_Torch_layers, run_reshape)
  134. {
  135. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
  136. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  137. runTorchNet("net_reshape_batch");
  138. runTorchNet("net_reshape_channels", "", false, true);
  139. }
  140. TEST_P(Test_Torch_layers, run_reshape_single_sample)
  141. {
  142. // Reference output values in range [14.4586, 18.4492].
  143. double l1 = default_l1, lInf = default_lInf;
  144. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16)
  145. {
  146. l1 = 0.033;
  147. lInf = 0.05;
  148. }
  149. else if (target == DNN_TARGET_CUDA_FP16)
  150. {
  151. l1 = 0.02;
  152. lInf = 0.04;
  153. }
  154. runTorchNet("net_reshape_single_sample", "", false, false, true, l1, lInf);
  155. }
  156. TEST_P(Test_Torch_layers, run_linear)
  157. {
  158. if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
  159. applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
  160. if (target == DNN_TARGET_CPU_FP16)
  161. applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
  162. runTorchNet("net_linear_2d");
  163. }
  164. TEST_P(Test_Torch_layers, run_concat)
  165. {
  166. runTorchNet("net_concat", "l5_torchMerge");
  167. }
  168. TEST_P(Test_Torch_layers, run_depth_concat)
  169. {
  170. double lInf = 0.0;
  171. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16)
  172. {
  173. lInf = 0.032;
  174. }
  175. else if (target == DNN_TARGET_CUDA_FP16)
  176. {
  177. lInf = 0.03;
  178. }
  179. runTorchNet("net_depth_concat", "", false, true, true, 0.0, lInf);
  180. }
  181. TEST_P(Test_Torch_layers, run_deconv)
  182. {
  183. runTorchNet("net_deconv");
  184. }
  185. TEST_P(Test_Torch_layers, run_batch_norm)
  186. {
  187. runTorchNet("net_batch_norm", "", false, true);
  188. runTorchNet("net_batch_norm_train", "", false, true, false);
  189. }
  190. TEST_P(Test_Torch_layers, net_prelu)
  191. {
  192. runTorchNet("net_prelu");
  193. }
  194. TEST_P(Test_Torch_layers, net_cadd_table)
  195. {
  196. runTorchNet("net_cadd_table");
  197. }
  198. TEST_P(Test_Torch_layers, net_softmax)
  199. {
  200. runTorchNet("net_softmax");
  201. runTorchNet("net_softmax_spatial");
  202. }
  203. TEST_P(Test_Torch_layers, net_logsoftmax)
  204. {
  205. runTorchNet("net_logsoftmax");
  206. runTorchNet("net_logsoftmax_spatial");
  207. }
  208. TEST_P(Test_Torch_layers, net_lp_pooling_square)
  209. {
  210. runTorchNet("net_lp_pooling_square", "", false, true);
  211. }
  212. TEST_P(Test_Torch_layers, net_lp_pooling_power)
  213. {
  214. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
  215. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  216. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  217. #endif
  218. runTorchNet("net_lp_pooling_power", "", false, true);
  219. }
  220. TEST_P(Test_Torch_layers, net_conv_gemm_lrn)
  221. {
  222. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
  223. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
  224. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  225. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  226. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  227. #endif
  228. double l1 = 0.0, lInf = 0.0;
  229. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_CPU_FP16)
  230. {
  231. l1 = 0.046;
  232. lInf = 0.023;
  233. }
  234. else if (target == DNN_TARGET_MYRIAD)
  235. {
  236. l1 = 0.02;
  237. lInf = 0.05;
  238. }
  239. else if (target == DNN_TARGET_CUDA_FP16)
  240. {
  241. l1 = 0.0042;
  242. lInf = 0.021;
  243. }
  244. // The OpenCL kernels use the native_ math functions which have
  245. // implementation defined accuracy, so we use relaxed thresholds. See
  246. // https://github.com/opencv/opencv/issues/9821 for more details.
  247. else if (target == DNN_TARGET_OPENCL)
  248. {
  249. l1 = 0.02;
  250. lInf = 0.02;
  251. }
  252. runTorchNet("net_conv_gemm_lrn", "", false, true, true, l1, lInf);
  253. }
  254. TEST_P(Test_Torch_layers, net_inception_block)
  255. {
  256. runTorchNet("net_inception_block", "", false, true);
  257. }
  258. TEST_P(Test_Torch_layers, net_normalize)
  259. {
  260. if(backend == DNN_BACKEND_CUDA)
  261. applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* only L1 and L2 norms are supported */
  262. runTorchNet("net_normalize", "", false, true);
  263. }
  264. TEST_P(Test_Torch_layers, net_padding)
  265. {
  266. runTorchNet("net_padding", "", false, true);
  267. runTorchNet("net_spatial_zero_padding", "", false, true);
  268. runTorchNet("net_spatial_reflection_padding", "", false, true);
  269. }
  270. TEST_P(Test_Torch_layers, net_non_spatial)
  271. {
  272. #if defined(INF_ENGINE_RELEASE) && ( \
  273. INF_ENGINE_VER_MAJOR_EQ(2021030000) || \
  274. INF_ENGINE_VER_MAJOR_EQ(2021040000) \
  275. )
  276. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  277. // 2021.3: crash
  278. // 2021.4: [ GENERAL_ERROR ] AssertionFailed: !out.networkInputs.empty()
  279. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  280. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
  281. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
  282. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
  283. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
  284. #endif
  285. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 &&
  286. (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16))
  287. applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
  288. CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  289. runTorchNet("net_non_spatial", "", false, true);
  290. }
  291. TEST_P(Test_Torch_layers, run_paralel)
  292. {
  293. if (backend != DNN_BACKEND_OPENCV || target != DNN_TARGET_CPU)
  294. throw SkipTestException(""); // TODO: Check this
  295. runTorchNet("net_parallel", "l5_torchMerge");
  296. }
  297. TEST_P(Test_Torch_layers, net_residual)
  298. {
  299. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_RELEASE == 2018050000
  300. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && (target == DNN_TARGET_OPENCL ||
  301. target == DNN_TARGET_OPENCL_FP16))
  302. applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
  303. CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  304. #endif
  305. runTorchNet("net_residual", "", false, true);
  306. }
  307. class Test_Torch_nets : public DNNTestLayer {};
  308. TEST_P(Test_Torch_nets, OpenFace_accuracy)
  309. {
  310. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2018050000)
  311. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD)
  312. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  313. #endif
  314. checkBackend();
  315. const string model = findDataFile("dnn/openface_nn4.small2.v1.t7", false);
  316. Net net = readNetFromTorch(model);
  317. net.setPreferableBackend(backend);
  318. net.setPreferableTarget(target);
  319. if (target == DNN_TARGET_CPU_FP16)
  320. net.enableWinograd(false);
  321. Mat sample = imread(findDataFile("cv/shared/lena.png"));
  322. Mat sampleF32(sample.size(), CV_32FC3);
  323. sample.convertTo(sampleF32, sampleF32.type());
  324. sampleF32 /= 255;
  325. resize(sampleF32, sampleF32, Size(96, 96), 0, 0, INTER_NEAREST);
  326. Mat inputBlob = blobFromImage(sampleF32, 1.0, Size(), Scalar(), /*swapRB*/true);
  327. net.setInput(inputBlob);
  328. Mat out = net.forward();
  329. // Reference output values are in range [-0.17212, 0.263492]
  330. // on Myriad problem layer: l4_Pooling - does not use pads_begin
  331. float l1 = 1e-5, lInf = 1e-3;
  332. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD || target == DNN_TARGET_CPU_FP16)
  333. {
  334. l1 = 2e-3;
  335. lInf = 5e-3;
  336. }
  337. else if (target == DNN_TARGET_CUDA_FP16)
  338. {
  339. l1 = 0.0004;
  340. lInf = 0.0012;
  341. }
  342. Mat outRef = readTorchBlob(_tf("net_openface_output.dat"), true);
  343. normAssert(out, outRef, "", l1, lInf);
  344. }
  345. static Mat getSegmMask(const Mat& scores)
  346. {
  347. const int rows = scores.size[2];
  348. const int cols = scores.size[3];
  349. const int numClasses = scores.size[1];
  350. Mat maxCl = Mat::zeros(rows, cols, CV_8UC1);
  351. Mat maxVal(rows, cols, CV_32FC1, Scalar(0));
  352. for (int ch = 0; ch < numClasses; ch++)
  353. {
  354. for (int row = 0; row < rows; row++)
  355. {
  356. const float *ptrScore = scores.ptr<float>(0, ch, row);
  357. uint8_t *ptrMaxCl = maxCl.ptr<uint8_t>(row);
  358. float *ptrMaxVal = maxVal.ptr<float>(row);
  359. for (int col = 0; col < cols; col++)
  360. {
  361. if (ptrScore[col] > ptrMaxVal[col])
  362. {
  363. ptrMaxVal[col] = ptrScore[col];
  364. ptrMaxCl[col] = (uchar)ch;
  365. }
  366. }
  367. }
  368. }
  369. return maxCl;
  370. }
  371. // Computer per-class intersection over union metric.
  372. static void normAssertSegmentation(const Mat& ref, const Mat& test)
  373. {
  374. CV_Assert_N(ref.dims == 4, test.dims == 4);
  375. const int numClasses = ref.size[1];
  376. CV_Assert(numClasses == test.size[1]);
  377. Mat refMask = getSegmMask(ref);
  378. Mat testMask = getSegmMask(test);
  379. EXPECT_LE(countNonZero(refMask != testMask), 2);
  380. }
  381. TEST_P(Test_Torch_nets, ENet_accuracy)
  382. {
  383. applyTestTag(target == DNN_TARGET_CPU ? "" : CV_TEST_TAG_MEMORY_512MB);
  384. checkBackend();
  385. if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16)
  386. throw SkipTestException("");
  387. if (backend == DNN_BACKEND_CUDA && target == DNN_TARGET_CUDA_FP16)
  388. applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA_FP16);
  389. if (target == DNN_TARGET_CPU_FP16)
  390. applyTestTag(CV_TEST_TAG_DNN_SKIP_CPU_FP16);
  391. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2020010000)
  392. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
  393. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  394. #else
  395. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
  396. {
  397. if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  398. if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  399. if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  400. throw SkipTestException("");
  401. }
  402. #endif
  403. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2023000000)
  404. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
  405. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  406. #endif
  407. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
  408. {
  409. if (target == DNN_TARGET_OPENCL_FP16) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  410. if (target == DNN_TARGET_OPENCL) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  411. if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  412. throw SkipTestException("");
  413. }
  414. Net net;
  415. {
  416. const string model = findDataFile("dnn/Enet-model-best.net", false);
  417. net = readNetFromTorch(model, true);
  418. ASSERT_TRUE(!net.empty());
  419. }
  420. net.enableWinograd(false);
  421. net.setPreferableBackend(backend);
  422. net.setPreferableTarget(target);
  423. Mat sample = imread(_tf("street.png", false));
  424. Mat inputBlob = blobFromImage(sample, 1./255, Size(), Scalar(), /*swapRB*/true);
  425. net.setInput(inputBlob, "");
  426. Mat out = net.forward();
  427. Mat ref = blobFromNPY(_tf("torch_enet_prob.npy", false));
  428. // Due to numerical instability in Pooling-Unpooling layers (indexes jittering)
  429. // thresholds for ENet must be changed. Accuracy of results was checked on
  430. // Cityscapes dataset and difference in mIOU with Torch is 10E-4%
  431. normAssert(ref, out, "", 0.0005, /*target == DNN_TARGET_CPU ? 0.453 : */0.552);
  432. normAssertSegmentation(ref, out);
  433. const int N = 3;
  434. for (int i = 0; i < N; i++)
  435. {
  436. net.setInput(inputBlob, "");
  437. Mat out = net.forward();
  438. normAssert(ref, out, "", 0.0005, /*target == DNN_TARGET_CPU ? 0.453 : */0.552);
  439. normAssertSegmentation(ref, out);
  440. }
  441. }
  442. // Check accuracy of style transfer models from https://github.com/jcjohnson/fast-neural-style
  443. // th fast_neural_style.lua \
  444. // -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
  445. // -output_image lena.png \
  446. // -median_filter 0 \
  447. // -image_size 0 \
  448. // -model models/eccv16/starry_night.t7
  449. // th fast_neural_style.lua \
  450. // -input_image ~/opencv_extra/testdata/dnn/googlenet_1.png \
  451. // -output_image lena.png \
  452. // -median_filter 0 \
  453. // -image_size 0 \
  454. // -model models/instance_norm/feathers.t7
  455. TEST_P(Test_Torch_nets, FastNeuralStyle_accuracy)
  456. {
  457. #if defined INF_ENGINE_RELEASE
  458. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_MYRIAD
  459. && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
  460. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  461. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD
  462. && getInferenceEngineVPUType() == CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
  463. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  464. #endif
  465. checkBackend();
  466. #if defined(INF_ENGINE_RELEASE)
  467. #if INF_ENGINE_RELEASE <= 2018050000
  468. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL)
  469. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
  470. #endif
  471. #endif
  472. std::string models[] = {"dnn/fast_neural_style_eccv16_starry_night.t7",
  473. "dnn/fast_neural_style_instance_norm_feathers.t7"};
  474. std::string targets[] = {"dnn/lena_starry_night.png", "dnn/lena_feathers.png"};
  475. for (int i = 0; i < 2; ++i)
  476. {
  477. const string model = findDataFile(models[i], false);
  478. Net net = readNetFromTorch(model);
  479. net.setPreferableBackend(backend);
  480. net.setPreferableTarget(target);
  481. Mat img = imread(findDataFile("dnn/googlenet_1.png"));
  482. Mat inputBlob = blobFromImage(img, 1.0, Size(), Scalar(103.939, 116.779, 123.68), false);
  483. if (target == DNN_TARGET_CPU_FP16)
  484. net.enableWinograd(false);
  485. net.setInput(inputBlob);
  486. Mat out = net.forward();
  487. // Deprocessing.
  488. getPlane(out, 0, 0) += 103.939;
  489. getPlane(out, 0, 1) += 116.779;
  490. getPlane(out, 0, 2) += 123.68;
  491. out = cv::min(cv::max(0, out), 255);
  492. Mat ref = imread(findDataFile(targets[i]));
  493. Mat refBlob = blobFromImage(ref, 1.0, Size(), Scalar(), false);
  494. if (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD)
  495. {
  496. double normL1 = cvtest::norm(refBlob, out, cv::NORM_L1) / refBlob.total();
  497. if (target == DNN_TARGET_MYRIAD)
  498. EXPECT_LE(normL1, 4.0f);
  499. else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
  500. EXPECT_LE(normL1, 1.0f);
  501. else
  502. EXPECT_LE(normL1, 0.6f);
  503. }
  504. else if(target == DNN_TARGET_CUDA_FP16)
  505. {
  506. normAssert(out, refBlob, "", 0.6, 26);
  507. }
  508. else if (target == DNN_TARGET_CPU_FP16)
  509. {
  510. normAssert(out, refBlob, "", 0.7, 25);
  511. }
  512. else
  513. normAssert(out, refBlob, "", 0.5, 1.16);
  514. }
  515. }
  516. INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_nets, dnnBackendsAndTargets());
  517. // Test a custom layer
  518. // https://github.com/torch/nn/blob/master/doc/convolution.md#nn.SpatialUpSamplingNearest
  519. class SpatialUpSamplingNearestLayer CV_FINAL : public Layer
  520. {
  521. public:
  522. SpatialUpSamplingNearestLayer(const LayerParams &params) : Layer(params)
  523. {
  524. scale = params.get<int>("scale_factor");
  525. }
  526. static Ptr<Layer> create(LayerParams& params)
  527. {
  528. return Ptr<Layer>(new SpatialUpSamplingNearestLayer(params));
  529. }
  530. virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,
  531. const int requiredOutputs,
  532. std::vector<std::vector<int> > &outputs,
  533. std::vector<std::vector<int> > &internals) const CV_OVERRIDE
  534. {
  535. std::vector<int> outShape(4);
  536. outShape[0] = inputs[0][0]; // batch size
  537. outShape[1] = inputs[0][1]; // number of channels
  538. outShape[2] = scale * inputs[0][2];
  539. outShape[3] = scale * inputs[0][3];
  540. outputs.assign(1, outShape);
  541. return false;
  542. }
  543. void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
  544. {
  545. CV_TRACE_FUNCTION();
  546. CV_TRACE_ARG_VALUE(name, "name", name.c_str());
  547. std::vector<Mat> inputs, outputs;
  548. inputs_arr.getMatVector(inputs);
  549. outputs_arr.getMatVector(outputs);
  550. Mat& inp = inputs[0];
  551. Mat& out = outputs[0];
  552. const int outHeight = out.size[2];
  553. const int outWidth = out.size[3];
  554. for (size_t n = 0; n < inp.size[0]; ++n)
  555. {
  556. for (size_t ch = 0; ch < inp.size[1]; ++ch)
  557. {
  558. resize(getPlane(inp, n, ch), getPlane(out, n, ch),
  559. Size(outWidth, outHeight), 0, 0, INTER_NEAREST);
  560. }
  561. }
  562. }
  563. private:
  564. int scale;
  565. };
  566. TEST_P(Test_Torch_layers, upsampling_nearest)
  567. {
  568. #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
  569. if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
  570. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // TODO
  571. #endif
  572. // Test a custom layer.
  573. CV_DNN_REGISTER_LAYER_CLASS(SpatialUpSamplingNearest, SpatialUpSamplingNearestLayer);
  574. try
  575. {
  576. runTorchNet("net_spatial_upsampling_nearest", "", false, true);
  577. }
  578. catch (...)
  579. {
  580. LayerFactory::unregisterLayer("SpatialUpSamplingNearest");
  581. throw;
  582. }
  583. LayerFactory::unregisterLayer("SpatialUpSamplingNearest");
  584. // Test an implemented layer.
  585. runTorchNet("net_spatial_upsampling_nearest", "", false, true);
  586. }
  587. INSTANTIATE_TEST_CASE_P(/**/, Test_Torch_layers, dnnBackendsAndTargets());
  588. }