Camera Calibration 정리

OpenJR·2023년 2월 19일
0

이 글은 핀홀 카메라만 다루고 있습니다.

카메라 캘리브레이션의 목적은 카메라 내부 파라미터 (Intrinsic parameter)와 왜곡 계수(Distortion Coefficients)를 구하는 것이다.

왜곡 계수

핀홀 카메라의 왜곡은 방사형 왜곡(Radial Distortion)과 접선 왜곡(Tangential Distortion) 2가지로 나뉜다.

방사형 왜곡

렌즈에 의해 발생하는 왜곡이다. 왜곡으로 인해 변형되는 픽셀의 값은 다음과 같다.

xd=(1+k1r2+k2r4+k3r6)xuyd=(1+k1r2+k2r4+k3r6)yur2=(xdcx)2+(ydcy)2x_d = (1+k_1r^2 + k_2r^4 +k_3r^6)x_{u}\\ y_d = (1+k_1r^2 + k_2r^4 +k_3r^6)y_{u}\\ r^2 = (x_d - c_x)^2 + (y_d - c_y)^2

접선 왜곡

접선 왜곡은 제조과정에서 카메라 렌즈와 카메라 센서(CMOS)가 완벽히 평행하지 않아 발행되는 왜곡이다.

xd=xu+[2p1xuyy+p2(r2+2xu2)]yd=yu+[2p2xuyy+p1(r2+2yu2)]r2=(xdcx)2+(ydcy)2x_d = x_u + [2p_1x_uy_y+p_2(r^2+2x^2_u)]\\ y_d = y_u + [2p_2x_uy_y+p_1(r^2+2y^2_u)]\\ r^2 = (x_d - c_x)^2 + (y_d - c_y)^2

결국, 우리가 알아내야 하는 값은 k1k_1, k2k_2, k3k_3, p1p_1, p2p_2이며 이 값들은 OpenCV에서 왜곡 계수는 [k1, k2, p1, p2, k3] 순으로 값이 구해지게 된다.

카메라 내부 파라미터


카메라 내부 파라미터를 구성하는 요소들은 다음과 같다.

  • Focal Length (초점 거리): 렌즈 중심에서 이미지 센서까지의 거리.
  • Principal Point (주점): 렌즈의 중심에서 이미지 센서에 내린 수선의 발의 이미지 상 좌표.
  • Skew Coefficient (비대칭 계수): 이미지 센서가 제조 공정상 기울어진 정도 (현대 카메라에서는 거의 없음)

위 값들은 3차원 물체의 위치를 2차원 이미지의 좌표로 투영할 때 사용된다.

OpenCV 코드

전체적인 코드를 보기를 전 주요한 OpenCV 함수들에 대해 먼저 알아보겠습니다.

findChessboardCorners()

retval, corners = cv2.findChessboardCorners(image, patternSize, flags)
  • image: 체커보드 이미지
  • patternSize: 체커보드 행과 열의 코너 수
  • flags: Corner Detection 알고리즘 적용 시 옵션 값 (default=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE)
    • CALIB_CB_ADAPTIVE_THRESH: 이진화 시, Adaptive Threshold 적용
    • CALIB_CB_NORMALIZE_IMAGE: 이진화 적용 전, 히스토그램 평활화로 흰색과 검은색 분리
    • CALIB_CB_FILTER_QUADS: 코너 점 찾은 후, 점들 간의 위치로 사각형의 코너가 아닌 점들을 필터링
    • CALIB_CB_FAST_CHECK: Corner Detection 알고리즘이 동작 전, 이미지에 체스보드 패턴이 있는지 검사해, 없으면 빠르게 false를 리턴

cornerSubPix()

corners2 = cv2.cornerSubPix(image, corners, winSize, zeroZone, criteria)
  • image: 체커보드 이미지
  • corners: findChessboardCorners()로 검출된 코너 값 (개선 전)
  • winSize: 코너를 개선하기위해 gradient vector를 고려할 윈도우의 크기. (11, 11)은 총 23X23의 윈도우 크기를 가진다.
  • zeroZone: winSize에서 배제될 영역의 크기, 보통은 (-1, -1)로 설정하지 않게 된다.
  • criteria: 알고리즘이 종료될 조건을 설정하는 부분. 보통 (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)로 설정하며, 이것은 최대 반복 수 30, 이전 값과의 차이 0.001 미만 일 때 종료라는 의미이다.


winSize=(3, 3), zeroZone=(1, 1)일 경우,

  • 초록색: grdient가 고려될 픽셀들
  • 회색: zeroZone으로 배제될 픽셀들

calibrateCamera()

return_value, camera_matrix, distortion_coefficients, rotation_vectors, translation_vectors = cv2.calibrateCamera(object_points, image_points, imageSize, init_matrix, init_coefficients, rvecs, tvecs, flags, criteria)
  • object_points: 실제 객체들의 3차원 좌표
  • image_points: 이미지에 투영된 객체들의 이미지 좌표
  • imageSize: 이미지 크기
  • init_matrix: 초기 추정 내부 파라미터
  • init_coefficients: 초기 추정 왜곡 계수
  • rvecs: 초기 추정 rotation vectors
  • tvecs: 초기 추정 translation vectors
  • flags: 캘리브레이션 옵션 (옵션이 13개나 있다. 이것 만큼은 직접 찾아보자. 주로 초기 추정 값이 있으면 아래의 옵션을 추가한다.)
    • CALIB_USE_INTRINSIC_GUESS: 내부 파라미터 초기 값으로 최적화
  • criteria: 알고리즘이 종료될 조건을 설정하는 부분. 보통 (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)로 설정하며, 이것은 최대 반복 수 30, 이전 값과의 차이 0.001 미만 일 때 종료라는 의미이다.

getOptimalNewCameraMatrix()

undistort()

initUndistortRectifyMap() & remap

profile
Jacob

0개의 댓글