t.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #!/usr/bin/python
  2. #
  3. # ENGR421 -- Applied Robotics, Spring 2013
  4. # OpenCV Python Demo
  5. # Taj Morton <mortont@onid.orst.edu>
  6. #
  7. import sys
  8. import cv2
  9. import time
  10. import numpy
  11. import os
  12. ##
  13. # Opens a video capture device with a resolution of 800x600
  14. # at 30 FPS.
  15. ##
  16. def open_camera(cam_id = 1):
  17. cap = cv2.VideoCapture(cam_id)
  18. # cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 600);
  19. # cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 800);
  20. # cap.set(cv2.cv.CV_CAP_PROP_FPS, 30);
  21. return cap
  22. ##
  23. # Gets a frame from an open video device, or returns None
  24. # if the capture could not be made.
  25. ##
  26. def get_frame(device):
  27. ret, img = device.read()
  28. if (ret == False): # failed to capture
  29. print >> sys.stderr, "Error capturing from video device."
  30. return None
  31. return img
  32. ##
  33. # Closes all OpenCV windows and releases video capture device
  34. # before exit.
  35. ##
  36. def cleanup(cam_id = 0):
  37. cv2.destroyAllWindows()
  38. cv2.VideoCapture(cam_id).release()
  39. ##
  40. # Creates a new RGB image of the specified size, initially
  41. # filled with black.
  42. ##
  43. def new_rgb_image(width, height):
  44. image = numpy.zeros( (height, width, 3), numpy.uint8)
  45. return image
  46. # Global variable containing the 4 points selected by the user in the corners of the board
  47. corner_point_list = []
  48. ##
  49. # This function is called by OpenCV when the user clicks
  50. # anywhere in a window displaying an image.
  51. ##
  52. def mouse_click_callback(event, x, y, flags, param):
  53. if event == cv2.EVENT_LBUTTONDOWN:
  54. print ("Click at (%d,%d)" % (x,y))
  55. corner_point_list.append( (x,y) )
  56. ##
  57. # Computes a perspective transform matrix by capturing a single
  58. # frame from a video source and displaying it to the user for
  59. # corner selection.
  60. #
  61. # Parameters:
  62. # * dev: Video Device (from open_camera())
  63. # * board_size: A tuple/list with 2 elements containing the width and height (respectively) of the gameboard (in arbitrary units, like inches)
  64. # * dpi: Scaling factor for elements of board_size
  65. # * calib_file: Optional. If specified, the perspective transform matrix is saved under this filename.
  66. # This file can be loaded later to bypass the calibration step (assuming nothing has moved).
  67. ##
  68. def get_transform_matrix(dev, board_size, dpi, calib_file = None):
  69. # Read a frame from the video device
  70. img = get_frame(dev)
  71. # Displace image to user
  72. cv2.imshow("Calibrate", img)
  73. # Register the mouse callback on this window. When
  74. # the user clicks anywhere in the "Calibrate" window,
  75. # the function mouse_click_callback() is called (defined above)
  76. cv2.setMouseCallback("Calibrate", mouse_click_callback)
  77. # Wait until the user has selected 4 points
  78. while True:
  79. # If the user has selected all 4 points, exit loop.
  80. if (len(corner_point_list) >= 4):
  81. print ("Got 4 points: "+str(corner_point_list))
  82. break
  83. # If the user hits a key, exit loop, otherwise remain.
  84. if (cv2.waitKey(10) >= 0):
  85. break;
  86. # Close the calibration window:
  87. cv2.destroyWindow("Calibrate")
  88. # If the user selected 4 points
  89. if (len(corner_point_list) >= 4):
  90. # Do calibration
  91. # src is a list of 4 points on the original image selected by the user
  92. # in the order [TOP_LEFT, BOTTOM_LEFT, TOP_RIGHT, BOTTOM_RIGHT]
  93. src = numpy.array(corner_point_list, numpy.float32)
  94. # dest is a list of where these 4 points should be located on the
  95. # rectangular board (in the same order):
  96. dest = numpy.array( [ (0, 0), (0, board_size[1]*dpi), (board_size[0]*dpi, 0), (board_size[0]*dpi, board_size[1]*dpi) ], numpy.float32)
  97. # Calculate the perspective transform matrix
  98. trans = cv2.getPerspectiveTransform(src, dest)
  99. # If we were given a calibration filename, save this matrix to a file
  100. if calib_file:
  101. numpy.savetxt(calib_file, trans)
  102. return trans
  103. else:
  104. return None
  105. #####################################################
  106. ### Calibration Example ###
  107. if __name__ == "__main__":
  108. cam_id = 0
  109. dev = open_camera(cam_id)
  110. # The size of the board in inches, measured between the two
  111. # robot boundaries:
  112. board_size = [22.3125, 45]
  113. # Number of pixels to display per inch in the final transformed image. This
  114. # was selected somewhat arbitrarily (I chose 17 because it fit on my screen):
  115. dpi = 17
  116. # Calculate the perspective transform matrix
  117. transform = get_transform_matrix(dev, board_size, dpi)
  118. # Size (in pixels) of the transformed image
  119. transform_size = (int(board_size[0]*dpi), int(board_size[1]*dpi))
  120. while True:
  121. img_orig = get_frame(dev)
  122. if img_orig is not None: # if we did get an image
  123. # Show the original (untransformed) image
  124. cv2.imshow("video", img_orig)
  125. # Apply the transformation matrix to skew the image and display it
  126. img = cv2.warpPerspective(img_orig, transform, dsize=transform_size)
  127. cv2.imshow("warped", img)
  128. else: # if we failed to capture (camera disconnected?), then quit
  129. break
  130. if (cv2.waitKey(2) >= 0):
  131. break
  132. cleanup(cam_id)