test_gapi_render.py 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. from tests_common import NewOpenCVTests
  8. try:
  9. if sys.version_info[:2] < (3, 0):
  10. raise unittest.SkipTest('Python 2.x is not supported')
  11. # FIXME: FText isn't supported yet.
  12. class gapi_render_test(NewOpenCVTests):
  13. def __init__(self, *args):
  14. super().__init__(*args)
  15. self.size = (300, 300, 3)
  16. # Rect
  17. self.rect = (30, 30, 50, 50)
  18. self.rcolor = (0, 255, 0)
  19. self.rlt = cv.LINE_4
  20. self.rthick = 2
  21. self.rshift = 3
  22. # Text
  23. self.text = 'Hello, world!'
  24. self.org = (100, 100)
  25. self.ff = cv.FONT_HERSHEY_SIMPLEX
  26. self.fs = 1.0
  27. self.tthick = 2
  28. self.tlt = cv.LINE_8
  29. self.tcolor = (255, 255, 255)
  30. self.blo = False
  31. # Circle
  32. self.center = (200, 200)
  33. self.radius = 200
  34. self.ccolor = (255, 255, 0)
  35. self.cthick = 2
  36. self.clt = cv.LINE_4
  37. self.cshift = 1
  38. # Line
  39. self.pt1 = (50, 50)
  40. self.pt2 = (200, 200)
  41. self.lcolor = (0, 255, 128)
  42. self.lthick = 5
  43. self.llt = cv.LINE_8
  44. self.lshift = 2
  45. # Poly
  46. self.pts = [(50, 100), (100, 200), (25, 250)]
  47. self.pcolor = (0, 0, 255)
  48. self.pthick = 3
  49. self.plt = cv.LINE_4
  50. self.pshift = 1
  51. # Image
  52. self.iorg = (150, 150)
  53. img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
  54. self.img = cv.resize(cv.imread(img_path), (50, 50))
  55. self.alpha = np.full(self.img.shape[:2], 0.8, dtype=np.float32)
  56. # Mosaic
  57. self.mos = (100, 100, 100, 100)
  58. self.cell_sz = 25
  59. self.decim = 0
  60. # Render primitives
  61. self.prims = [cv.gapi.wip.draw.Rect(self.rect, self.rcolor, self.rthick, self.rlt, self.rshift),
  62. cv.gapi.wip.draw.Text(self.text, self.org, self.ff, self.fs, self.tcolor, self.tthick, self.tlt, self.blo),
  63. cv.gapi.wip.draw.Circle(self.center, self.radius, self.ccolor, self.cthick, self.clt, self.cshift),
  64. cv.gapi.wip.draw.Line(self.pt1, self.pt2, self.lcolor, self.lthick, self.llt, self.lshift),
  65. cv.gapi.wip.draw.Mosaic(self.mos, self.cell_sz, self.decim),
  66. cv.gapi.wip.draw.Image(self.iorg, self.img, self.alpha),
  67. cv.gapi.wip.draw.Poly(self.pts, self.pcolor, self.pthick, self.plt, self.pshift)]
  68. def cvt_nv12_to_yuv(self, y, uv):
  69. h,w,_ = uv.shape
  70. upsample_uv = cv.resize(uv, (h * 2, w * 2))
  71. return cv.merge([y, upsample_uv])
  72. def cvt_yuv_to_nv12(self, yuv, y_out, uv_out):
  73. chs = cv.split(yuv, [y_out, None, None])
  74. uv = cv.merge([chs[1], chs[2]])
  75. uv_out = cv.resize(uv, (uv.shape[0] // 2, uv.shape[1] // 2), dst=uv_out)
  76. return y_out, uv_out
  77. def cvt_bgr_to_yuv_color(self, bgr):
  78. y = bgr[2] * 0.299000 + bgr[1] * 0.587000 + bgr[0] * 0.114000;
  79. u = bgr[2] * -0.168736 + bgr[1] * -0.331264 + bgr[0] * 0.500000 + 128;
  80. v = bgr[2] * 0.500000 + bgr[1] * -0.418688 + bgr[0] * -0.081312 + 128;
  81. return (y, u, v)
  82. def blend_img(self, background, org, img, alpha):
  83. x, y = org
  84. h, w, _ = img.shape
  85. roi_img = background[x:x+w, y:y+h, :]
  86. img32f_w = cv.merge([alpha] * 3).astype(np.float32)
  87. roi32f_w = np.full(roi_img.shape, 1.0, dtype=np.float32)
  88. roi32f_w -= img32f_w
  89. img32f = (img / 255).astype(np.float32)
  90. roi32f = (roi_img / 255).astype(np.float32)
  91. cv.multiply(img32f, img32f_w, dst=img32f)
  92. cv.multiply(roi32f, roi32f_w, dst=roi32f)
  93. roi32f += img32f
  94. roi_img[...] = np.round(roi32f * 255)
  95. # This is quite naive implementations used as a simple reference
  96. # doesn't consider corner cases.
  97. def draw_mosaic(self, img, mos, cell_sz, decim):
  98. x,y,w,h = mos
  99. mosaic_area = img[x:x+w, y:y+h, :]
  100. for i in range(0, mosaic_area.shape[0], cell_sz):
  101. for j in range(0, mosaic_area.shape[1], cell_sz):
  102. cell_roi = mosaic_area[j:j+cell_sz, i:i+cell_sz, :]
  103. s0, s1, s2 = cv.mean(cell_roi)[:3]
  104. mosaic_area[j:j+cell_sz, i:i+cell_sz] = (round(s0), round(s1), round(s2))
  105. def render_primitives_bgr_ref(self, img):
  106. cv.rectangle(img, self.rect, self.rcolor, self.rthick, self.rlt, self.rshift)
  107. cv.putText(img, self.text, self.org, self.ff, self.fs, self.tcolor, self.tthick, self.tlt, self.blo)
  108. cv.circle(img, self.center, self.radius, self.ccolor, self.cthick, self.clt, self.cshift)
  109. cv.line(img, self.pt1, self.pt2, self.lcolor, self.lthick, self.llt, self.lshift)
  110. cv.fillPoly(img, np.expand_dims(np.array([self.pts]), axis=0), self.pcolor, self.plt, self.pshift)
  111. self.draw_mosaic(img, self.mos, self.cell_sz, self.decim)
  112. self.blend_img(img, self.iorg, self.img, self.alpha)
  113. def render_primitives_nv12_ref(self, y_plane, uv_plane):
  114. yuv = self.cvt_nv12_to_yuv(y_plane, uv_plane)
  115. cv.rectangle(yuv, self.rect, self.cvt_bgr_to_yuv_color(self.rcolor), self.rthick, self.rlt, self.rshift)
  116. cv.putText(yuv, self.text, self.org, self.ff, self.fs, self.cvt_bgr_to_yuv_color(self.tcolor), self.tthick, self.tlt, self.blo)
  117. cv.circle(yuv, self.center, self.radius, self.cvt_bgr_to_yuv_color(self.ccolor), self.cthick, self.clt, self.cshift)
  118. cv.line(yuv, self.pt1, self.pt2, self.cvt_bgr_to_yuv_color(self.lcolor), self.lthick, self.llt, self.lshift)
  119. cv.fillPoly(yuv, np.expand_dims(np.array([self.pts]), axis=0), self.cvt_bgr_to_yuv_color(self.pcolor), self.plt, self.pshift)
  120. self.draw_mosaic(yuv, self.mos, self.cell_sz, self.decim)
  121. self.blend_img(yuv, self.iorg, cv.cvtColor(self.img, cv.COLOR_BGR2YUV), self.alpha)
  122. self.cvt_yuv_to_nv12(yuv, y_plane, uv_plane)
  123. def test_render_primitives_on_bgr_graph(self):
  124. expected = np.zeros(self.size, dtype=np.uint8)
  125. actual = np.array(expected, copy=True)
  126. # OpenCV
  127. self.render_primitives_bgr_ref(expected)
  128. # G-API
  129. g_in = cv.GMat()
  130. g_prims = cv.GArray.Prim()
  131. g_out = cv.gapi.wip.draw.render3ch(g_in, g_prims)
  132. comp = cv.GComputation(cv.GIn(g_in, g_prims), cv.GOut(g_out))
  133. actual = comp.apply(cv.gin(actual, self.prims))
  134. self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
  135. def test_render_primitives_on_bgr_function(self):
  136. expected = np.zeros(self.size, dtype=np.uint8)
  137. actual = np.array(expected, copy=True)
  138. # OpenCV
  139. self.render_primitives_bgr_ref(expected)
  140. # G-API
  141. cv.gapi.wip.draw.render(actual, self.prims)
  142. self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
  143. def test_render_primitives_on_nv12_graph(self):
  144. y_expected = np.zeros((self.size[0], self.size[1], 1), dtype=np.uint8)
  145. uv_expected = np.zeros((self.size[0] // 2, self.size[1] // 2, 2), dtype=np.uint8)
  146. y_actual = np.array(y_expected, copy=True)
  147. uv_actual = np.array(uv_expected, copy=True)
  148. # OpenCV
  149. self.render_primitives_nv12_ref(y_expected, uv_expected)
  150. # G-API
  151. g_y = cv.GMat()
  152. g_uv = cv.GMat()
  153. g_prims = cv.GArray.Prim()
  154. g_out_y, g_out_uv = cv.gapi.wip.draw.renderNV12(g_y, g_uv, g_prims)
  155. comp = cv.GComputation(cv.GIn(g_y, g_uv, g_prims), cv.GOut(g_out_y, g_out_uv))
  156. y_actual, uv_actual = comp.apply(cv.gin(y_actual, uv_actual, self.prims))
  157. self.assertEqual(0.0, cv.norm(y_expected, y_actual, cv.NORM_INF))
  158. self.assertEqual(0.0, cv.norm(uv_expected, uv_actual, cv.NORM_INF))
  159. def test_render_primitives_on_nv12_function(self):
  160. y_expected = np.zeros((self.size[0], self.size[1], 1), dtype=np.uint8)
  161. uv_expected = np.zeros((self.size[0] // 2, self.size[1] // 2, 2), dtype=np.uint8)
  162. y_actual = np.array(y_expected, copy=True)
  163. uv_actual = np.array(uv_expected, copy=True)
  164. # OpenCV
  165. self.render_primitives_nv12_ref(y_expected, uv_expected)
  166. # G-API
  167. cv.gapi.wip.draw.render(y_actual, uv_actual, self.prims)
  168. self.assertEqual(0.0, cv.norm(y_expected, y_actual, cv.NORM_INF))
  169. self.assertEqual(0.0, cv.norm(uv_expected, uv_actual, cv.NORM_INF))
  170. except unittest.SkipTest as e:
  171. message = str(e)
  172. class TestSkip(unittest.TestCase):
  173. def setUp(self):
  174. self.skipTest('Skip tests: ' + message)
  175. def test_skip():
  176. pass
  177. pass
  178. if __name__ == '__main__':
  179. NewOpenCVTests.bootstrap()