plane_ar.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #!/usr/bin/env python
  2. '''
  3. Planar augmented reality
  4. ==================
  5. This sample shows an example of augmented reality overlay over a planar object
  6. tracked by PlaneTracker from plane_tracker.py. solvePnP function is used to
  7. estimate the tracked object location in 3d space.
  8. video: http://www.youtube.com/watch?v=pzVbhxx6aog
  9. Usage
  10. -----
  11. plane_ar.py [<video source>]
  12. Keys:
  13. SPACE - pause video
  14. c - clear targets
  15. Select a textured planar object to track by drawing a box with a mouse.
  16. Use 'focal' slider to adjust to camera focal length for proper video augmentation.
  17. '''
  18. # Python 2/3 compatibility
  19. from __future__ import print_function
  20. import numpy as np
  21. import cv2 as cv
  22. import video
  23. import common
  24. from plane_tracker import PlaneTracker
  25. from video import presets
  26. # Simple model of a house - cube with a triangular prism "roof"
  27. ar_verts = np.float32([[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0],
  28. [0, 0, 1], [0, 1, 1], [1, 1, 1], [1, 0, 1],
  29. [0, 0.5, 2], [1, 0.5, 2]])
  30. ar_edges = [(0, 1), (1, 2), (2, 3), (3, 0),
  31. (4, 5), (5, 6), (6, 7), (7, 4),
  32. (0, 4), (1, 5), (2, 6), (3, 7),
  33. (4, 8), (5, 8), (6, 9), (7, 9), (8, 9)]
  34. class App:
  35. def __init__(self, src):
  36. self.cap = video.create_capture(src, presets['book'])
  37. self.frame = None
  38. self.paused = False
  39. self.tracker = PlaneTracker()
  40. cv.namedWindow('plane')
  41. cv.createTrackbar('focal', 'plane', 25, 50, common.nothing)
  42. self.rect_sel = common.RectSelector('plane', self.on_rect)
  43. def on_rect(self, rect):
  44. self.tracker.add_target(self.frame, rect)
  45. def run(self):
  46. while True:
  47. playing = not self.paused and not self.rect_sel.dragging
  48. if playing or self.frame is None:
  49. ret, frame = self.cap.read()
  50. if not ret:
  51. break
  52. self.frame = frame.copy()
  53. vis = self.frame.copy()
  54. if playing:
  55. tracked = self.tracker.track(self.frame)
  56. for tr in tracked:
  57. cv.polylines(vis, [np.int32(tr.quad)], True, (255, 255, 255), 2)
  58. for (x, y) in np.int32(tr.p1):
  59. cv.circle(vis, (x, y), 2, (255, 255, 255))
  60. self.draw_overlay(vis, tr)
  61. self.rect_sel.draw(vis)
  62. cv.imshow('plane', vis)
  63. ch = cv.waitKey(1)
  64. if ch == ord(' '):
  65. self.paused = not self.paused
  66. if ch == ord('c'):
  67. self.tracker.clear()
  68. if ch == 27:
  69. break
  70. def draw_overlay(self, vis, tracked):
  71. x0, y0, x1, y1 = tracked.target.rect
  72. quad_3d = np.float32([[x0, y0, 0], [x1, y0, 0], [x1, y1, 0], [x0, y1, 0]])
  73. fx = 0.5 + cv.getTrackbarPos('focal', 'plane') / 50.0
  74. h, w = vis.shape[:2]
  75. K = np.float64([[fx*w, 0, 0.5*(w-1)],
  76. [0, fx*w, 0.5*(h-1)],
  77. [0.0,0.0, 1.0]])
  78. dist_coef = np.zeros(4)
  79. _ret, rvec, tvec = cv.solvePnP(quad_3d, tracked.quad, K, dist_coef)
  80. verts = ar_verts * [(x1-x0), (y1-y0), -(x1-x0)*0.3] + (x0, y0, 0)
  81. verts = cv.projectPoints(verts, rvec, tvec, K, dist_coef)[0].reshape(-1, 2)
  82. for i, j in ar_edges:
  83. (x0, y0), (x1, y1) = verts[i], verts[j]
  84. cv.line(vis, (int(x0), int(y0)), (int(x1), int(y1)), (255, 255, 0), 2)
  85. if __name__ == '__main__':
  86. print(__doc__)
  87. import sys
  88. try:
  89. video_src = sys.argv[1]
  90. except:
  91. video_src = 0
  92. App(video_src).run()