Radial 왜곡 보정

카메라 렌즈에서 발생하는 가장 일반적인 왜곡은 Radial 왜곡이다. 이는 렌즈의 곡률로 인해 발생하며, 이미지의 중심에서 벗어날수록 왜곡이 심해진다. Radial 왜곡은 이미지의 객체가 바깥으로 밀려나거나 당겨지는 현상을 초래한다. 이를 보정하기 위해서는 왜곡 파라미터를 이용하여 보정할 수 있다.

Radial 왜곡은 보통 왜곡 파라미터 k_1, k_2, k_3을 사용하여 모델링된다. 이러한 파라미터는 이미지 좌표를 보정하는 데 활용된다.

이미지에서의 픽셀 좌표 \mathbf{x}_{\text{distorted}}와 보정된 좌표 \mathbf{x}_{\text{undistorted}} 간의 관계는 다음과 같이 정의된다:

\mathbf{x}_{\text{undistorted}} = \mathbf{x}_{\text{distorted}} \cdot \left( 1 + k_1 r^2 + k_2 r^4 + k_3 r^6 \right)

여기서: - r은 픽셀 좌표 \mathbf{x}_{\text{distorted}}와 이미지 중심 간의 거리로, r = \sqrt{x^2 + y^2}로 계산된다. - k_1, k_2, k_3는 각각 1차, 2차, 3차 Radial 왜곡 계수이다.

이 수식을 통해 왜곡된 이미지 좌표를 보정하여 직선이 곡선으로 보이는 현상을 해결할 수 있다.

Tangential 왜곡 보정

Tangential 왜곡은 렌즈가 이미지 평면에 완벽하게 평행하지 않을 때 발생하는 왜곡이다. 이는 일반적으로 렌즈의 제작 불량이나 카메라 센서의 정렬 문제로 인해 발생한다. Tangential 왜곡은 Radial 왜곡과 달리 이미지를 비대칭적으로 왜곡시킨다.

Tangential 왜곡 보정을 위해서는 왜곡 파라미터 p_1, p_2가 사용된다. 보정된 좌표는 다음과 같은 수식으로 계산된다:

x_{\text{undistorted}} = x_{\text{distorted}} + \left[ 2 p_1 xy + p_2 \left( r^2 + 2x^2 \right) \right]
y_{\text{undistorted}} = y_{\text{distorted}} + \left[ p_1 \left( r^2 + 2y^2 \right) + 2 p_2 xy \right]

여기서: - p_1, p_2는 각각 1차, 2차 Tangential 왜곡 계수이다. - x, y는 왜곡된 좌표의 x, y 값을 의미한다. - r은 Radial 왜곡에서와 동일하게 정의된다.

Tangential 왜곡 보정은 Radial 왜곡 보정과 함께 적용하여 전체적으로 왜곡된 이미지를 원래 형태로 되돌릴 수 있다.

보정 알고리즘 설명

왜곡을 보정하기 위해서는 카메라의 내부 파라미터 및 왜곡 계수를 정확하게 추정하는 과정이 필요하다. 이러한 추정 과정에서 주로 사용되는 알고리즘은 비선형 최적화 기법이다. 여기서는 Levenberg-Marquardt 최적화와 같은 방법을 통해 카메라 파라미터를 최적화하여 왜곡을 보정할 수 있다.

Levenberg-Marquardt 최적화

Levenberg-Marquardt(줄여서 LM) 알고리즘은 최소 자승법(Least Squares)을 기반으로 한 비선형 최적화 알고리즘이다. 카메라 보정에서는 재투영 오차(Reprojection Error)를 최소화하는 것이 목표인데, 이는 다음과 같이 정의된다:

\mathbf{E} = \sum_{i=1}^{n} \left( \mathbf{x}_{\text{observed},i} - \mathbf{x}_{\text{projected},i} \right)^2

여기서: - \mathbf{x}_{\text{observed},i}는 실제 이미지 상에서 관측된 2D 점이고, - \mathbf{x}_{\text{projected},i}는 3D 점이 카메라 모델을 통해 투영된 2D 점이다. - n은 사용된 관측점의 총 개수이다.

이 오차를 최소화하기 위해, LM 알고리즘은 Newton's methodGradient Descent의 혼합형태로, 계산 속도와 정확성을 동시에 개선한다.

LM 알고리즘의 업데이트 규칙은 다음과 같다:

