Study: Artificial Intelligence(AI)/AI: 2D Vision(Det, Seg, Trac)

[Perception] ์นด๋ฉ”๋ผ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์‹ค์Šต (camera calibration): opencv, intrinsic, extrinsic, checker(chess) board ํ™œ์šฉ

DrawingProcess 2024. 2. 17. 12:46
๋ฐ˜์‘ํ˜•
๐Ÿ’ก ๋ณธ ๋ฌธ์„œ๋Š” '[Perception] ์นด๋ฉ”๋ผ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜ ์‹ค์Šต (camera calibration): intrinsic, checker(chess) board ํ™œ์šฉ'์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋†“์€ ๊ธ€์ž…๋‹ˆ๋‹ค.
Checker board๋ฅผ ํ™œ์šฉํ•˜์—ฌ Intrinsic Metrix๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ๋˜ ์ฝ”๋“œ ๋ฐ return๊ฐ’์— ๋Œ€ํ•ด ์ •๋ฆฌํ•˜์˜€์œผ๋‹ˆ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Intrinsic Metrix(K) ์ „์ฒด ์ฝ”๋“œ

import numpy as np
import cv2 as cv
import glob

wc = 8 - 1
hc = 5 - 1
square_size = 70     # QHD 7cm
square_size = 52.5   # FHD 5.25cm

# termination criteria
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((wc*hc,3), np.float32)
objp[:,:2] = np.mgrid[0:wc,0:hc].T.reshape(-1,2)*square_size # square_size unit [mm]
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

dataset = "/home/avs/dataset/blackbox_intrinsic/QHD/"
images = glob.glob(dataset + '*.jpg')

for fname in images:
    img = cv.imread(fname)
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners = cv.findChessboardCorners(gray, (wc,hc), None)
    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)
        corners2 = cv.cornerSubPix(gray,corners, (11,11), (-1,-1), criteria)
        imgpoints.append(corners)
        # Draw and display the corners
        cv.drawChessboardCorners(img, (wc,hc), corners2, ret)
        print(fname)
        # cv.imshow('img', img)
        # cv.waitKey(1000)

cv.destroyAllWindows()

ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

print(ret, mtx, dist,rvecs,tvecs,sep='\n')

Intrinsic Metrix ๋ถ€๋ถ„ ์„ค๋ช…

calibration metrix๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋Œ€๊ฒŒ chess board ์ฝ”๋„ˆ์˜ Width, Height์™€ chess board square size๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ€๋กœ์˜ ์‚ฌ๊ฐํ˜• ๊ฐœ์ˆ˜์ธ 8๊ฐœ, ์„ธ๋กœ ์‚ฌ๊ฐํ˜• ๊ฐœ์ˆ˜์ธ 5๊ฐœ ์‚ฌ์ด์˜ internal ์ฝ”๋„ˆ์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด์„œ 1์”ฉ ๋นผ์คŒ์œผ๋กœ์„œ ๋„ฃ์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ chess board square size๋Š” ์‹ค์ œ ํฌ๊ธฐ๋ฅผ ๊ตฌํ•œ ํ›„ mm ๋‹จ์œ„๋กœ ๋„ฃ์–ด์ฃผ์–ด 3์ฐจ์› ๋ณ€ํ™˜์‹œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

wc = 8 - 1
hc = 5 - 1
square_size = 70     # QHD 7cm
...
objp[:,:2] = np.mgrid[0:wc,0:hc].T.reshape(-1,2)*square_size # square_size unit [mm]

์ดํ›„์˜ ์ฝ”๋“œ๋Š” ๊ทธ๋Œ€๋กœ ๋„ฃ์–ด์ฃผ๋ฉด๋˜๋ฉฐ, ๊ฒฐ๊ณผ ๊ฐ’์œผ๋กœ ๋ฝ‘ํžˆ๋Š” ๊ฐ’๋“ค์„ ๋ถ„์„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

cv.calibrateCamera() which returns the camera matrix, distortion coefficients, rotation and translation vectors etc.

  • retval: average re-projection error. This number gives a good estimation of precision of the found parameters. This should be as close to zero as possible.
  • camera matrix(mtx): intrinsic parameters of the camera
  • distortion coefficients(dist): radial and tangential distortion parameters (k1, k2, p1, p2, k3)
  • rotation and translation vectors(rvecs, tvecs): extrinsic parameters of the camera

์ถ”๊ฐ€๋กœ retval ์˜ ๊ฒฝ์šฐ, parameter๋ฅผ ์–ผ๋งˆ๋‚˜ ์ž˜ ์ถ”์ •ํ–ˆ๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ, rms ๊ฐ’์ด 1์ผ ๊ฒฝ์šฐ 3D chess board point๋ฅผ 2D์— ํˆฌ์˜ํ–ˆ์„ ๋•Œ image point์™€ ๋น„๊ตํ•˜์—ฌ ํ‰๊ท ์ ์œผ๋กœ 1.0px๊ฐ€ ์ฐจ์ด๊ฐ€ ๋‚˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์ข‹์€ ๊ฐ’์ด๋ฉฐ, ๋Œ€๊ฒŒ [0,1] ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ–๋Š”๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

์ฐธ๊ณ 

๋ฐ˜์‘ํ˜•