''' Camera position estimation from center marker ''' import cv2 from cv2 import aruco import numpy as np import math import sys import os sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from default_config import * visualization = True # Tải dữ liệu hiệu chuẩn camera, phù hợp với độ phân giải ban đầu calib_data_path = f"camera_calibration/calib_data/{set_resolution}/MultiMatrix.npz" calib_data = np.load(calib_data_path) print('resolution:', set_resolution) cam_mat = calib_data["camMatrix"] dist_coef = calib_data["distCoef"] marker_dict = aruco.getPredefinedDictionary(aruco.DICT_7X7_50) param_markers = aruco.DetectorParameters() cap = cv2.VideoCapture(0) # Thay đổi độ phân giải phù hợp với yêu cầu ban đầu new_height = RESOLUTION_STANDARDS[set_resolution] new_width, new_height = change_resolution(cap,new_height) print(f'Resolution camera {new_width}x{new_height}') fps = cap.get(cv2.CAP_PROP_FPS) print(f"Frames per second: {fps}") # convert rotation matrix to euler angles (degrees) def rotationMatrixEulerAngles(rotMatrix): assert rotMatrix.shape == (3, 3), "Ma trận quay phải có kích thước 3x3" sy = math.sqrt(rotMatrix[0, 0]* rotMatrix[0, 0] + rotMatrix[1, 0]*rotMatrix[1, 0]) singular = sy < 1e-6 if not singular: x = math.atan2(rotMatrix[2, 1], rotMatrix[2, 2]) x = np.round(np.degrees(x)) y = math.atan2(-rotMatrix[2, 0], sy) y = np.round(np.degrees(y)) z = math.atan2(rotMatrix[1, 0], rotMatrix[0, 0]) z = np.round(np.degrees(z)) else: x = math.atan2(rotMatrix[1, 0], rotMatrix[0, 0]) x = np.round(np.degrees(x)) y = math.atan2(-rotMatrix[2, 0], sy) y = np.round(np.degrees(y)) z = 0 return np.array([x, y, z]) while True: ret, frame = cap.read() center_y, center_x = frame.shape[0]//2, frame.shape[1]//2 cv2.drawMarker(frame, (center_x, center_y), (0,0,255), markerType=cv2.MARKER_CROSS, markerSize=10, thickness=1, line_type=cv2.LINE_AA) if not ret: break gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) marker_corners, marker_IDs, reject = aruco.detectMarkers( gray_frame, marker_dict, parameters=param_markers ) if marker_corners: rVec, tVec, _ = aruco.estimatePoseSingleMarkers( marker_corners, MARKER_SIZE, cam_mat, dist_coef ) total_markers = range(0, marker_IDs.size) markers = {} for ids, corners, i in zip(marker_IDs, marker_corners, total_markers): corners = corners.reshape(4, 2) corners = corners.astype(int) top_right = corners[0].ravel() top_left = corners[1].ravel() bottom_right = corners[2].ravel() bottom_left = corners[3].ravel() # Chuyển đổi rVec thành ma trận quay R R, _ = cv2.Rodrigues(rVec[i]) # Tính toán tọa độ các điểm của marker so với camera object_points = np.array([ [-MARKER_SIZE / 2, MARKER_SIZE / 2, 0], [MARKER_SIZE / 2, MARKER_SIZE / 2, 0], [MARKER_SIZE / 2, -MARKER_SIZE / 2, 0], [-MARKER_SIZE / 2, -MARKER_SIZE / 2, 0] ]) marker_points_camera = R @ object_points.T + tVec[i].reshape(3, 1) marker_points_camera = marker_points_camera.T distance = np.linalg.norm(tVec[i][0]) # Draw the pose of the marker point = cv2.drawFrameAxes(frame, cam_mat, dist_coef, rVec[i], tVec[i], 4, 4) # R, _ = cv2.Rodrigues(rVec[i]) # Chuyển rVec sang ma trận quay # 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) # position = - R_inv @ tVec[i].reshape(3, 1) # Tính vị trí camera trong hệ marker # # # position = position.reshape(3,) position =np.array([-tVec[i][0][0], tVec[i][0][1], tVec[i][0][2]]) position += default_positions[ids[0]] angles = rotationMatrixEulerAngles(R.T) markers[f'marker {ids[0]}'] = np.hstack((position, angles)) if visualization: cv2.putText( frame, f"id: {ids[0]}", top_right, cv2.FONT_HERSHEY_PLAIN, 1.3, (0, 0, 255), 2, cv2.LINE_AA ) # 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 if 'marker 0' in markers.keys(): cam_position = markers['marker 0'] # Nếu không, xét trung bình các marker else: cam_position = np.array([0., 0., 0., 0., 0., 0.]) for v in markers.values(): cam_position += v cam_position /= len(markers) print(','.join(f'{i:.1f}' for i in cam_position.tolist())) if visualization: cv2.putText( frame, ','.join(f'{i:.1f}' for i in cam_position[:3].tolist()), (10, 20), cv2.FONT_HERSHEY_PLAIN, 1., (0, 255, 0), 1, cv2.LINE_AA ) cv2.putText( frame, ','.join(f'{i:.1f}' for i in cam_position[3:].tolist()), (10, 40), cv2.FONT_HERSHEY_PLAIN, 1., (0, 0, 255), 1, cv2.LINE_AA ) if visualization: cv2.imshow("frame", frame) key = cv2.waitKey(1) if key == ord("q"): break cap.release() if visualization: cv2.destroyAllWindows()