본문 바로가기

Embedded LAB Semina

공까지의 거리 추적하기(2) :: 발돋움,, 이미지 캡쳐 + 카메라 캘리브레이션

import cv2

# 비디오 캡처 초기화
cap = cv2.VideoCapture(1)

img_counter = 0

while True:
    ret, frame = cap.read()
    if not ret:
        break

    cv2.imshow('Frame', frame)

    k = cv2.waitKey(1)
    if k % 256 == 27:
        # ESC 키를 눌러 종료
        break
    elif k % 256 == 115:
        # 's' 키를 눌러 이미지 저장
        img_name = f"image_{img_counter}.png"
        cv2.imwrite(img_name, frame)
        print(f"{img_name} 저장 완료")
        img_counter += 1

cap.release()
cv2.destroyAllWindows()

 

import cv2
import numpy as np
import glob

# 체스보드 크기
chessboard_size = (8, 6)
square_size = 0.021  # 체스보드 한 칸의 크기 (미터 단위)

# 체스보드의 3D 포인트 준비
objp = np.zeros((np.prod(chessboard_size), 3), dtype=np.float32)
objp[:, :2] = np.indices(chessboard_size).T.reshape(-1, 2)
objp *= square_size

# 3D 포인트와 2D 이미지 포인트 저장
obj_points = []
img_points = []
gray = None

# 저장된 이미지 파일 불러오기
images = glob.glob('calibration_image/*.png')  # 이미지 경로에 맞게 수정

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
    
    if ret:
        obj_points.append(objp)
        img_points.append(corners)
        cv2.drawChessboardCorners(img, chessboard_size, corners, ret)
        cv2.imshow('Image', img)
        cv2.waitKey(500)

cv2.destroyAllWindows()

if gray is not None:
    # 캘리브레이션 수행
    ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None)
    print(f'Camera Matrix: \n{camera_matrix}')
    print(f'Distortion Coefficients: \n{dist_coeffs}')

    # 초점 거리 추출 및 평균 계산
    fx = camera_matrix[0, 0]
    fy = camera_matrix[1, 1]
    focal_length = (fx + fy) / 2
    print(f'Focal Length: {focal_length}')
else:
    print("이미지를 불러오지 못했습니다.")