gapi_streaming_tests.cpp 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516
  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) 2019-2021 Intel Corporation
  6. #include "../test_precomp.hpp"
  7. #include "../common/gapi_streaming_tests_common.hpp"
  8. #include <thread> // sleep_for (Delay)
  9. #include <opencv2/gapi/cpu/core.hpp>
  10. #include <opencv2/gapi/cpu/imgproc.hpp>
  11. #include <opencv2/gapi/fluid/core.hpp>
  12. #include <opencv2/gapi/fluid/imgproc.hpp>
  13. #include <opencv2/gapi/fluid/gfluidkernel.hpp>
  14. #include <opencv2/gapi/ocl/core.hpp>
  15. #include <opencv2/gapi/ocl/imgproc.hpp>
  16. #include <opencv2/gapi/streaming/cap.hpp>
  17. #include <opencv2/gapi/streaming/desync.hpp>
  18. #include <opencv2/gapi/streaming/format.hpp>
  19. #include <opencv2/gapi/gstreaming.hpp>
  20. namespace opencv_test
  21. {
  22. namespace
  23. {
  24. enum class KernelPackage: int
  25. {
  26. OCV,
  27. OCV_FLUID,
  28. OCL,
  29. OCL_FLUID,
  30. };
  31. std::ostream& operator<< (std::ostream &os, const KernelPackage &e)
  32. {
  33. switch (e)
  34. {
  35. #define _C(X) case KernelPackage::X: os << #X; break
  36. _C(OCV);
  37. _C(OCV_FLUID);
  38. _C(OCL);
  39. _C(OCL_FLUID);
  40. #undef _C
  41. default: GAPI_Assert(false);
  42. }
  43. return os;
  44. }
  45. struct GAPI_Streaming: public ::testing::TestWithParam<std::tuple<KernelPackage,
  46. cv::optional<size_t>>> {
  47. GAPI_Streaming() {
  48. KernelPackage pkg_kind;
  49. std::tie(pkg_kind, cap) = GetParam();
  50. pkg = getKernelPackage(pkg_kind);
  51. }
  52. const cv::optional<size_t>& getQueueCapacity()
  53. {
  54. return cap;
  55. }
  56. cv::GKernelPackage getKernelPackage(KernelPackage pkg_kind)
  57. {
  58. using namespace cv::gapi;
  59. switch (pkg_kind)
  60. {
  61. case KernelPackage::OCV:
  62. return cv::gapi::combine(core::cpu::kernels(),
  63. imgproc::cpu::kernels());
  64. break;
  65. case KernelPackage::OCV_FLUID:
  66. return cv::gapi::combine(core::cpu::kernels(),
  67. imgproc::cpu::kernels(),
  68. core::fluid::kernels());
  69. break;
  70. // FIXME: OpenCL backend seem to work fine with Streaming
  71. // however the results are not very bit exact with CPU
  72. // It may be a problem but may be just implementation innacuracy.
  73. // Need to customize the comparison function in tests where OpenCL
  74. // is involved.
  75. case KernelPackage::OCL:
  76. return cv::gapi::combine(core::ocl::kernels(),
  77. imgproc::ocl::kernels());
  78. break;
  79. case KernelPackage::OCL_FLUID:
  80. return cv::gapi::combine(core::ocl::kernels(),
  81. imgproc::ocl::kernels(),
  82. core::fluid::kernels());
  83. break;
  84. }
  85. throw std::logic_error("Unknown package");
  86. }
  87. cv::GCompileArgs getCompileArgs() {
  88. using namespace cv::gapi;
  89. auto args = cv::compile_args(use_only{pkg});
  90. if (cap) {
  91. args += cv::compile_args(cv::gapi::streaming::queue_capacity{cap.value()});
  92. }
  93. return args;
  94. }
  95. cv::GKernelPackage pkg;
  96. cv::optional<size_t> cap;
  97. };
  98. G_API_OP(Delay, <cv::GMat(cv::GMat, int)>, "org.opencv.test.delay") {
  99. static cv::GMatDesc outMeta(const cv::GMatDesc &in, int) { return in; }
  100. };
  101. GAPI_OCV_KERNEL(OCVDelay, Delay) {
  102. static void run(const cv::Mat &in, int ms, cv::Mat &out) {
  103. std::this_thread::sleep_for(std::chrono::milliseconds{ms});
  104. in.copyTo(out);
  105. }
  106. };
  107. class TestMediaBGR final: public cv::MediaFrame::IAdapter {
  108. cv::Mat m_mat;
  109. using Cb = cv::MediaFrame::View::Callback;
  110. Cb m_cb;
  111. public:
  112. explicit TestMediaBGR(cv::Mat m, Cb cb = [](){})
  113. : m_mat(m), m_cb(cb) {
  114. }
  115. cv::GFrameDesc meta() const override {
  116. return cv::GFrameDesc{cv::MediaFormat::BGR, cv::Size(m_mat.cols, m_mat.rows)};
  117. }
  118. cv::MediaFrame::View access(cv::MediaFrame::Access) override {
  119. cv::MediaFrame::View::Ptrs pp = { m_mat.ptr(), nullptr, nullptr, nullptr };
  120. cv::MediaFrame::View::Strides ss = { m_mat.step, 0u, 0u, 0u };
  121. return cv::MediaFrame::View(std::move(pp), std::move(ss), Cb{m_cb});
  122. }
  123. };
  124. class TestMediaNV12 final: public cv::MediaFrame::IAdapter {
  125. cv::Mat m_y;
  126. cv::Mat m_uv;
  127. public:
  128. TestMediaNV12(cv::Mat y, cv::Mat uv) : m_y(y), m_uv(uv) {
  129. }
  130. cv::GFrameDesc meta() const override {
  131. return cv::GFrameDesc{cv::MediaFormat::NV12, m_y.size()};
  132. }
  133. cv::MediaFrame::View access(cv::MediaFrame::Access) override {
  134. cv::MediaFrame::View::Ptrs pp = {
  135. m_y.ptr(), m_uv.ptr(), nullptr, nullptr
  136. };
  137. cv::MediaFrame::View::Strides ss = {
  138. m_y.step, m_uv.step, 0u, 0u
  139. };
  140. return cv::MediaFrame::View(std::move(pp), std::move(ss));
  141. }
  142. };
  143. class TestMediaGRAY final : public cv::MediaFrame::IAdapter {
  144. cv::Mat m_mat;
  145. using Cb = cv::MediaFrame::View::Callback;
  146. Cb m_cb;
  147. public:
  148. explicit TestMediaGRAY(cv::Mat m, Cb cb = []() {})
  149. : m_mat(m), m_cb(cb) {
  150. }
  151. cv::GFrameDesc meta() const override {
  152. return cv::GFrameDesc{ cv::MediaFormat::GRAY, cv::Size(m_mat.cols, m_mat.rows) };
  153. }
  154. cv::MediaFrame::View access(cv::MediaFrame::Access) override {
  155. cv::MediaFrame::View::Ptrs pp = { m_mat.ptr(), nullptr, nullptr, nullptr };
  156. cv::MediaFrame::View::Strides ss = { m_mat.step, 0u, 0u, 0u };
  157. return cv::MediaFrame::View(std::move(pp), std::move(ss), Cb{ m_cb });
  158. }
  159. };
  160. class BGRSource : public cv::gapi::wip::GCaptureSource {
  161. public:
  162. explicit BGRSource(const std::string& pipeline)
  163. : cv::gapi::wip::GCaptureSource(pipeline) {
  164. }
  165. bool pull(cv::gapi::wip::Data& data) {
  166. if (cv::gapi::wip::GCaptureSource::pull(data)) {
  167. data = cv::MediaFrame::Create<TestMediaBGR>(cv::util::get<cv::Mat>(data));
  168. return true;
  169. }
  170. return false;
  171. }
  172. GMetaArg descr_of() const override {
  173. return cv::GMetaArg{cv::GFrameDesc{cv::MediaFormat::BGR,
  174. cv::util::get<cv::GMatDesc>(
  175. cv::gapi::wip::GCaptureSource::descr_of()).size}};
  176. }
  177. };
  178. void cvtBGR2NV12(const cv::Mat& bgr, cv::Mat& y, cv::Mat& uv) {
  179. cv::Size frame_sz = bgr.size();
  180. cv::Size half_sz = frame_sz / 2;
  181. cv::Mat yuv;
  182. cv::cvtColor(bgr, yuv, cv::COLOR_BGR2YUV_I420);
  183. // Copy Y plane
  184. yuv.rowRange(0, frame_sz.height).copyTo(y);
  185. // Merge sampled U and V planes
  186. std::vector<int> dims = {half_sz.height, half_sz.width};
  187. auto start = frame_sz.height;
  188. auto range_h = half_sz.height/2;
  189. std::vector<cv::Mat> uv_planes = {
  190. yuv.rowRange(start, start + range_h) .reshape(0, dims),
  191. yuv.rowRange(start + range_h, start + range_h*2).reshape(0, dims)
  192. };
  193. cv::merge(uv_planes, uv);
  194. }
  195. class NV12Source : public cv::gapi::wip::GCaptureSource {
  196. public:
  197. explicit NV12Source(const std::string& pipeline)
  198. : cv::gapi::wip::GCaptureSource(pipeline) {
  199. }
  200. bool pull(cv::gapi::wip::Data& data) {
  201. if (cv::gapi::wip::GCaptureSource::pull(data)) {
  202. cv::Mat bgr = cv::util::get<cv::Mat>(data);
  203. cv::Mat y, uv;
  204. cvtBGR2NV12(bgr, y, uv);
  205. data = cv::MediaFrame::Create<TestMediaNV12>(y, uv);
  206. return true;
  207. }
  208. return false;
  209. }
  210. GMetaArg descr_of() const override {
  211. return cv::GMetaArg{cv::GFrameDesc{cv::MediaFormat::NV12,
  212. cv::util::get<cv::GMatDesc>(
  213. cv::gapi::wip::GCaptureSource::descr_of()).size}};
  214. }
  215. };
  216. class GRAYSource : public cv::gapi::wip::GCaptureSource {
  217. public:
  218. explicit GRAYSource(const std::string& pipeline)
  219. : cv::gapi::wip::GCaptureSource(pipeline) {
  220. }
  221. bool pull(cv::gapi::wip::Data& data) {
  222. if (cv::gapi::wip::GCaptureSource::pull(data)) {
  223. cv::Mat bgr = cv::util::get<cv::Mat>(data);
  224. cv::Mat gray;
  225. cvtColor(bgr, gray, cv::COLOR_BGR2GRAY);
  226. data = cv::MediaFrame::Create<TestMediaGRAY>(gray);
  227. return true;
  228. }
  229. return false;
  230. }
  231. GMetaArg descr_of() const override {
  232. return cv::GMetaArg{ cv::GFrameDesc{cv::MediaFormat::GRAY,
  233. cv::util::get<cv::GMatDesc>(
  234. cv::gapi::wip::GCaptureSource::descr_of()).size} };
  235. }
  236. };
  237. void checkPullOverload(const cv::Mat& ref,
  238. const bool has_output,
  239. cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>& args) {
  240. EXPECT_TRUE(has_output);
  241. using runArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
  242. cv::Mat out_mat;
  243. switch (args.index()) {
  244. case runArgs::index_of<cv::GRunArgs>():
  245. {
  246. auto outputs = util::get<cv::GRunArgs>(args);
  247. EXPECT_EQ(1u, outputs.size());
  248. out_mat = cv::util::get<cv::Mat>(outputs[0]);
  249. break;
  250. }
  251. case runArgs::index_of<cv::GOptRunArgs>():
  252. {
  253. auto outputs = util::get<cv::GOptRunArgs>(args);
  254. EXPECT_EQ(1u, outputs.size());
  255. auto opt_mat = cv::util::get<cv::optional<cv::Mat>>(outputs[0]);
  256. ASSERT_TRUE(opt_mat.has_value());
  257. out_mat = *opt_mat;
  258. break;
  259. }
  260. default: GAPI_Assert(false && "Incorrect type of Args");
  261. }
  262. EXPECT_EQ(0., cv::norm(ref, out_mat, cv::NORM_INF));
  263. }
  264. } // anonymous namespace
  265. TEST_P(GAPI_Streaming, SmokeTest_ConstInput_GMat)
  266. {
  267. // This graph models the following use-case:
  268. // Canny here is used as some "feature detector"
  269. //
  270. // Island/device layout may be different given the contents
  271. // of the passed kernel package.
  272. //
  273. // The expectation is that we get as much islands in the
  274. // graph as backends the GKernelPackage contains.
  275. //
  276. // [Capture] --> Crop --> Resize --> Canny --> [out]
  277. const auto crop_rc = cv::Rect(13, 75, 377, 269);
  278. const auto resample_sz = cv::Size(224, 224);
  279. const auto thr_lo = 64.;
  280. const auto thr_hi = 192.;
  281. cv::GMat in;
  282. auto roi = cv::gapi::crop(in, crop_rc);
  283. auto res = cv::gapi::resize(roi, resample_sz);
  284. auto out = cv::gapi::Canny(res, thr_lo, thr_hi);
  285. cv::GComputation c(in, out);
  286. // Input data
  287. cv::Mat in_mat = cv::imread(findDataFile("cv/edgefilter/kodim23.png"));
  288. cv::Mat out_mat_gapi;
  289. // OpenCV reference image
  290. cv::Mat out_mat_ocv;
  291. {
  292. cv::Mat tmp;
  293. cv::resize(in_mat(crop_rc), tmp, resample_sz);
  294. cv::Canny(tmp, out_mat_ocv, thr_lo, thr_hi);
  295. }
  296. // Compilation & testing
  297. auto ccomp = c.compileStreaming(cv::descr_of(in_mat), getCompileArgs());
  298. EXPECT_TRUE(ccomp);
  299. EXPECT_FALSE(ccomp.running());
  300. ccomp.setSource(cv::gin(in_mat));
  301. ccomp.start();
  302. EXPECT_TRUE(ccomp.running());
  303. // Fetch the result 15 times
  304. for (int i = 0; i < 15; i++) {
  305. // With constant inputs, the stream is endless so
  306. // the blocking pull() should never return `false`.
  307. EXPECT_TRUE(ccomp.pull(cv::gout(out_mat_gapi)));
  308. // Fluid's and OpenCV's Resizes aren't bit exact.
  309. // So 1% is here because it is max difference between them.
  310. EXPECT_TRUE(AbsSimilarPoints(0, 1).to_compare_f()(out_mat_gapi, out_mat_ocv));
  311. }
  312. EXPECT_TRUE(ccomp.running());
  313. ccomp.stop();
  314. EXPECT_FALSE(ccomp.running());
  315. }
  316. TEST_P(GAPI_Streaming, SmokeTest_VideoInput_GMat)
  317. {
  318. const auto crop_rc = cv::Rect(13, 75, 377, 269);
  319. const auto resample_sz = cv::Size(224, 224);
  320. const auto thr_lo = 64.;
  321. const auto thr_hi = 192.;
  322. cv::GMat in;
  323. auto roi = cv::gapi::crop(in, crop_rc);
  324. auto res = cv::gapi::resize(roi, resample_sz);
  325. auto out = cv::gapi::Canny(res, thr_lo, thr_hi);
  326. cv::GComputation c(cv::GIn(in), cv::GOut(cv::gapi::copy(in), out));
  327. // OpenCV reference image code
  328. auto opencv_ref = [&](const cv::Mat &in_mat, cv::Mat &out_mat) {
  329. cv::Mat tmp;
  330. cv::resize(in_mat(crop_rc), tmp, resample_sz);
  331. cv::Canny(tmp, out_mat, thr_lo, thr_hi);
  332. };
  333. // Compilation & testing
  334. auto ccomp = c.compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  335. getCompileArgs());
  336. EXPECT_TRUE(ccomp);
  337. EXPECT_FALSE(ccomp.running());
  338. auto path = findDataFile("cv/video/768x576.avi");
  339. try {
  340. ccomp.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path));
  341. } catch(...) {
  342. throw SkipTestException("Video file can not be opened");
  343. }
  344. ccomp.start();
  345. EXPECT_TRUE(ccomp.running());
  346. // Process the full video
  347. cv::Mat in_mat_gapi, out_mat_gapi;
  348. std::size_t frames = 0u;
  349. while (ccomp.pull(cv::gout(in_mat_gapi, out_mat_gapi))) {
  350. frames++;
  351. cv::Mat out_mat_ocv;
  352. opencv_ref(in_mat_gapi, out_mat_ocv);
  353. // Fluid's and OpenCV's Resizes aren't bit exact.
  354. // So 1% is here because it is max difference between them.
  355. EXPECT_TRUE(AbsSimilarPoints(0, 1).to_compare_f()(out_mat_gapi, out_mat_ocv));
  356. }
  357. EXPECT_LT(0u, frames);
  358. EXPECT_FALSE(ccomp.running());
  359. // Stop can be called at any time (even if the pipeline is not running)
  360. ccomp.stop();
  361. EXPECT_FALSE(ccomp.running());
  362. }
  363. TEST_P(GAPI_Streaming, Regression_CompileTimeScalar)
  364. {
  365. // There was a bug with compile-time GScalars. Compile-time
  366. // GScalars generate their own DATA nodes at GModel/GIslandModel
  367. // level, resulting in an extra link at the GIslandModel level, so
  368. // GStreamingExecutor automatically assigned an input queue to
  369. // such edges. Since there were no in-graph producer for that
  370. // data, no data were pushed to such queue what lead to a
  371. // deadlock.
  372. cv::GMat in;
  373. cv::GMat tmp = cv::gapi::copy(in);
  374. for (int i = 0; i < 3; i++) {
  375. tmp = tmp & cv::gapi::blur(in, cv::Size(3,3));
  376. }
  377. cv::GComputation c(cv::GIn(in), cv::GOut(tmp, tmp + 1));
  378. auto ccomp = c.compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,512}},
  379. getCompileArgs());
  380. cv::Mat in_mat = cv::imread(findDataFile("cv/edgefilter/kodim23.png"));
  381. cv::Mat out_mat1, out_mat2;
  382. // Fetch the result 15 times
  383. ccomp.setSource(cv::gin(in_mat));
  384. ccomp.start();
  385. for (int i = 0; i < 15; i++) {
  386. EXPECT_TRUE(ccomp.pull(cv::gout(out_mat1, out_mat2)));
  387. }
  388. ccomp.stop();
  389. }
  390. TEST_P(GAPI_Streaming, SmokeTest_StartRestart)
  391. {
  392. cv::GMat in;
  393. auto res = cv::gapi::resize(in, cv::Size{300,200});
  394. auto out = cv::gapi::Canny(res, 95, 220);
  395. cv::GComputation c(cv::GIn(in), cv::GOut(cv::gapi::copy(in), out));
  396. auto ccomp = c.compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  397. getCompileArgs());
  398. EXPECT_TRUE(ccomp);
  399. EXPECT_FALSE(ccomp.running());
  400. // Run 1
  401. auto path = findDataFile("cv/video/768x576.avi");
  402. std::size_t num_frames1 = 0u;
  403. try {
  404. ccomp.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path));
  405. } catch(...) {
  406. throw SkipTestException("Video file can not be opened");
  407. }
  408. ccomp.start();
  409. EXPECT_TRUE(ccomp.running());
  410. cv::Mat out1, out2;
  411. while (ccomp.pull(cv::gout(out1, out2))) num_frames1++;
  412. EXPECT_FALSE(ccomp.running());
  413. // Run 2
  414. std::size_t num_frames2 = 0u;
  415. try {
  416. ccomp.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path));
  417. } catch(...) {
  418. throw SkipTestException("Video file can not be opened");
  419. }
  420. ccomp.start();
  421. EXPECT_TRUE(ccomp.running());
  422. while (ccomp.pull(cv::gout(out1, out2))) num_frames2++;
  423. EXPECT_FALSE(ccomp.running());
  424. EXPECT_LT(0u, num_frames1);
  425. EXPECT_LT(0u, num_frames2);
  426. EXPECT_EQ(num_frames1, num_frames2);
  427. }
  428. TEST_P(GAPI_Streaming, SmokeTest_VideoConstSource_NoHang)
  429. {
  430. // A video source is a finite one, while const source is not.
  431. // Check that pipeline completes when a video source completes.
  432. auto refc = cv::GComputation([](){
  433. cv::GMat in;
  434. return cv::GComputation(in, cv::gapi::copy(in));
  435. }).compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}}, getCompileArgs());
  436. auto path = findDataFile("cv/video/768x576.avi");
  437. try {
  438. refc.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path));
  439. } catch(...) {
  440. throw SkipTestException("Video file can not be opened");
  441. }
  442. refc.start();
  443. std::size_t ref_frames = 0u;
  444. cv::Mat tmp;
  445. while (refc.pull(cv::gout(tmp))) ref_frames++;
  446. EXPECT_EQ(100u, ref_frames);
  447. cv::GMat in;
  448. cv::GMat in2;
  449. cv::GMat roi = cv::gapi::crop(in2, cv::Rect{1,1,256,256});
  450. cv::GMat blr = cv::gapi::blur(roi, cv::Size(3,3));
  451. cv::GMat out = blr - in;
  452. auto testc = cv::GComputation(cv::GIn(in, in2), cv::GOut(out))
  453. .compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{256,256}},
  454. cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  455. getCompileArgs());
  456. cv::Mat in_const = cv::Mat::eye(cv::Size(256,256), CV_8UC3);
  457. testc.setSource(cv::gin(in_const,
  458. gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  459. testc.start();
  460. std::size_t test_frames = 0u;
  461. while (testc.pull(cv::gout(tmp))) test_frames++;
  462. EXPECT_EQ(ref_frames, test_frames);
  463. }
  464. TEST_P(GAPI_Streaming, SmokeTest_AutoMeta)
  465. {
  466. cv::GMat in;
  467. cv::GMat in2;
  468. cv::GMat roi = cv::gapi::crop(in2, cv::Rect{1,1,256,256});
  469. cv::GMat blr = cv::gapi::blur(roi, cv::Size(3,3));
  470. cv::GMat out = blr - in;
  471. auto testc = cv::GComputation(cv::GIn(in, in2), cv::GOut(out))
  472. .compileStreaming(getCompileArgs());
  473. cv::Mat in_const = cv::Mat::eye(cv::Size(256,256), CV_8UC3);
  474. cv::Mat tmp;
  475. // Test with one video source
  476. auto path = findDataFile("cv/video/768x576.avi");
  477. try {
  478. testc.setSource(cv::gin(in_const, gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  479. } catch(...) {
  480. throw SkipTestException("Video file can not be opened");
  481. }
  482. testc.start();
  483. std::size_t test_frames = 0u;
  484. while (testc.pull(cv::gout(tmp))) test_frames++;
  485. EXPECT_EQ(100u, test_frames);
  486. // Now test with another one
  487. path = findDataFile("cv/video/1920x1080.avi");
  488. try {
  489. testc.setSource(cv::gin(in_const, gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  490. } catch(...) {
  491. throw SkipTestException("Video file can not be opened");
  492. }
  493. testc.start();
  494. test_frames = 0u;
  495. while (testc.pull(cv::gout(tmp))) test_frames++;
  496. EXPECT_EQ(165u, test_frames);
  497. }
  498. TEST_P(GAPI_Streaming, SmokeTest_AutoMeta_2xConstMat)
  499. {
  500. cv::GMat in;
  501. cv::GMat in2;
  502. cv::GMat roi = cv::gapi::crop(in2, cv::Rect{1,1,256,256});
  503. cv::GMat blr = cv::gapi::blur(roi, cv::Size(3,3));
  504. cv::GMat out = blr - in;
  505. auto testc = cv::GComputation(cv::GIn(in, in2), cv::GOut(out))
  506. .compileStreaming(getCompileArgs());
  507. cv::Mat in_const = cv::Mat::eye(cv::Size(256,256), CV_8UC3);
  508. cv::Mat tmp;
  509. // Test with first image
  510. auto in_src = cv::imread(findDataFile("cv/edgefilter/statue.png"));
  511. testc.setSource(cv::gin(in_const, in_src));
  512. testc.start();
  513. ASSERT_TRUE(testc.pull(cv::gout(tmp)));
  514. testc.stop();
  515. // Now test with second image
  516. in_src = cv::imread(findDataFile("cv/edgefilter/kodim23.png"));
  517. testc.setSource(cv::gin(in_const, in_src));
  518. testc.start();
  519. ASSERT_TRUE(testc.pull(cv::gout(tmp)));
  520. testc.stop();
  521. }
  522. TEST_P(GAPI_Streaming, SmokeTest_AutoMeta_VideoScalar)
  523. {
  524. cv::GMat in_m;
  525. cv::GScalar in_s;
  526. cv::GMat out_m = in_m * in_s;
  527. auto testc = cv::GComputation(cv::GIn(in_m, in_s), cv::GOut(out_m))
  528. .compileStreaming(getCompileArgs());
  529. cv::Mat tmp;
  530. // Test with one video source and scalar
  531. auto path = findDataFile("cv/video/768x576.avi");
  532. try {
  533. testc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path), cv::Scalar{1.25}));
  534. } catch(...) {
  535. throw SkipTestException("Video file can not be opened");
  536. }
  537. testc.start();
  538. std::size_t test_frames = 0u;
  539. while (testc.pull(cv::gout(tmp))) test_frames++;
  540. EXPECT_EQ(100u, test_frames);
  541. // Now test with another one video source and scalar
  542. path = findDataFile("cv/video/1920x1080.avi");
  543. try {
  544. testc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path), cv::Scalar{0.75}));
  545. } catch(...) {
  546. throw SkipTestException("Video file can not be opened");
  547. }
  548. testc.start();
  549. test_frames = 0u;
  550. while (testc.pull(cv::gout(tmp))) test_frames++;
  551. EXPECT_EQ(165u, test_frames);
  552. }
  553. INSTANTIATE_TEST_CASE_P(TestStreaming, GAPI_Streaming,
  554. Combine(Values( KernelPackage::OCV
  555. //, KernelPackage::OCL // FIXME: Fails bit-exactness check, maybe relax it?
  556. , KernelPackage::OCV_FLUID
  557. //, KernelPackage::OCL // FIXME: Fails bit-exactness check, maybe relax it?
  558. ),
  559. Values(cv::optional<size_t>{}, 1u, 4u))
  560. );
  561. namespace TypesTest
  562. {
  563. G_API_OP(SumV, <cv::GArray<int>(cv::GMat)>, "test.gapi.sumv") {
  564. static cv::GArrayDesc outMeta(const cv::GMatDesc &) {
  565. return cv::empty_array_desc();
  566. }
  567. };
  568. G_API_OP(AddV, <cv::GMat(cv::GMat,cv::GArray<int>)>, "test.gapi.addv") {
  569. static cv::GMatDesc outMeta(const cv::GMatDesc &in, const cv::GArrayDesc &) {
  570. return in;
  571. }
  572. };
  573. GAPI_OCV_KERNEL(OCVSumV, SumV) {
  574. static void run(const cv::Mat &in, std::vector<int> &out) {
  575. CV_Assert(in.depth() == CV_8U);
  576. const auto length = in.cols * in.channels();
  577. out.resize(length);
  578. const uchar *ptr = in.ptr(0);
  579. for (int c = 0; c < length; c++) {
  580. out[c] = ptr[c];
  581. }
  582. for (int r = 1; r < in.rows; r++) {
  583. ptr = in.ptr(r);
  584. for (int c = 0; c < length; c++) {
  585. out[c] += ptr[c];
  586. }
  587. }
  588. }
  589. };
  590. GAPI_OCV_KERNEL(OCVAddV, AddV) {
  591. static void run(const cv::Mat &in, const std::vector<int> &inv, cv::Mat &out) {
  592. CV_Assert(in.depth() == CV_8U);
  593. const auto length = in.cols * in.channels();
  594. CV_Assert(length == static_cast<int>(inv.size()));
  595. for (int r = 0; r < in.rows; r++) {
  596. const uchar *in_ptr = in.ptr(r);
  597. uchar *out_ptr = out.ptr(r);
  598. for (int c = 0; c < length; c++) {
  599. out_ptr[c] = cv::saturate_cast<uchar>(in_ptr[c] + inv[c]);
  600. }
  601. }
  602. }
  603. };
  604. GAPI_FLUID_KERNEL(FluidAddV, AddV, false) {
  605. static const int Window = 1;
  606. static void run(const cv::gapi::fluid::View &in,
  607. const std::vector<int> &inv,
  608. cv::gapi::fluid::Buffer &out) {
  609. const uchar *in_ptr = in.InLineB(0);
  610. uchar *out_ptr = out.OutLineB(0);
  611. const auto length = in.meta().size.width * in.meta().chan;
  612. CV_Assert(length == static_cast<int>(inv.size()));
  613. for (int c = 0; c < length; c++) {
  614. out_ptr[c] = cv::saturate_cast<uchar>(in_ptr[c] + inv[c]);
  615. }
  616. }
  617. };
  618. } // namespace TypesTest
  619. TEST_P(GAPI_Streaming, SmokeTest_AutoMeta_VideoArray)
  620. {
  621. cv::GMat in_m;
  622. cv::GArray<int> in_v;
  623. cv::GMat out_m = TypesTest::AddV::on(in_m, in_v) - in_m;
  624. // Run pipeline
  625. auto args = cv::compile_args(cv::gapi::kernels<TypesTest::OCVAddV>());
  626. auto capacity = getQueueCapacity();
  627. if (capacity)
  628. {
  629. args += cv::compile_args(
  630. cv::gapi::streaming::queue_capacity{capacity.value()});
  631. }
  632. auto testc = cv::GComputation(cv::GIn(in_m, in_v), cv::GOut(out_m))
  633. .compileStreaming(std::move(args));
  634. cv::Mat tmp;
  635. // Test with one video source and vector
  636. auto path = findDataFile("cv/video/768x576.avi");
  637. std::vector<int> first_in_vec(768*3, 1);
  638. try {
  639. testc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path), first_in_vec));
  640. } catch(...) {
  641. throw SkipTestException("Video file can not be opened");
  642. }
  643. testc.start();
  644. std::size_t test_frames = 0u;
  645. while (testc.pull(cv::gout(tmp))) test_frames++;
  646. EXPECT_EQ(100u, test_frames);
  647. // Now test with another one
  648. path = findDataFile("cv/video/1920x1080.avi");
  649. std::vector<int> second_in_vec(1920*3, 1);
  650. try {
  651. testc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path), second_in_vec));
  652. } catch(...) {
  653. throw SkipTestException("Video file can not be opened");
  654. }
  655. testc.start();
  656. test_frames = 0u;
  657. while (testc.pull(cv::gout(tmp))) test_frames++;
  658. EXPECT_EQ(165u, test_frames);
  659. }
  660. TEST(GAPI_Streaming_Types, InputScalar)
  661. {
  662. // This test verifies if Streaming works with Scalar data @ input.
  663. cv::GMat in_m;
  664. cv::GScalar in_s;
  665. cv::GMat out_m = in_m * in_s;
  666. cv::GComputation c(cv::GIn(in_m, in_s), cv::GOut(out_m));
  667. // Input data
  668. cv::Mat in_mat = cv::Mat::eye(256, 256, CV_8UC1);
  669. cv::Scalar in_scl = 32;
  670. // Run pipeline
  671. auto sc = c.compileStreaming(cv::descr_of(in_mat), cv::descr_of(in_scl));
  672. sc.setSource(cv::gin(in_mat, in_scl));
  673. sc.start();
  674. for (int i = 0; i < 10; i++)
  675. {
  676. cv::Mat out;
  677. EXPECT_TRUE(sc.pull(cv::gout(out)));
  678. EXPECT_EQ(0., cv::norm(out, in_mat.mul(in_scl), cv::NORM_INF));
  679. }
  680. }
  681. TEST(GAPI_Streaming_Types, InputVector)
  682. {
  683. // This test verifies if Streaming works with Vector data @ input.
  684. cv::GMat in_m;
  685. cv::GArray<int> in_v;
  686. cv::GMat out_m = TypesTest::AddV::on(in_m, in_v) - in_m;
  687. cv::GComputation c(cv::GIn(in_m, in_v), cv::GOut(out_m));
  688. // Input data
  689. cv::Mat in_mat = cv::Mat::eye(256, 256, CV_8UC1);
  690. std::vector<int> in_vec;
  691. TypesTest::OCVSumV::run(in_mat, in_vec);
  692. EXPECT_EQ(std::vector<int>(256,1), in_vec); // self-sanity-check
  693. auto opencv_ref = [&](const cv::Mat &in, const std::vector<int> &inv, cv::Mat &out) {
  694. cv::Mat tmp = in_mat.clone(); // allocate the same amount of memory as graph does
  695. TypesTest::OCVAddV::run(in, inv, tmp);
  696. out = tmp - in;
  697. };
  698. // Run pipeline
  699. auto sc = c.compileStreaming(cv::descr_of(in_mat),
  700. cv::descr_of(in_vec),
  701. cv::compile_args(cv::gapi::kernels<TypesTest::OCVAddV>()));
  702. sc.setSource(cv::gin(in_mat, in_vec));
  703. sc.start();
  704. for (int i = 0; i < 10; i++)
  705. {
  706. cv::Mat out_mat;
  707. EXPECT_TRUE(sc.pull(cv::gout(out_mat)));
  708. cv::Mat ref_mat;
  709. opencv_ref(in_mat, in_vec, ref_mat);
  710. EXPECT_EQ(0., cv::norm(ref_mat, out_mat, cv::NORM_INF));
  711. }
  712. }
  713. TEST(GAPI_Streaming_Types, XChangeScalar)
  714. {
  715. // This test verifies if Streaming works when pipeline steps
  716. // (islands) exchange Scalar data.
  717. cv::GMat in;
  718. cv::GScalar m = cv::gapi::mean(in);
  719. cv::GMat tmp = cv::gapi::convertTo(in, CV_32F) - m;
  720. cv::GMat out = cv::gapi::blur(tmp, cv::Size(3,3));
  721. cv::GComputation c(cv::GIn(in), cv::GOut(cv::gapi::copy(in),
  722. cv::gapi::convertTo(out, CV_8U)));
  723. auto ocv_ref = [](const cv::Mat &in_mat, cv::Mat &out_mat) {
  724. cv::Scalar ocv_m = cv::mean(in_mat);
  725. cv::Mat ocv_tmp;
  726. in_mat.convertTo(ocv_tmp, CV_32F);
  727. ocv_tmp -= ocv_m;
  728. cv::blur(ocv_tmp, ocv_tmp, cv::Size(3,3));
  729. ocv_tmp.convertTo(out_mat, CV_8U);
  730. };
  731. // Here we want mean & convertTo run on OCV
  732. // and subC & blur3x3 on Fluid.
  733. // FIXME: With the current API it looks quite awful:
  734. auto ocv_kernels = cv::gapi::core::cpu::kernels(); // convertTo
  735. ocv_kernels.remove<cv::gapi::core::GSubC>();
  736. auto fluid_kernels = cv::gapi::combine(cv::gapi::core::fluid::kernels(), // subC
  737. cv::gapi::imgproc::fluid::kernels()); // box3x3
  738. fluid_kernels.remove<cv::gapi::core::GConvertTo>();
  739. fluid_kernels.remove<cv::gapi::core::GMean>();
  740. // FIXME: Now
  741. // - fluid kernels take over ocv kernels (including Copy, SubC, & Box3x3)
  742. // - selected kernels (which were removed from the fluid package) remain in OCV
  743. // (ConvertTo + some others)
  744. // FIXME: This is completely awful. User should easily pick up specific kernels
  745. // to an empty kernel package to craft his own but not do it via exclusion.
  746. // Need to expose kernel declarations to public headers to enable kernels<..>()
  747. // on user side.
  748. auto kernels = cv::gapi::combine(ocv_kernels, fluid_kernels);
  749. // Compile streaming pipeline
  750. auto sc = c.compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  751. cv::compile_args(cv::gapi::use_only{kernels}));
  752. auto path = findDataFile("cv/video/768x576.avi");
  753. try {
  754. sc.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path));
  755. } catch(...) {
  756. throw SkipTestException("Video file can not be opened");
  757. }
  758. sc.start();
  759. cv::Mat in_frame;
  760. cv::Mat out_mat_gapi;
  761. cv::Mat out_mat_ref;
  762. std::size_t num_frames = 0u;
  763. while (sc.pull(cv::gout(in_frame, out_mat_gapi))) {
  764. num_frames++;
  765. ocv_ref(in_frame, out_mat_ref);
  766. EXPECT_EQ(0., cv::norm(out_mat_gapi, out_mat_ref, cv::NORM_INF));
  767. }
  768. EXPECT_LT(0u, num_frames);
  769. }
  770. TEST(GAPI_Streaming_Types, XChangeVector)
  771. {
  772. // This test verifies if Streaming works when pipeline steps
  773. // (islands) exchange Vector data.
  774. cv::GMat in1, in2;
  775. cv::GMat in = cv::gapi::crop(in1, cv::Rect{0,0,576,576});
  776. cv::GScalar m = cv::gapi::mean(in);
  777. cv::GArray<int> s = TypesTest::SumV::on(in2); // (in2 = eye, so s = [1,0,0,1,..])
  778. cv::GMat out = TypesTest::AddV::on(in - m, s);
  779. cv::GComputation c(cv::GIn(in1, in2), cv::GOut(cv::gapi::copy(in), out));
  780. auto ocv_ref = [](const cv::Mat &in_mat1, const cv::Mat &in_mat2, cv::Mat &out_mat) {
  781. cv::Mat in_roi = in_mat1(cv::Rect{0,0,576,576});
  782. cv::Scalar ocv_m = cv::mean(in_roi);
  783. std::vector<int> ocv_v;
  784. TypesTest::OCVSumV::run(in_mat2, ocv_v);
  785. out_mat.create(cv::Size(576,576), CV_8UC3);
  786. cv::Mat in_tmp = in_roi - ocv_m;
  787. TypesTest::OCVAddV::run(in_tmp, ocv_v, out_mat);
  788. };
  789. // Let crop/mean/sumV be calculated via OCV,
  790. // and AddV/subC be calculated via Fluid
  791. auto ocv_kernels = cv::gapi::core::cpu::kernels();
  792. ocv_kernels.remove<cv::gapi::core::GSubC>();
  793. ocv_kernels.include<TypesTest::OCVSumV>();
  794. auto fluid_kernels = cv::gapi::core::fluid::kernels();
  795. fluid_kernels.include<TypesTest::FluidAddV>();
  796. // Here OCV takes precedense over Fluid, with SubC & SumV remaining
  797. // in Fluid.
  798. auto kernels = cv::gapi::combine(fluid_kernels, ocv_kernels);
  799. // Compile streaming pipeline
  800. cv::Mat in_eye = cv::Mat::eye(cv::Size(576, 576), CV_8UC3);
  801. auto sc = c.compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  802. cv::GMatDesc{CV_8U,3,cv::Size{576,576}},
  803. cv::compile_args(cv::gapi::use_only{kernels}));
  804. auto path = findDataFile("cv/video/768x576.avi");
  805. try {
  806. sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path),
  807. in_eye));
  808. } catch(...) {
  809. throw SkipTestException("Video file can not be opened");
  810. }
  811. sc.start();
  812. cv::Mat in_frame;
  813. cv::Mat out_mat_gapi;
  814. cv::Mat out_mat_ref;
  815. std::size_t num_frames = 0u;
  816. while (sc.pull(cv::gout(in_frame, out_mat_gapi))) {
  817. num_frames++;
  818. ocv_ref(in_frame, in_eye, out_mat_ref);
  819. EXPECT_EQ(0., cv::norm(out_mat_gapi, out_mat_ref, cv::NORM_INF));
  820. }
  821. EXPECT_LT(0u, num_frames);
  822. }
  823. TEST(GAPI_Streaming_Types, OutputScalar)
  824. {
  825. // This test verifies if Streaming works when pipeline
  826. // produces scalar data only
  827. cv::GMat in;
  828. cv::GScalar out = cv::gapi::mean(in);
  829. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(out))
  830. .compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}});
  831. std::string video_path;
  832. video_path = findDataFile("cv/video/768x576.avi");
  833. try {
  834. sc.setSource(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(video_path));
  835. } catch(...) {
  836. throw SkipTestException("Video file can not be opened");
  837. }
  838. sc.start();
  839. cv::VideoCapture cap;
  840. cap.open(video_path);
  841. if (!cap.isOpened())
  842. throw SkipTestException("Video file can not be opened");
  843. cv::Mat tmp;
  844. cv::Scalar out_scl;
  845. std::size_t num_frames = 0u;
  846. while (sc.pull(cv::gout(out_scl)))
  847. {
  848. num_frames++;
  849. cap >> tmp;
  850. cv::Scalar out_ref = cv::mean(tmp);
  851. EXPECT_EQ(out_ref, out_scl);
  852. }
  853. EXPECT_LT(0u, num_frames);
  854. }
  855. TEST(GAPI_Streaming_Types, OutputVector)
  856. {
  857. // This test verifies if Streaming works when pipeline
  858. // produces vector data only
  859. auto pkg = cv::gapi::kernels<TypesTest::OCVSumV>();
  860. cv::GMat in1, in2;
  861. cv::GMat roi = cv::gapi::crop(in2, cv::Rect(3,3,256,256));
  862. cv::GArray<int> out = TypesTest::SumV::on(cv::gapi::mul(roi, in1));
  863. auto sc = cv::GComputation(cv::GIn(in1, in2), cv::GOut(out))
  864. .compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{256,256}},
  865. cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  866. cv::compile_args(pkg));
  867. auto ocv_ref = [](const cv::Mat &ocv_in1,
  868. const cv::Mat &ocv_in2,
  869. std::vector<int> &ocv_out) {
  870. auto ocv_roi = ocv_in2(cv::Rect{3,3,256,256});
  871. TypesTest::OCVSumV::run(ocv_roi.mul(ocv_in1), ocv_out);
  872. };
  873. cv::Mat in_eye = cv::Mat::eye(cv::Size(256, 256), CV_8UC3);
  874. std::string video_path;
  875. video_path = findDataFile("cv/video/768x576.avi");
  876. try {
  877. sc.setSource(cv::gin(in_eye, gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(video_path)));
  878. } catch(...) {
  879. throw SkipTestException("Video file can not be opened");
  880. }
  881. sc.start();
  882. cv::VideoCapture cap;
  883. cap.open(video_path);
  884. if (!cap.isOpened())
  885. throw SkipTestException("Video file can not be opened");
  886. cv::Mat tmp;
  887. std::vector<int> ref_vec;
  888. std::vector<int> out_vec;
  889. std::size_t num_frames = 0u;
  890. while (sc.pull(cv::gout(out_vec)))
  891. {
  892. num_frames++;
  893. cap >> tmp;
  894. ref_vec.clear();
  895. ocv_ref(in_eye, tmp, ref_vec);
  896. EXPECT_EQ(ref_vec, out_vec);
  897. }
  898. EXPECT_LT(0u, num_frames);
  899. }
  900. G_API_OP(DimsChans,
  901. <std::tuple<cv::GArray<int>, cv::GOpaque<int>>(cv::GMat)>,
  902. "test.streaming.dims_chans") {
  903. static std::tuple<cv::GArrayDesc, cv::GOpaqueDesc> outMeta(const cv::GMatDesc &) {
  904. return std::make_tuple(cv::empty_array_desc(),
  905. cv::empty_gopaque_desc());
  906. }
  907. };
  908. GAPI_OCV_KERNEL(OCVDimsChans, DimsChans) {
  909. static void run(const cv::Mat &in, std::vector<int> &ov, int &oi) {
  910. ov = {in.cols, in.rows};
  911. oi = in.channels();
  912. }
  913. };
  914. struct GAPI_Streaming_TemplateTypes: ::testing::Test {
  915. // There was a problem in GStreamingExecutor
  916. // when outputs were formally not used by the graph
  917. // but still should be in place as operation need
  918. // to produce them, and host data type constructors
  919. // were missing for GArray and GOpaque in this case.
  920. // This test tests exactly this.
  921. GAPI_Streaming_TemplateTypes() {
  922. // Prepare everything for the test:
  923. // Graph itself
  924. blur = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  925. cv::GMat blur_d = cv::gapi::streaming::desync(blur);
  926. std::tie(vec, opq) = DimsChans::on(blur_d);
  927. // Kernel package
  928. pkg = cv::gapi::kernels<OCVDimsChans>();
  929. // Input mat
  930. in_mat = cv::Mat::eye(cv::Size(320,240), CV_8UC3);
  931. }
  932. cv::GMat in;
  933. cv::GMat blur;
  934. cv::GArray<int> vec;
  935. cv::GOpaque<int> opq;
  936. cv::GKernelPackage pkg;
  937. cv::Mat in_mat;
  938. };
  939. TEST_F(GAPI_Streaming_TemplateTypes, UnusedVectorIsOK)
  940. {
  941. // Declare graph without listing vec as output
  942. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(blur, opq))
  943. .compileStreaming(cv::compile_args(pkg));
  944. sc.setSource(cv::gin(in_mat));
  945. sc.start();
  946. cv::optional<cv::Mat> out_mat;
  947. cv::optional<int> out_int;
  948. int counter = 0;
  949. while (sc.pull(cv::gout(out_mat, out_int))) {
  950. if (counter++ == 10) {
  951. // Stop the test after 10 iterations
  952. sc.stop();
  953. break;
  954. }
  955. GAPI_Assert(out_mat || out_int);
  956. if (out_int) {
  957. EXPECT_EQ(3, out_int.value());
  958. }
  959. }
  960. }
  961. TEST_F(GAPI_Streaming_TemplateTypes, UnusedOpaqueIsOK)
  962. {
  963. // Declare graph without listing opq as output
  964. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(blur, vec))
  965. .compileStreaming(cv::compile_args(pkg));
  966. sc.setSource(cv::gin(in_mat));
  967. sc.start();
  968. cv::optional<cv::Mat> out_mat;
  969. cv::optional<std::vector<int> > out_vec;
  970. int counter = 0;
  971. while (sc.pull(cv::gout(out_mat, out_vec))) {
  972. if (counter++ == 10) {
  973. // Stop the test after 10 iterations
  974. sc.stop();
  975. break;
  976. }
  977. GAPI_Assert(out_mat || out_vec);
  978. if (out_vec) {
  979. EXPECT_EQ(320, out_vec.value()[0]);
  980. EXPECT_EQ(240, out_vec.value()[1]);
  981. }
  982. }
  983. }
  984. struct GAPI_Streaming_Unit: public ::testing::Test {
  985. cv::Mat m;
  986. cv::GComputation cc;
  987. cv::GStreamingCompiled sc;
  988. cv::GCompiled ref;
  989. GAPI_Streaming_Unit()
  990. : m(cv::Mat::ones(224,224,CV_8UC3))
  991. , cc([]{
  992. cv::GMat a, b;
  993. cv::GMat c = a + b*2;
  994. return cv::GComputation(cv::GIn(a, b), cv::GOut(c));
  995. })
  996. {
  997. const auto a_desc = cv::descr_of(m);
  998. const auto b_desc = cv::descr_of(m);
  999. sc = cc.compileStreaming(a_desc, b_desc);
  1000. ref = cc.compile(a_desc, b_desc);
  1001. }
  1002. };
  1003. // FIXME: (GAPI_Streaming_Types, InputOpaque) test is missing here!
  1004. // FIXME: (GAPI_Streaming_Types, XChangeOpaque) test is missing here!
  1005. // FIXME: (GAPI_Streaming_Types, OutputOpaque) test is missing here!
  1006. TEST(GAPI_Streaming, TestTwoVideosDifferentLength)
  1007. {
  1008. auto desc = cv::GMatDesc{CV_8U,3,{768,576}};
  1009. auto path1 = findDataFile("cv/video/768x576.avi");
  1010. auto path2 = findDataFile("highgui/video/big_buck_bunny.avi");
  1011. cv::GMat in1, in2;
  1012. auto out = in1 + cv::gapi::resize(in2, desc.size);
  1013. cv::GComputation cc(cv::GIn(in1, in2), cv::GOut(out));
  1014. auto sc = cc.compileStreaming();
  1015. try {
  1016. sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path1),
  1017. gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path2)));
  1018. } catch(...) {
  1019. throw SkipTestException("Video file can not be found");
  1020. }
  1021. sc.start();
  1022. cv::Mat out_mat;
  1023. std::size_t frames = 0u;
  1024. while(sc.pull(cv::gout(out_mat))) {
  1025. frames++;
  1026. }
  1027. // big_buck_bunny.avi has 125 frames, 768x576.avi - 100 frames,
  1028. // expect framework to stop after 100 frames
  1029. EXPECT_EQ(100u, frames);
  1030. }
  1031. TEST_F(GAPI_Streaming_Unit, TestStartWithoutnSetSource)
  1032. {
  1033. EXPECT_ANY_THROW(sc.start());
  1034. }
  1035. TEST_F(GAPI_Streaming_Unit, TestStopWithoutStart1)
  1036. {
  1037. // It is ok!
  1038. EXPECT_NO_THROW(sc.stop());
  1039. }
  1040. TEST_F(GAPI_Streaming_Unit, TestStopWithoutStart2)
  1041. {
  1042. // It should be ok as well
  1043. sc.setSource(cv::gin(m, m));
  1044. EXPECT_NO_THROW(sc.stop());
  1045. }
  1046. TEST_F(GAPI_Streaming_Unit, StopStartStop)
  1047. {
  1048. cv::Mat out;
  1049. EXPECT_NO_THROW(sc.stop());
  1050. EXPECT_NO_THROW(sc.setSource(cv::gin(m, m)));
  1051. EXPECT_NO_THROW(sc.start());
  1052. std::size_t i = 0u;
  1053. while (i++ < 10u) {EXPECT_TRUE(sc.pull(cv::gout(out)));};
  1054. EXPECT_NO_THROW(sc.stop());
  1055. }
  1056. TEST_F(GAPI_Streaming_Unit, ImplicitStop)
  1057. {
  1058. EXPECT_NO_THROW(sc.setSource(cv::gin(m, m)));
  1059. EXPECT_NO_THROW(sc.start());
  1060. // No explicit stop here - pipeline stops successfully at the test exit
  1061. }
  1062. TEST_F(GAPI_Streaming_Unit, StartStopStart_NoSetSource)
  1063. {
  1064. EXPECT_NO_THROW(sc.setSource(cv::gin(m, m)));
  1065. EXPECT_NO_THROW(sc.start());
  1066. EXPECT_NO_THROW(sc.stop());
  1067. EXPECT_ANY_THROW(sc.start()); // Should fail since setSource was not called
  1068. }
  1069. TEST_F(GAPI_Streaming_Unit, StartStopStress_Const)
  1070. {
  1071. // Runs 100 times with no deadlock - assumed stable (robust) enough
  1072. for (int i = 0; i < 100; i++)
  1073. {
  1074. sc.stop();
  1075. sc.setSource(cv::gin(m, m));
  1076. sc.start();
  1077. cv::Mat out;
  1078. for (int j = 0; j < 5; j++) EXPECT_TRUE(sc.pull(cv::gout(out)));
  1079. }
  1080. }
  1081. TEST_F(GAPI_Streaming_Unit, StartStopStress_Video)
  1082. {
  1083. // Runs 100 times with no deadlock - assumed stable (robust) enough
  1084. sc = cc.compileStreaming(cv::GMatDesc{CV_8U,3,cv::Size{768,576}},
  1085. cv::GMatDesc{CV_8U,3,cv::Size{768,576}});
  1086. m = cv::Mat::eye(cv::Size{768,576}, CV_8UC3);
  1087. auto path = findDataFile("cv/video/768x576.avi");
  1088. for (int i = 0; i < 100; i++)
  1089. {
  1090. sc.stop();
  1091. try {
  1092. sc.setSource(cv::gin(cv::gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path), m));
  1093. } catch(...) {
  1094. throw SkipTestException("Video file can not be opened");
  1095. }
  1096. sc.start();
  1097. cv::Mat out;
  1098. for (int j = 0; j < 5; j++) EXPECT_TRUE(sc.pull(cv::gout(out)));
  1099. }
  1100. }
  1101. TEST_F(GAPI_Streaming_Unit, PullNoStart)
  1102. {
  1103. sc.setSource(cv::gin(m, m));
  1104. cv::Mat out;
  1105. EXPECT_ANY_THROW(sc.pull(cv::gout(out)));
  1106. }
  1107. TEST_F(GAPI_Streaming_Unit, SetSource_Multi_BeforeStart)
  1108. {
  1109. cv::Mat eye = cv::Mat::eye (224, 224, CV_8UC3);
  1110. cv::Mat zrs = cv::Mat::zeros(224, 224, CV_8UC3);
  1111. // Call setSource two times, data specified last time
  1112. // should be actually processed.
  1113. sc.setSource(cv::gin(zrs, zrs));
  1114. sc.setSource(cv::gin(eye, eye));
  1115. // Run the pipeline, acquire result once
  1116. sc.start();
  1117. cv::Mat out, out_ref;
  1118. EXPECT_TRUE(sc.pull(cv::gout(out)));
  1119. sc.stop();
  1120. // Pipeline should process `eye` mat, not `zrs`
  1121. ref(cv::gin(eye, eye), cv::gout(out_ref));
  1122. EXPECT_EQ(0., cv::norm(out, out_ref, cv::NORM_INF));
  1123. }
  1124. TEST_F(GAPI_Streaming_Unit, SetSource_During_Execution)
  1125. {
  1126. cv::Mat zrs = cv::Mat::zeros(224, 224, CV_8UC3);
  1127. sc.setSource(cv::gin(m, m));
  1128. sc.start();
  1129. EXPECT_ANY_THROW(sc.setSource(cv::gin(zrs, zrs)));
  1130. EXPECT_ANY_THROW(sc.setSource(cv::gin(zrs, zrs)));
  1131. EXPECT_ANY_THROW(sc.setSource(cv::gin(zrs, zrs)));
  1132. sc.stop();
  1133. }
  1134. TEST_F(GAPI_Streaming_Unit, SetSource_After_Completion)
  1135. {
  1136. sc.setSource(cv::gin(m, m));
  1137. // Test pipeline with `m` input
  1138. sc.start();
  1139. cv::Mat out, out_ref;
  1140. EXPECT_TRUE(sc.pull(cv::gout(out)));
  1141. sc.stop();
  1142. // Test against ref
  1143. ref(cv::gin(m, m), cv::gout(out_ref));
  1144. EXPECT_EQ(0., cv::norm(out, out_ref, cv::NORM_INF));
  1145. // Now set another source
  1146. cv::Mat eye = cv::Mat::eye(224, 224, CV_8UC3);
  1147. sc.setSource(cv::gin(eye, m));
  1148. sc.start();
  1149. EXPECT_TRUE(sc.pull(cv::gout(out)));
  1150. sc.stop();
  1151. // Test against new ref
  1152. ref(cv::gin(eye, m), cv::gout(out_ref));
  1153. EXPECT_EQ(0., cv::norm(out, out_ref, cv::NORM_INF));
  1154. }
  1155. // NB: Check pull overload for python
  1156. TEST(Streaming, Python_Pull_Overload)
  1157. {
  1158. cv::GMat in;
  1159. auto out = cv::gapi::copy(in);
  1160. cv::GComputation c(in, out);
  1161. cv::Size sz(3,3);
  1162. cv::Mat in_mat(sz, CV_8UC3);
  1163. cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
  1164. auto ccomp = c.compileStreaming();
  1165. EXPECT_TRUE(ccomp);
  1166. EXPECT_FALSE(ccomp.running());
  1167. ccomp.setSource(cv::gin(in_mat));
  1168. ccomp.start();
  1169. EXPECT_TRUE(ccomp.running());
  1170. bool has_output;
  1171. cv::GRunArgs outputs;
  1172. using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
  1173. RunArgs args;
  1174. std::tie(has_output, args) = ccomp.pull();
  1175. checkPullOverload(in_mat, has_output, args);
  1176. ccomp.stop();
  1177. EXPECT_FALSE(ccomp.running());
  1178. }
  1179. TEST(GAPI_Streaming_Desync, Python_Pull_Overload)
  1180. {
  1181. cv::GMat in;
  1182. cv::GMat out = cv::gapi::streaming::desync(in);
  1183. cv::GComputation c(in, out);
  1184. cv::Size sz(3,3);
  1185. cv::Mat in_mat(sz, CV_8UC3);
  1186. cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
  1187. auto ccomp = c.compileStreaming();
  1188. EXPECT_TRUE(ccomp);
  1189. EXPECT_FALSE(ccomp.running());
  1190. ccomp.setSource(cv::gin(in_mat));
  1191. ccomp.start();
  1192. EXPECT_TRUE(ccomp.running());
  1193. bool has_output;
  1194. cv::GRunArgs outputs;
  1195. using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
  1196. RunArgs args;
  1197. std::tie(has_output, args) = ccomp.pull();
  1198. checkPullOverload(in_mat, has_output, args);
  1199. ccomp.stop();
  1200. EXPECT_FALSE(ccomp.running());
  1201. }
  1202. TEST(GAPI_Streaming_Desync, SmokeTest_Regular)
  1203. {
  1204. cv::GMat in;
  1205. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1206. cv::GMat out1 = cv::gapi::Canny(tmp1, 32, 128, 3);
  1207. // FIXME: Unary desync should not require tie!
  1208. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1209. cv::GMat out2 = tmp2 / cv::gapi::Sobel(tmp2, CV_8U, 1, 1);;
  1210. cv::Mat test_in = cv::Mat::eye(cv::Size(32,32), CV_8UC3);
  1211. cv::Mat test_out1, test_out2;
  1212. cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1213. .apply(cv::gin(test_in), cv::gout(test_out1, test_out2));
  1214. }
  1215. TEST(GAPI_Streaming_Desync, SmokeTest_Streaming)
  1216. {
  1217. cv::GMat in;
  1218. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1219. cv::GMat out1 = cv::gapi::Canny(tmp1, 32, 128, 3);
  1220. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1221. cv::GMat out2 = Delay::on(tmp2,10) / cv::gapi::Sobel(tmp2, CV_8U, 1, 1);
  1222. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1223. .compileStreaming(cv::compile_args(cv::gapi::kernels<OCVDelay>()));
  1224. auto path = findDataFile("cv/video/768x576.avi");
  1225. try {
  1226. sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  1227. } catch(...) {
  1228. throw SkipTestException("Video file can not be opened");
  1229. }
  1230. sc.start();
  1231. std::size_t out1_hits = 0u;
  1232. std::size_t out2_hits = 0u;
  1233. cv::optional<cv::Mat> test_out1, test_out2;
  1234. while (sc.pull(cv::gout(test_out1, test_out2))) {
  1235. GAPI_Assert(test_out1 || test_out2);
  1236. if (test_out1) out1_hits++;
  1237. if (test_out2) out2_hits++;
  1238. }
  1239. EXPECT_EQ(100u, out1_hits); // out1 must be available for all frames
  1240. EXPECT_LE(out2_hits, out1_hits); // out2 must appear less times than out1
  1241. }
  1242. TEST(GAPI_Streaming_Desync, SmokeTest_Streaming_TwoParts)
  1243. {
  1244. cv::GMat in;
  1245. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1246. cv::GMat out1 = cv::gapi::Canny(tmp1, 32, 128, 3);
  1247. // Desynchronized path 1
  1248. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1249. cv::GMat out2 = tmp2 / cv::gapi::Sobel(tmp2, CV_8U, 1, 1);
  1250. // Desynchronized path 2
  1251. cv::GMat tmp3 = cv::gapi::streaming::desync(tmp1);
  1252. cv::GMat out3 = 0.5*tmp3 + 0.5*cv::gapi::medianBlur(tmp3, 7);
  1253. // The code should compile and execute well (desynchronized parts don't cross)
  1254. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2, out3))
  1255. .compileStreaming();
  1256. auto path = findDataFile("cv/video/768x576.avi");
  1257. try {
  1258. sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  1259. } catch(...) {
  1260. throw SkipTestException("Video file can not be opened");
  1261. }
  1262. sc.start();
  1263. std::size_t test_frames = 0u;
  1264. cv::optional<cv::Mat> test_out1, test_out2, test_out3;
  1265. while (sc.pull(cv::gout(test_out1, test_out2, test_out3))) {
  1266. GAPI_Assert(test_out1 || test_out2 || test_out3);
  1267. if (test_out1) {
  1268. // count frames only for synchronized output
  1269. test_frames++;
  1270. }
  1271. }
  1272. EXPECT_EQ(100u, test_frames);
  1273. }
  1274. TEST(GAPI_Streaming_Desync, Negative_NestedDesync_Tier0)
  1275. {
  1276. cv::GMat in;
  1277. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1278. // Desynchronized path 1
  1279. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1280. cv::GMat out1 = cv::gapi::medianBlur(tmp2, 3);
  1281. // Desynchronized path 2, nested from 1 (directly from desync)
  1282. cv::GMat tmp3 = cv::gapi::streaming::desync(tmp2);
  1283. cv::GMat out2 = 0.5*tmp3;
  1284. // This shouldn't compile
  1285. EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1286. .compileStreaming());
  1287. }
  1288. TEST(GAPI_Streaming_Desync, Negative_NestedDesync_Tier1)
  1289. {
  1290. cv::GMat in;
  1291. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1292. // Desynchronized path 1
  1293. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1294. cv::GMat out1 = cv::gapi::medianBlur(tmp2, 3);
  1295. // Desynchronized path 2, nested from 1 (indirectly from desync)
  1296. cv::GMat tmp3 = cv::gapi::streaming::desync(out1);
  1297. cv::GMat out2 = 0.5*tmp3;
  1298. // This shouldn't compile
  1299. EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1300. .compileStreaming());
  1301. }
  1302. TEST(GAPI_Streaming_Desync, Negative_CrossMainPart_Tier0)
  1303. {
  1304. cv::GMat in;
  1305. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1306. // Desynchronized path: depends on both tmp1 and tmp2
  1307. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1308. cv::GMat out1 = 0.5*tmp1 + 0.5*tmp2;
  1309. // This shouldn't compile
  1310. EXPECT_ANY_THROW(cv::GComputation(in, out1).compileStreaming());
  1311. }
  1312. TEST(GAPI_Streaming_Desync, Negative_CrossMainPart_Tier1)
  1313. {
  1314. cv::GMat in;
  1315. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1316. // Desynchronized path: depends on both tmp1 and tmp2
  1317. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1318. cv::GMat out1 = 0.5*tmp1 + 0.5*cv::gapi::medianBlur(tmp2, 3);
  1319. // This shouldn't compile
  1320. EXPECT_ANY_THROW(cv::GComputation(in, out1).compileStreaming());
  1321. }
  1322. TEST(GAPI_Streaming_Desync, Negative_CrossOtherDesync_Tier0)
  1323. {
  1324. cv::GMat in;
  1325. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1326. // Desynchronized path 1
  1327. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1328. cv::GMat out1 = 0.5*tmp2;
  1329. // Desynchronized path 2 (depends on 1)
  1330. cv::GMat tmp3 = cv::gapi::streaming::desync(tmp1);
  1331. cv::GMat out2 = 0.5*tmp3 + tmp2;
  1332. // This shouldn't compile
  1333. EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1334. .compileStreaming());
  1335. }
  1336. TEST(GAPI_Streaming_Desync, Negative_CrossOtherDesync_Tier1)
  1337. {
  1338. cv::GMat in;
  1339. cv::GMat tmp1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1340. // Desynchronized path 1
  1341. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp1);
  1342. cv::GMat out1 = 0.5*tmp2;
  1343. // Desynchronized path 2 (depends on 1)
  1344. cv::GMat tmp3 = cv::gapi::streaming::desync(tmp1);
  1345. cv::GMat out2 = 0.5*cv::gapi::medianBlur(tmp3,3) + 1.0*tmp2;
  1346. // This shouldn't compile
  1347. EXPECT_ANY_THROW(cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1348. .compileStreaming());
  1349. }
  1350. TEST(GAPI_Streaming_Desync, Negative_SynchronizedPull)
  1351. {
  1352. cv::GMat in;
  1353. cv::GMat out1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1354. cv::GMat tmp1 = cv::gapi::streaming::desync(out1);
  1355. cv::GMat out2 = 0.5*tmp1;
  1356. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1357. .compileStreaming();
  1358. auto path = findDataFile("cv/video/768x576.avi");
  1359. try {
  1360. sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  1361. } catch(...) {
  1362. throw SkipTestException("Video file can not be opened");
  1363. }
  1364. sc.start();
  1365. cv::Mat o1, o2;
  1366. EXPECT_ANY_THROW(sc.pull(cv::gout(o1, o2)));
  1367. }
  1368. TEST(GAPI_Streaming_Desync, UseSpecialPull)
  1369. {
  1370. cv::GMat in;
  1371. cv::GMat out1 = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1372. cv::GMat tmp1 = cv::gapi::streaming::desync(out1);
  1373. cv::GMat out2 = 0.5*tmp1;
  1374. auto sc = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2))
  1375. .compileStreaming();
  1376. auto path = findDataFile("cv/video/768x576.avi");
  1377. try {
  1378. sc.setSource(cv::gin(gapi::wip::make_src<cv::gapi::wip::GCaptureSource>(path)));
  1379. } catch(...) {
  1380. throw SkipTestException("Video file can not be opened");
  1381. }
  1382. sc.start();
  1383. cv::optional<cv::Mat> o1, o2;
  1384. std::size_t num_frames = 0u;
  1385. while (sc.pull(cv::gout(o1, o2))) {
  1386. if (o1) num_frames++;
  1387. }
  1388. EXPECT_EQ(100u, num_frames);
  1389. }
  1390. G_API_OP(ProduceVector, <cv::GArray<int>(cv::GMat)>, "test.desync.vector") {
  1391. static cv::GArrayDesc outMeta(const cv::GMatDesc &) {
  1392. return cv::empty_array_desc();
  1393. }
  1394. };
  1395. G_API_OP(ProduceOpaque, <cv::GOpaque<int>(cv::GMat)>, "test.desync.opaque") {
  1396. static cv::GOpaqueDesc outMeta(const cv::GMatDesc &) {
  1397. return cv::empty_gopaque_desc();
  1398. }
  1399. };
  1400. GAPI_OCV_KERNEL(OCVVector, ProduceVector) {
  1401. static void run(const cv::Mat& in, std::vector<int> &out) {
  1402. out = {in.cols, in.rows};
  1403. }
  1404. };
  1405. GAPI_OCV_KERNEL(OCVOpaque, ProduceOpaque) {
  1406. static void run(const cv::Mat &in, int &v) {
  1407. v = in.channels();
  1408. }
  1409. };
  1410. namespace {
  1411. cv::GStreamingCompiled desyncTestObject() {
  1412. cv::GMat in;
  1413. cv::GMat blur = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1414. cv::GMat blur_d = cv::gapi::copy(cv::gapi::streaming::desync(blur));
  1415. cv::GMat d1 = Delay::on(blur_d, 10);
  1416. cv::GMat d2 = Delay::on(blur_d, 30);
  1417. cv::GArray<int> vec = ProduceVector::on(d1);
  1418. cv::GOpaque<int> opq = ProduceOpaque::on(d2);
  1419. auto pkg = cv::gapi::kernels<OCVDelay, OCVVector, OCVOpaque>();
  1420. return cv::GComputation(cv::GIn(in), cv::GOut(blur, vec, opq))
  1421. .compileStreaming(cv::compile_args(pkg));
  1422. }
  1423. } // anonymous namespace
  1424. TEST(GAPI_Streaming_Desync, MultipleDesyncOutputs_1) {
  1425. auto sc = desyncTestObject();
  1426. const cv::Mat in_mat = cv::Mat::eye(cv::Size(320,240), CV_8UC3);
  1427. sc.setSource(cv::gin(in_mat));
  1428. sc.start();
  1429. cv::optional<cv::Mat> out_mat;
  1430. cv::optional<std::vector<int> > out_vec;
  1431. cv::optional<int> out_int;
  1432. int counter = 0;
  1433. while (sc.pull(cv::gout(out_mat, out_vec, out_int))) {
  1434. if (counter++ == 1000) {
  1435. // Stop the test after 1000 iterations
  1436. sc.stop();
  1437. break;
  1438. }
  1439. GAPI_Assert(out_mat || out_vec || out_int);
  1440. // out_vec and out_int are on the same desynchronized path
  1441. // they MUST arrive together. If one is available, the other
  1442. // also must be available.
  1443. if (out_vec) { ASSERT_TRUE(out_int.has_value()); }
  1444. if (out_int) { ASSERT_TRUE(out_vec.has_value()); }
  1445. if (out_vec || out_int) {
  1446. EXPECT_EQ(320, out_vec.value()[0]);
  1447. EXPECT_EQ(240, out_vec.value()[1]);
  1448. EXPECT_EQ(3, out_int.value());
  1449. }
  1450. }
  1451. }
  1452. TEST(GAPI_Streaming_Desync, StartStop_Stress) {
  1453. auto sc = desyncTestObject();
  1454. const cv::Mat in_mat = cv::Mat::eye(cv::Size(320,240), CV_8UC3);
  1455. cv::optional<cv::Mat> out_mat;
  1456. cv::optional<std::vector<int> > out_vec;
  1457. cv::optional<int> out_int;
  1458. for (int i = 0; i < 10; i++) {
  1459. sc.setSource(cv::gin(in_mat));
  1460. sc.start();
  1461. int counter = 0;
  1462. while (counter++ < 100) {
  1463. sc.pull(cv::gout(out_mat, out_vec, out_int));
  1464. GAPI_Assert(out_mat || out_vec || out_int);
  1465. if (out_vec) { ASSERT_TRUE(out_int.has_value()); }
  1466. if (out_int) { ASSERT_TRUE(out_vec.has_value()); }
  1467. }
  1468. sc.stop();
  1469. }
  1470. }
  1471. TEST(GAPI_Streaming_Desync, DesyncObjectConsumedByTwoIslandsViaSeparateDesync) {
  1472. // See comment in the implementation of cv::gapi::streaming::desync (.cpp)
  1473. cv::GMat in;
  1474. cv::GMat tmp = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1475. cv::GMat tmp1 = cv::gapi::streaming::desync(tmp);
  1476. cv::GMat out1 = cv::gapi::copy(tmp1); // ran via Streaming backend
  1477. cv::GMat tmp2 = cv::gapi::streaming::desync(tmp);
  1478. cv::GMat out2 = tmp2 * 0.5; // ran via OCV backend
  1479. auto c = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2));
  1480. EXPECT_NO_THROW(c.compileStreaming());
  1481. }
  1482. TEST(GAPI_Streaming_Desync, DesyncObjectConsumedByTwoIslandsViaSameDesync) {
  1483. // See comment in the implementation of cv::gapi::streaming::desync (.cpp)
  1484. cv::GMat in;
  1485. cv::GMat tmp = cv::gapi::boxFilter(in, -1, cv::Size(3,3));
  1486. cv::GMat tmp1 = cv::gapi::streaming::desync(tmp);
  1487. cv::GMat out1 = cv::gapi::copy(tmp1); // ran via Streaming backend
  1488. cv::GMat out2 = out1 - 0.5*tmp1; // ran via OCV backend
  1489. auto c = cv::GComputation(cv::GIn(in), cv::GOut(out1, out2));
  1490. EXPECT_NO_THROW(c.compileStreaming());
  1491. }
  1492. TEST(GAPI_Streaming, CopyFrame)
  1493. {
  1494. std::string filepath = findDataFile("cv/video/768x576.avi");
  1495. cv::GFrame in;
  1496. auto out = cv::gapi::copy(in);
  1497. cv::GComputation comp(cv::GIn(in), cv::GOut(out));
  1498. auto cc = comp.compileStreaming();
  1499. try {
  1500. cc.setSource<BGRSource>(filepath);
  1501. } catch(...) {
  1502. throw SkipTestException("Video file can not be opened");
  1503. }
  1504. cv::VideoCapture cap;
  1505. cap.open(filepath);
  1506. if (!cap.isOpened())
  1507. throw SkipTestException("Video file can not be opened");
  1508. cv::MediaFrame frame;
  1509. cv::Mat ocv_mat;
  1510. std::size_t num_frames = 0u;
  1511. std::size_t max_frames = 10u;
  1512. cc.start();
  1513. while (cc.pull(cv::gout(frame)) && num_frames < max_frames)
  1514. {
  1515. auto view = frame.access(cv::MediaFrame::Access::R);
  1516. cv::Mat gapi_mat(frame.desc().size, CV_8UC3, view.ptr[0]);
  1517. num_frames++;
  1518. cap >> ocv_mat;
  1519. EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
  1520. }
  1521. }
  1522. TEST(GAPI_Streaming, CopyFrameGray)
  1523. {
  1524. std::string filepath = findDataFile("cv/video/768x576.avi");
  1525. cv::GFrame in;
  1526. auto out = cv::gapi::copy(in);
  1527. cv::GComputation comp(cv::GIn(in), cv::GOut(out));
  1528. auto cc = comp.compileStreaming();
  1529. try {
  1530. cc.setSource<GRAYSource>(filepath);
  1531. }
  1532. catch (...) {
  1533. throw SkipTestException("Video file can not be opened");
  1534. }
  1535. cv::VideoCapture cap;
  1536. cap.open(filepath);
  1537. if (!cap.isOpened())
  1538. throw SkipTestException("Video file can not be opened");
  1539. cv::MediaFrame frame;
  1540. cv::Mat ocv_mat;
  1541. std::size_t num_frames = 0u;
  1542. std::size_t max_frames = 10u;
  1543. cc.start();
  1544. while (cc.pull(cv::gout(frame)) && num_frames < max_frames)
  1545. {
  1546. auto view = frame.access(cv::MediaFrame::Access::R);
  1547. cv::Mat gapi_mat(frame.desc().size, CV_8UC1, view.ptr[0]);
  1548. num_frames++;
  1549. cap >> ocv_mat;
  1550. cv::Mat gray;
  1551. cvtColor(ocv_mat, gray, cv::COLOR_BGR2GRAY);
  1552. EXPECT_EQ(0, cvtest::norm(gray, gapi_mat, NORM_INF));
  1553. }
  1554. }
  1555. TEST(GAPI_Streaming, CopyMat)
  1556. {
  1557. std::string filepath = findDataFile("cv/video/768x576.avi");
  1558. cv::GMat in;
  1559. auto out = cv::gapi::copy(in);
  1560. cv::GComputation comp(cv::GIn(in), cv::GOut(out));
  1561. auto cc = comp.compileStreaming();
  1562. try {
  1563. cc.setSource<cv::gapi::wip::GCaptureSource>(filepath);
  1564. } catch(...) {
  1565. throw SkipTestException("Video file can not be opened");
  1566. }
  1567. cv::VideoCapture cap;
  1568. cap.open(filepath);
  1569. if (!cap.isOpened())
  1570. throw SkipTestException("Video file can not be opened");
  1571. cv::Mat out_mat;
  1572. cv::Mat ocv_mat;
  1573. std::size_t num_frames = 0u;
  1574. std::size_t max_frames = 10u;
  1575. cc.start();
  1576. while (cc.pull(cv::gout(out_mat)) && num_frames < max_frames)
  1577. {
  1578. num_frames++;
  1579. cap >> ocv_mat;
  1580. EXPECT_EQ(0, cvtest::norm(ocv_mat, out_mat, NORM_INF));
  1581. }
  1582. }
  1583. TEST(GAPI_Streaming, Reshape)
  1584. {
  1585. std::string filepath = findDataFile("cv/video/768x576.avi");
  1586. cv::GFrame in;
  1587. auto out = cv::gapi::copy(in);
  1588. cv::GComputation comp(cv::GIn(in), cv::GOut(out));
  1589. auto cc = comp.compileStreaming();
  1590. try {
  1591. cc.setSource<BGRSource>(filepath);
  1592. } catch(...) {
  1593. throw SkipTestException("Video file can not be opened");
  1594. }
  1595. cv::VideoCapture cap;
  1596. cap.open(filepath);
  1597. if (!cap.isOpened())
  1598. throw SkipTestException("Video file can not be opened");
  1599. cv::MediaFrame frame;
  1600. cv::Mat ocv_mat;
  1601. std::size_t num_frames = 0u;
  1602. std::size_t max_frames = 10u;
  1603. cc.start();
  1604. while (cc.pull(cv::gout(frame)) && num_frames < max_frames)
  1605. {
  1606. auto view = frame.access(cv::MediaFrame::Access::R);
  1607. cv::Mat gapi_mat(frame.desc().size, CV_8UC3, view.ptr[0]);
  1608. num_frames++;
  1609. cap >> ocv_mat;
  1610. EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
  1611. }
  1612. // Reshape the graph meta
  1613. filepath = findDataFile("cv/video/1920x1080.avi");
  1614. cc.stop();
  1615. try {
  1616. cc.setSource<BGRSource>(filepath);
  1617. } catch(...) {
  1618. throw SkipTestException("Video file can not be opened");
  1619. }
  1620. cap.open(filepath);
  1621. if (!cap.isOpened())
  1622. throw SkipTestException("Video file can not be opened");
  1623. cv::MediaFrame frame2;
  1624. cv::Mat ocv_mat2;
  1625. num_frames = 0u;
  1626. cc.start();
  1627. while (cc.pull(cv::gout(frame2)) && num_frames < max_frames)
  1628. {
  1629. auto view = frame2.access(cv::MediaFrame::Access::R);
  1630. cv::Mat gapi_mat(frame2.desc().size, CV_8UC3, view.ptr[0]);
  1631. num_frames++;
  1632. cap >> ocv_mat2;
  1633. EXPECT_EQ(0, cvtest::norm(ocv_mat2, gapi_mat, NORM_INF));
  1634. }
  1635. }
  1636. TEST(GAPI_Streaming, ReshapeGray)
  1637. {
  1638. std::string filepath = findDataFile("cv/video/768x576.avi");
  1639. cv::GFrame in;
  1640. auto out = cv::gapi::copy(in);
  1641. cv::GComputation comp(cv::GIn(in), cv::GOut(out));
  1642. auto cc = comp.compileStreaming();
  1643. try {
  1644. cc.setSource<GRAYSource>(filepath);
  1645. }
  1646. catch (...) {
  1647. throw SkipTestException("Video file can not be opened");
  1648. }
  1649. cv::VideoCapture cap;
  1650. cap.open(filepath);
  1651. if (!cap.isOpened())
  1652. throw SkipTestException("Video file can not be opened");
  1653. cv::MediaFrame frame;
  1654. cv::Mat ocv_mat;
  1655. std::size_t num_frames = 0u;
  1656. std::size_t max_frames = 10u;
  1657. cc.start();
  1658. while (cc.pull(cv::gout(frame)) && num_frames < max_frames)
  1659. {
  1660. auto view = frame.access(cv::MediaFrame::Access::R);
  1661. cv::Mat gapi_mat(frame.desc().size, CV_8UC1, view.ptr[0]);
  1662. num_frames++;
  1663. cap >> ocv_mat;
  1664. cv::Mat gray;
  1665. cvtColor(ocv_mat, gray, cv::COLOR_BGR2GRAY);
  1666. EXPECT_EQ(0, cvtest::norm(gray, gapi_mat, NORM_INF));
  1667. }
  1668. // Reshape the graph meta
  1669. filepath = findDataFile("cv/video/1920x1080.avi");
  1670. cc.stop();
  1671. try {
  1672. cc.setSource<GRAYSource>(filepath);
  1673. }
  1674. catch (...) {
  1675. throw SkipTestException("Video file can not be opened");
  1676. }
  1677. cap.open(filepath);
  1678. if (!cap.isOpened())
  1679. throw SkipTestException("Video file can not be opened");
  1680. cv::MediaFrame frame2;
  1681. cv::Mat ocv_mat2;
  1682. num_frames = 0u;
  1683. cc.start();
  1684. while (cc.pull(cv::gout(frame2)) && num_frames < max_frames)
  1685. {
  1686. auto view = frame2.access(cv::MediaFrame::Access::R);
  1687. cv::Mat gapi_mat(frame2.desc().size, CV_8UC1, view.ptr[0]);
  1688. num_frames++;
  1689. cap >> ocv_mat2;
  1690. cv::Mat gray;
  1691. cvtColor(ocv_mat2, gray, cv::COLOR_BGR2GRAY);
  1692. EXPECT_EQ(0, cvtest::norm(gray, gapi_mat, NORM_INF));
  1693. }
  1694. }
  1695. namespace {
  1696. enum class TestSourceType {
  1697. BGR,
  1698. NV12,
  1699. GRAY
  1700. };
  1701. std::ostream& operator<<(std::ostream& os, TestSourceType a) {
  1702. os << "Source:";
  1703. switch (a) {
  1704. case TestSourceType::BGR: return os << "BGR";
  1705. case TestSourceType::NV12: return os << "NV12";
  1706. case TestSourceType::GRAY: return os << "GRAY";
  1707. default: CV_Assert(false && "unknown TestSourceType");
  1708. }
  1709. }
  1710. cv::gapi::wip::IStreamSource::Ptr createTestSource(TestSourceType sourceType,
  1711. const std::string& pipeline) {
  1712. assert(sourceType == TestSourceType::BGR || sourceType == TestSourceType::NV12 || sourceType == TestSourceType::GRAY);
  1713. cv::gapi::wip::IStreamSource::Ptr ptr { };
  1714. switch (sourceType) {
  1715. case TestSourceType::BGR: {
  1716. try {
  1717. ptr = cv::gapi::wip::make_src<BGRSource>(pipeline);
  1718. }
  1719. catch(...) {
  1720. throw SkipTestException(std::string("BGRSource for '") + pipeline +
  1721. "' couldn't be created!");
  1722. }
  1723. break;
  1724. }
  1725. case TestSourceType::NV12: {
  1726. try {
  1727. ptr = cv::gapi::wip::make_src<NV12Source>(pipeline);
  1728. }
  1729. catch(...) {
  1730. throw SkipTestException(std::string("NV12Source for '") + pipeline +
  1731. "' couldn't be created!");
  1732. }
  1733. break;
  1734. }
  1735. case TestSourceType::GRAY: {
  1736. try {
  1737. ptr = cv::gapi::wip::make_src<GRAYSource>(pipeline);
  1738. }
  1739. catch (...) {
  1740. throw SkipTestException(std::string("GRAYSource for '") + pipeline +
  1741. "' couldn't be created!");
  1742. }
  1743. break;
  1744. }
  1745. default: {
  1746. throw SkipTestException("Incorrect type of source! "
  1747. "Something went wrong in the test!");
  1748. }
  1749. }
  1750. return ptr;
  1751. }
  1752. enum class TestAccessType {
  1753. BGR,
  1754. Y,
  1755. UV
  1756. };
  1757. std::ostream& operator<<(std::ostream& os, TestAccessType a) {
  1758. os << "Accessor:";
  1759. switch (a) {
  1760. case TestAccessType::BGR: return os << "BGR";
  1761. case TestAccessType::Y: return os << "Y";
  1762. case TestAccessType::UV: return os << "UV";
  1763. default: CV_Assert(false && "unknown TestAccessType");
  1764. }
  1765. }
  1766. using GapiFunction = std::function<cv::GMat(const cv::GFrame&)>;
  1767. static std::map<TestAccessType, GapiFunction> gapi_functions = {
  1768. { TestAccessType::BGR, cv::gapi::streaming::BGR },
  1769. { TestAccessType::Y, cv::gapi::streaming::Y },
  1770. { TestAccessType::UV, cv::gapi::streaming::UV }
  1771. };
  1772. using RefFunction = std::function<cv::Mat(const cv::Mat&)>;
  1773. static std::map<std::pair<TestSourceType,TestAccessType>, RefFunction> ref_functions = {
  1774. { std::make_pair(TestSourceType::BGR, TestAccessType::BGR),
  1775. [](const cv::Mat& bgr) { return bgr; } },
  1776. { std::make_pair(TestSourceType::BGR, TestAccessType::Y),
  1777. [](const cv::Mat& bgr) {
  1778. cv::Mat y, uv;
  1779. cvtBGR2NV12(bgr, y, uv);
  1780. return y;
  1781. } },
  1782. { std::make_pair(TestSourceType::BGR, TestAccessType::UV),
  1783. [](const cv::Mat& bgr) {
  1784. cv::Mat y, uv;
  1785. cvtBGR2NV12(bgr, y, uv);
  1786. return uv;
  1787. } },
  1788. { std::make_pair(TestSourceType::NV12, TestAccessType::BGR),
  1789. [](const cv::Mat& bgr) {
  1790. cv::Mat y, uv, out_bgr;
  1791. cvtBGR2NV12(bgr, y, uv);
  1792. cv::cvtColorTwoPlane(y, uv, out_bgr,
  1793. cv::COLOR_YUV2BGR_NV12);
  1794. return out_bgr;
  1795. } },
  1796. { std::make_pair(TestSourceType::NV12, TestAccessType::Y),
  1797. [](const cv::Mat& bgr) {
  1798. cv::Mat y, uv;
  1799. cvtBGR2NV12(bgr, y, uv);
  1800. return y;
  1801. } },
  1802. { std::make_pair(TestSourceType::NV12, TestAccessType::UV),
  1803. [](const cv::Mat& bgr) {
  1804. cv::Mat y, uv;
  1805. cvtBGR2NV12(bgr, y, uv);
  1806. return uv;
  1807. } },
  1808. { std::make_pair(TestSourceType::GRAY, TestAccessType::BGR),
  1809. [](const cv::Mat& bgr) {
  1810. cv::Mat gray;
  1811. cv::cvtColor(bgr, gray, cv::COLOR_BGR2GRAY);
  1812. cv::Mat out_bgr;
  1813. cv::cvtColor(gray, out_bgr, cv::COLOR_GRAY2BGR);
  1814. return out_bgr;
  1815. } },
  1816. { std::make_pair(TestSourceType::GRAY, TestAccessType::Y),
  1817. [](const cv::Mat& bgr) {
  1818. cv::Mat gray;
  1819. cv::cvtColor(bgr, gray, cv::COLOR_BGR2GRAY);
  1820. return gray;
  1821. } },
  1822. { std::make_pair(TestSourceType::GRAY, TestAccessType::UV),
  1823. [](const cv::Mat& bgr) {
  1824. cv::Mat uv(bgr.size() / 2, CV_8UC2, cv::Scalar::all(127));
  1825. return uv;
  1826. } },
  1827. };
  1828. } // anonymous namespace
  1829. struct GAPI_Accessors_In_Streaming : public TestWithParam<
  1830. std::tuple<std::string,TestSourceType,TestAccessType>>
  1831. { };
  1832. TEST_P(GAPI_Accessors_In_Streaming, AccuracyTest)
  1833. {
  1834. std::string filepath{};
  1835. TestSourceType sourceType = TestSourceType::BGR;
  1836. TestAccessType accessType = TestAccessType::BGR;
  1837. std::tie(filepath, sourceType, accessType) = GetParam();
  1838. auto accessor = gapi_functions[accessType];
  1839. auto fromBGR = ref_functions[std::make_pair(sourceType, accessType)];
  1840. const std::string& absFilePath = findDataFile(filepath);
  1841. cv::GFrame in;
  1842. cv::GMat out = accessor(in);
  1843. cv::GComputation comp(cv::GIn(in), cv::GOut(out));
  1844. auto cc = comp.compileStreaming();
  1845. auto src = createTestSource(sourceType, absFilePath);
  1846. cc.setSource(src);
  1847. cv::VideoCapture cap;
  1848. cap.open(absFilePath);
  1849. if (!cap.isOpened())
  1850. throw SkipTestException("Video file can not be opened");
  1851. cv::Mat cap_mat, ocv_mat, gapi_mat;
  1852. std::size_t num_frames = 0u;
  1853. std::size_t max_frames = 10u;
  1854. cc.start();
  1855. while (num_frames < max_frames && cc.pull(cv::gout(gapi_mat)))
  1856. {
  1857. num_frames++;
  1858. cap >> cap_mat;
  1859. ocv_mat = fromBGR(cap_mat);
  1860. EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
  1861. }
  1862. cc.stop();
  1863. }
  1864. INSTANTIATE_TEST_CASE_P(TestAccessor, GAPI_Accessors_In_Streaming,
  1865. Combine(Values("cv/video/768x576.avi"),
  1866. Values(TestSourceType::BGR, TestSourceType::NV12, TestSourceType::GRAY),
  1867. Values(TestAccessType::BGR, TestAccessType::Y, TestAccessType::UV)
  1868. ));
  1869. struct GAPI_Accessors_Meta_In_Streaming : public TestWithParam<
  1870. std::tuple<std::string,TestSourceType,TestAccessType>>
  1871. { };
  1872. TEST_P(GAPI_Accessors_Meta_In_Streaming, AccuracyTest)
  1873. {
  1874. std::string filepath{};
  1875. TestSourceType sourceType = TestSourceType::BGR;
  1876. TestAccessType accessType = TestAccessType::BGR;
  1877. std::tie(filepath, sourceType, accessType) = GetParam();
  1878. auto accessor = gapi_functions[accessType];
  1879. auto fromBGR = ref_functions[std::make_pair(sourceType, accessType)];
  1880. const std::string& absFilePath = findDataFile(filepath);
  1881. cv::GFrame in;
  1882. cv::GMat gmat = accessor(in);
  1883. cv::GMat resized = cv::gapi::resize(gmat, cv::Size(1920, 1080));
  1884. cv::GOpaque<int64_t> outId = cv::gapi::streaming::seq_id(resized);
  1885. cv::GOpaque<int64_t> outTs = cv::gapi::streaming::timestamp(resized);
  1886. cv::GComputation comp(cv::GIn(in), cv::GOut(resized, outId, outTs));
  1887. auto cc = comp.compileStreaming();
  1888. auto src = createTestSource(sourceType, absFilePath);
  1889. cc.setSource(src);
  1890. cv::VideoCapture cap;
  1891. cap.open(absFilePath);
  1892. if (!cap.isOpened())
  1893. throw SkipTestException("Video file can not be opened");
  1894. cv::Mat cap_mat, req_mat, ocv_mat, gapi_mat;
  1895. int64_t seq_id = 0, timestamp = 0;
  1896. std::set<int64_t> all_seq_ids;
  1897. std::vector<int64_t> all_timestamps;
  1898. std::size_t num_frames = 0u;
  1899. std::size_t max_frames = 10u;
  1900. cc.start();
  1901. while (num_frames < max_frames && cc.pull(cv::gout(gapi_mat, seq_id, timestamp)))
  1902. {
  1903. num_frames++;
  1904. cap >> cap_mat;
  1905. req_mat = fromBGR(cap_mat);
  1906. cv::resize(req_mat, ocv_mat, cv::Size(1920, 1080));
  1907. EXPECT_EQ(0, cvtest::norm(ocv_mat, gapi_mat, NORM_INF));
  1908. all_seq_ids.insert(seq_id);
  1909. all_timestamps.push_back(timestamp);
  1910. }
  1911. cc.stop();
  1912. EXPECT_EQ(all_seq_ids.begin(), all_seq_ids.find(0L));
  1913. auto last_elem_it = --all_seq_ids.end();
  1914. EXPECT_EQ(last_elem_it, all_seq_ids.find(int64_t(max_frames - 1L)));
  1915. EXPECT_EQ(max_frames, all_seq_ids.size());
  1916. EXPECT_EQ(max_frames, all_timestamps.size());
  1917. EXPECT_TRUE(std::is_sorted(all_timestamps.begin(), all_timestamps.end()));
  1918. }
  1919. INSTANTIATE_TEST_CASE_P(AccessorMeta, GAPI_Accessors_Meta_In_Streaming,
  1920. Combine(Values("cv/video/768x576.avi"),
  1921. Values(TestSourceType::BGR, TestSourceType::NV12, TestSourceType::GRAY),
  1922. Values(TestAccessType::BGR, TestAccessType::Y, TestAccessType::UV)
  1923. ));
  1924. TEST(GAPI_Streaming, TestPythonAPI)
  1925. {
  1926. cv::Size sz(200, 200);
  1927. cv::Mat in_mat(sz, CV_8UC3);
  1928. cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
  1929. const auto crop_rc = cv::Rect(13, 75, 100, 100);
  1930. // OpenCV reference image
  1931. cv::Mat ocv_mat;
  1932. {
  1933. ocv_mat = in_mat(crop_rc);
  1934. }
  1935. cv::GMat in;
  1936. auto roi = cv::gapi::crop(in, crop_rc);
  1937. cv::GComputation comp(cv::GIn(in), cv::GOut(roi));
  1938. // NB: Used by python bridge
  1939. auto cc = comp.compileStreaming(cv::detail::ExtractMetaCallback{[&](const cv::GTypesInfo& info)
  1940. {
  1941. GAPI_Assert(info.size() == 1u);
  1942. GAPI_Assert(info[0].shape == cv::GShape::GMAT);
  1943. return cv::GMetaArgs{cv::GMetaArg{cv::descr_of(in_mat)}};
  1944. }});
  1945. // NB: Used by python bridge
  1946. cc.setSource(cv::detail::ExtractArgsCallback{[&](const cv::GTypesInfo& info)
  1947. {
  1948. GAPI_Assert(info.size() == 1u);
  1949. GAPI_Assert(info[0].shape == cv::GShape::GMAT);
  1950. return cv::GRunArgs{in_mat};
  1951. }});
  1952. cc.start();
  1953. bool is_over = false;
  1954. cv::GRunArgs out_args;
  1955. using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
  1956. RunArgs args;
  1957. // NB: Used by python bridge
  1958. std::tie(is_over, args) = cc.pull();
  1959. switch (args.index()) {
  1960. case RunArgs::index_of<cv::GRunArgs>():
  1961. out_args = util::get<cv::GRunArgs>(args); break;
  1962. default: GAPI_Assert(false && "Incorrect type of return value");
  1963. }
  1964. ASSERT_EQ(1u, out_args.size());
  1965. ASSERT_TRUE(cv::util::holds_alternative<cv::Mat>(out_args[0]));
  1966. EXPECT_EQ(0, cvtest::norm(ocv_mat, cv::util::get<cv::Mat>(out_args[0]), NORM_INF));
  1967. EXPECT_TRUE(is_over);
  1968. cc.stop();
  1969. }
  1970. #ifdef HAVE_ONEVPL
  1971. TEST(OneVPL_Source, Init)
  1972. {
  1973. using CfgParam = cv::gapi::wip::onevpl::CfgParam;
  1974. std::vector<CfgParam> src_params;
  1975. src_params.push_back(CfgParam::create_implementation(MFX_IMPL_TYPE_HARDWARE));
  1976. src_params.push_back(CfgParam::create_acceleration_mode(MFX_ACCEL_MODE_VIA_D3D11));
  1977. src_params.push_back(CfgParam::create_decoder_id(MFX_CODEC_HEVC));
  1978. std::stringstream stream(std::ios_base::in | std::ios_base::out | std::ios_base::binary);
  1979. EXPECT_TRUE(stream.write(reinterpret_cast<char*>(const_cast<unsigned char *>(streaming::onevpl::hevc_header)),
  1980. sizeof(streaming::onevpl::hevc_header)));
  1981. std::shared_ptr<cv::gapi::wip::onevpl::IDataProvider> stream_data_provider =
  1982. std::make_shared<streaming::onevpl::StreamDataProvider>(stream);
  1983. cv::Ptr<cv::gapi::wip::IStreamSource> cap;
  1984. bool cap_created = false;
  1985. try {
  1986. cap = cv::gapi::wip::make_onevpl_src(stream_data_provider, src_params);
  1987. cap_created = true;
  1988. } catch (const std::exception&) {
  1989. }
  1990. ASSERT_TRUE(cap_created);
  1991. cv::gapi::wip::Data out;
  1992. while (cap->pull(out)) {
  1993. (void)out;
  1994. }
  1995. EXPECT_TRUE(stream_data_provider->empty());
  1996. }
  1997. #endif // HAVE_ONEVPL
  1998. TEST(GAPI_Streaming, TestDesyncRMat) {
  1999. cv::GMat in;
  2000. auto blurred = cv::gapi::blur(in, cv::Size{3,3});
  2001. auto desynced = cv::gapi::streaming::desync(blurred);
  2002. auto out = in - blurred;
  2003. auto pipe = cv::GComputation(cv::GIn(in), cv::GOut(desynced, out)).compileStreaming();
  2004. cv::Size sz(32,32);
  2005. cv::Mat in_mat(sz, CV_8UC3);
  2006. cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
  2007. pipe.setSource(cv::gin(in_mat));
  2008. pipe.start();
  2009. cv::optional<cv::RMat> out_desync;
  2010. cv::optional<cv::RMat> out_rmat;
  2011. while (true) {
  2012. // Initially it threw "bad variant access" since there was
  2013. // no RMat handling in wrap_opt_arg
  2014. EXPECT_NO_THROW(pipe.pull(cv::gout(out_desync, out_rmat)));
  2015. if (out_rmat) break;
  2016. }
  2017. }
  2018. G_API_OP(GTestBlur, <GFrame(GFrame)>, "test.blur") {
  2019. static GFrameDesc outMeta(GFrameDesc d) { return d; }
  2020. };
  2021. GAPI_OCV_KERNEL(GOcvTestBlur, GTestBlur) {
  2022. static void run(const cv::MediaFrame& in, cv::MediaFrame& out) {
  2023. auto d = in.desc();
  2024. GAPI_Assert(d.fmt == cv::MediaFormat::BGR);
  2025. auto view = in.access(cv::MediaFrame::Access::R);
  2026. cv::Mat mat(d.size, CV_8UC3, view.ptr[0]);
  2027. cv::Mat blurred;
  2028. cv::blur(mat, blurred, cv::Size{3,3});
  2029. out = cv::MediaFrame::Create<TestMediaBGR>(blurred);
  2030. }
  2031. };
  2032. TEST(GAPI_Streaming, TestDesyncMediaFrame) {
  2033. cv::GFrame in;
  2034. auto blurred = GTestBlur::on(in);
  2035. auto desynced = cv::gapi::streaming::desync(blurred);
  2036. auto out = GTestBlur::on(blurred);
  2037. auto pipe = cv::GComputation(cv::GIn(in), cv::GOut(desynced, out))
  2038. .compileStreaming(cv::compile_args(cv::gapi::kernels<GOcvTestBlur>()));
  2039. std::string filepath = findDataFile("cv/video/768x576.avi");
  2040. try {
  2041. pipe.setSource<BGRSource>(filepath);
  2042. } catch(...) {
  2043. throw SkipTestException("Video file can not be opened");
  2044. }
  2045. pipe.start();
  2046. cv::optional<cv::MediaFrame> out_desync;
  2047. cv::optional<cv::MediaFrame> out_frame;
  2048. while (true) {
  2049. // Initially it threw "bad variant access" since there was
  2050. // no MediaFrame handling in wrap_opt_arg
  2051. EXPECT_NO_THROW(pipe.pull(cv::gout(out_desync, out_frame)));
  2052. if (out_frame) break;
  2053. }
  2054. }
  2055. G_API_OP(GTestBlurGray, <GFrame(GFrame)>, "test.blur_gray") {
  2056. static GFrameDesc outMeta(GFrameDesc d) { return d; }
  2057. };
  2058. GAPI_OCV_KERNEL(GOcvTestBlurGray, GTestBlurGray) {
  2059. static void run(const cv::MediaFrame & in, cv::MediaFrame & out) {
  2060. auto d = in.desc();
  2061. GAPI_Assert(d.fmt == cv::MediaFormat::GRAY);
  2062. auto view = in.access(cv::MediaFrame::Access::R);
  2063. cv::Mat mat(d.size, CV_8UC1, view.ptr[0]);
  2064. cv::Mat blurred;
  2065. cv::blur(mat, blurred, cv::Size{ 3,3 });
  2066. out = cv::MediaFrame::Create<TestMediaGRAY>(blurred);
  2067. }
  2068. };
  2069. TEST(GAPI_Streaming, TestDesyncMediaFrameGray) {
  2070. cv::GFrame in;
  2071. auto blurred = GTestBlurGray::on(in);
  2072. auto desynced = cv::gapi::streaming::desync(blurred);
  2073. auto out = GTestBlurGray::on(blurred);
  2074. auto pipe = cv::GComputation(cv::GIn(in), cv::GOut(desynced, out))
  2075. .compileStreaming(cv::compile_args(cv::gapi::kernels<GOcvTestBlurGray>()));
  2076. std::string filepath = findDataFile("cv/video/768x576.avi");
  2077. try {
  2078. pipe.setSource<GRAYSource>(filepath);
  2079. }
  2080. catch (...) {
  2081. throw SkipTestException("Video file can not be opened");
  2082. }
  2083. pipe.start();
  2084. cv::optional<cv::MediaFrame> out_desync;
  2085. cv::optional<cv::MediaFrame> out_frame;
  2086. while (true) {
  2087. // Initially it threw "bad variant access" since there was
  2088. // no MediaFrame handling in wrap_opt_arg
  2089. EXPECT_NO_THROW(pipe.pull(cv::gout(out_desync, out_frame)));
  2090. if (out_frame) break;
  2091. }
  2092. }
  2093. } // namespace opencv_test