camera_position.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. ''' Camera position estimation from center marker '''
  2. import cv2
  3. from cv2 import aruco
  4. import numpy as np
  5. import math
  6. import sys
  7. import os
  8. sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
  9. from default_config import *
  10. visualization = True
  11. # Tải dữ liệu hiệu chuẩn camera, phù hợp với độ phân giải ban đầu
  12. calib_data_path = f"camera_calibration/calib_data/{set_resolution}/MultiMatrix.npz"
  13. calib_data = np.load(calib_data_path)
  14. print('resolution:', set_resolution)
  15. cam_mat = calib_data["camMatrix"]
  16. dist_coef = calib_data["distCoef"]
  17. marker_dict = aruco.getPredefinedDictionary(aruco.DICT_7X7_50)
  18. param_markers = aruco.DetectorParameters()
  19. cap = cv2.VideoCapture(0)
  20. # Thay đổi độ phân giải phù hợp với yêu cầu ban đầu
  21. new_height = RESOLUTION_STANDARDS[set_resolution]
  22. new_width, new_height = change_resolution(cap,new_height)
  23. print(f'Resolution camera {new_width}x{new_height}')
  24. fps = cap.get(cv2.CAP_PROP_FPS)
  25. print(f"Frames per second: {fps}")
  26. # convert rotation matrix to euler angles (degrees)
  27. def rotationMatrixEulerAngles(rotMatrix):
  28. assert rotMatrix.shape == (3, 3), "Ma trận quay phải có kích thước 3x3"
  29. sy = math.sqrt(rotMatrix[0, 0]* rotMatrix[0, 0] + rotMatrix[1, 0]*rotMatrix[1, 0])
  30. singular = sy < 1e-6
  31. if not singular:
  32. x = math.atan2(rotMatrix[2, 1], rotMatrix[2, 2])
  33. x = np.round(np.degrees(x))
  34. y = math.atan2(-rotMatrix[2, 0], sy)
  35. y = np.round(np.degrees(y))
  36. z = math.atan2(rotMatrix[1, 0], rotMatrix[0, 0])
  37. z = np.round(np.degrees(z))
  38. else:
  39. x = math.atan2(rotMatrix[1, 0], rotMatrix[0, 0])
  40. x = np.round(np.degrees(x))
  41. y = math.atan2(-rotMatrix[2, 0], sy)
  42. y = np.round(np.degrees(y))
  43. z = 0
  44. return np.array([x, y, z])
  45. while True:
  46. ret, frame = cap.read()
  47. center_y, center_x = frame.shape[0]//2, frame.shape[1]//2
  48. cv2.drawMarker(frame, (center_x, center_y), (0,0,255), markerType=cv2.MARKER_CROSS, markerSize=10, thickness=1, line_type=cv2.LINE_AA)
  49. if not ret:
  50. break
  51. gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  52. marker_corners, marker_IDs, reject = aruco.detectMarkers(
  53. gray_frame, marker_dict, parameters=param_markers
  54. )
  55. if marker_corners:
  56. rVec, tVec, _ = aruco.estimatePoseSingleMarkers(
  57. marker_corners, MARKER_SIZE, cam_mat, dist_coef
  58. )
  59. total_markers = range(0, marker_IDs.size)
  60. markers = {}
  61. for ids, corners, i in zip(marker_IDs, marker_corners, total_markers):
  62. corners = corners.reshape(4, 2)
  63. corners = corners.astype(int)
  64. top_right = corners[0].ravel()
  65. top_left = corners[1].ravel()
  66. bottom_right = corners[2].ravel()
  67. bottom_left = corners[3].ravel()
  68. # Chuyển đổi rVec thành ma trận quay R
  69. R, _ = cv2.Rodrigues(rVec[i])
  70. # Tính toán tọa độ các điểm của marker so với camera
  71. object_points = np.array([
  72. [-MARKER_SIZE / 2, MARKER_SIZE / 2, 0],
  73. [MARKER_SIZE / 2, MARKER_SIZE / 2, 0],
  74. [MARKER_SIZE / 2, -MARKER_SIZE / 2, 0],
  75. [-MARKER_SIZE / 2, -MARKER_SIZE / 2, 0]
  76. ])
  77. marker_points_camera = R @ object_points.T + tVec[i].reshape(3, 1)
  78. marker_points_camera = marker_points_camera.T
  79. distance = np.linalg.norm(tVec[i][0])
  80. # Draw the pose of the marker
  81. point = cv2.drawFrameAxes(frame, cam_mat, dist_coef, rVec[i], tVec[i], 4, 4)
  82. # R, _ = cv2.Rodrigues(rVec[i]) # Chuyển rVec sang ma trận quay
  83. # R_inv = R.T # Lấy nghịch đảo của ma trận quay (tức là R^T nếu R là trực giao)
  84. # position = - R_inv @ tVec[i].reshape(3, 1) # Tính vị trí camera trong hệ marker
  85. #
  86. #
  87. # position = position.reshape(3,)
  88. position =np.array([-tVec[i][0][0], tVec[i][0][1], tVec[i][0][2]])
  89. position += default_positions[ids[0]]
  90. angles = rotationMatrixEulerAngles(R.T)
  91. markers[f'marker {ids[0]}'] = np.hstack((position, angles))
  92. if visualization:
  93. cv2.putText(
  94. frame,
  95. f"id: {ids[0]}",
  96. top_right,
  97. cv2.FONT_HERSHEY_PLAIN,
  98. 1.3,
  99. (0, 0, 255), 2, cv2.LINE_AA
  100. )
  101. # Nếu marker trung tâm (marker 0) xuất hiện thì chỉ cần lấy vị trí so với marker này
  102. if 'marker 0' in markers.keys():
  103. cam_position = markers['marker 0']
  104. # Nếu không, xét trung bình các marker
  105. else:
  106. cam_position = np.array([0., 0., 0., 0., 0., 0.])
  107. for v in markers.values():
  108. cam_position += v
  109. cam_position /= len(markers)
  110. print(','.join(f'{i:.1f}' for i in cam_position.tolist()))
  111. if visualization:
  112. cv2.putText(
  113. frame,
  114. ','.join(f'{i:.1f}' for i in cam_position[:3].tolist()),
  115. (10, 20),
  116. cv2.FONT_HERSHEY_PLAIN,
  117. 1.,
  118. (0, 255, 0), 1, cv2.LINE_AA
  119. )
  120. cv2.putText(
  121. frame,
  122. ','.join(f'{i:.1f}' for i in cam_position[3:].tolist()),
  123. (10, 40),
  124. cv2.FONT_HERSHEY_PLAIN,
  125. 1.,
  126. (0, 0, 255), 1, cv2.LINE_AA
  127. )
  128. if visualization:
  129. cv2.imshow("frame", frame)
  130. key = cv2.waitKey(1)
  131. if key == ord("q"):
  132. break
  133. cap.release()
  134. if visualization:
  135. cv2.destroyAllWindows()