이미지 왜곡 보정
, 3D 포인트 복원 등 다양한 컴퓨터 비전 작업에 필수적다양한 각도와 거리에서 촬영
코너 검출 알고리즘: OpenCV의 findChessboardCorners
함수를 사용합니다.
코드 예시:
import cv2
import numpy as np
# 체스보드 크기
chessboard_size = (9, 6)
# 객체 포인트와 이미지 포인트 저장할 배열
objpoints = []
imgpoints = []
# 체스보드 패턴 생성
objp = np.zeros((np.prod(chessboard_size), 3), np.float32)
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
# 이미지 로드
images = [...] # 캘리브레이션 이미지 파일 리스트
for image in images:
img = cv2.imread(image)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None)
if ret:
objpoints.append(objp)
imgpoints.append(corners)
# 코너를 이미지에 그립니다.
cv2.drawChessboardCorners(img, chessboard_size, corners, ret)
cv2.imshow('img', img)
cv2.waitKey(500)
cv2.destroyAllWindows()
캘리브레이션 함수: cv2.calibrateCamera
를 사용하여 intrinsic 파라미터를 구합니다.
코드 예시:
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# 결과 출력
print("Camera matrix:\n", mtx)
print("Distortion coefficients:\n", dist)
캘리브레이션이 잘 되었는지 확인하기 위해 몇 가지 검증 단계를 거칩니다.
리프로젝션 에러 계산:
mean_error = 0
for i in range(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2)/len(imgpoints2)
mean_error += error
print("Total error: ", mean_error/len(objpoints))
캘리브레이션된 파라미터를 사용하여 왜곡 보정된 이미지를 확인합니다.
코드 예시:
img = cv2.imread(images[0])
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
# 왜곡 보정
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
# 결과를 자르고 저장
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png', dst)
cv2.findChessboardCorners
메서드cv2.findChessboardCorners
는 체스보드 패턴에서 코너를 찾는 함수입니다.
알고리즘은 다음 단계를 거칩니다:
1. 그레이스케일 변환:
(열, 행) 쌍
으로, None
으로 전달None
으로 설정되며, 다양한 설정 값을 지정할 수 있습니다.True
이면 코너를 찾았음을 의미ret
이 True
일 때 유효합니다.cv2.cornerSubPix
메서드cv2.cornerSubPix
는 감지된 코너의 위치를 서브픽셀 수준으로 정제cv2.findChessboardCorners
의 출력 값입니다.cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER
로 설정하여 최대 반복 횟수와 정확도를 기준으로 정지합니다.corners
배열의 정제된 버전cv2.drawChessboardCorners
메서드cv2.drawChessboardCorners
는 체스보드 패턴에서 감지된 코너를 이미지 위에 그리는 함수체스보드 패턴의 내부 코너 개수 (열, 행) 쌍.
cv2.findChessboardCorners
나 cv2.cornerSubPix
의 출력 값입니다.cv::calibrateCamera
함수std::vector<std::vector<cv::Vec3f>>
). std::vector<std::vector<cv::Vec2f>>
). imagePoints.size()
와 objectPoints.size()
, i
에 대해 imagePoints[i].size()
와 objectPoints[i].size()
가 같아야 합니다. CALIB_USE_INTRINSIC_GUESS
및/또는 CALIB_FIX_ASPECT_RATIO
, CALIB_FIX_PRINCIPAL_POINT
또는 CALIB_FIX_FOCAL_LENGTH
가 지정된 경우, 호출 전에 fx
, fy
, cx
, cy
의 일부 또는 전부가 초기화되어야 합니다.[k1, k2, p1, p2, k3]
을 포함하며, (array([[ 0.01413114], [ 0.01593625], [-0.00571477]]),)
(array([[-3.89025738], [-2.26881858], [ 7.43518093]]),)
CALIB_FIX_K?
가 지정된 경우 제외).imagePoints
와 objectPoints
간의 projectPoints
를 참조하십시오.findChessboardCorners
로 캘리브레이션을 수행하며, calibrateCamera
가 잘못된 값을 반환하는 경우 (왜곡 계수가 0이고, cx
및 cy
가 이미지 중심에서 매우 멀리 떨어져 있으며, fx
와 fy
간의 큰 차이 (비율이 10:1 이상)), patternSize=cvSize(rows, cols)
대신 patternSize=cvSize(cols, rows)
를 사용하고 있는지 확인하십시오.cv2.getOptimalNewCameraMatrix()
함수를 사용하여 카메라 메트릭스(intrinsic)
를 개선할 수 있음왜곡 현상을 제거할 하나를 사용해 이미지의 크기를 얻고
, 카메라 메트릭스(intrinsic)를 얻는 코드
는 다음과 같습니다.img = cv2.imread('./data/chess/left12.jpg')
h, w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
cv::getOptimalNewCameraMatrix
함수initUndistortRectifyMap
에 전달되어 remap
용 맵을 생성원본 이미지의 모든 픽셀
이 왜곡 보정된 이미지
에 유지)stereoRectify
를 참조imageSize
로 설정됩니다.출력되는 새로운 카메라 intrinsic 행렬.
왜곡 보정된 이미지에서 모든 유효 픽셀 영역을 둘러싼 사각형
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)
cv::undistort
함수initUndistortRectifyMap
(단위 행렬 R을 사용)remap
(쌍선형 보간법을 사용)initUndistortRectifyMap
함수를 참조newCameraMatrix
로 조정할 수 있습니다.카메라 행렬
및 왜곡 파라미터
는 calibrateCamera
를 사용하여 결정할 수 있음fx
와 fy
, cx
와 cy
는 각각 스케일링되어야 하며, 왜곡 계수는 동일하게 유지됨newCameraMatrix
를 사용할 수 있음cameraMatrix
와 동일하지만, 다른 행렬을 사용하여 결과를 추가로 스케일링하고 이동시킬 수 있음mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)
왜곡 제거: 이미지의 프로젝션
cv2.projectPoints()
함수가 사용 tot_error = 0
for i in range(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
tot_error += error
print("total error: ", tot_error/len(objpoints))