OpenCV로 배우는 영상 처리 및 응용/ 기하학 처리

  • 영상 처리에서 기하학 처리는 영상 내에 있는 기하학적인 대상의 공간적 배치를 변경하는 과정을 말한다.
    • 이것을 화소의 입장에서 보면 영상을 구성하는 화소들의 공간적 위치를 재배치하는 과정이라 할 수 있다.
    • 이러한 변환에는 회전, 크기 변경, 평행이동 등이 있다.

사상(Mapping)

  • 사상은 화소들의 배치를 변경할 때, 입력 영상의 좌표가 새롭게 배치될 해당 목적 영상의 좌표를 찾아서 화소값을 옮기는 과정을 말한다.
    • 사상에는 순방향 사상(forward mapping)과 역방향 사상(reverse mapping)의 두 가지 방식이 있다.
  • 순방향 사상은 원본 영상의 좌표를 중심으로 목적영상의 좌표를 계산하여 화소의 위치를 변환하는 방식이다.
    • 이 방식은 원본 영상과 목적 영상의 크기가 같을 때는 유용하지만 그렇지 않으면 홀(hole)이나 오버랩(overlap)의 문제가 발생할 수 있다.
    • 아래 그림에서 홀과 오버랩에 대해 나타내었는데, 홀은 입력 영상의 좌표들로 목적영상의 좌표를 만드는 과정에서 사상되지 않은 화소를 가리킨다. 보통 영상을 확대하거나 회전할 때 발생한다.
    • 반면 오버랩은 원본 영상의 여러 화소가 목적영상의 한 화소로 사상되는 것으로 영상을 축소할 때 주로 발생한다.
  • 이런 문제를 해결할 수 있는 방법이 역방향 사상이다. 역방향 사사은 목적 영상의 좌표를 중심으로 역변환을 계산하여 해당하는 입력 영상의 좌표를 찾아서 화소값을 가져오는 방식이다.
    • 아래 그램의 예시에서 입력영상의 하단 왼쪽 한 개의 화소가 목적 영상의 두 개 화소로 각각 사상된다. 이 경우에도 역방향 사상의 방식은 홀이나 오버랩은 발생하지 않는다.
    • 다만 입력영상의 한 화소를 목적영상의 여러 화소에서 사용하게 되면 결과 영상의 품질이 떨어질 수 있다.

크기 변경(Scaling)

  • 크기 변경은 입력 영상의 가로와 세로로 크기를 변경해서 목적영상을 만드는 방법으로 입력영상보다 변경하고자 하는 영상의 크기가 커지면 확대가 되고, 작아지면 축소가 된다.
  • 영상의 크기 변경은 비율을 이용해서 수행할 수 있다. 가로와 세로로 변경하고자 하는 비율을 지정하여 입력영상의 좌표에 곱하면 목적영상의 좌표를 계산할 수 있다.

x' = x \cdot ratio X \\ y' = y \cdot ratio Y

  • 목적영상의 크기를 지정해서 변경할 수도 있는데, 이것은 입력영상과 목적영상의 크기로 비율을 계산하고, 계산된 비율을 이용해서 목적영상의 좌표를 계산한다.

ratio X = {dst_{width} \over org_{width}}, ratio Y = {dst_{height} \over org_{height}}

보간(Interpolation)

  • 아래 그림은 입력영상을 두 배 확대할 때 목적영상의 화소 배치를 보인 것이다. 순방향 사상으로 목적영상의 화소를 찾은 경우에는 입력영상의 4개 화소는 쉽게 배치가 되지만, 목적영상에서 확대되는 나머지 화소들은 홀이 발생한다.
    • 이런 문제를 해결하는 방법으로 역방향 사상을 통해서 홀의 화소들을 입력영상에서 찾아서 목적영상의 화소에 대입함으로써 목적영상의 화질을 유지할 수 있다.
  • 이렇게 목적영상에서 홀의 화소들을 채우고 오버랩이 되지 않게 화소들을 배치하여 목적영상을 만드는 기법을 보간법이라한다.
    • 이렇나 보간법의 종류에는 최근접 이웃 보간법(nearest neighbor interpolation), 양선형 보간법(bilinear interpolation), 3차 회선 보간법(cubic convolution interpolation) 등이 있다.

