test_misc.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  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. #include "test_precomp.hpp"
  8. #include "npy_blob.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. namespace opencv_test { namespace {
  13. TEST(blobRectToImageRect, DNN_PMODE_NULL)
  14. {
  15. Size inputSize(50 + (rand() % 100) / 4 * 4, 50 + (rand() % 100) / 4 * 4);
  16. Size imgSize(200 + (rand() % 100) / 4 * 4, 200 + (rand() % 100) / 4 * 4);
  17. Rect rBlob(inputSize.width / 2 - inputSize.width / 4, inputSize.height / 2 - inputSize.height / 4, inputSize.width / 2, inputSize.height / 2);
  18. Image2BlobParams paramNet;
  19. paramNet.scalefactor = Scalar::all(1.f);
  20. paramNet.size = inputSize;
  21. paramNet.ddepth = CV_32F;
  22. paramNet.mean = Scalar();
  23. paramNet.swapRB = false;
  24. paramNet.datalayout = DNN_LAYOUT_NHWC;
  25. paramNet.paddingmode = DNN_PMODE_NULL;
  26. Rect rOri = paramNet.blobRectToImageRect(rBlob, imgSize);
  27. Rect rImg = Rect(rBlob.x * (float)imgSize.width / inputSize.width, rBlob.y * (float)imgSize.height / inputSize.height,
  28. rBlob.width * (float)imgSize.width / inputSize.width, rBlob.height * (float)imgSize.height / inputSize.height);
  29. ASSERT_EQ(rImg, rOri);
  30. }
  31. TEST(blobRectToImageRect, DNN_PMODE_CROP_CENTER)
  32. {
  33. Size inputSize(50 + (rand() % 100) / 4 * 4, 50 + (rand() % 100) / 4 * 4);
  34. Size imgSize(200 + (rand() % 100) / 4 * 4, 200 + (rand() % 100) / 4 * 4);
  35. Rect rBlob(inputSize.width / 2 - inputSize.width / 4, inputSize.height / 2 - inputSize.height / 4, inputSize.width / 2, inputSize.height / 2);
  36. Image2BlobParams paramNet;
  37. paramNet.scalefactor = Scalar::all(1.f);
  38. paramNet.size = inputSize;
  39. paramNet.ddepth = CV_32F;
  40. paramNet.mean = Scalar();
  41. paramNet.swapRB = false;
  42. paramNet.datalayout = DNN_LAYOUT_NHWC;
  43. paramNet.paddingmode = DNN_PMODE_CROP_CENTER;
  44. Rect rOri = paramNet.blobRectToImageRect(rBlob, imgSize);
  45. float resizeFactor = std::max(inputSize.width / (float)imgSize.width,
  46. inputSize.height / (float)imgSize.height);
  47. Rect rImg = Rect((rBlob.x + 0.5 * (imgSize.width * resizeFactor - inputSize.width)) / resizeFactor, (rBlob.y + 0.5 * (imgSize.height * resizeFactor - inputSize.height)) / resizeFactor,
  48. rBlob.width / resizeFactor, rBlob.height / resizeFactor);
  49. ASSERT_EQ(rImg, rOri);
  50. }
  51. TEST(blobRectToImageRect, DNN_PMODE_LETTERBOX)
  52. {
  53. Size inputSize(50 + (rand() % 100) / 4 * 4, 50 + (rand() % 100) / 4 * 4);
  54. Size imgSize(200 + (rand() % 100) / 4 * 4, 200 + (rand() % 100) / 4 * 4);
  55. Rect rBlob(inputSize.width / 2 - inputSize.width / 4, inputSize.height / 2 - inputSize.height / 4, inputSize.width / 2, inputSize.height / 2);
  56. Image2BlobParams paramNet;
  57. paramNet.scalefactor = Scalar::all(1.f);
  58. paramNet.size = inputSize;
  59. paramNet.ddepth = CV_32F;
  60. paramNet.mean = Scalar();
  61. paramNet.swapRB = false;
  62. paramNet.datalayout = DNN_LAYOUT_NHWC;
  63. paramNet.paddingmode = DNN_PMODE_LETTERBOX;
  64. Rect rOri = paramNet.blobRectToImageRect(rBlob, imgSize);
  65. float resizeFactor = std::min(inputSize.width / (float)imgSize.width,
  66. inputSize.height / (float)imgSize.height);
  67. int rh = int(imgSize.height * resizeFactor);
  68. int rw = int(imgSize.width * resizeFactor);
  69. int top = (inputSize.height - rh) / 2;
  70. int left = (inputSize.width - rw) / 2;
  71. Rect rImg = Rect((rBlob.x - left) / resizeFactor, (rBlob.y - top) / resizeFactor, rBlob.width / resizeFactor, rBlob.height / resizeFactor);
  72. ASSERT_EQ(rImg, rOri);
  73. }
  74. TEST(blobFromImage_4ch, Regression)
  75. {
  76. Mat ch[4];
  77. for (int i = 0; i < 4; i++)
  78. ch[i] = Mat::ones(10, 10, CV_8U) * i;
  79. Mat img;
  80. merge(ch, 4, img);
  81. Mat blob = dnn::blobFromImage(img, 1., Size(), Scalar(), false, false);
  82. for (int i = 0; i < 4; i++)
  83. {
  84. ch[i] = Mat(img.rows, img.cols, CV_32F, blob.ptr(0, i));
  85. ASSERT_DOUBLE_EQ(cvtest::norm(ch[i], cv::NORM_INF), i);
  86. }
  87. }
  88. TEST(blobFromImage, allocated)
  89. {
  90. int size[] = { 1, 3, 4, 5 };
  91. Mat img(size[2], size[3], CV_32FC(size[1]));
  92. Mat blob(4, size, CV_32F);
  93. void* blobData = blob.data;
  94. dnn::blobFromImage(img, blob, 1.0 / 255, Size(), Scalar(), false, false);
  95. ASSERT_EQ(blobData, blob.data);
  96. }
  97. TEST(imagesFromBlob, Regression)
  98. {
  99. int nbOfImages = 8;
  100. std::vector<cv::Mat> inputImgs(nbOfImages);
  101. for (int i = 0; i < nbOfImages; i++)
  102. {
  103. inputImgs[i] = cv::Mat::ones(100, 100, CV_32FC3);
  104. cv::randu(inputImgs[i], cv::Scalar::all(0), cv::Scalar::all(1));
  105. }
  106. cv::Mat blob = cv::dnn::blobFromImages(inputImgs, 1., cv::Size(), cv::Scalar(), false, false);
  107. std::vector<cv::Mat> outputImgs;
  108. cv::dnn::imagesFromBlob(blob, outputImgs);
  109. for (int i = 0; i < nbOfImages; i++)
  110. {
  111. EXPECT_EQ(0, cvtest::norm(inputImgs[i], outputImgs[i], NORM_INF))
  112. << "i=" << i
  113. << " inputImgs[i]=" << inputImgs[i].size
  114. << " outputImgs[i]=" << outputImgs[i].size;
  115. }
  116. }
  117. TEST(blobFromImageWithParams_4ch, NHWC_scalar_scale)
  118. {
  119. Mat img(10, 10, CV_8UC4, cv::Scalar(0, 1, 2, 3));
  120. std::vector<double> factorVec = { 0.1, 0.2, 0.3, 0.4 };
  121. Scalar scalefactor(factorVec[0], factorVec[1], factorVec[2], factorVec[3]);
  122. Image2BlobParams param;
  123. param.scalefactor = scalefactor;
  124. param.datalayout = DNN_LAYOUT_NHWC;
  125. Mat blob = dnn::blobFromImageWithParams(img, param); // [1, 10, 10, 4]
  126. float* blobPtr = blob.ptr<float>(0);
  127. std::vector<float> targetVec = { (float)factorVec[0] * 0, (float)factorVec[1] * 1, (float)factorVec[2] * 2, (float)factorVec[3] * 3 }; // Target Value.
  128. for (int hi = 0; hi < 10; hi++)
  129. {
  130. for (int wi = 0; wi < 10; wi++)
  131. {
  132. float* hwPtr = blobPtr + hi * 10 * 4 + wi * 4;
  133. // Check equal
  134. EXPECT_NEAR(hwPtr[0], targetVec[0], 1e-5);
  135. EXPECT_NEAR(hwPtr[1], targetVec[1], 1e-5);
  136. EXPECT_NEAR(hwPtr[2], targetVec[2], 1e-5);
  137. EXPECT_NEAR(hwPtr[3], targetVec[3], 1e-5);
  138. }
  139. }
  140. }
  141. TEST(blobFromImageWithParams_CustomPadding, letter_box)
  142. {
  143. Mat img(40, 20, CV_8UC4, Scalar(0, 1, 2, 3));
  144. // Custom padding value that you have added
  145. Scalar customPaddingValue(5, 6, 7, 8); // Example padding value
  146. Size targetSize(20, 20);
  147. Mat targetImg = img.clone();
  148. cv::copyMakeBorder(
  149. targetImg, targetImg, 0, 0,
  150. targetSize.width / 2,
  151. targetSize.width / 2,
  152. BORDER_CONSTANT,
  153. customPaddingValue);
  154. // Set up Image2BlobParams with your new functionality
  155. Image2BlobParams param;
  156. param.size = targetSize;
  157. param.paddingmode = DNN_PMODE_LETTERBOX;
  158. param.borderValue = customPaddingValue; // Use your new feature here
  159. // Create blob with custom padding
  160. Mat blob = dnn::blobFromImageWithParams(img, param);
  161. // Create target blob for comparison
  162. Mat targetBlob = dnn::blobFromImage(targetImg, 1.0, targetSize);
  163. EXPECT_EQ(0, cvtest::norm(targetBlob, blob, NORM_INF));
  164. }
  165. TEST(blobFromImageWithParams_4ch, letter_box)
  166. {
  167. Mat img(40, 20, CV_8UC4, cv::Scalar(0, 1, 2, 3));
  168. // Construct target mat.
  169. Mat targetCh[4];
  170. // The letterbox will add zero at the left and right of output blob.
  171. // After the letterbox, every row data would have same value showing as valVec.
  172. std::vector<uint8_t> valVec = { 0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0 };
  173. Mat rowM(1, 20, CV_8UC1, valVec.data());
  174. for (int i = 0; i < 4; i++)
  175. {
  176. targetCh[i] = rowM * i;
  177. }
  178. Mat targetImg;
  179. merge(targetCh, 4, targetImg);
  180. Size targeSize(20, 20);
  181. Image2BlobParams param;
  182. param.size = targeSize;
  183. param.paddingmode = DNN_PMODE_LETTERBOX;
  184. Mat blob = dnn::blobFromImageWithParams(img, param);
  185. Mat targetBlob = dnn::blobFromImage(targetImg, 1.0, targeSize); // only convert data from uint8 to float32.
  186. EXPECT_EQ(0, cvtest::norm(targetBlob, blob, NORM_INF));
  187. }
  188. TEST(blobFromImagesWithParams_4ch, multi_image)
  189. {
  190. Mat img(10, 10, CV_8UC4, cv::Scalar(0, 1, 2, 3));
  191. Scalar scalefactor(0.1, 0.2, 0.3, 0.4);
  192. Image2BlobParams param;
  193. param.scalefactor = scalefactor;
  194. param.datalayout = DNN_LAYOUT_NHWC;
  195. Mat blobs = blobFromImagesWithParams(std::vector<Mat> { img, 2 * img }, param);
  196. vector<Range> ranges;
  197. ranges.push_back(Range(0, 1));
  198. ranges.push_back(Range(0, blobs.size[1]));
  199. ranges.push_back(Range(0, blobs.size[2]));
  200. ranges.push_back(Range(0, blobs.size[3]));
  201. Mat blob0 = blobs(ranges);
  202. ranges[0] = Range(1, 2);
  203. Mat blob1 = blobs(ranges);
  204. EXPECT_EQ(0, cvtest::norm(2 * blob0, blob1, NORM_INF));
  205. }
  206. TEST(readNet, Regression)
  207. {
  208. Net net = readNet(findDataFile("dnn/squeezenet_v1.1.prototxt"),
  209. findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
  210. EXPECT_FALSE(net.empty());
  211. net = readNet(findDataFile("dnn/opencv_face_detector.caffemodel", false),
  212. findDataFile("dnn/opencv_face_detector.prototxt"));
  213. EXPECT_FALSE(net.empty());
  214. net = readNet(findDataFile("dnn/openface_nn4.small2.v1.t7", false));
  215. EXPECT_FALSE(net.empty());
  216. net = readNet(findDataFile("dnn/tiny-yolo-voc.cfg"),
  217. findDataFile("dnn/tiny-yolo-voc.weights", false));
  218. EXPECT_FALSE(net.empty());
  219. net = readNet(findDataFile("dnn/ssd_mobilenet_v1_coco.pbtxt"),
  220. findDataFile("dnn/ssd_mobilenet_v1_coco.pb", false));
  221. EXPECT_FALSE(net.empty());
  222. }
  223. TEST(readNet, do_not_call_setInput) // https://github.com/opencv/opencv/issues/16618
  224. {
  225. // 1. load network
  226. const string proto = findDataFile("dnn/squeezenet_v1.1.prototxt");
  227. const string model = findDataFile("dnn/squeezenet_v1.1.caffemodel", false);
  228. Net net = readNetFromCaffe(proto, model);
  229. // 2. mistake: no inputs are specified through .setInput()
  230. // 3. try inference
  231. Mat res;
  232. EXPECT_THROW(
  233. {
  234. res = net.forward(); // no inputs after loading => should fail
  235. }, cv::Exception);
  236. EXPECT_TRUE(res.empty()) << res.size;
  237. }
  238. TEST(Net, empty_forward_18392)
  239. {
  240. cv::dnn::Net net;
  241. Mat image(Size(512, 512), CV_8UC3, Scalar::all(0));
  242. Mat inputBlob = cv::dnn::blobFromImage(image, 1.0, Size(512, 512), Scalar(0,0,0), true, false);
  243. net.setInput(inputBlob);
  244. EXPECT_ANY_THROW(Mat output = net.forward());
  245. }
  246. #ifdef HAVE_INF_ENGINE
  247. static
  248. void test_readNet_IE_do_not_call_setInput(Backend backendId)
  249. {
  250. const Target targetId = DNN_TARGET_CPU;
  251. const std::string& model = findDataFile("dnn/layers/layer_convolution.bin");
  252. const std::string& proto = findDataFile("dnn/layers/layer_convolution.xml");
  253. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  254. Net net = readNet(model, proto);
  255. net.setPreferableBackend(backendId);
  256. net.setPreferableTarget(targetId);
  257. // 2. mistake: no inputs are specified through .setInput()
  258. // 3. try inference
  259. Mat res;
  260. EXPECT_THROW(
  261. {
  262. res = net.forward(); // no inputs after loading => should fail
  263. }, cv::Exception);
  264. EXPECT_TRUE(res.empty()) << res.size;
  265. }
  266. #ifdef HAVE_DNN_IE_NN_BUILDER_2019
  267. TEST(readNet, do_not_call_setInput_IE_NN_BUILDER_2019)
  268. {
  269. test_readNet_IE_do_not_call_setInput(DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019);
  270. }
  271. #endif
  272. #ifdef HAVE_DNN_NGRAPH
  273. TEST(readNet, do_not_call_setInput_IE_NGRAPH)
  274. {
  275. test_readNet_IE_do_not_call_setInput(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH);
  276. }
  277. #endif
  278. #endif // HAVE_INF_ENGINE
  279. typedef testing::TestWithParam<tuple<Backend, Target> > dump;
  280. TEST_P(dump, Regression)
  281. {
  282. const int backend = get<0>(GetParam());
  283. const int target = get<1>(GetParam());
  284. Net net = readNet(findDataFile("dnn/squeezenet_v1.1.prototxt"),
  285. findDataFile("dnn/squeezenet_v1.1.caffemodel", false));
  286. ASSERT_EQ(net.getLayerInputs(net.getLayerId("fire2/concat")).size(), 2);
  287. int size[] = {1, 3, 227, 227};
  288. Mat input = cv::Mat::ones(4, size, CV_32F);
  289. net.setInput(input);
  290. net.setPreferableBackend(backend);
  291. net.setPreferableTarget(target);
  292. EXPECT_FALSE(net.dump().empty());
  293. net.forward();
  294. EXPECT_FALSE(net.dump().empty());
  295. }
  296. INSTANTIATE_TEST_CASE_P(/**/, dump, dnnBackendsAndTargets());
  297. class FirstCustomLayer CV_FINAL : public Layer
  298. {
  299. public:
  300. FirstCustomLayer(const LayerParams &params) : Layer(params) {}
  301. static Ptr<Layer> create(LayerParams& params)
  302. {
  303. return Ptr<Layer>(new FirstCustomLayer(params));
  304. }
  305. void forward(InputArrayOfArrays, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
  306. {
  307. CV_TRACE_FUNCTION();
  308. CV_TRACE_ARG_VALUE(name, "name", name.c_str());
  309. std::vector<Mat> outputs;
  310. outputs_arr.getMatVector(outputs);
  311. outputs[0].setTo(1);
  312. }
  313. };
  314. class SecondCustomLayer CV_FINAL : public Layer
  315. {
  316. public:
  317. SecondCustomLayer(const LayerParams &params) : Layer(params) {}
  318. static Ptr<Layer> create(LayerParams& params)
  319. {
  320. return Ptr<Layer>(new SecondCustomLayer(params));
  321. }
  322. void forward(InputArrayOfArrays, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays) CV_OVERRIDE
  323. {
  324. CV_TRACE_FUNCTION();
  325. CV_TRACE_ARG_VALUE(name, "name", name.c_str());
  326. std::vector<Mat> outputs;
  327. outputs_arr.getMatVector(outputs);
  328. outputs[0].setTo(2);
  329. }
  330. };
  331. TEST(LayerFactory, custom_layers)
  332. {
  333. LayerParams lp;
  334. lp.name = "name";
  335. lp.type = "CustomType";
  336. Mat inp(1, 1, CV_32FC1);
  337. for (int i = 0; i < 3; ++i)
  338. {
  339. if (i == 0) { CV_DNN_REGISTER_LAYER_CLASS(CustomType, FirstCustomLayer); }
  340. else if (i == 1) { CV_DNN_REGISTER_LAYER_CLASS(CustomType, SecondCustomLayer); }
  341. else if (i == 2) { LayerFactory::unregisterLayer("CustomType"); }
  342. Net net;
  343. net.addLayerToPrev(lp.name, lp.type, lp);
  344. net.setInput(inp);
  345. net.setPreferableBackend(DNN_BACKEND_OPENCV);
  346. Mat output = net.forward();
  347. if (i == 0) { EXPECT_EQ(output.at<float>(0), 1); }
  348. else if (i == 1) { EXPECT_EQ(output.at<float>(0), 2); }
  349. else if (i == 2) { EXPECT_EQ(output.at<float>(0), 1); }
  350. }
  351. LayerFactory::unregisterLayer("CustomType");
  352. }
  353. typedef testing::TestWithParam<tuple<float, Vec3f, int, tuple<Backend, Target> > > setInput;
  354. TEST_P(setInput, normalization)
  355. {
  356. const float kScale = get<0>(GetParam());
  357. const Scalar kMean = get<1>(GetParam());
  358. const int dtype = get<2>(GetParam());
  359. const int backend = get<0>(get<3>(GetParam()));
  360. const int target = get<1>(get<3>(GetParam()));
  361. const bool kSwapRB = true;
  362. if(backend == DNN_BACKEND_CUDA)
  363. applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA);
  364. if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_OPENCL_FP16 && dtype != CV_32F)
  365. applyTestTag(CV_TEST_TAG_DNN_SKIP_OPENCL_FP16);
  366. if (backend == DNN_BACKEND_VKCOM && dtype != CV_32F)
  367. applyTestTag(CV_TEST_TAG_DNN_SKIP_VULKAN);
  368. Mat inp(5, 5, CV_8UC3);
  369. randu(inp, 0, 255);
  370. Mat ref = blobFromImage(inp, kScale, Size(), kMean, kSwapRB, /*crop*/false);
  371. LayerParams lp;
  372. Net net;
  373. net.addLayerToPrev("testLayer", "Identity", lp);
  374. net.setPreferableBackend(backend);
  375. net.setPreferableTarget(target);
  376. Mat blob = blobFromImage(inp, 1.0, Size(), Scalar(), kSwapRB, /*crop*/false, dtype);
  377. ASSERT_EQ(blob.type(), dtype);
  378. net.setInput(blob, "", kScale, kMean);
  379. Mat out = net.forward();
  380. ASSERT_EQ(out.type(), CV_32F);
  381. normAssert(ref, out, "", 4e-4, 1e-3);
  382. }
  383. INSTANTIATE_TEST_CASE_P(/**/, setInput, Combine(
  384. Values(1.0f, 1.0 / 127.5),
  385. Values(Vec3f(), Vec3f(50, 50, 50), Vec3f(10, 50, 140)),
  386. Values(CV_32F, CV_8U),
  387. dnnBackendsAndTargets()
  388. ));
  389. class CustomLayerWithDeprecatedForward CV_FINAL : public Layer
  390. {
  391. public:
  392. CustomLayerWithDeprecatedForward(const LayerParams &params) : Layer(params) {}
  393. static Ptr<Layer> create(LayerParams& params)
  394. {
  395. return Ptr<Layer>(new CustomLayerWithDeprecatedForward(params));
  396. }
  397. virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
  398. {
  399. CV_Assert_N(inputs[0]->depth() == CV_32F, outputs[0].depth() == CV_32F);
  400. cv::add(*inputs[0], 0.5f, outputs[0]);
  401. }
  402. };
  403. class CustomLayerWithDeprecatedForwardAndFallback CV_FINAL : public Layer
  404. {
  405. public:
  406. CustomLayerWithDeprecatedForwardAndFallback(const LayerParams &params) : Layer(params) {}
  407. static Ptr<Layer> create(LayerParams& params)
  408. {
  409. return Ptr<Layer>(new CustomLayerWithDeprecatedForwardAndFallback(params));
  410. }
  411. void forward(InputArrayOfArrays inputs, OutputArrayOfArrays outputs, OutputArrayOfArrays internals) CV_OVERRIDE
  412. {
  413. CV_TRACE_FUNCTION();
  414. CV_TRACE_ARG_VALUE(name, "name", name.c_str());
  415. CV_OCL_RUN(preferableTarget == DNN_TARGET_OPENCL || preferableTarget == DNN_TARGET_OPENCL_FP16,
  416. forward_ocl(inputs, outputs, internals));
  417. Layer::forward_fallback(inputs, outputs, internals);
  418. }
  419. virtual void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals) CV_OVERRIDE
  420. {
  421. CV_Assert_N(inputs[0]->depth() == CV_32F, outputs[0].depth() == CV_32F);
  422. cv::add(*inputs[0], 0.5f, outputs[0]);
  423. }
  424. #ifdef HAVE_OPENCL
  425. bool forward_ocl(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
  426. {
  427. if (inputs_arr.depth() != CV_32F)
  428. return false;
  429. std::vector<UMat> inputs;
  430. std::vector<UMat> outputs;
  431. inputs_arr.getUMatVector(inputs);
  432. outputs_arr.getUMatVector(outputs);
  433. cv::add(inputs[0], 0.5f, outputs[0]);
  434. return true;
  435. }
  436. #endif
  437. };
  438. typedef testing::TestWithParam<tuple<Backend, Target> > DeprecatedForward;
  439. TEST_P(DeprecatedForward, CustomLayer)
  440. {
  441. const int backend = get<0>(GetParam());
  442. const int target = get<1>(GetParam());
  443. Mat inp(5, 5, CV_32FC1);
  444. randu(inp, -1.0f, 1.0f);
  445. inp = blobFromImage(inp);
  446. CV_DNN_REGISTER_LAYER_CLASS(CustomType, CustomLayerWithDeprecatedForward);
  447. try
  448. {
  449. LayerParams lp;
  450. Net net;
  451. net.addLayerToPrev("testLayer", "CustomType", lp);
  452. net.setPreferableBackend(backend);
  453. net.setPreferableTarget(target);
  454. net.setInput(inp);
  455. Mat out = net.forward();
  456. normAssert(out, inp + 0.5f, "", 2e-4, 7e-4);
  457. }
  458. catch (...)
  459. {
  460. LayerFactory::unregisterLayer("CustomType");
  461. throw;
  462. }
  463. LayerFactory::unregisterLayer("CustomType");
  464. }
  465. TEST_P(DeprecatedForward, CustomLayerWithFallback)
  466. {
  467. const int backend = get<0>(GetParam());
  468. const int target = get<1>(GetParam());
  469. Mat inp(5, 5, CV_32FC1);
  470. randu(inp, -1.0f, 1.0f);
  471. inp = blobFromImage(inp);
  472. CV_DNN_REGISTER_LAYER_CLASS(CustomType, CustomLayerWithDeprecatedForwardAndFallback);
  473. try
  474. {
  475. LayerParams lp;
  476. Net net;
  477. net.addLayerToPrev("testLayer", "CustomType", lp);
  478. net.setPreferableBackend(backend);
  479. net.setPreferableTarget(target);
  480. net.setInput(inp);
  481. Mat out = net.forward();
  482. normAssert(out, inp + 0.5f, "", 2e-4, 7e-4);
  483. }
  484. catch (...)
  485. {
  486. LayerFactory::unregisterLayer("CustomType");
  487. throw;
  488. }
  489. LayerFactory::unregisterLayer("CustomType");
  490. }
  491. INSTANTIATE_TEST_CASE_P(/**/, DeprecatedForward, dnnBackendsAndTargets());
  492. TEST(Net, forwardAndRetrieve)
  493. {
  494. std::string prototxt =
  495. "input: \"data\"\n"
  496. "layer {\n"
  497. " name: \"testLayer\"\n"
  498. " type: \"Slice\"\n"
  499. " bottom: \"data\"\n"
  500. " top: \"firstCopy\"\n"
  501. " top: \"secondCopy\"\n"
  502. " slice_param {\n"
  503. " axis: 0\n"
  504. " slice_point: 2\n"
  505. " }\n"
  506. "}";
  507. Net net = readNetFromCaffe(&prototxt[0], prototxt.size());
  508. net.setPreferableBackend(DNN_BACKEND_OPENCV);
  509. Mat inp(4, 5, CV_32F);
  510. randu(inp, -1, 1);
  511. net.setInput(inp);
  512. std::vector<String> outNames;
  513. outNames.push_back("testLayer");
  514. std::vector<std::vector<Mat> > outBlobs;
  515. net.forward(outBlobs, outNames);
  516. EXPECT_EQ(outBlobs.size(), 1);
  517. EXPECT_EQ(outBlobs[0].size(), 2);
  518. normAssert(outBlobs[0][0], inp.rowRange(0, 2), "first part");
  519. normAssert(outBlobs[0][1], inp.rowRange(2, 4), "second part");
  520. }
  521. #ifdef HAVE_INF_ENGINE
  522. static const std::chrono::milliseconds async_timeout(10000);
  523. // This test runs network in synchronous mode for different inputs and then
  524. // runs the same model asynchronously for the same inputs.
  525. typedef testing::TestWithParam<tuple<int, tuple<Backend, Target> > > Async;
  526. TEST_P(Async, model_optimizer_pipeline_set_and_forward_single)
  527. {
  528. const int dtype = get<0>(GetParam());
  529. const Backend backendId = get<0>(get<1>(GetParam()));
  530. const Target targetId = get<1>(get<1>(GetParam()));
  531. if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD)
  532. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  533. if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
  534. throw SkipTestException("No support for async forward");
  535. const std::string& model = findDataFile("dnn/layers/layer_convolution.bin");
  536. const std::string& proto = findDataFile("dnn/layers/layer_convolution.xml");
  537. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  538. Net netSync = readNet(model, proto);
  539. netSync.setPreferableBackend(backendId);
  540. netSync.setPreferableTarget(targetId);
  541. Net netAsync = readNet(model, proto);
  542. netAsync.setPreferableBackend(backendId);
  543. netAsync.setPreferableTarget(targetId);
  544. // Generate inputs.
  545. const int numInputs = 10;
  546. std::vector<Mat> inputs(numInputs);
  547. int blobSize[] = {2, 6, 75, 113};
  548. for (int i = 0; i < numInputs; ++i)
  549. {
  550. inputs[i].create(4, &blobSize[0], dtype);
  551. randu(inputs[i], 0, 255);
  552. }
  553. // Run synchronously.
  554. std::vector<Mat> refs(numInputs);
  555. for (int i = 0; i < numInputs; ++i)
  556. {
  557. netSync.setInput(inputs[i]);
  558. refs[i] = netSync.forward().clone();
  559. }
  560. // Run asynchronously. To make test more robust, process inputs in the reversed order.
  561. for (int i = numInputs - 1; i >= 0; --i)
  562. {
  563. netAsync.setInput(inputs[i]);
  564. AsyncArray out = netAsync.forwardAsync();
  565. ASSERT_TRUE(out.valid());
  566. Mat result;
  567. EXPECT_TRUE(out.get(result, async_timeout));
  568. normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
  569. }
  570. }
  571. TEST_P(Async, model_optimizer_pipeline_set_and_forward_all)
  572. {
  573. const int dtype = get<0>(GetParam());
  574. const Backend backendId = get<0>(get<1>(GetParam()));
  575. const Target targetId = get<1>(get<1>(GetParam()));
  576. if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD)
  577. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  578. if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
  579. throw SkipTestException("No support for async forward");
  580. const std::string& model = findDataFile("dnn/layers/layer_convolution.bin");
  581. const std::string& proto = findDataFile("dnn/layers/layer_convolution.xml");
  582. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  583. Net netSync = readNet(model, proto);
  584. netSync.setPreferableBackend(backendId);
  585. netSync.setPreferableTarget(targetId);
  586. Net netAsync = readNet(model, proto);
  587. netAsync.setPreferableBackend(backendId);
  588. netAsync.setPreferableTarget(targetId);
  589. // Generate inputs.
  590. const int numInputs = 10;
  591. std::vector<Mat> inputs(numInputs);
  592. int blobSize[] = {2, 6, 75, 113};
  593. for (int i = 0; i < numInputs; ++i)
  594. {
  595. inputs[i].create(4, &blobSize[0], dtype);
  596. randu(inputs[i], 0, 255);
  597. }
  598. // Run synchronously.
  599. std::vector<Mat> refs(numInputs);
  600. for (int i = 0; i < numInputs; ++i)
  601. {
  602. netSync.setInput(inputs[i]);
  603. refs[i] = netSync.forward().clone();
  604. }
  605. // Run asynchronously. To make test more robust, process inputs in the reversed order.
  606. std::vector<AsyncArray> outs(numInputs);
  607. for (int i = numInputs - 1; i >= 0; --i)
  608. {
  609. netAsync.setInput(inputs[i]);
  610. outs[i] = netAsync.forwardAsync();
  611. }
  612. for (int i = numInputs - 1; i >= 0; --i)
  613. {
  614. ASSERT_TRUE(outs[i].valid());
  615. Mat result;
  616. EXPECT_TRUE(outs[i].get(result, async_timeout));
  617. normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
  618. }
  619. }
  620. TEST_P(Async, create_layer_pipeline_set_and_forward_all)
  621. {
  622. const int dtype = get<0>(GetParam());
  623. const Backend backendId = get<0>(get<1>(GetParam()));
  624. const Target targetId = get<1>(get<1>(GetParam()));
  625. if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
  626. throw SkipTestException("No support for async forward");
  627. // Exception: Default implementation fallbacks in asynchronous mode
  628. if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && dtype == CV_8U)
  629. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
  630. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  631. Net netSync;
  632. Net netAsync;
  633. {
  634. int inChannels = 4;
  635. int outChannels = 12;
  636. int group = 3;
  637. Size inSize(113, 75);
  638. Size kernel(4, 5);
  639. Size stride(2, 3);
  640. Size pad(0, 1);
  641. Size dilation(1, 1);
  642. bool hasBias = true;
  643. int sz[] = {outChannels, inChannels / group, kernel.height, kernel.width};
  644. Mat weights(4, &sz[0], CV_32F);
  645. randu(weights, -1.0f, 1.0f);
  646. LayerParams lp;
  647. lp.set("kernel_w", kernel.width);
  648. lp.set("kernel_h", kernel.height);
  649. lp.set("pad_w", pad.width);
  650. lp.set("pad_h", pad.height);
  651. lp.set("stride_w", stride.width);
  652. lp.set("stride_h", stride.height);
  653. lp.set("dilation_w", dilation.width);
  654. lp.set("dilation_h", dilation.height);
  655. lp.set("num_output", outChannels);
  656. lp.set("group", group);
  657. lp.set("bias_term", hasBias);
  658. lp.type = "Convolution";
  659. lp.name = "testLayer";
  660. lp.blobs.push_back(weights);
  661. if (hasBias)
  662. {
  663. Mat bias(1, outChannels, CV_32F);
  664. randu(bias, -1.0f, 1.0f);
  665. lp.blobs.push_back(bias);
  666. }
  667. int inpSz[] = {1, inChannels, inSize.height, inSize.width};
  668. Mat input(4, &inpSz[0], CV_32F);
  669. netSync.addLayerToPrev(lp.name, lp.type, lp);
  670. netAsync.addLayerToPrev(lp.name, lp.type, lp);
  671. }
  672. netSync.setPreferableBackend(backendId);
  673. netSync.setPreferableTarget(targetId);
  674. netAsync.setPreferableBackend(backendId);
  675. netAsync.setPreferableTarget(targetId);
  676. // Generate inputs.
  677. const int numInputs = 10;
  678. std::vector<Mat> inputs(numInputs);
  679. int blobSize[] = {1, 4, 75, 113};
  680. for (int i = 0; i < numInputs; ++i)
  681. {
  682. inputs[i].create(4, &blobSize[0], dtype);
  683. randu(inputs[i], 0, 255);
  684. }
  685. // Run synchronously.
  686. std::vector<Mat> refs(numInputs);
  687. for (int i = 0; i < numInputs; ++i)
  688. {
  689. netSync.setInput(inputs[i]);
  690. refs[i] = netSync.forward().clone();
  691. }
  692. // Run asynchronously. To make test more robust, process inputs in the reversed order.
  693. std::vector<AsyncArray> outs(numInputs);
  694. for (int i = numInputs - 1; i >= 0; --i)
  695. {
  696. netAsync.setInput(inputs[i]);
  697. outs[i] = netAsync.forwardAsync();
  698. }
  699. for (int i = numInputs - 1; i >= 0; --i)
  700. {
  701. ASSERT_TRUE(outs[i].valid());
  702. Mat result;
  703. EXPECT_TRUE(outs[i].get(result, async_timeout));
  704. normAssert(refs[i], result, format("Index: %d", i).c_str(), 0, 0);
  705. }
  706. }
  707. INSTANTIATE_TEST_CASE_P(/**/, Async, Combine(
  708. Values(CV_32F, CV_8U),
  709. dnnBackendsAndTargetsIE()
  710. ));
  711. typedef testing::TestWithParam<tuple<Backend, Target> > Test_Model_Optimizer;
  712. TEST_P(Test_Model_Optimizer, forward_two_nets)
  713. {
  714. const Backend backendId = get<0>(GetParam());
  715. const Target targetId = get<1>(GetParam());
  716. if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD)
  717. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  718. const std::string& model = findDataFile("dnn/layers/layer_convolution.bin");
  719. const std::string& proto = findDataFile("dnn/layers/layer_convolution.xml");
  720. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  721. Net net0 = readNet(model, proto);
  722. net0.setPreferableTarget(targetId);
  723. Net net1 = readNet(model, proto);
  724. net1.setPreferableTarget(targetId);
  725. // Generate inputs.
  726. int blobSize[] = {2, 6, 75, 113};
  727. Mat input(4, &blobSize[0], CV_32F);
  728. randu(input, 0, 255);
  729. net0.setInput(input);
  730. Mat ref0 = net0.forward().clone();
  731. net1.setInput(input);
  732. Mat ref1 = net1.forward();
  733. net0.setInput(input);
  734. Mat ref2 = net0.forward();
  735. normAssert(ref0, ref2, 0, 0);
  736. }
  737. TEST_P(Test_Model_Optimizer, readFromBuffer)
  738. {
  739. const Backend backendId = get<0>(GetParam());
  740. const Target targetId = get<1>(GetParam());
  741. if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD)
  742. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  743. if (backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
  744. throw SkipTestException("No support for async forward");
  745. const std::string& weightsFile = findDataFile("dnn/layers/layer_convolution.bin");
  746. const std::string& modelFile = findDataFile("dnn/layers/layer_convolution.xml");
  747. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  748. Net net1 = readNetFromModelOptimizer(modelFile, weightsFile);
  749. net1.setPreferableBackend(backendId);
  750. net1.setPreferableTarget(targetId);
  751. std::vector<char> modelConfig;
  752. readFileContent(modelFile, modelConfig);
  753. std::vector<char> weights;
  754. readFileContent(weightsFile, weights);
  755. Net net2 = readNetFromModelOptimizer(
  756. (const uchar*)modelConfig.data(), modelConfig.size(),
  757. (const uchar*)weights.data(), weights.size()
  758. );
  759. net2.setPreferableBackend(backendId);
  760. net2.setPreferableTarget(targetId);
  761. int blobSize[] = {2, 6, 75, 113};
  762. Mat input(4, &blobSize[0], CV_32F);
  763. randu(input, 0, 255);
  764. Mat ref, actual;
  765. {
  766. net1.setInput(input);
  767. ref = net1.forward();
  768. }
  769. {
  770. net2.setInput(input);
  771. actual = net2.forward();
  772. }
  773. normAssert(ref, actual, "", 0, 0);
  774. }
  775. TEST_P(Test_Model_Optimizer, flexible_inputs)
  776. {
  777. const Backend backendId = get<0>(GetParam());
  778. const Target targetId = get<1>(GetParam());
  779. if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && targetId == DNN_TARGET_MYRIAD)
  780. applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
  781. const std::string& model = findDataFile("dnn/layers/layer_convolution.bin");
  782. const std::string& proto = findDataFile("dnn/layers/layer_convolution.xml");
  783. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  784. Net net0 = readNet(model, proto);
  785. net0.setPreferableTarget(targetId);
  786. Net net1 = readNet(model, proto);
  787. net1.setPreferableTarget(targetId);
  788. // Generate inputs.
  789. int blobSize0[] = {2, 6, 75, 113};
  790. Mat input0(4, &blobSize0[0], CV_32F);
  791. randu(input0, 0, 255);
  792. net0.setInput(input0);
  793. Mat ref = net0.forward().clone();
  794. int blobSize1[] = {1, 6, 10, 9};
  795. Mat input1(4, &blobSize1[0], CV_32F);
  796. randu(input1, 0, 255);
  797. net1.setInput(input1);
  798. Mat out = net1.forward();
  799. EXPECT_NE(out.size, ref.size);
  800. net1.setInput(input0);
  801. out = net1.forward();
  802. normAssert(ref, out, 0, 0);
  803. }
  804. TEST_P(Test_Model_Optimizer, readONNX)
  805. {
  806. const Backend backendId = get<0>(GetParam());
  807. const Target targetId = get<1>(GetParam());
  808. ASSERT_EQ(DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, backendId);
  809. const std::string& model = findDataFile("dnn/onnx/models/convolution.onnx");
  810. std::vector<Net> nets = {
  811. // Old API
  812. readNetFromModelOptimizer(model, ""),
  813. readNet("", model, "dldt"),
  814. // New API
  815. readNetFromModelOptimizer(model),
  816. readNet(model, "", "openvino")
  817. };
  818. Mat inp = blobFromNPY(findDataFile("dnn/onnx/data/input_convolution.npy"));
  819. Mat ref = blobFromNPY(findDataFile("dnn/onnx/data/output_convolution.npy"));
  820. for (int i = 0; i < nets.size(); ++i) {
  821. nets[i].setPreferableTarget(targetId);
  822. nets[i].setInput(inp);
  823. Mat out = nets[i].forward();
  824. normAssert(out, ref, format("Index: %d", i).c_str());
  825. }
  826. }
  827. INSTANTIATE_TEST_CASE_P(/**/, Test_Model_Optimizer,
  828. dnnBackendsAndTargetsIE()
  829. );
  830. #endif // HAVE_INF_ENGINE
  831. typedef testing::TestWithParam<tuple<MatDepth, MatDepth, tuple<Backend, Target> > > Test_two_inputs;
  832. TEST_P(Test_two_inputs, basic)
  833. {
  834. static const float kScale = 0.5f;
  835. static const float kScaleInv = 1.0f / kScale;
  836. Backend backendId = get<0>(get<2>(GetParam()));
  837. Target targetId = get<1>(get<2>(GetParam()));
  838. int type1 = get<0>(GetParam());
  839. int type2 = get<1>(GetParam());
  840. if (backendId == DNN_BACKEND_VKCOM && !(type1 == CV_32F && type2 == CV_32F))
  841. applyTestTag(CV_TEST_TAG_DNN_SKIP_VULKAN);
  842. Net net;
  843. LayerParams lp;
  844. lp.type = "Eltwise";
  845. lp.name = "testLayer";
  846. lp.set("operation", "sum");
  847. int eltwiseId = net.addLayerToPrev(lp.name, lp.type, lp); // connect to a first input
  848. net.connect(0, 1, eltwiseId, 1); // connect to a second input
  849. int inpSize[] = {1, 2, 3, 4};
  850. Mat firstInp(4, &inpSize[0], type1);
  851. Mat secondInp(4, &inpSize[0], type2);
  852. randu(firstInp, 0, 100);
  853. randu(secondInp, 0, 100);
  854. std::vector<String> input_names;
  855. input_names.push_back("data");
  856. input_names.push_back("second_input");
  857. net.setInputsNames(input_names);
  858. net.setInput(firstInp, "data", kScale);
  859. net.setInput(secondInp, "second_input", kScaleInv);
  860. net.setPreferableBackend(backendId);
  861. net.setPreferableTarget(targetId);
  862. Mat out = net.forward();
  863. Mat ref;
  864. addWeighted(firstInp, kScale, secondInp, kScaleInv, 0, ref, CV_32F);
  865. double l1 = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD || targetId == DNN_TARGET_CUDA_FP16) ? 0.06 : 1e-6;
  866. double lInf = (targetId == DNN_TARGET_OPENCL_FP16 || targetId == DNN_TARGET_MYRIAD || targetId == DNN_TARGET_CUDA_FP16) ? 0.3 : 1e-5;
  867. normAssert(out, ref, "", l1, lInf);
  868. if (cvtest::debugLevel > 0 || HasFailure())
  869. {
  870. std::cout << "input1 scale=" << kScale << " input2 scale=" << kScaleInv << std::endl;
  871. std::cout << "input1: " << firstInp.size << " " << firstInp.reshape(1, 1) << std::endl;
  872. std::cout << "input2: " << secondInp.size << " " << secondInp.reshape(1, 1) << std::endl;
  873. std::cout << "ref: " << ref.reshape(1, 1) << std::endl;
  874. std::cout << "out: " << out.reshape(1, 1) << std::endl;
  875. }
  876. }
  877. INSTANTIATE_TEST_CASE_P(/*nothing*/, Test_two_inputs, Combine(
  878. Values(CV_32F, CV_8U),
  879. Values(CV_32F, CV_8U),
  880. dnnBackendsAndTargets()
  881. ));
  882. }} // namespace