Contents — find the section you need

카메라를 약간 옆으로 움직여 같은 장면을 촬영하면, 가까운 물체는 멀리 있는 물체보다 배경과 대비되어 더 크게 움직입니다. 이러한 시차 덕분에 2D 이미지에서 3D 형상과 카메라 움직임을 복원할 수 있습니다. 하지만 단순히 이미지 간에 "동일한 물리적 지점"을 일치시키는 것만으로는 충분하지 않습니다. 불일치, 렌즈 왜곡, 순수 회전, 평면, 움직이는 물체 등으로 가득한 실제 이미지에서는 단일 카메라 움직임과 일치하는 점 쌍을 판별해야 합니다. 에피폴라 기하학은 바로 이러한 작업을 수행하는 데 사용되는 공통 언어입니다.

이는 단순히 스테레오 측정에만 국한된 것이 아닙니다. SfM(Structure from Motion), 비주얼 오도메트리, 비주얼 SLAM, AR 평면 추적, 로봇 자체 위치 추정, COLMAP의 희소 재구성 등 모든 기술이 대응점과 투영 기하학에 기반합니다. 이 글에서는 좌표계를 명확하게 정의하고, 각 행렬의 의미, 어떤 추정기를 선택해야 하는지, 그리고 결과를 신뢰해서는 안 되는 경우를 설명합니다.

스테레오 카메라 EyeSight 운전자 보조 시스템이 장착된 스바루 WRX S4스테레오 카메라 차량의 예

이미지: 스바루 WRX S4 2.0GT-S EyeSight (Tokumeigakarinoaoshima, CC BY-SA 4.0), Wikimedia Commons. 외부 모습이며, 카메라 내부 클로즈업 사진이 아닙니다.

0. 30초 요약

  • 두 카메라 중심과 하나의 3D 점으로 이루어진 평면을 에피폴라 평면이라고 합니다. 이 평면은 각 이미지를 선으로 자르므로, 이에 대응하는 점은 한 이미지는 다른 이미지의 해당 선, 즉 에피폴라 선에만 나타날 수 있습니다.
  • 보정되지 않은 이미지의 경우, 기본 행렬 F는 \mathbf{x}'^\mathsf{T}F\mathbf{x}=0을 만족합니다. 알려진 내부 특성을 가진 정규화된 좌표계에서는 필수 행렬 E=[\mathbf{t}]_\times R가 사용됩니다. E는 회전 R과 변환의 방향을 복구하지만, 단일 단안 2개 시점 쌍으로는 변환의 절대 크기를 복구할 수 없습니다.
  • 정규화된 8점 알고리즘은 구현하기 쉬운 선형 초기 추정치입니다. 5점 알고리즘은 보정된 카메라에 대해 더 적은 대응점을 필요로 하는 최소 솔버입니다. 두 알고리즘 모두 불일치에 취약하므로 실제로는 RANSAC/USAC를 사용하여 이상치를 제거하고 재투영 오차로 평가합니다.

  • 삼각측량은 두 시선의 교점을 찾지만, 시차가 작을 때 깊이가 불안정해지고 기준선이 불안정해집니다. 짧거나 이미지 노이즈가 큰 경우. 추정 후, 번들 조정은 카메라 포즈와 3D 포인트를 함께 정밀하게 조정합니다.

  • 평면 장면만 있거나 카메라가 거의 순수 회전하는 경우, 호모그래피 H이 이미지를 잘 설명하지만, F/E을 통한 변환/깊이 복구는 효율이 떨어집니다. 모델 선택은 인라이어 개수에만 의존해서는 안 되며, 잔차, 시차, 공간 분포 및 치에라리티를 함께 확인해야 합니다.

1. 좌표에서 2면 투영 작성

세계 좌표계의 한 점을 동차 좌표 \mathbf{X}=(X,Y,Z,1)^\mathsf{T}라고 합시다. 핀홀 카메라 투영은 스케일에 맞춰 다음과 같이 표현됩니다.

\tilde{\mathbf{x}} \sim P\mathbf{X},\qquad P=K[R\mid\mathbf{t}]

여기서 \tilde{\mathbf{x}}=(u,v,1)^\mathsf{T}은 동차 이미지 좌표이고, K는 내부 행렬이며, R\in SO(3) 및 \mathbf{t}는 월드 좌표계에서 카메라 좌표계로의 외부 포즈입니다. 일반적으로

K=\begin{bmatrix}f_x&s&c_x\\0&f_y&c_y\\0&0&1\end{bmatrix}