최근접 이웃 보간법(Nearest Neighbor Interpolation)

  • 최근접 이웃 보간법은 목적영상을 만드는 과정에서 홀이 되어 할당 받지 못하는 화소들의 값을 찾을 때, 목적영상의 화소에 가장 가깝에 이웃한 입력영상의 화소값을 가져오는 방법이다.
  • 이 방법은 목적화소의 좌표를 반올림하는 간단한 알고리즘으로 비어있는 홀들을 채울 수 있어 쉽고 빠르게 목적영상의 품질을 높일 수 있다.
    • 다만 확대의 비율이 커지면 영상 내에서 경계선이나 모서리 부분에서 계단현상이 나타날 수 있다.

양선형 보간법(Bililnear Interpolation)

  • 영상을 확대할 때 확대비율이 커지면 최근접 이웃 보간법은 모자이크 현상 혹은 경계부근에서 계단현상이 나타나게 된다. 이러한 문제를 보완할 수 있는 방법이 양선형 보간법이다.
  • 여기서 선형의 의미는 중첩의 원리(superposition principle)가 적용되낟는 것이다. 
    • 쉽게 표현하면 직선의 특징을 가지고 있다는 것인데, 직선의 방정식을 예로 들 수 있다.
    • 아래 그림과 같이 두 개의 화소 값을 알고 있을 때 그 값으로 직선을 그리면, 직선의 선상에 위치한 중간 화소들의 값은 직선의 수식을 이용해서 쉽게 계산할 수 있다.
  • 양선형 보간법은 이와 같은 선형 보간을 두 번에 걸쳐서 수행하기에 붙여진 이름이다. 그 세부적인 방법은 아래 그림을 이용해 설명한다.
  • 먼저 목적영상의 화소(P)를 역변환으로 계산하여 가장 가까운 위치에 있는 입력영상의 4개 화소(A, B, C, D)를 가져온다.
    • (b) 그림과 같이 가져온 4개 화소를 두 개씩(AB, CD) 묶어서 화소값(P1, P2, P3, P4)으로 두 화소를 잇는 직선을 구성한다.
    • 다음으로 직선의 선상에서 목적영상의 화소의 좌표로 중간 위치를 찾고, 그 위치의 화소값(M1, M2)를 계산한다. 이때 중간 위치의 화소값은 기준 화소값 (P1, P2, P3, P4)과 거리 비율(α, 1-α)을 바탕으로 짓건의 수식을 이용해서 계산한다.
    • 마지막으로 구해진 중간 화소값(M1, M2)을 잇는 직선을 다시 구성하고, 두 개의 중간 화소값과 거리 비율(β, 1-β)을 바탕으로 직선의 수식을 이용해서 최종 화소값 (P)를 계산한다.
    • 이때 최종 화소값이 목적영상의 해당 좌표의 화소값이 된다.
  • 정확히는 세 번의 선형 보간을 수행하지만, 4개 화소값(P1, P2, P3, P4) 에 대해서 수행하는 선형 보간은 1차 보간으로 간주한다.
    • 그리고 중간 화소값(M1, M2)에 대해 수행하는 선형 보간을 2차 보간으로 간주하기 때문에 양선형 보간이라 한다.
    • 이를 수식으로 표현하면 다음과 같다.

M_{1} = \alpha \cdot B + (1-\alpha) \cdot A = A + \alpha \cdot (B - A) \\ M_{2} = \alpha \cdot D + (1-\alpha) \cdot C = C + \alpha \cdot (D - C) \\ P = \beta \cdot M_{2} + (1 - \beta) \cdot M_{1} = M_{1} + \beta \cdot (M_{2} - M_{1})

  • OpenCV에서는 보간이 필요한 함수들을 위해 아래와 같은 옵션값을 제공한다.
