test_gapi_streaming.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. #!/usr/bin/env python
  2. import numpy as np
  3. import cv2 as cv
  4. import os
  5. import sys
  6. import unittest
  7. import time
  8. from tests_common import NewOpenCVTests
  9. try:
  10. if sys.version_info[:2] < (3, 0):
  11. raise unittest.SkipTest('Python 2.x is not supported')
  12. @cv.gapi.op('custom.delay', in_types=[cv.GMat], out_types=[cv.GMat])
  13. class GDelay:
  14. """Delay for 10 ms."""
  15. @staticmethod
  16. def outMeta(desc):
  17. return desc
  18. @cv.gapi.kernel(GDelay)
  19. class GDelayImpl:
  20. """Implementation for GDelay operation."""
  21. @staticmethod
  22. def run(img):
  23. time.sleep(0.01)
  24. return img
  25. def convertNV12p2BGR(in_nv12):
  26. shape = in_nv12.shape
  27. y_height = shape[0] // 3 * 2
  28. uv_shape = (shape[0] // 3, shape[1])
  29. new_uv_shape = (uv_shape[0], uv_shape[1] // 2, 2)
  30. return cv.cvtColorTwoPlane(in_nv12[:y_height, :],
  31. in_nv12[ y_height:, :].reshape(new_uv_shape),
  32. cv.COLOR_YUV2BGR_NV12)
  33. class test_gapi_streaming(NewOpenCVTests):
  34. def test_image_input(self):
  35. sz = (1280, 720)
  36. in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
  37. # OpenCV
  38. expected = cv.medianBlur(in_mat, 3)
  39. # G-API
  40. g_in = cv.GMat()
  41. g_out = cv.gapi.medianBlur(g_in, 3)
  42. c = cv.GComputation(g_in, g_out)
  43. ccomp = c.compileStreaming(cv.gapi.descr_of(in_mat))
  44. ccomp.setSource(cv.gin(in_mat))
  45. ccomp.start()
  46. _, actual = ccomp.pull()
  47. # Assert
  48. self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
  49. def test_video_input(self):
  50. ksize = 3
  51. path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
  52. # OpenCV
  53. cap = cv.VideoCapture(path)
  54. # G-API
  55. g_in = cv.GMat()
  56. g_out = cv.gapi.medianBlur(g_in, ksize)
  57. c = cv.GComputation(g_in, g_out)
  58. ccomp = c.compileStreaming()
  59. source = cv.gapi.wip.make_capture_src(path)
  60. ccomp.setSource(cv.gin(source))
  61. ccomp.start()
  62. # Assert
  63. max_num_frames = 10
  64. proc_num_frames = 0
  65. while cap.isOpened():
  66. has_expected, expected = cap.read()
  67. has_actual, actual = ccomp.pull()
  68. self.assertEqual(has_expected, has_actual)
  69. if not has_actual:
  70. break
  71. self.assertEqual(0.0, cv.norm(cv.medianBlur(expected, ksize), actual, cv.NORM_INF))
  72. proc_num_frames += 1
  73. if proc_num_frames == max_num_frames:
  74. break
  75. def test_video_split3(self):
  76. path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
  77. # OpenCV
  78. cap = cv.VideoCapture(path)
  79. # G-API
  80. g_in = cv.GMat()
  81. b, g, r = cv.gapi.split3(g_in)
  82. c = cv.GComputation(cv.GIn(g_in), cv.GOut(b, g, r))
  83. ccomp = c.compileStreaming()
  84. source = cv.gapi.wip.make_capture_src(path)
  85. ccomp.setSource(cv.gin(source))
  86. ccomp.start()
  87. # Assert
  88. max_num_frames = 10
  89. proc_num_frames = 0
  90. while cap.isOpened():
  91. has_expected, frame = cap.read()
  92. has_actual, actual = ccomp.pull()
  93. self.assertEqual(has_expected, has_actual)
  94. if not has_actual:
  95. break
  96. expected = cv.split(frame)
  97. for e, a in zip(expected, actual):
  98. self.assertEqual(0.0, cv.norm(e, a, cv.NORM_INF))
  99. proc_num_frames += 1
  100. if proc_num_frames == max_num_frames:
  101. break
  102. def test_video_add(self):
  103. sz = (576, 768, 3)
  104. in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
  105. path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
  106. # OpenCV
  107. cap = cv.VideoCapture(path)
  108. # G-API
  109. g_in1 = cv.GMat()
  110. g_in2 = cv.GMat()
  111. out = cv.gapi.add(g_in1, g_in2)
  112. c = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(out))
  113. ccomp = c.compileStreaming()
  114. source = cv.gapi.wip.make_capture_src(path)
  115. ccomp.setSource(cv.gin(source, in_mat))
  116. ccomp.start()
  117. # Assert
  118. max_num_frames = 10
  119. proc_num_frames = 0
  120. while cap.isOpened():
  121. has_expected, frame = cap.read()
  122. has_actual, actual = ccomp.pull()
  123. self.assertEqual(has_expected, has_actual)
  124. if not has_actual:
  125. break
  126. expected = cv.add(frame, in_mat)
  127. self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
  128. proc_num_frames += 1
  129. if proc_num_frames == max_num_frames:
  130. break
  131. def test_video_good_features_to_track(self):
  132. path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
  133. # NB: goodFeaturesToTrack configuration
  134. max_corners = 50
  135. quality_lvl = 0.01
  136. min_distance = 10
  137. block_sz = 3
  138. use_harris_detector = True
  139. k = 0.04
  140. mask = None
  141. # OpenCV
  142. cap = cv.VideoCapture(path)
  143. # G-API
  144. g_in = cv.GMat()
  145. g_gray = cv.gapi.RGB2Gray(g_in)
  146. g_out = cv.gapi.goodFeaturesToTrack(g_gray, max_corners, quality_lvl,
  147. min_distance, mask, block_sz, use_harris_detector, k)
  148. c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
  149. ccomp = c.compileStreaming()
  150. source = cv.gapi.wip.make_capture_src(path)
  151. ccomp.setSource(cv.gin(source))
  152. ccomp.start()
  153. # Assert
  154. max_num_frames = 10
  155. proc_num_frames = 0
  156. while cap.isOpened():
  157. has_expected, frame = cap.read()
  158. has_actual, actual = ccomp.pull()
  159. self.assertEqual(has_expected, has_actual)
  160. if not has_actual:
  161. break
  162. # OpenCV
  163. frame = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)
  164. expected = cv.goodFeaturesToTrack(frame, max_corners, quality_lvl,
  165. min_distance, mask=mask,
  166. blockSize=block_sz, useHarrisDetector=use_harris_detector, k=k)
  167. for e, a in zip(expected, actual):
  168. # NB: OpenCV & G-API have different output shapes:
  169. # OpenCV - (num_points, 1, 2)
  170. # G-API - (num_points, 2)
  171. self.assertEqual(0.0, cv.norm(e.flatten(),
  172. np.array(a, np.float32).flatten(),
  173. cv.NORM_INF))
  174. proc_num_frames += 1
  175. if proc_num_frames == max_num_frames:
  176. break
  177. def test_gapi_streaming_meta(self):
  178. path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
  179. # G-API
  180. g_in = cv.GMat()
  181. g_ts = cv.gapi.streaming.timestamp(g_in)
  182. g_seqno = cv.gapi.streaming.seqNo(g_in)
  183. g_seqid = cv.gapi.streaming.seq_id(g_in)
  184. c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_ts, g_seqno, g_seqid))
  185. ccomp = c.compileStreaming()
  186. source = cv.gapi.wip.make_capture_src(path)
  187. ccomp.setSource(cv.gin(source))
  188. ccomp.start()
  189. # Assert
  190. max_num_frames = 10
  191. curr_frame_number = 0
  192. while True:
  193. has_frame, (ts, seqno, seqid) = ccomp.pull()
  194. if not has_frame:
  195. break
  196. self.assertEqual(curr_frame_number, seqno)
  197. self.assertEqual(curr_frame_number, seqid)
  198. curr_frame_number += 1
  199. if curr_frame_number == max_num_frames:
  200. break
  201. def test_desync(self):
  202. path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
  203. # G-API
  204. g_in = cv.GMat()
  205. g_out1 = cv.gapi.copy(g_in)
  206. des = cv.gapi.streaming.desync(g_in)
  207. g_out2 = GDelay.on(des)
  208. c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out1, g_out2))
  209. kernels = cv.gapi.kernels(GDelayImpl)
  210. ccomp = c.compileStreaming(args=cv.gapi.compile_args(kernels))
  211. source = cv.gapi.wip.make_capture_src(path)
  212. ccomp.setSource(cv.gin(source))
  213. ccomp.start()
  214. # Assert
  215. max_num_frames = 10
  216. proc_num_frames = 0
  217. out_counter = 0
  218. desync_out_counter = 0
  219. none_counter = 0
  220. while True:
  221. has_frame, (out1, out2) = ccomp.pull()
  222. if not has_frame:
  223. break
  224. if not out1 is None:
  225. out_counter += 1
  226. if not out2 is None:
  227. desync_out_counter += 1
  228. else:
  229. none_counter += 1
  230. proc_num_frames += 1
  231. if proc_num_frames == max_num_frames:
  232. ccomp.stop()
  233. break
  234. self.assertLess(0, proc_num_frames)
  235. self.assertLess(desync_out_counter, out_counter)
  236. self.assertLess(0, none_counter)
  237. def test_compile_streaming_empty(self):
  238. g_in = cv.GMat()
  239. comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3))
  240. comp.compileStreaming()
  241. def test_compile_streaming_args(self):
  242. g_in = cv.GMat()
  243. comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3))
  244. comp.compileStreaming(cv.gapi.compile_args(cv.gapi.streaming.queue_capacity(1)))
  245. def test_compile_streaming_descr_of(self):
  246. g_in = cv.GMat()
  247. comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3))
  248. img = np.zeros((3,300,300), dtype=np.float32)
  249. comp.compileStreaming(cv.gapi.descr_of(img))
  250. def test_compile_streaming_descr_of_and_args(self):
  251. g_in = cv.GMat()
  252. comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3))
  253. img = np.zeros((3,300,300), dtype=np.float32)
  254. comp.compileStreaming(cv.gapi.descr_of(img),
  255. cv.gapi.compile_args(cv.gapi.streaming.queue_capacity(1)))
  256. def test_compile_streaming_meta(self):
  257. g_in = cv.GMat()
  258. comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3))
  259. img = np.zeros((3,300,300), dtype=np.float32)
  260. comp.compileStreaming([cv.GMatDesc(cv.CV_8U, 3, (300, 300))])
  261. def test_compile_streaming_meta_and_args(self):
  262. g_in = cv.GMat()
  263. comp = cv.GComputation(g_in, cv.gapi.medianBlur(g_in, 3))
  264. img = np.zeros((3,300,300), dtype=np.float32)
  265. comp.compileStreaming([cv.GMatDesc(cv.CV_8U, 3, (300, 300))],
  266. cv.gapi.compile_args(cv.gapi.streaming.queue_capacity(1)))
  267. def get_gst_source(self, gstpipeline):
  268. # NB: Skip test in case gstreamer isn't available.
  269. try:
  270. return cv.gapi.wip.make_gst_src(gstpipeline)
  271. except cv.error as e:
  272. if str(e).find('Built without GStreamer support!') == -1:
  273. raise e
  274. else:
  275. raise unittest.SkipTest(str(e))
  276. def test_gst_source(self):
  277. if not cv.videoio_registry.hasBackend(cv.CAP_GSTREAMER):
  278. raise unittest.SkipTest("Backend is not available/disabled: GSTREAMER")
  279. gstpipeline = """videotestsrc is-live=true pattern=colors num-buffers=10 !
  280. videorate ! videoscale ! video/x-raw,width=1920,height=1080,
  281. framerate=30/1 ! appsink"""
  282. g_in = cv.GMat()
  283. g_out = cv.gapi.copy(g_in)
  284. c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
  285. ccomp = c.compileStreaming()
  286. source = self.get_gst_source(gstpipeline)
  287. ccomp.setSource(cv.gin(source))
  288. ccomp.start()
  289. has_frame, output = ccomp.pull()
  290. while has_frame:
  291. self.assertTrue(output.size != 0)
  292. has_frame, output = ccomp.pull()
  293. def open_VideoCapture_gstreamer(self, gstpipeline):
  294. try:
  295. cap = cv.VideoCapture(gstpipeline, cv.CAP_GSTREAMER)
  296. except Exception as e:
  297. raise unittest.SkipTest("Backend GSTREAMER can't open the video; " +
  298. "cause: " + str(e))
  299. if not cap.isOpened():
  300. raise unittest.SkipTest("Backend GSTREAMER can't open the video")
  301. return cap
  302. def test_gst_source_accuracy(self):
  303. if not cv.videoio_registry.hasBackend(cv.CAP_GSTREAMER):
  304. raise unittest.SkipTest("Backend is not available/disabled: GSTREAMER")
  305. path = self.find_file('highgui/video/big_buck_bunny.avi',
  306. [os.environ['OPENCV_TEST_DATA_PATH']])
  307. gstpipeline = """filesrc location=""" + path + """ ! decodebin ! videoconvert !
  308. videoscale ! video/x-raw,format=NV12 ! appsink"""
  309. # G-API pipeline
  310. g_in = cv.GMat()
  311. g_out = cv.gapi.copy(g_in)
  312. c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
  313. ccomp = c.compileStreaming()
  314. # G-API Gst-source
  315. source = self.get_gst_source(gstpipeline)
  316. ccomp.setSource(cv.gin(source))
  317. ccomp.start()
  318. # OpenCV Gst-source
  319. cap = self.open_VideoCapture_gstreamer(gstpipeline)
  320. # Assert
  321. max_num_frames = 10
  322. for _ in range(max_num_frames):
  323. has_expected, expected = cap.read()
  324. has_actual, actual = ccomp.pull()
  325. self.assertEqual(has_expected, has_actual)
  326. if not has_expected:
  327. break
  328. self.assertEqual(0.0, cv.norm(convertNV12p2BGR(expected), actual, cv.NORM_INF))
  329. def get_gst_pipeline(self, gstpipeline):
  330. # NB: Skip test in case gstreamer isn't available.
  331. try:
  332. return cv.gapi.wip.GStreamerPipeline(gstpipeline)
  333. except cv.error as e:
  334. if str(e).find('Built without GStreamer support!') == -1:
  335. raise e
  336. else:
  337. raise unittest.SkipTest(str(e))
  338. except SystemError as e:
  339. raise unittest.SkipTest(str(e) + ", casued by " + str(e.__cause__))
  340. def test_gst_multiple_sources(self):
  341. if not cv.videoio_registry.hasBackend(cv.CAP_GSTREAMER):
  342. raise unittest.SkipTest("Backend is not available/disabled: GSTREAMER")
  343. gstpipeline = """videotestsrc is-live=true pattern=colors num-buffers=10 !
  344. videorate ! videoscale !
  345. video/x-raw,width=1920,height=1080,framerate=30/1 !
  346. appsink name=sink1
  347. videotestsrc is-live=true pattern=colors num-buffers=10 !
  348. videorate ! videoscale !
  349. video/x-raw,width=1920,height=1080,framerate=30/1 !
  350. appsink name=sink2"""
  351. g_in1 = cv.GMat()
  352. g_in2 = cv.GMat()
  353. g_out = cv.gapi.add(g_in1, g_in2)
  354. c = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
  355. ccomp = c.compileStreaming()
  356. pp = self.get_gst_pipeline(gstpipeline)
  357. src1 = cv.gapi.wip.get_streaming_source(pp, "sink1")
  358. src2 = cv.gapi.wip.get_streaming_source(pp, "sink2")
  359. ccomp.setSource(cv.gin(src1, src2))
  360. ccomp.start()
  361. has_frame, out = ccomp.pull()
  362. while has_frame:
  363. self.assertTrue(out.size != 0)
  364. has_frame, out = ccomp.pull()
  365. def test_gst_multiple_sources_accuracy(self):
  366. if not cv.videoio_registry.hasBackend(cv.CAP_GSTREAMER):
  367. raise unittest.SkipTest("Backend is not available/disabled: GSTREAMER")
  368. path = self.find_file('highgui/video/big_buck_bunny.avi',
  369. [os.environ['OPENCV_TEST_DATA_PATH']])
  370. gstpipeline1 = """filesrc location=""" + path + """ ! decodebin ! videoconvert !
  371. videoscale ! video/x-raw,format=NV12 ! appsink"""
  372. gstpipeline2 = """filesrc location=""" + path + """ ! decodebin !
  373. videoflip method=clockwise ! videoconvert ! videoscale !
  374. video/x-raw,format=NV12 ! appsink"""
  375. gstpipeline_gapi = gstpipeline1 + ' name=sink1 ' + gstpipeline2 + ' name=sink2'
  376. # G-API pipeline
  377. g_in1 = cv.GMat()
  378. g_in2 = cv.GMat()
  379. g_out1 = cv.gapi.copy(g_in1)
  380. g_out2 = cv.gapi.copy(g_in2)
  381. c = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out1, g_out2))
  382. ccomp = c.compileStreaming()
  383. # G-API Gst-source
  384. pp = self.get_gst_pipeline(gstpipeline_gapi)
  385. src1 = cv.gapi.wip.get_streaming_source(pp, "sink1")
  386. src2 = cv.gapi.wip.get_streaming_source(pp, "sink2")
  387. ccomp.setSource(cv.gin(src1, src2))
  388. ccomp.start()
  389. # OpenCV Gst-source
  390. cap1 = self.open_VideoCapture_gstreamer(gstpipeline1)
  391. cap2 = self.open_VideoCapture_gstreamer(gstpipeline2)
  392. # Assert
  393. max_num_frames = 10
  394. for _ in range(max_num_frames):
  395. has_expected1, expected1 = cap1.read()
  396. has_expected2, expected2 = cap2.read()
  397. has_actual, (actual1, actual2) = ccomp.pull()
  398. self.assertEqual(has_expected1, has_expected2)
  399. has_expected = has_expected1 and has_expected2
  400. self.assertEqual(has_expected, has_actual)
  401. if not has_expected:
  402. break
  403. self.assertEqual(0.0, cv.norm(convertNV12p2BGR(expected1), actual1, cv.NORM_INF))
  404. self.assertEqual(0.0, cv.norm(convertNV12p2BGR(expected2), actual2, cv.NORM_INF))
  405. except unittest.SkipTest as e:
  406. message = str(e)
  407. class TestSkip(unittest.TestCase):
  408. def setUp(self):
  409. self.skipTest('Skip tests: ' + message)
  410. def test_skip():
  411. pass
  412. pass
  413. if __name__ == '__main__':
  414. NewOpenCVTests.bootstrap()