여기서 f_x,f_y는 픽셀 단위의 초점 거리이고, (c_x,c_y)는 주점이며, s는 기울기입니다. 왜곡이 보정되면 정규화된 이미지 좌표는 \mathbf{x}=K^{-1}\tilde{\mathbf{x}}가 됩니다. 이후부터는 왼쪽 카메라를 P_1=K[I\mid\mathbf{0}]으로, 오른쪽 카메라를 P_2=K[R\mid\mathbf{t}]으로 기준으로 사용합니다.

Diagram 1 · Use the button to switch views
The epipolar plane and two image planesDiagram showing two camera centers C and C prime, a 3D point X, two image planes, corresponding points x and x prime, and the epipolar line on each image. Epipolar plane C C′ X x x′ Baseline Image 1Image 2 l = Fᵀx′l′ = Fx

그림에서 C,C'은 카메라 중심이고, CC'는 기준선입니다. 점 X와 두 중심점으로 정의되는 평면은 왼쪽 이미지 평면을 l이라는 에피폴라 선으로, 오른쪽 이미지 평면을 l'이라는 에피폴라 선으로 자릅니다. 왼쪽 이미지에서 대응하는 점 \mathbf{x}을 찾으면 오른쪽 이미지의 2D 검색 영역이 단일 선으로 축소됩니다. 보정된 스테레오 쌍의 경우 이 선은 수평이며, 대응점 검색은 동일한 스캔라인을 따라 1D 검색으로 변경됩니다.

2. 필수 행렬 및 기본 행렬