옵션 상수 설명
INTER_NEAREST 0 최근접 이웃 보간
INTER_LINEAR 1 양선형 보간(기본값)
INTER_CUBIC 2 바이큐빅 보간 – 4×4 이웃 화소 이용
INTER_AREA 3 픽셀 영역의 관계로 리샘플링
INTER_LANCZOS4 4 Lanczos 보간 – 8×8 이웃 화소 이용

평행이동(Translation)

  • 영상에서 원점 좌표는 좌상단이다. 평행이동은 영상의 원점을 기준으로 모든 화소를 동일하게 가로, 세로 방향으로 옮기는 것을 말한다.
    • 아래 그림은 최상단 오른쪽의 원점에서 가로 방향으로 dx, 세로 방향으로 dy 만큼 전체 영상의 모든 화소를 이동시키는 예이다.
    • 여기서 옮겨진 후에 입력영상의 범위를 벗어나는 부분(오른쪽 부분과 하단 부분)은 목적영상에서 제거된다.
    • 평행이동할 화소가 없는 부분인 상단과 왼쪽 부분은 0(검은색) 혹은 255(흰색)로 지정한다.
  • 평행이동을 수식으로 표현하면 다음과 같다.
    • 순방향 사상을 적용하면 입력영상의 화소(x, y)에서 이동할 화소 수만큼 가로 방향과 세로 방향으로 더해 주어서 목적영상의 화소(x’, y’) 위치를 정한다.

순방향 사상

x' = x + dx \\ y' = y + dy

역방향 사상

x = x' - dx \\ y = y' - dy

회전(Rotation)

  • 회전은 입력영상의 모든 화소를 영상의 원점을 기준으로 원하는 각도만큼 모든 화소에 대해 회전 변환을 시키는 것을 말한다.
    • 이것은 2차원 평면에서 회전 변환을 나타내는 행렬을 통해서 수식으로 표현할 수 있다.

순방향 사상

x' = x \cdot cos \theta - y \cdot sin \theta \\ y' = x \cdot sin \theta + y \cdot cos \theta

역방향 사상

x = x' \cdot cos \theta + y' \cdot sin \theta \\ y = - x' \cdot sin \theta + y' \cdot cos \theta

  • 목적영상의 모든 화소(x’, y’)에 대해 역방향 사상의 수식을 적용하여 입력화소를 계산하면 아래 그림과 같이 원점으로부터 시계 방향으로 정해진 각도만큼 회전된 영상이 생성된다.
    • 직교 좌표계에서 회전 변환은 반시계 방향으로 적용된다. 그러나 영상 좌표계에서는 y좌표가 하단으로 내려갈수록 증가하기 때문에 시계방향의 회전으로 표현됨에 유의한다.
  • 평행이동과 마찬가지로 목적영사으이 범위를 벗어나는 입력화소는 제거되며, 입력영상에서 찾지 못하는 화소는 검은색이나 흰색으로 지정한다.
  • 일반적으로 영상을 회전시킬 때 회전의 기준을 영상의 기준 원점인 좌상단으로 하지 않고, 물체의 중심(center X, center Y)으로 하는 경우가 많다.
    • 이런 경우에는 평행이동의 수식을 포함하여 회전 변환을 수행한다. 이것은 영상의 기준점을 원점으로 이동시킨 후 회전을 수행하고, 다시 기준점으로 이동하는 것이다.

x = (x' - cneter X) \cdot cos \theta + (y' - center Y) \cdot sin \theta + center X \\ y = -(x' - cneter X) \cdot sin \theta + (y' - center Y) \cdot cos \theta + center Y

행렬 연산을 통한 기하학 변환 – 어파인 변환(Affine Transform)

  • 앞서 기술한 기하학 변환들의 수식은 행렬식으로 표현 가능하다. 즉, 기하학 변환 수식이 행렬의 곱으로 표현되는 것이다. 각 변환식은 다음과 같은 수식으로 표현할 수 있다.

