__init__.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. __all__ = ['op', 'kernel']
  2. import sys
  3. import cv2 as cv
  4. # NB: Register function in specific module
  5. def register(mname):
  6. def parameterized(func):
  7. sys.modules[mname].__dict__[func.__name__] = func
  8. return func
  9. return parameterized
  10. @register('cv2.gapi')
  11. def networks(*args):
  12. return cv.gapi_GNetPackage(list(map(cv.detail.strip, args)))
  13. @register('cv2.gapi')
  14. def compile_args(*args):
  15. return list(map(cv.GCompileArg, args))
  16. @register('cv2')
  17. def GIn(*args):
  18. return [*args]
  19. @register('cv2')
  20. def GOut(*args):
  21. return [*args]
  22. @register('cv2')
  23. def gin(*args):
  24. return [*args]
  25. @register('cv2.gapi')
  26. def descr_of(*args):
  27. return [*args]
  28. @register('cv2')
  29. class GOpaque():
  30. # NB: Inheritance from c++ class cause segfault.
  31. # So just aggregate cv.GOpaqueT instead of inheritance
  32. def __new__(cls, argtype):
  33. return cv.GOpaqueT(argtype)
  34. class Bool():
  35. def __new__(self):
  36. return cv.GOpaqueT(cv.gapi.CV_BOOL)
  37. class Int():
  38. def __new__(self):
  39. return cv.GOpaqueT(cv.gapi.CV_INT)
  40. class Double():
  41. def __new__(self):
  42. return cv.GOpaqueT(cv.gapi.CV_DOUBLE)
  43. class Float():
  44. def __new__(self):
  45. return cv.GOpaqueT(cv.gapi.CV_FLOAT)
  46. class String():
  47. def __new__(self):
  48. return cv.GOpaqueT(cv.gapi.CV_STRING)
  49. class Point():
  50. def __new__(self):
  51. return cv.GOpaqueT(cv.gapi.CV_POINT)
  52. class Point2f():
  53. def __new__(self):
  54. return cv.GOpaqueT(cv.gapi.CV_POINT2F)
  55. class Point3f():
  56. def __new__(self):
  57. return cv.GOpaqueT(cv.gapi.CV_POINT3F)
  58. class Size():
  59. def __new__(self):
  60. return cv.GOpaqueT(cv.gapi.CV_SIZE)
  61. class Rect():
  62. def __new__(self):
  63. return cv.GOpaqueT(cv.gapi.CV_RECT)
  64. class Prim():
  65. def __new__(self):
  66. return cv.GOpaqueT(cv.gapi.CV_DRAW_PRIM)
  67. class Any():
  68. def __new__(self):
  69. return cv.GOpaqueT(cv.gapi.CV_ANY)
  70. @register('cv2')
  71. class GArray():
  72. # NB: Inheritance from c++ class cause segfault.
  73. # So just aggregate cv.GArrayT instead of inheritance
  74. def __new__(cls, argtype):
  75. return cv.GArrayT(argtype)
  76. class Bool():
  77. def __new__(self):
  78. return cv.GArrayT(cv.gapi.CV_BOOL)
  79. class Int():
  80. def __new__(self):
  81. return cv.GArrayT(cv.gapi.CV_INT)
  82. class Double():
  83. def __new__(self):
  84. return cv.GArrayT(cv.gapi.CV_DOUBLE)
  85. class Float():
  86. def __new__(self):
  87. return cv.GArrayT(cv.gapi.CV_FLOAT)
  88. class String():
  89. def __new__(self):
  90. return cv.GArrayT(cv.gapi.CV_STRING)
  91. class Point():
  92. def __new__(self):
  93. return cv.GArrayT(cv.gapi.CV_POINT)
  94. class Point2f():
  95. def __new__(self):
  96. return cv.GArrayT(cv.gapi.CV_POINT2F)
  97. class Point3f():
  98. def __new__(self):
  99. return cv.GArrayT(cv.gapi.CV_POINT3F)
  100. class Size():
  101. def __new__(self):
  102. return cv.GArrayT(cv.gapi.CV_SIZE)
  103. class Rect():
  104. def __new__(self):
  105. return cv.GArrayT(cv.gapi.CV_RECT)
  106. class Scalar():
  107. def __new__(self):
  108. return cv.GArrayT(cv.gapi.CV_SCALAR)
  109. class Mat():
  110. def __new__(self):
  111. return cv.GArrayT(cv.gapi.CV_MAT)
  112. class GMat():
  113. def __new__(self):
  114. return cv.GArrayT(cv.gapi.CV_GMAT)
  115. class Prim():
  116. def __new__(self):
  117. return cv.GArray(cv.gapi.CV_DRAW_PRIM)
  118. class Any():
  119. def __new__(self):
  120. return cv.GArray(cv.gapi.CV_ANY)
  121. # NB: Top lvl decorator takes arguments
  122. def op(op_id, in_types, out_types):
  123. garray_types= {
  124. cv.GArray.Bool: cv.gapi.CV_BOOL,
  125. cv.GArray.Int: cv.gapi.CV_INT,
  126. cv.GArray.Double: cv.gapi.CV_DOUBLE,
  127. cv.GArray.Float: cv.gapi.CV_FLOAT,
  128. cv.GArray.String: cv.gapi.CV_STRING,
  129. cv.GArray.Point: cv.gapi.CV_POINT,
  130. cv.GArray.Point2f: cv.gapi.CV_POINT2F,
  131. cv.GArray.Point3f: cv.gapi.CV_POINT3F,
  132. cv.GArray.Size: cv.gapi.CV_SIZE,
  133. cv.GArray.Rect: cv.gapi.CV_RECT,
  134. cv.GArray.Scalar: cv.gapi.CV_SCALAR,
  135. cv.GArray.Mat: cv.gapi.CV_MAT,
  136. cv.GArray.GMat: cv.gapi.CV_GMAT,
  137. cv.GArray.Prim: cv.gapi.CV_DRAW_PRIM,
  138. cv.GArray.Any: cv.gapi.CV_ANY
  139. }
  140. gopaque_types= {
  141. cv.GOpaque.Size: cv.gapi.CV_SIZE,
  142. cv.GOpaque.Rect: cv.gapi.CV_RECT,
  143. cv.GOpaque.Bool: cv.gapi.CV_BOOL,
  144. cv.GOpaque.Int: cv.gapi.CV_INT,
  145. cv.GOpaque.Double: cv.gapi.CV_DOUBLE,
  146. cv.GOpaque.Float: cv.gapi.CV_FLOAT,
  147. cv.GOpaque.String: cv.gapi.CV_STRING,
  148. cv.GOpaque.Point: cv.gapi.CV_POINT,
  149. cv.GOpaque.Point2f: cv.gapi.CV_POINT2F,
  150. cv.GOpaque.Point3f: cv.gapi.CV_POINT3F,
  151. cv.GOpaque.Size: cv.gapi.CV_SIZE,
  152. cv.GOpaque.Rect: cv.gapi.CV_RECT,
  153. cv.GOpaque.Prim: cv.gapi.CV_DRAW_PRIM,
  154. cv.GOpaque.Any: cv.gapi.CV_ANY
  155. }
  156. type2str = {
  157. cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' ,
  158. cv.gapi.CV_INT: 'cv.gapi.CV_INT' ,
  159. cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' ,
  160. cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' ,
  161. cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' ,
  162. cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' ,
  163. cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' ,
  164. cv.gapi.CV_POINT3F: 'cv.gapi.CV_POINT3F' ,
  165. cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE',
  166. cv.gapi.CV_RECT: 'cv.gapi.CV_RECT',
  167. cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR',
  168. cv.gapi.CV_MAT: 'cv.gapi.CV_MAT',
  169. cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT',
  170. cv.gapi.CV_DRAW_PRIM: 'cv.gapi.CV_DRAW_PRIM'
  171. }
  172. # NB: Second lvl decorator takes class to decorate
  173. def op_with_params(cls):
  174. if not in_types:
  175. raise Exception('{} operation should have at least one input!'.format(cls.__name__))
  176. if not out_types:
  177. raise Exception('{} operation should have at least one output!'.format(cls.__name__))
  178. for i, t in enumerate(out_types):
  179. if t not in [cv.GMat, cv.GScalar, *garray_types, *gopaque_types]:
  180. raise Exception('{} unsupported output type: {} in position: {}'
  181. .format(cls.__name__, t.__name__, i))
  182. def on(*args):
  183. if len(in_types) != len(args):
  184. raise Exception('Invalid number of input elements!\nExpected: {}, Actual: {}'
  185. .format(len(in_types), len(args)))
  186. for i, (t, a) in enumerate(zip(in_types, args)):
  187. if t in garray_types:
  188. if not isinstance(a, cv.GArrayT):
  189. raise Exception("{} invalid type for argument {}.\nExpected: {}, Actual: {}"
  190. .format(cls.__name__, i, cv.GArrayT.__name__, type(a).__name__))
  191. elif a.type() != garray_types[t]:
  192. raise Exception("{} invalid GArrayT type for argument {}.\nExpected: {}, Actual: {}"
  193. .format(cls.__name__, i, type2str[garray_types[t]], type2str[a.type()]))
  194. elif t in gopaque_types:
  195. if not isinstance(a, cv.GOpaqueT):
  196. raise Exception("{} invalid type for argument {}.\nExpected: {}, Actual: {}"
  197. .format(cls.__name__, i, cv.GOpaqueT.__name__, type(a).__name__))
  198. elif a.type() != gopaque_types[t]:
  199. raise Exception("{} invalid GOpaque type for argument {}.\nExpected: {}, Actual: {}"
  200. .format(cls.__name__, i, type2str[gopaque_types[t]], type2str[a.type()]))
  201. else:
  202. if t != type(a):
  203. raise Exception('{} invalid input type for argument {}.\nExpected: {}, Actual: {}'
  204. .format(cls.__name__, i, t.__name__, type(a).__name__))
  205. op = cv.gapi.__op(op_id, cls.outMeta, *args)
  206. out_protos = []
  207. for i, out_type in enumerate(out_types):
  208. if out_type == cv.GMat:
  209. out_protos.append(op.getGMat())
  210. elif out_type == cv.GScalar:
  211. out_protos.append(op.getGScalar())
  212. elif out_type in gopaque_types:
  213. out_protos.append(op.getGOpaque(gopaque_types[out_type]))
  214. elif out_type in garray_types:
  215. out_protos.append(op.getGArray(garray_types[out_type]))
  216. else:
  217. raise Exception("""In {}: G-API operation can't produce the output with type: {} in position: {}"""
  218. .format(cls.__name__, out_type.__name__, i))
  219. return tuple(out_protos) if len(out_protos) != 1 else out_protos[0]
  220. # NB: Extend operation class
  221. cls.id = op_id
  222. cls.on = staticmethod(on)
  223. return cls
  224. return op_with_params
  225. def kernel(op_cls):
  226. # NB: Second lvl decorator takes class to decorate
  227. def kernel_with_params(cls):
  228. # NB: Add new members to kernel class
  229. cls.id = op_cls.id
  230. cls.outMeta = op_cls.outMeta
  231. return cls
  232. return kernel_with_params
  233. cv.gapi.wip.GStreamerPipeline = cv.gapi_wip_gst_GStreamerPipeline