import numpy as np
import cv2
import label as lb
import calib as cl
# 캘리브레이션 행렬(P2) 반환
def load_calibration():
return cl.calib_matrix["P2"]
# 객체 1개의 3D 바운딩 박스 꼭짓점 8개 (3x8)를 rectified camera 좌표계로 계산
def get_3d_box_corners(data):
h, w, l = data['dimensions']
x, y, z = data['location']
yaw = data['rotation_y']
# 회전 행렬
R = np.array([
[np.cos(yaw), 0, np.sin(yaw)],
[0, 1, 0],
[-np.sin(yaw), 0, np.cos(yaw)]
])
# 바운딩 박스 8개 꼭짓점 (중심 기준)
x_corners = [l/2, l/2, -l/2, -l/2, l/2, l/2, -l/2, -l/2]
y_corners = [h/2, h/2, h/2, h/2, -h/2, -h/2, -h/2, -h/2]
z_corners = [w/2, -w/2, -w/2, w/2, w/2, -w/2, -w/2, w/2]
corners_3d = R @ np.vstack([x_corners, y_corners, z_corners]) + np.array([[x], [y], [z]])
return corners_3d # shape (3, 8)
# 3D 점들(3xN)을 P 행렬로 2D 이미지 좌표계(2xN)로 투영
def project_to_image(corners_3d, P):
corners_3d_hom = np.vstack([corners_3d, np.ones((1, corners_3d.shape[1]))])
corners_2d_hom = P @ corners_3d_hom
corners_2d_hom[:2, :] /= corners_2d_hom[2, :] # x/z, y/z
return corners_2d_hom[:2, :]
# 2D 영상 위에 바운딩 박스의 꼭짓점 번호와 선을 그림
def draw_3d_box(image, corners_2d, box_id=None):
# 각 꼭짓점 번호 출력
for i in range(corners_2d.shape[1]):
pt = (int(corners_2d[0, i]), int(corners_2d[1, i]))
cv2.putText(image, str(i), pt, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
# 3D 박스 연결선
lineset = np.array([
[0, 1], [1, 2], [2, 3], [3, 0], # 윗면
[4, 5], [5, 6], [6, 7], [7, 4], # 아랫면
[0, 4], [1, 5], [2, 6], [3, 7] # 측면
])
for i, j in lineset:
pt1 = (int(corners_2d[0, i]), int(corners_2d[1, i]))
pt2 = (int(corners_2d[0, j]), int(corners_2d[1, j]))
cv2.line(image, pt1, pt2, (255, 0, 0), 2)
# 객체 ID가 주어졌다면 왼쪽 위에 출력
if box_id is not None:
pt = (int(np.min(corners_2d[0])), int(np.min(corners_2d[1])) - 5)
cv2.putText(image, f"Obj {box_id}", pt, cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 255), 2)
# main 함수
def main():
# 파일 경로
image_file_path = "../../dataset/data_object_image_2/training/image_2/000010.png"
# 이미지 불러오기
image = cv2.imread(image_file_path)
if image is None:
raise FileNotFoundError(f"이미지를 불러올 수 없습니다: {image_file_path}")
# P2 행렬 불러오기
P2 = load_calibration()
# 모든 객체에 대해 바운딩 박스 처리
for idx, data in enumerate(lb.labels):
corners_3d = get_3d_box_corners(data)
corners_2d = project_to_image(corners_3d, P2)
draw_3d_box(image, corners_2d, box_id=idx)
# 시각화
cv2.imshow('3D Bounding Boxes on Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 실행
if __name__ == "__main__":
main()