video.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. import numpy as np
  2. import cv2
  3. from time import clock
  4. from numpy import pi, sin, cos
  5. import common
  6. class VideoSynthBase(object):
  7. def __init__(self, size=None, noise=0.0, bg = None, **params):
  8. self.bg = None
  9. self.frame_size = (640, 480)
  10. if bg is not None:
  11. self.bg = cv2.imread(bg, 1)
  12. h, w = self.bg.shape[:2]
  13. self.frame_size = (w, h)
  14. if size is not None:
  15. w, h = map(int, size.split('x'))
  16. self.frame_size = (w, h)
  17. self.bg = cv2.resize(self.bg, self.frame_size)
  18. self.noise = float(noise)
  19. def render(self, dst):
  20. pass
  21. def read(self, dst=None):
  22. w, h = self.frame_size
  23. if self.bg is None:
  24. buf = np.zeros((h, w, 3), np.uint8)
  25. else:
  26. buf = self.bg.copy()
  27. self.render(buf)
  28. if self.noise > 0.0:
  29. noise = np.zeros((h, w, 3), np.int8)
  30. cv2.randn(noise, np.zeros(3), np.ones(3)*255*self.noise)
  31. buf = cv2.add(buf, noise, dtype=cv2.CV_8UC3)
  32. return True, buf
  33. class Chess(VideoSynthBase):
  34. def __init__(self, **kw):
  35. super(Chess, self).__init__(**kw)
  36. w, h = self.frame_size
  37. self.grid_size = sx, sy = 10, 7
  38. white_quads = []
  39. black_quads = []
  40. for i, j in np.ndindex(sy, sx):
  41. q = [[j, i, 0], [j+1, i, 0], [j+1, i+1, 0], [j, i+1, 0]]
  42. [white_quads, black_quads][(i + j) % 2].append(q)
  43. self.white_quads = np.float32(white_quads)
  44. self.black_quads = np.float32(black_quads)
  45. fx = 0.9
  46. self.K = np.float64([[fx*w, 0, 0.5*(w-1)],
  47. [0, fx*w, 0.5*(h-1)],
  48. [0.0,0.0, 1.0]])
  49. self.dist_coef = np.float64([-0.2, 0.1, 0, 0])
  50. self.t = 0
  51. def draw_quads(self, img, quads, color = (0, 255, 0)):
  52. img_quads = cv2.projectPoints(quads.reshape(-1, 3), self.rvec, self.tvec, self.K, self.dist_coef) [0]
  53. img_quads.shape = quads.shape[:2] + (2,)
  54. for q in img_quads:
  55. cv2.fillConvexPoly(img, np.int32(q*4), color, cv2.CV_AA, shift=2)
  56. def render(self, dst):
  57. t = self.t
  58. self.t += 1.0/30.0
  59. sx, sy = self.grid_size
  60. center = np.array([0.5*sx, 0.5*sy, 0.0])
  61. phi = pi/3 + sin(t*3)*pi/8
  62. c, s = cos(phi), sin(phi)
  63. ofs = np.array([sin(1.2*t), cos(1.8*t), 0]) * sx * 0.2
  64. eye_pos = center + np.array([cos(t)*c, sin(t)*c, s]) * 15.0 + ofs
  65. target_pos = center + ofs
  66. R, self.tvec = common.lookat(eye_pos, target_pos)
  67. self.rvec = common.mtx2rvec(R)
  68. self.draw_quads(dst, self.white_quads, (245, 245, 245))
  69. self.draw_quads(dst, self.black_quads, (10, 10, 10))
  70. classes = dict(chess=Chess)
  71. def create_capture(source):
  72. '''
  73. source: <int> or '<int>' or '<filename>' or 'synth:<params>'
  74. '''
  75. try: source = int(source)
  76. except ValueError: pass
  77. else:
  78. return cv2.VideoCapture(source)
  79. source = str(source).strip()
  80. if source.startswith('synth'):
  81. ss = filter(None, source.split(':'))
  82. params = dict( s.split('=') for s in ss[1:] )
  83. try: Class = classes[params['class']]
  84. except: Class = VideoSynthBase
  85. return Class(**params)
  86. return cv2.VideoCapture(source)
  87. presets = dict(
  88. empty = 'synth:',
  89. lena = 'synth:bg=../cpp/lena.jpg:noise=0.1',
  90. chess = 'synth:class=chess:bg=../cpp/lena.jpg:noise=0.1:size=640x480'
  91. )
  92. if __name__ == '__main__':
  93. import sys
  94. import getopt
  95. print 'USAGE: video.py [--shotdir <dir>] [source0] [source1] ...'
  96. print "source: '<int>' or '<filename>' or 'synth:<params>'"
  97. print
  98. args, sources = getopt.getopt(sys.argv[1:], '', 'shotdir=')
  99. args = dict(args)
  100. shotdir = args.get('--shotdir', '.')
  101. if len(sources) == 0:
  102. sources = [ presets['chess'] ]
  103. print 'Press SPACE to save current frame'
  104. caps = map(create_capture, sources)
  105. shot_idx = 0
  106. while True:
  107. imgs = []
  108. for i, cap in enumerate(caps):
  109. ret, img = cap.read()
  110. imgs.append(img)
  111. cv2.imshow('capture %d' % i, img)
  112. ch = cv2.waitKey(1)
  113. if ch == 27:
  114. break
  115. if ch == ord(' '):
  116. for i, img in enumerate(imgs):
  117. fn = '%s/shot_%d_%03d.bmp' % (shotdir, i, shot_idx)
  118. cv2.imwrite(fn, img)
  119. print fn, 'saved'
  120. shot_idx += 1