logo

카메라 교정

카메라 왜곡

  • 카메라 렌즈의 효과로 생기는 왜곡: 볼록하면 배럴(barrel), 오목하면 핀쿠션(pincushion)
  • 교정 방법
  • 교정 패턴(Calibration pattern): 다양한 관점에서 알려진 차원의 패턴의 이미지를 여러 장 캡처 (체커보드 패턴, 원형 패턴 등)
  • 기하학적 단서(Geometric clues): 직선과 소실점과 같은 기하학적 단서를 사용
  • 딥러닝 기반: 다양한 렌즈의 이미지를 딥러닝으로 학습시켜 보정 (한 장만 있어도 사용할 수 있음, 학습된 모델이 필요)

카메라 왜곡 이미지 1

카메라 왜곡 이미지 2

체커보드 패턴 다운로드 받기

체커보드 패턴 다운로드 받기 이미지 1

체커보드 패턴의 교차점 찾기

src = cv.imread('fisheye01.jpg')
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)  # 흑백으로
patternSize = 7, 10  # + 모양 교차점의 개수(7행 10열)
flags = (cv.CALIB_CB_ADAPTIVE_THRESH | cv.CALIB_CB_FAST_CHECK |
         cv.CALIB_CB_NORMALIZE_IMAGE)
# 교차 찾기(찾는데 성공하면 retval == True)
retval, corners = cv.findChessboardCorners(gray, patternSize, flags=flags)

체커보드 패턴의 교차점 찾기 이미지 1

교차점을 더 정확하게

# 11x11 범위에서 더 정확하게 찾기. (-1, -1)은 제외하는 범위가 없다는 뜻.
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners2 = cv.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
# 찾은 교차점을 원본 이미지에 추가
img_corner = cv.drawChessboardCorners(src, patternSize, corners2, retval)

교차점을 더 정확하게 이미지 1

교정 준비

# fisheye 로 시작하는 jpg 파일 모두 찾기 (*은 "아무 글자들"을 뜻함)
import glob
filenames = glob.glob('fisheye*.jpg')

# 좌표들
objpoints = [] # 3차원 좌표
imgpoints = [] # 2차원 좌표
objp = np.zeros((1, patternSize[0] * patternSize[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:patternSize[0], 0:patternSize[1]].T.reshape(-1, 2)

모든 이미지에서 교차점 좌표 찾기

for fname in filenames:  # 모든 파일에 대해
    gray = cv.imread(fname, cv.IMREAD_GRAYSCALE)
    retval, corners = cv.findChessboardCorners(gray, patternSize,flags=flags)
    if retval:  # 교차점을 찾았으면
        objpoints.append(objp)  # 3차원 좌표 추가
        corners2 = cv.cornerSubPix(gray, corners, (11,11),(-1,-1), criteria)
        imgpoints.append(corners2)  # 2차원 좌표 추가

카메라 교정

ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(
    objpoints, imgpoints, gray.shape[::-1], None, None)
  • mtx: 카메라에서 3차원 이미지를 2차원으로 만드는 행렬
  • dist: 렌즈의 왜곡
  • rvecs: 카메라의 회전
  • tvecs: 카메라의 수평이동

이미지에서 렌즈 왜곡 교정

src = cv.imread('fisheye01.jpg')  # 이미지 열기
# 왜곡 제거를 위한 교정치 얻기
h,w = gray.shape[:2]
newcameramtx, roi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
dst = cv.undistort(src, mtx, dist, None, newcameramtx) # 교정치 적용

결과 비교

  • 교정 전: 결과 비교 이미지 1
  • 교정 후: 결과 비교 이미지 2
Previous
기하학적 변환: 투시 변환