회전 

\left[ \begin{array}{rr} x' \\ y'  \end{array} \right] = \left[ \begin{array}{rr} cos \theta & - sin \theta \\ sin \theta & cos \theta \end{array} \right] \left[ \begin{array}{rr} x \\ y  \end{array} \right]

크기변경

\left[ \begin{array}{rr} x' \\ y'  \end{array} \right] = \left[ \begin{array}{rr} \alpha & 0 \\ 0 & \beta \end{array} \right] \left[ \begin{array}{rr} x \\ y  \end{array} \right]

평행이동

\left[ \begin{array}{rr} x' \\ y'  \end{array} \right] = \left[ \begin{array}{rr} x \\ y \end{array} \right] \left[ \begin{array}{rr} t_{x} \\ t_{y}  \end{array} \right]

  • 회전과 크기변경은 2×2 행렬로 표현이 가능하지만, 평행이동까지 포함하려면 2×3 행렬이 필요하다. 다음 수식과 같이 2×3 행렬로 변환 행렬을 구성하는 것을 어파인 변환이라 한다.

\left[ \begin{array}{rr} x' \\ y'  \end{array} \right] = \left[ \begin{array}{rrr} \alpha_{11} & \alpha_{12} & \alpha_{13} \\ \alpha_{21} & \alpha_{22} & \alpha_{23} \end{array} \right] \cdot \left[ \begin{array}{rrr} x \\ y \\ 1  \end{array} \right]

  • 어파인 변환은 변환 전과 변환 후의 두 어파인 공간 사이의 공선점을 보존하는 변환이다.
    • 따라서 변환 전에 직선은 변환 후에도 그대로 직선이며, 그 거리의 비도 유지된다. 또한 변환 전에 평행선도 변환 후에 평행선이 된다.
  • 어파인 변환을 수행하는 방법은 크게 2가지가 있다.
    • 하나는 회전 각도, 크기변경 비율, 평행이동의 정도를 지정해서 각각 변환 행렬을 구성한다. 그리고 각 변환 행렬을 행렬 곱으로 구성하면 하나의 변환 행렬을 만들 수 있다.
    • 각 행렬들을 곱하는 순서는 변환하고자는 방식에 따라서 달라질 수 있다.
    • 이때 2×3 크기의 어파인 행렬로 구성하면 행렬의 곱을 계산할 수 없기 때문에 다음 수식과 같이 3×3 크기의 행렬로 구성하여 행렬 곱을 수행한다.

어파인 변환행렬