외적 자세에만 초점을 맞춰 보정되고 정규화된 좌표 (\mathbf{x},\mathbf{x}')을 고려해 보겠습니다. 왼쪽 카메라에서 해당 점까지의 시선 방향은 \mathbf{x}이고, 오른쪽 카메라의 프레임에서는 R\mathbf{x}입니다. 변환 벡터 \mathbf{t}와 두 시선이 동일 평면상에 있다는 사실은 다음과 같은 0 스칼라 삼중곱으로 나타낼 수 있습니다.

\mathbf{x}'^\mathsf{T}[\mathbf{t}]_\times R\mathbf{x}=0

여기서 [\mathbf{t}]_\times는 외적의 비대칭 행렬 형태입니다.

[\mathbf{t}]_\times= \begin{bmatrix}0&-t_z&t_y\\t_z&0&-t_x\\-t_y&t_x&0\end{bmatrix},\qquad [\mathbf{t}]_\times\mathbf{a}=\mathbf{t}\times\mathbf{a}

이 E=[\mathbf{t}]_\times R를 필수 행렬이라고 합니다. E는 임의의 3\times3 행렬이 아니라, 두 개의 0이 아닌 특이값이 같다는 제약 조건을 만족하는 랭크 2의 행렬입니다. 특이값 분해(SVD)를 통해 E=U\operatorname{diag}(s,s,0)V^\mathsf{T} 형태로 투영하면 이 물리적 제약 조건을 복원할 수 있습니다.

보정되지 않은 경우, 원시 픽셀 좌표를 직접 사용하면 다음과 같습니다.

\tilde{\mathbf{x}}'^\mathsf{T}F\tilde{\mathbf{x}}=0,\qquad F=K_2^{-\mathsf{T}}EK_1^{-1}

그리고 F는 기본 행렬입니다. F\tilde{\mathbf{x}}는 오른쪽 이미지에서 에피폴라 선 l'을 제공하고, F^\mathsf{T}\tilde{\mathbf{x}}'는 왼쪽 이미지에서 선 l을 제공합니다. F은 내부 파라미터를 흡수하므로 이미지 쌍의 기하학적 검증에 편리하지만, 미터법 단위로 포즈를 해석하려면 보정이 필요합니다.

행렬 좌표 필요한 알려진 양 형상 제약 조건 결과 주요 용도
F 원시 픽셀 동차 좌표 없음 랭크 2, 7 자유도 에피폴라 선 보정되지 않은 SfM, 대응 검증
E K^{-1}\tilde{\mathbf{x}} 두 카메라의 K 랭크 2, 특이값 (s,s,0) R 및 \mathbf{t}의 방향 VO, SLAM, 보정된 스테레오
H 평면 또는 순수 회전 하의 픽셀 평면 또는 회전 모델 일반적으로 8자유도 평면 왜곡 AR 평면, 이미지 스티칭

에피폴이 알려주는 것

오른쪽 카메라의 중심이 왼쪽 이미지에 투영되는 지점이 왼쪽 에피폴 \mathbf{e}이며, F\mathbf{e}=0을 만족합니다. 마찬가지로 F^\mathsf{T}\mathbf{e}'=0도 만족합니다. 에피폴이 이미지 내부에 있으면 에피폴라 선이 방사형으로 수렴하여 카메라가 대략 앞뒤로 이동했음을 나타냅니다. 에피폴이 무한대에 있으면 선이 거의 평행하여 측면 이동에 가까운 움직임을 나타냅니다. 이는 유용한 진단 방법이지만, 잘못된 추정치만으로도 비정상적인 에피폴 위치가 생성될 수 있으므로, 이 방법만으로는 절대 움직임을 판단해서는 안 됩니다.

3. 대응점을 이용한 행렬 추정: 8점 알고리즘

단일 대응점 \tilde{\mathbf{x}}=(u,v,1)^\mathsf{T}과 \tilde{\mathbf{x}}'=(u',v',1)^\mathsf{T}은 F의 9개 항목에 대한 하나의 선형 제약 조건을 제공합니다. 예를 들어, \mathbf{f}=\operatorname{vec}(F)의 경우,

[u'u,\ u'v,\ u',\ v'u,\ v'v,\ v',\ u,\ v,\ 1]\mathbf{f}=0

8개 이상의 대응점을 A 행렬로 쌓는 8점 알고리즘은 A\mathbf{f}=0의 가장 작은 특이 벡터를 구합니다. 이 이름은 자유도를 만족하는 8개의 대응점에서 유래했지만, 실제 잡음이 많은 경우에는 최소 제곱법에서 훨씬 더 많은 점이 사용됩니다.

원시 픽셀 좌표를 사용하여 계산하면 좌표값의 크기로 인해 조건이 나빠집니다. Hartley의 정규화된 8점 알고리즘은 각 이미지의 점 집합을 유사 변환 T,T'를 사용하여 정규화하여 중심점을 0으로 만들고 평균 거리를 \sqrt{2}로 설정한 후, 해당 공간에서 해를 구하고 최종적으로

F=T'^\mathsf{T}F_{\text{norm}}T
을 복원합니다.

또한, 결과 F의 특이값 분해(SVD)를 수행하고 가장 작은 특이값을 0으로 만듦으로써 랭크 2를 강제합니다. 이는 사소한 구현 세부 사항처럼 보이지만, 해의 안정성에 큰 영향을 미칩니다.

보정된 경우, 동일한 아이디어를 사용하여 정규화된 대응점으로부터 E의 초기 추정값을 생성할 수 있습니다. 그러나 8점으로부터 얻은 선형 해는 필수 행렬의 더 강력한 특이값 제약 조건을 자동으로 만족시키지 않습니다. 따라서 E=U\operatorname{diag}(\sigma_1,\sigma_2,\sigma_3)V^\mathsf{T}을 계산하고 이를 \operatorname{diag}((\sigma_1+\sigma_2)/2,(\sigma_1+\sigma_2)/2,0)로 대체하여 투영해야 합니다.

4. 5점 알고리즘: 보정을 통한 최소 샘플 크기 축소

필수 행렬은 5개의 자유도를 가집니다. 5점 알고리즘은 5개의 대응점을 이용하여 유한한 E개의 후보를 찾는 최소 해법입니다. 니스터(Nistér) 방법은 널 공간을 다항식 제약 조건으로 대체하여 최대 10개의 실수 해 후보를 열거합니다. 유도 및 구현 과정은 8점 알고리즘보다 복잡하지만, RANSAC 가설당 5개의 점만 필요하다는 장점이 매우 큽니다.

인라이어 비율이 w이고, 단일 추출에서 모든 데이터가 인라이어일 확률이 w^s, 실패 확률이 p, 최소 샘플 크기가 s일 때, 필요한 반복 횟수 추정치는 다음과 같습니다.

N=\frac{\log p}{\log(1-w^s)}

w=0.5,p=0.01의 경우, s=8는 약 1177번의 반복이 필요한 반면, s=5은 약 145번의 반복이 필요합니다. 실제로는 PROSAC과 같은 방법은 매칭 품질 순서대로 샘플을 추출하고 적응적으로 종료하기 때문에 이러한 비교가 간단하지는 않습니다. 그럼에도 불구하고, 인라이어 비율이 낮은 환경에서 5점 알고리즘의 유용성은 분명합니다.

OpenCV의 findEssentialMat은 RANSAC/LMEDS와 5점 알고리즘 계열 구현을 제공하며, recoverPose은 후보 분해 및 치어리티 검사를 처리합니다. 구현자에게는 입력이 왜곡되지 않았는지/정규화되었는지, 그리고 임계값에 사용되는 좌표 단위가 무엇인지 확인하는 것이 "5점 알고리즘을 사용했다"는 사실보다 더 중요합니다.

5. RANSAC: 이상치를 가정하면서 기하학을 활용

SIFT, ORB, SuperPoint, LoFTR과 같은 매처는 반복되는 텍스처, 반사, 반복되는 그리드, 가림 현상으로 인해 불일치를 발생시킵니다. 최소 제곱법을 사용하여 모든 대응점에 F을 맞추는 방식은 소수의 오류로 인해 전체 행렬이 손상될 수 있습니다. RANSAC은 다음 과정을 반복합니다.

  1. 최소한의 대응점 집합을 무작위로 선택하고 F 또는 E 가설을 구축합니다. 2. 모든 대응점에 대한 잔차를 계산하고, 임계값 내에 있는 대응점을 인라이어로 표시합니다.

  2. 가장 많은 지지를 받거나 가장 높은 로버스트 점수를 얻은 가설을 유지합니다.

  3. 최종 인라이어를 모두 사용하여 다시 추정하고, 필요한 경우 비선형 최적화를 통해 개선합니다.

에피폴라 제약 조건에 대한 임계값 설정은 대수적 오차(\mathbf{x}'^\mathsf{T}F\mathbf{x})만을 사용해서는 안 됩니다. 이는F)의 스케일에 의존하기 때문입니다. 실제로는 샘슨 거리(Sampson distance)가 일반적으로 사용됩니다.

샘슨 거리는 기하학적 오차의 1차 근사치로, 각 대응점에서 에피폴라 선까지의 거리를 정규화한 값입니다. 픽셀 좌표에서의 임계값은 이미지 해상도, 키포인트 위치 정확도, 잔차 왜곡 및 흐림 정도에 따라 달라집니다. 보편적인 "1픽셀" 값은 없습니다. 잔차 히스토그램과 이미지 상의 인라이어 공간 분포를 시각화하여 임계값을 조정합니다.

현재 OpenCV는 USAC 계열의 강건한 추정 기능을 제공합니다. 품질 순서 샘플링, 지역 최적화 및 퇴화 검사를 결합하여 일반 RANSAC보다 빠르고 안정적일 수 있습니다. 그러나 통계적 이상치 제거는 "대부분이 단일하고 정적인 강체 운동을 따른다"는 가정을 완전히 극복할 수는 없습니다. 프레임의 대부분이 움직이는 차량이나 사람인 경우, 시맨틱 마스크, 모션 분할, IMU 또는 깊이 정보와 같은 추가 정보를 사용해야 합니다.

6. E를 포즈로 분해하고 적절한 후보 선택

수정된 E=U\operatorname{diag}(s,s,0)V^\mathsf{T}의 경우,

W=\begin{bmatrix}0&-1&0\\1&0&0\\0&0&1\end{bmatrix}
을 사용하면

회전 후보는 R=UWV^\mathsf{T} 또는 UW^\mathsf{T}V^\mathsf{T}이고, 변환 방향 후보는 \pm U_{:,3}입니다. 부호와 회전의 조합은 4가지가 있습니다. 여기서 중요한 것은 두 시점 제약 조건만으로 모든 후보가 동일한 E와 대수적으로 일관성을 유지한다는 점입니다.

선택은 중심성(양의 깊이)을 사용합니다. 각 후보에 대해 소수의 인라이어를 삼각측량하고 두 카메라 프레임 모두에서 가장 많은 점에 대해 Z>0를 제공하는 후보를 선택합니다. 또한 회전 행렬의 행렬식이 +1인지, 재투영 오차가 작은지, 그리고 충분한 시차가 있는지 확인합니다. 특히 기억해야 할 한 가지 제한 사항은 \mathbf{t}는 방향까지만 복구할 수 있다는 것입니다. \mathbf{t}와 모든 3D 점을 동일한 비율로 스케일링해도 투영은 변경되지 않습니다. 알려진 스테레오 기준선, 휠 오도메트리, IMU, 알려진 크기의 객체 또는 GNSS를 통해 스케일을 얻을 수 있습니다.

7. 삼각분할: 두 개의 광선에서 3D 점으로

투영 방정식 \mathbf{x}\times(P\mathbf{X})=\mathbf{0}은 뷰당 두 개의 독립적인 방정식을 생성합니다. DLT 삼각분할은 두 뷰에서 얻은 선형 시스템 A\mathbf{X}=0을 특이값 분해(SVD)를 통해 해결합니다. 이 방법은 간단하며, OpenCV의 triangulatePoints는 이와 유사한 형태입니다. 예를 들어, \mathbf{p}_{ij}^\mathsf{T}을 P_i의 j번째 행이라고 하면, 점 (u_i,v_i)은 다음과 같습니다.

\begin{bmatrix} u_i\mathbf{p}_{i3}^\mathsf{T}-\mathbf{p}_{i1}^\mathsf{T}\\ v_i\mathbf{p}_{i3}^\mathsf{T}-\mathbf{p}_{i2}^\mathsf{T} \end{bmatrix}\mathbf{X}=\mathbf{0}

마지막에 동차 성분으로 나누기 전에 w이 너무 작지 않은지 확인하십시오.

수평 스테레오 쌍의 경우 이 과정이 더 직관적입니다. 좌우 시차(좌우 좌표 차이)가 d=u_L-u_R, 초점 거리가 f, 기준선이 B일 때,

Z=\frac{fB}{d},\qquad X=\frac{(u_L-c_x)Z}{f}

깊이 오차는 대략 \delta Z\simeq \frac{Z^2}{fB}\delta d입니다. 거리가 멀어질수록, 그리고 초점 거리나 기준선이 짧아질수록 동일한 1픽셀 시차 오차에서 발생하는 깊이 오차가 커집니다. 따라서 "일치했으니 포인트 클라우드에 추가"하는 대신, 삼각측량 각도, 시차, 재투영 오차, 그리고 양의 깊이 값을 품질 기준으로 사용해야 합니다.

선형 삼각측량은 초기 추정치일 뿐이며, 이미지 노이즈를 정확하게 최소화하지 못합니다. 카메라 포즈(P_i)와 점(\mathbf{X}_j)을 동시에 최적화하는 번들 조정은 다음 식을 만족합니다.

\min_{\{R_i,\mathbf{t}_i,\mathbf{X}_j\}} \sum_{(i,j)\in\mathcal{O}}\rho\left(\left\|\pi(K_i(R_i\mathbf{X}_j+\mathbf{t}_i))-\tilde{\mathbf{x}}_{ij}\right\|^2\right)

여기서 \rho은 Huber 또는 Cauchy와 같은 강건한 손실 함수이고, \pi은 원근 분할입니다. 이것이 COLMAP, Theia 또는 Ceres Solver를 사용한 재구성의 정확도가 향상되는 이유입니다. 측정 자유도를 고정하려면 첫 번째 카메라를 원점에 배치하고, 필요한 경우 알려진 하나의 스케일을 고정합니다.

8. 에피폴라 기하학과 호모그래피 중 선택

장면의 모든 점이 단일 평면(\pi) 위에 있거나 카메라가 순수 회전을 하는 경우, 이미지 간의 대응 관계는 3×3 호모그래피(\tilde{\mathbf{x}}'\sim H\tilde{\mathbf{x}})로 잘 설명됩니다. 평면의 법선 벡터 \mathbf{n}과 거리 벡터 d로 보정하면,

H=K\left(R+\frac{\mathbf{t}\mathbf{n}^\mathsf{T}}{d}\right)K^{-1}
이 됩니다.

순수 회전의 경우, 변환 항은 사라지고 H=KRK^{-1}이 됩니다. 포스터, 책상, 건물 외관 또는 멀리 있는 장면을 패닝하는 영상의 경우, H은 훌륭한 모델이 되며, AR 평면 앵커 및 이미지 스티칭에 있어 자연스러운 첫 번째 선택입니다.

그러나 평면 데이터만으로 F/E을 추정하면 3D 구조와 변환을 안정적으로 분리할 수 없으면서 많은 인라이어가 나타날 수 있습니다. 반대로, 일반적인 비평면 장면을 단일 H에 강제로 적용하면 가까운 객체와 멀리 있는 객체가 일관성 없이 왜곡됩니다. 구현 시, F/E과 H을 모두 RANSAC으로 추정하고, 재구성 후 잔차, 설명된 점 개수, 점 분포 및 시차를 비교하십시오. 매칭 개수만으로 모델을 수용할지 여부를 결정하면, 큰 평면 벽이나 이미지 중심을 지배하는 평면으로 치우치게 될 수 있습니다.

상황 첫 번째 후보 결과 주의 사항
보정된, 일반 3D, 변환 포함 E + 5점 알고리즘 상대적 자세, 희소한 깊이 스케일 미확정, 낮은 시차에서 불안정
보정되지 않은 이미지 쌍 F + 정규화된 8점 알고리즘 에피폴라 선, 대응점 검증 K 없이는 물리적 자세를 해석하지 마십시오
거의 평면, 포스터, 책상 H + 4점 알고리즘 평면 왜곡, 평면 포즈 후보 평면 외 깊이 없음
순수 회전/파노라마 H 이미지 정렬, 회전 변환 및 깊이 관측 불가
2D 관측값을 사용하는 알려진 3D 지도 PnP + RANSAC 절대 포즈 지도 품질 및 축척에 따라 다름

9. 보정은 전처리 단계가 아니라 모델의 일부입니다

체커보드, Charuco 또는 AprilTag 그리드를 여러 거리, 기울기 및 이미지 위치에서 촬영하여 K 및 왜곡 계수를 추정합니다. 브라운-콘래디 방사 왜곡은 정규화된 반경 r^2=x^2+y^2에 대해 대략 다음과 같이 표현됩니다.

x_d=x(1+k_1r^2+k_2r^4+k_3r^6)+2p_1xy+p_2(r^2+2x^2)

광각 렌즈 및 어안 렌즈의 경우 표준 핀홀 왜곡 모델을 강제로 사용하지 말고 OpenCV의 어안 모델 또는 사용 중인 렌즈에 맞는 모델을 선택하십시오. 보정의 평균 재투영 오차가 작더라도 이미지 가장자리, 초점 거리, 온도, 초점 또는 해상도 변화에 따라 오차 구조가 달라질 수 있습니다.

두 시점 처리 단계로 넘어가기 전에 보정 값이 현재 촬영과 동일한 해상도, 크롭 및 디지털 줌 조건에서 얻어졌는지 확인하십시오. undistortPoints를 통해 정규화된 점에서 E을 추정하는 것과 왜곡 보정된 이미지에서 F을 추정하는 것을 혼동하기 쉽습니다. API가 초점 거리, 주점, 왜곡을 내부적으로 사용하는지, 아니면 이미 보정된 좌표를 기대하는지 항상 확인하세요. 스테레오 리그의 경우, 두 카메라의 내부 매개변수 외에도 stereoCalibrate을 사용하여 상대 자세를 찾고 stereoRectify을 사용하여 에피폴라 선을 수평으로 정류해야 합니다.

10. OpenCV의 최소 파이프라인

아래는 보정된 단안 카메라의 두 프레임에서 상대 자세와 품질 필터링된 희소 3D 포인트 세트를 얻기 위한 기본 구조입니다. 특징 추출에는 ORB를 사용하지만, 촬영 조건에 따라 SIFT 또는 학습 기반 매처로 대체할 수 있습니다. 실제로는 노출, 움직이는 물체, 시간 동기화 정보도 기록해야 합니다.

import cv2 as cv
import numpy as np

# K, dist are values calibrated for this capture resolution and lens
orb = cv.ORB_create(nfeatures=3000)
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
matches = cv.BFMatcher(cv.NORM_HAMMING).knnMatch(des1, des2, k=2)
good = [m for m, n in matches if m.distance < 0.75 * n.distance]

p1 = np.float32([kp1[m.queryIdx].pt for m in good])
p2 = np.float32([kp2[m.trainIdx].pt for m in good])
# threshold is in pixel units. Decide it from the residual distribution, not an initial guess.
E, mask = cv.findEssentialMat(p1, p2, K, method=cv.USAC_MAGSAC,
                              prob=0.999, threshold=1.0)
in1, in2 = p1[mask.ravel() != 0], p2[mask.ravel() != 0]
count, R, t, pose_mask = cv.recoverPose(E, in1, in2, K)

# P1, P2 are for normalized coordinates. Scale is arbitrary, so t's length is not a physical unit.
n1 = cv.undistortPoints(in1.reshape(-1, 1, 2), K, dist).reshape(-1, 2)
n2 = cv.undistortPoints(in2.reshape(-1, 1, 2), K, dist).reshape(-1, 2)
P1 = np.hstack([np.eye(3), np.zeros((3, 1))])
P2 = np.hstack([R, t])
X4 = cv.triangulatePoints(P1, P2, n1.T, n2.T)
X = (X4[:3] / X4[3]).T

# Further filter by positive depth in both views, reprojection error, and triangulation angle.
z1 = X[:, 2]
z2 = (R @ X.T + t).T[:, 2]
valid = (z1 > 0) & (z2 > 0) & np.isfinite(X).all(axis=1)

이 예제는 원시 픽셀과 K 값을 findEssentialMat 함수에 직접 전달하지만, 왜곡이 무시할 수 없을 정도로 심각한 경우에는 먼저 undistortPoints 함수에서 정규화된 점들을 전달한 후 해당 API 형식으로 전환해야 합니다. 또한 recoverPose 함수에서 반환되는 \mathbf{t} 값을 "이동 거리"로 간주하는 것은 잘못된 것입니다. 스케일이 필요한 애플리케이션은 알려진 기준선, VIO, 휠 오도메트리, 깊이 센서 등을 사용하여 스케일을 제한해야 합니다.

COLMAP은 특징 추출, 매칭, 기하학적 검증, 증분 매핑 및 번들 조정을 하나의 연결된 파이프라인으로 구현합니다. 소규모 데이터셋의 경우 GUI를 통해 카메라 모델과 재구성 결과를 확인할 수 있습니다. 명령줄에서는 카메라 모델 선택, EXIF 초점 거리 처리 방식, 매칭 전략(완전 탐색/순차 탐색/어휘 트리 탐색), 이미지 쌍 간의 시간 간격이 정확도와 계산 비용에 영향을 미칩니다. 재구성 후에는 포인트 개수가 아니라 등록된 이미지 수, 평균 재투영 오차, 이미지당 관측 횟수, 포인트 클라우드의 간격을 확인하십시오.

11. 일반적인 오류 조건 및 진단 방법

작은 시차, 기준선 없음

전진 이동, 먼 장면 또는 짧은 프레임 간격의 경우 깊이 정보 없이 대응점만 얻을 수 있습니다. 에피폴라 선이 적절해 보이지만 삼각측량 각도가 0에 가까운 경우, 깊이 정보 업데이트를 강제하기보다는 보류하십시오. 근본적인 해결 방법은 키프레임 간격을 넓히거나, 측면 이동으로 관측값을 캡처하거나, 기준선이 알려진 스테레오 장비를 사용하는 것입니다.

순수 회전 또는 평면 퇴화

패닝 샷이나 벽만 포함된 시야에서는 H가 설명력이 있습니다. E의 높은 인라이어 개수가 반드시 변환이 관측되었다는 것을 의미하지는 않습니다. H과 E 간의 경쟁을 기록하고, 삼각측량 후 양의 깊이 비율과 중앙값 시차를 기준으로 게이팅합니다. AR 포스터 트래킹에서 이는 실패가 아니라 올바른 모델 선택입니다.

불일치, 반복 패턴, 반사

창문, 타일, 책장, LCD 화면, 수면은 유사한 로컬 디스크립터를 생성합니다. 비율 테스트, 상호 최근접 이웃 매칭, 기하학적 RANSAC을 적용하여 인라이어 포인트가 이미지 전체에 분포되어 있는지 확인합니다. 거울 이미지와 투명한 물체는 강체 및 램버트 반사율 가정을 위반하므로 임계값 조정을 아무리 해도 해결할 수 없습니다.

동적 객체 및 다중 모션

RANSAC은 가장 큰 단일 모션만 선택합니다. 배경이 소수인 경우 자동차의 움직임을 잘못 추정할 수 있습니다. 응용 분야에 따라 사람/차량을 의미론적으로 제외하거나, 광학 흐름을 클러스터링하거나, 다중 모델 추정을 실행하거나, 깊이/IMU와 정렬하는 방법 중에서 선택하십시오.

렌즈 왜곡, 롤링 셔터, 비동기

보정되지 않은 광각 렌즈 가장자리를 사용하면 에피폴라 라인에 체계적인 곡률이 발생합니다. 빠른 움직임 촬영 시 롤링 셔터가 발생하면 한 프레임 내에서 자세가 변하므로 단일 E으로는 근사치만 구할 수 있습니다. 스테레오 이미지 쌍에서 좌우 노출 타이밍이 약간만 어긋나도 움직이는 물체에서 잘못된 시차가 발생합니다. 글로벌 셔터, 짧은 노출 시간, 행 타이밍 모델, IMU 기반 보정 및 하드웨어 동기화를 고려하십시오.

수치 및 좌표계 오류

픽셀 좌표와 정규화된 좌표를 혼용하거나, R,\mathbf{t}에서 월드-카메라 좌표와 카메라-월드 좌표를 혼동하거나, 좌우 점 순서를 바꾸거나, 이미지 크기 조정 후 K를 업데이트하는 것을 잊는 것은 모두 흔한 실수입니다. 추정값을 액면 그대로 받아들이지 마십시오. 대응점과 에피폴라 선을 겹쳐 확인하고, 두 카메라 모두에서 양의 깊이, 재투영 오류, \det R=1 및 R^\mathsf{T}R\simeq I에 대한 검사를 자동화하십시오.

12. 실용적인 평가 지표 및 설계 체크리스트

단순히 "행렬이 반환되었다"는 이유만으로 두 시점 추정이 성공적이라고 단정하지 마십시오. 매칭 횟수는 텍스처 양에 따라 왜곡될 수 있으며, 평균 오류만으로는 몇몇 좋은 점에 가려질 수 있습니다. 프레임별로 다음 항목을 저장하면 센서/매처/자세 추정 체인 중 어느 부분에서 오류가 발생했는지 나중에 파악할 수 있습니다.

  • 검출 횟수, 비율 테스트 통과 횟수, RANSAC 인라이어 횟수/비율, 이미지 그리드 셀 분포
  • Sampson 거리 및 재투영 오차의 중앙값 및 상위 백분위수, 양성 깊이 비율, 삼각측량 각도 분포
  • H과 E/F에 대한 지원 횟수 및 로버스트 점수, 그리고 모델이 승인되거나 거부된 이유
  • 추정된 회전 크기, 변환 방향의 시간적 연속성, 스케일링된 외부 센서와의 일관성
  • 노출 시간, 게인, IMU 각속도, 좌/우 시간 오프셋, 블러 측정값, 이미지 마스크 비율

실측 데이터가 있는 연구 또는 제품 평가의 경우, 상대 회전 오차, 변환 방향 오차, 궤적 ATE/RPE, 절대/상대 깊이 오차를 별도로 보고하십시오. 단안 2시점 변환은 스케일 모호성을 가지므로, 오류가 정규화 후인지 Sim(3) 정렬 후인지 명확히 명시해야 합니다. 실패한 프레임을 평균에서 제외하는 대신, 각 실패가 발생한 퇴화 조건이나 시각적 조건을 기록하는 것이 시스템의 한계를 더 솔직하게 보여줍니다.

13. 최근 개발 동향: 학습이 기하학을 대체했는가?

학습 기반 키포인트 및 디스크립터(SuperPoint), 세밀화 매처(LoFTR), 범용 대응 추정(LightGlue 등)은 텍스처 또는 시점 변화가 적은 환경에서 기존 디스크립터보다 더 많은 후보 매칭을 생성할 수 있습니다. 그러나 네트워크에서 반환된 대응은 여전히 잘못될 수 있으며, 카메라 움직임, 평면, 롤링 셔터, 스케일과 같은 물리적 모호성은 사라지지 않습니다. 실제 SfM/SLAM에서는 E/F/H의 강건한 추정과 번들 조정을 통해 학습된 매처의 출력을 검증하는 하이브리드 방식이 여전히 실용적인 선택입니다.

더 넓은 관점에서 보면, NeRF나 3D 가우시안 스플래팅과 같은 신경망/명시적 장면 표현 방식은 여러 시점 간의 일관성을 활용합니다. 이러한 방식은 매력적인 새로운 시점 합성을 가능하게 하지만, 카메라 포즈와 관측 기하학의 품질에 민감하며, 많은 구현체가 COLMAP에서 파생된 포즈로 초기화됩니다. 대규모의 동적이고 반사적인 환경에서 대응점, 깊이, 분할, 관성 데이터 및 타이밍 모델을 동시에 추정하는 연구가 계속 진행 중입니다.

따라서 새로운 모델을 채택할지 여부를 결정할 때는 단순히 "ORB에 비해 매칭 횟수가 늘었는가"만을 기준으로 해서는 안 됩니다. 추정 후 인라이어 분포, 포즈 오류, 연산 지연 시간, GPU 요구 사항, 훈련 조건 외에서의 성능 저하, 라이선스 문제 등도 고려해야 합니다. 기하학은 구식 전처리 단계가 아닙니다. 학습된 모델의 출력을 실제 3D 구조와 비교하여 검증하는 중요한 요소로 남아 있습니다.

14. 결론

에피폴라 기하학은 두 이미지 간의 대응점을 "가장 유사해 보이는 점"에서 "단일 카메라 움직임으로 설명 가능한 점"으로 끌어올리는 프레임워크입니다. 내부 매개변수가 알려져 있으면 E=[\mathbf{t}]_\times R을 통해 상대적 자세를 계산하고, 그렇지 않으면 F을 사용하여 에피폴라 선과 대응점을 검증합니다. 8점 알고리즘은 이해와 초기화의 기초가 되며, 5점 알고리즘은 견고한 추정을 위한 효율적인 최소 솔버입니다. RANSAC은 이상치를 처리하는 메커니즘이고, 삼각측량과 번들 조정은 3D로의 연결 고리 역할을 합니다.

그러나 시차가 없고 평면만 존재하거나, 순수 회전이거나, 움직이는 객체가 많거나, 심한 왜곡/비동기 현상이 있는 경우, 반환된 행렬이 물리적으로 의미 있는 깊이나 변환을 보장하지는 않습니다. 호모그래피에 기반한 모델 선택 설계, 캘리브레이션 조건 관리, 재투영 오류 및 양의 깊이 확인, 그리고 외부 스케일과의 융합을 단일 파이프라인으로 구현하는 것이 재현 가능한 컴퓨터 비전을 구현하는 핵심입니다.

이해도 점검
에피폴라 라인이 유일하게 일치하는 부분을 판별하는 기준이 되나요?

에피폴라 라인은 검색 범위를 특정 라인으로 좁혀줍니다.

이미지 증거는 여전히 해당 지점을 정확히 찾아내야 하며, 반복이나 가려짐으로 인해 모호해질 수 있습니다.

참고 자료 (주요 출처 및 공식 문서)

What to read next

Review the background동형성 입문 — 단일 3x3 행렬을 이용한 평면 대응 설명Continue the seriesPnP 기초 — 3D 포인트와 이미지만으로 카메라 포즈 복원하기Explore another aspect of this field이미지 밝기·휘도 Lab — 노출, 감마, 클리핑 비교