\Delta \mathbf{\theta} = -\left( \mathbf{J}^T \mathbf{J} + \lambda \mathbf{I} \right)^{-1} \mathbf{J}^T \mathbf{r}

여기서: - \mathbf{J}는 오차 함수의 Jacobian 행렬, - \mathbf{r}는 잔차(residual) 벡터로, 관측된 값과 모델이 예측한 값의 차이, - \lambda댐핑 파라미터로, Newton 방식과 Gradient Descent 방식을 조절하는 역할을 한다.

댐핑 파라미터 \lambda는 알고리즘 진행 과정에서 동적으로 조정되며, 오차가 줄어들면 \lambda를 감소시키고, 오차가 커지면 \lambda를 증가시켜 알고리즘이 안정적으로 수렴하도록 한다.

Gauss-Newton 방법

Gauss-Newton 알고리즘은 Levenberg-Marquardt와 유사하게 비선형 최소 자승 문제를 해결하는 방법이다. 그러나 Gauss-Newton 방법은 댐핑 파라미터 \lambda 없이, 순수하게 Newton 방식에 기반한 최적화 알고리즘이다. 이 방법은 재투영 오차를 줄이는 데 집중하며, 다음과 같은 업데이트 규칙을 따른다:

\Delta \mathbf{\theta} = -\left( \mathbf{J}^T \mathbf{J} \right)^{-1} \mathbf{J}^T \mathbf{r}

여기서: - \mathbf{J}는 오차 함수의 Jacobian 행렬이다. 각 관측된 점에 대한 오차의 변화율을 나타낸다. - \mathbf{r}는 잔차(residual) 벡터이다.

Gauss-Newton 방법은 비교적 단순하지만, Jacobian 행렬 \mathbf{J}의 특성에 따라 수렴 속도가 느리거나 수렴하지 않을 수 있다. 이는 Hessian 행렬을 근사하는 방식에서 기인하는데, 오차 함수가 심하게 비선형일 경우에는 성능이 저하될 수 있다. 이때, Levenberg-Marquardt 방식이 더 좋은 성능을 보일 수 있다.

Gauss-Newton 방법의 장점은 단순성과 계산 효율성이다. Jacobian 행렬의 계산이 복잡하지 않다면, Gauss-Newton 방식은 적절한 초기값만으로도 빠른 수렴을 보일 수 있다.

Non-linear 최적화 기법

왜곡 보정에서 사용되는 최적화 문제는 대체로 비선형이며, 이는 단순한 선형 모델로는 해결할 수 없다. 위에서 설명한 Levenberg-Marquardt와 Gauss-Newton 방법 외에도 다양한 비선형 최적화 기법이 존재한다.

Gradient Descent (경사 하강법)

Gradient Descent는 비선형 최적화 문제에서 널리 사용되는 기법으로, 재투영 오차의 경사를 계산하고 그 경사를 따라 점진적으로 최소화하는 방식이다. 업데이트 규칙은 다음과 같다:

\mathbf{\theta}_{\text{new}} = \mathbf{\theta}_{\text{old}} - \alpha \nabla \mathbf{E}

여기서: - \mathbf{\theta}_{\text{old}}는 이전 파라미터 값, - \alpha학습률로, 얼마나 크게 업데이트할지를 결정한다, - \nabla \mathbf{E}는 오차 함수의 기울기(gradient)이다.

Gradient Descent는 단순하지만, 학습률 \alpha의 선택에 민감하다. 너무 크면 수렴하지 않거나 발산할 수 있고, 너무 작으면 수렴 속도가 매우 느릴 수 있다.

Conjugate Gradient (CG) 방법

Conjugate Gradient 방법은 선형 대수학에서 시작된 최적화 방법으로, Gradient Descent와는 다르게 매 반복마다 경사면의 모든 방향을 다시 계산하지 않는다. 대신, 이전 단계에서의 최적화 방향과 직교(Conjugate)인 방향을 계산하여 보다 효율적으로 최적화한다. 이 방식은 많은 변수를 포함하는 문제에서 Gradient Descent보다 더 빠르게 수렴할 수 있다.

Conjugate Gradient 방법은 다음과 같이 작동한다:

  1. 초기 방향을 기울기(gradient)로 설정한다.
  2. 새로운 방향을 이전 방향과 직교인 방향으로 조정한다.
  3. 경사를 계산하고, 파라미터를 업데이트한다.

이 방식은 특히 큰 문제에서 계산 효율성을 높이는 데 유리하다.