Processing math: 100%

상세 컨텐츠

본문 제목

컴퓨터 비전 공부하기(3D Vision - 핀홀 카메라 모델)

카테고리 없음

by zmo 2024. 12. 1. 19:15

본문

오늘부터는 컴퓨터 비전을 공부하기 위해 핵심이라 할수 있는 3D Vision에 대해 알아보기로 하자. 우리가 그냥 이미지를 학습할수 있는 딥러닝 모델을 찾아 사용할수도 있겠지만 이렇게 되면 만일 학습도중 오류가 발생했을때 원인을 찾지 못해 난처한 상황이 벌어질 것이다. 그리고 우리가 어떤 학습데이터를 준비해야 더 효율적이고 오류없는 학습을 할수 있을지 아는 것도 중요하다.

그러기 위해서 3D Vision 이론의 정석이라 할수 있는 다중관점 기하학(Multiple View Geometry in Computer Vision) 책을 정리한 글을 참고할 것이며, 우리가 이것을 짧은 시간에 전부 이해하기는 어렵기 때문에 다음과 같은 4가지 개념만 알아가고자 한다.

 

핀홀 카메라 모델: 카메라의 기본 작동 원리와 매개변수(내부/외부)를 이해.

에필로라 기하학: 두 이미지 간의 관계(본질 행렬과 기본 행렬).

Triangulation: 3D 포인트 복원 원리.

Bundle Adjustment: 최적화 단계에서 어떤 일이 일어나는지 기본적인 이해.

 

이중에서도 오늘은 핀홀 카메라 모델이란 무엇인지 알아보고자 한다.

 

 

 

오늘 알아보기

핀홀 카메라 모델

핀홀 카메라는 중심 투영의 원리를 따른다

실제 카메라와 핀홀 모델의 차이점 (캘리브레이션하기)

핀홀 모델의 한계

 

 

 


 

핀홀 카메라 모델

 

핀홀 카메라 모델이란 3D점을 2D로 매핑하는 것이다.

x=K[R∣t]X

이 뜻이 무엇이냐 하면

X = [X, Y, Z, 1]ᵀ: 3D 세계 좌표계에서의 동차 좌표(homogeneous coordinates).

x = [u, v, 1]ᵀ: 2D 이미지 좌표계에서의 동차 좌표.

K: 카메라의 내부 파라미터 행렬(intrinsic matrix).

 

K=[fx0cx0fycy001]

 

\quad f_x , \quad f_y : 카메라의 초점 거리(focal length).

\quad c_x , \quad c_y : 이미지 센서의 중심 좌표(principal point).

[R|t]: 카메라의 외부 파라미터 행렬(extrinsic matrix).

R: 회전 행렬, 카메라와 세계 좌표계 간의 방향 관계.

t: 이동 벡터, 카메라의 위치.

를 뜻한다.

 

 

핀홀 카메라는 중심 투영의 원리를 따른다

 

중심투영의 원리란 카메라 중심에서 이미지 평면으로 빛이 수렴되며, 3D 점은 이미지 평면에서 선형 투영된다는 것이다. 3D 공간의 점에서 출발한 빛이 핀홀을 통과하며, 직선 경로로 2D 평면에 투영되는 카메라와 같다(이게 핀홀 카메라다)

가볍게 말하면 우리가 풍경을 보고 스케치북에 그림을 그리듯이 3D를 2D로 투영한다는 것인데 이게 xy축만 아니라 z축도 있기 때문에 이에 일정한 비례 관계를 적용하여 표현(?)한다는 것이다. 그리고 이를 선형 투영이라고 한다.

u=fZX,v=fZY

이때 카메라 렌즈의 왜곡이나 줌 정도도 모델링한다고 한다.

 

실제 카메라와 핀홀 모델의 차이점 (캘리브레이션)

 

다중 관점 기하학에서는 이상적인 핀홀 카메라 모델과 실제 카메라의 차이를 설명한다