\left[ \begin{array}{rrr} cos \theta & -sin' \theta & 0 \\ sin \theta & cos \theta & 0 \\ 0 & 0 & 1 \end{array} \right] \cdot \left[ \begin{array}{rrr} \alpha & 0 & 0 \\ 0 & \beta & 0 \\ 0 & 0 & 1 \end{array} \right] \cdot \left[ \begin{array}{rrr} 1 & 0 & t_{x} \\ 0 & 1 & t_{y} \\ 0 & 0 & 1 \end{array} \right]

  • 행렬 곱을 완성하면 3×3 행렬에서 마지막 행(0 0 1)을 삭제하면 최종적으로 2×3 형태의 어파인 행렬이 된다.
  • 다른 한 가지 방법으로 위 그림과 같이 변환 전인 입력영상의 좌표 3개 (x1, x2, x3)와 변환이 완료된 목적영상에서 상응하는 좌표 3개 (x’1, x’2, x’3)를 알면 두 좌표 (x -> x’) 사이를 변환해 주는 어파인 변환 행렬을 구할 수 있다.
  • 이렇게 행렬의 곱으로 기하학 변환을 적용하면 단순하면서도 쉽게 입력영상에 대한 변환이 가능하다.
    • OpenCV 에서도 어파인 변환을 수행할 수 있는 cv::wrapAffine() 함수를 제공한다. 이 함수는 지정된 어파인 변환 행렬을 적용하면 입력영상에 어파인 변환을 수행한 목적영상을 반환한다.
  • 또한 어파인 변환 행렬을 만드는 함수로는 cv::getAffineTransform()과 cv::getRotationMatrix2D()가 있다.
    • cv::getAffineTransform()는 변환 전의 좌표 3개와 변환 후의 좌표 3개를 지정하면 해당 변환을 수행해 줄 수 있는 어파인 행렬을 반환한다.
    • cv::getRotationMatrix2D()는 회전 변호나과 크기 변경ㅇㄹ 수행하는 어파인 행렬을 반환한다. 여기서 회전의 방향은 양수일 때 반시계 방향으로 회전하는 행렬을 반환한다.
반환형 이름 파라미터 내용
void wrapAffine

InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags,
int borderMode

입력영상에 어파인 변환을 수행해서 반환한다.
Mat getAffineTransform InputArray src,
OutputArray dst,
Point2f src[],
Point2f dst[]
3개의 좌표쌍을 입력하면 어파인 변환 행렬을 반환한다.
Mat getAffineTransform const Point2f src[],
const Point2f dst[]
 
Mat getRotationMatrix2D Point2f center,
double angle,
double scale
회전 변환과 크기 변경을 수행할 수 있는 어파인 행렬을 반환한다.

원근 투시(투영) 변환 (Perspective Projection Transformation)

  • 원근 투시 변환은 원근법을 영상 좌표계에서 표현하는 것이다. 원근 투시 변환은 아래 그림과 같이 3차원의 실세계의 좌표를 투영 스크린상의 2차원 좌표로 표현할 수 있도록 변환해 주는 것을 말한다.
  • 영상 처리에서 원근변환은 주로 2차원 영상을 다른 2차원 영상으로 변환할 때 사용한다.
    • 예컨대 카메라에서 입력 받은 영상에서 카메라 렌즈에 의한 왜곡을 보정할 수 있다. 그리고 원근감이 잘 표현된 2차원 영상을 변환하여 3차원 공간상의 거리를 측정하고자 할 때 사용될 수도 있다.
  • 원근 투영 변환을 사용할 때는 동차 좌표계(homogeneous coordinates)를 사용하는 것이 편리하다.
    • 동차 좌표계는 모든 항의 차수가 동일하기 때문에 붙여진 이름으로 n차원의 투영 공간을 n+1개의 좌표로 나타내는 좌표계이다. 좀 더 쉽게 말하면 직교 좌표인 (x, y)를 (x, y, 1)로 표현하는 것이다.
    • 이것을 일반화해서 표현하면 0이 아닌 상수 w에 대해 (x, y)를 (wx, wy, w)로 표현한다. 이렇게 되면 상수 w가 무한히 많기 때문에 (x, y)에 대한 동차 좌표 표현은 무한히 많이 존재하게 된다.
    • 거꾸로 동차 좌표계에서 한 점 (wx, wy, w)을 직교 좌표로 나타내면 각 원소를 w로 나누어저 (x/w, y/w)가 된다.
  • 원근변환을 수행할 수 있는 행렬은 다음과 같다. 이 수식으로 입력영상의 좌표를 목적영상의 좌표로 변환하면 원근변환이 수행된다.

w \cdot \left[ \begin{array}{rrr} x' \\ y' \\ 1\end{array} \right] = \left[ \begin{array}{rrr} \alpha_{11} & \alpha_{12} & \alpha_{13} \\ \alpha_{21} & \alpha_{22} & \alpha_{23} \\ \alpha_{31} & \alpha_{32} & \alpha_{33} \end{array} \right] \cdot \left[ \begin{array}{rrr} x \\ y \\ 1 \end{array} \right]

[ssba]

The author

지성을 추구하는 사람/ suyeongpark@abyne.com

댓글 남기기

This site uses Akismet to reduce spam. Learn how your comment data is processed.