실제 카메라는 다음과 같은 현상이 발생한다

  1. 렌즈 왜곡: 광학적 왜곡으로 인해 직선이 곡선처럼 보이는 현상.
  2. 센서 불균일성: 이미지 센서의 픽셀 간 간격이 일정하지 않을 수 있음.
  3. 노이즈: 이미지 데이터에 추가되는 불규칙성.

이러한 현상으로 인해 발생하는 차이를 보정하기 위해 카메라 캘리브레이션(camera calibration) 과정이 필요하다.

이때 캘리브레이션은 카메라의 렌즈 왜곡, 카메라의 줌 정도 등의 자료를 가지고 실제 3D모델과 사진의 차이를 계산해준다. 위에서 설명한 선형 투영이 어느정도 캘리브레이션 역할을 수행해 줄수 있지만 완벽하게 수행해주지는 못한다.

고로 이미지에서 격자 무늬를 놓고 특징점을 추출하는 체커보드(Checkerboard) 패턴 또는 원형 무늬를 놓고 특징점을 추출하는 원형 패턴을 함께 촬영하여, 사진에 포함된 기하학적 정보를 통해 캘리브레이션을 수행할수 있다.

 

체커보드는 단순하고 제작 비용이 낮은 대신 왜곡이 많거나 하는 사진에는 정확한 계산이 어려울수 있고 원형 패턴은 상당히 정밀한 계산을 수행할수 있는 대신에 제작 비용이 상대적으로 높다.

격자를 그리고 교차점에서 사진을 찍는것과 점을 촘촘히 찍어 원을 그려놓고 모든 위치에서 사진을 찍는 것은 누가 봐도 후자가 더 번거롭다.

체커보드를 실제 어떻게 사용하는지 코드로 잠시 감상하며 순서를 알아보자.

import cv2
import numpy as np

# 체커보드 크기 정의하기
checkerboard_size = (9, 6)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# 3D 점과 2D 이미지 점 초기화
objpoints = []  # 3D 점
imgpoints = []  # 2D 점

# 3D 체커보드 좌표
objp = np.zeros((checkerboard_size[0] * checkerboard_size[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:checkerboard_size[0], 0:checkerboard_size[1]].T.reshape(-1, 2)

# 이미지 읽기
images = ["image1.jpg", "image2.jpg", ...]  # 체커보드 이미지 리스트
for image_file in images:
    img = cv2.imread(image_file)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 체커보드 코너 검출
    ret, corners = cv2.findChessboardCorners(gray, checkerboard_size, None)
    
    if ret:
        objpoints.append(objp)
        imgpoints.append(corners)
        
        # 코너 시각화
        cv2.drawChessboardCorners(img, checkerboard_size, corners, ret)
        cv2.imshow("Corners", img)
        cv2.waitKey(500)

cv2.destroyAllWindows()

# 캘리브레이션 수행하기
ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
print("Camera Matrix (K):", K)
print("Distortion Coefficients:", dist)

하지만 체커보드와 원형 패턴을 모두 사용하기 힘들때는 OpenCV를 사용하여 캘리브레이션을 할수 있다. 이는 장면 캘리브레이션이라 하고 사진의 품질이나 정확한 구도를 필요로 하게 된다.

장면 캘리브레이션은 다음과 같은 순서로 특징점을 찾고 진행될수 있다.

 

특징점 탐지

이미지에서 SIFT, ORB, 또는 Harris Corner Detector를 사용하여 특징점을 추출한다.

 

특징점 매칭

여러 장의 이미지를 입력으로 제공하여 동일한 3D 점이 서로 다른 이미지에서 어떻게 대응하는지 매칭한다.

 

기하학적 제약 조건 활용

에피폴라 기하학(epipolar geometry)을 활용하여 카메라의 매개변수를 추정한다.

findFundamentalMat와 findEssentialMat을 사용하여 기본 행렬(F)과 필수 행렬(E)을 계산한다.

 

카메라 매개변수 추정

  • 추정된 행렬을 기반으로 내부 및 외부 매개변수를 계산한다.

아래 ORB를 사용한 코드를 확인해보자 참고로 SIFT는 특허가 있지만 ORB는 공개되어있기 때문에 이를 예시에서도 사용해보았다.

import cv2
import numpy as np

# 두 이미지를 불러옴
img1 = cv2.imread("image1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("image2.jpg", cv2.IMREAD_GRAYSCALE)

# 1. 특징점 탐지 (ORB 사용함)
orb = cv2.ORB_create()
keypoints1, descriptors1 = orb.detectAndCompute(img1, None)
keypoints2, descriptors2 = orb.detectAndCompute(img2, None)

# 2. 특징점 매칭 (KNN 매칭하기)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(descriptors1, descriptors2)
matches = sorted(matches, key=lambda x: x.distance)

# 3. 매칭된 특징점 좌표 추출하기
pts1 = np.float32([keypoints1[m.queryIdx].pt for m in matches])
pts2 = np.float32([keypoints2[m.trainIdx].pt for m in matches])

# 4. 기본 행렬(F) 계산
F, mask = cv2.findFundamentalMat(pts1, pts2, cv2.FM_RANSAC)

# 5. 필수 행렬(E) 계산 (카메라 매트릭스가 필요한 경우 사용한다)
K = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])  # 대략적인 카메라 매트릭스 추정
E = K.T @ F @ K

# 6. 카메라의 외부 매개변수(R, T) 추정
_, R, T, _ = cv2.recoverPose(E, pts1, pts2, K)

# 7. 결과를 출력해보자
print("Fundamental Matrix (F):\n", F)
print("Essential Matrix (E):\n", E)
print("Rotation Matrix (R):\n", R)
print("Translation Vector (T):\n", T)

그러면 에피폴라 기하학은 그렇다 치고 SIFT, ORB, 또는 Harris Corner Detector는 무엇일까?

SIFT는 입력 이미지에서 가우시안 블러를 여러 스케일로 적용하여 스케일 공간을 생성한다고 한다.

 

가우시안 블러는.. 이미지에서 크기(scale)와 회전(rotation)에 강한 능력이라고 생각하자

ORB는 특정 픽셀이 주변 픽셀과 얼마나 다른지를 기준으로 코너점을 찾을수 있다고 알아두면 된다.

회전 불변성과 조명 변화에 강건하지만 크기에는 약하다

 

Harris Corner Detector는 이미지에서 코너(corners)를 검출하는 가장 기본적인 알고리즘 중 하나로,

이미지에서 경계가 교차하는 지점인 코너는 위치를 추적하기 좋은 특징점이다.

 

이에 관해 더 알고 싶다면 아래의 링크를 참조하자 (아주 자세하다)

https://landonswartz.github.io/posts/2023/11/HarrisCorner/

 

Implementing the Harris Corner Detector

 

landonswartz.github.io

 https://docs.opencv.org/3.4/d1/d89/tutorial_py_orb.html

 

Implementing the Harris Corner Detector

 

landonswartz.github.io

 

https://blog.finxter.com/mastering-corner-detection-harris-corner-detector-in-python-with-opencv/

 

Mastering Corner Detection: Harris Corner Detector in Python with OpenCV – Be on the Right Side of Change

💡 Problem Formulation: Corner detection is a fundamental step in many computer vision applications. It involves identifying points within an image that have significant variation in intensity in all directions. The Harris Corner Detector algorithm is a

blog.finxter.com

 

우리는 이같은 정보를 익히지 않고도 사용할수는 있지만 이렇게 작은 특징이라도 알아두면 이후에 오류가 발생했을 때 등등 유용하게 사용할수 있을 것이다

 

핀홀 모델의 한계

 

핀홀 모델은 이상적인 모델이지만 현실적이지 않은 부분으로핀홀의 구멍이 작아질수록 빛이 적게 들어오므로 실제로는 렌즈가 필요.

  1. 깊이 정보 손실: 2D 이미지에서 Z축 정보를 직접적으로 복구할 수 없음.
  2. 제한된 해상도와 시야각.
  3. 핀홀의 구멍이 작아질수록 빛이 적게 들어오므로 실제로는 렌즈가 필요.