본문 바로가기
  • AI 개발자가 될래요
컴퓨터비전

[Python/OpenCV] Affine Transform

by 꿀개 2022. 5. 6.

● Affine Transform

- 영상을 평행 이동시키거나 회전, 크기 변환, 전단 변환 등을 통해 만들 수 있는 변환을 통칭한다.

- 직선은 그대로 직선으로 나타나고, 직선 간의 길이 비율과 평행 관계는 그대로 유지된다.


 * 전단 변환: 직사각형 형태의 영상을 한쪽 방향으로 밀어서 평행사변형 모양으로 변형되는 변환

                 가로, 세로 방향 정의 가능

 

 

(a)는 y 좌표가 증가함에 따라 영상이 조금씩 가로 방향으로 이동하는 가로 방향 전단 변환

(b)는 x 좌표가 증가함에 따라 영상이 조금씩 세로 방향으로 이동하는 세로 방향 전단 변환

출처: https://thebook.io/006939/ch08/01/03/


아래 그림은 어파인 변환의 예를 나타낸다.

 

(a): 입력으로 사용한 원본 영상

(b): 입력 영상을 x축과 y축 방향으로 일정 크기만큼 평행 이동

(c): y 좌표가 증가함에 따라 영상의 x축 시작 위치를 조금씩 오른쪽 이동한 전단 변환

(d): 가로 방향으로는 축소하고, 세로 방향으로는 확대한 크기 변환

(e): 원점 기준 시계 방향으로 10º 회전

(f): 이동, 크기, 회전, 전단 변환을 복합적으로 적용하여 만든 어파인 변환 결과 영상

 

 

 

 

 

어파인 변환은 모두 여섯 개의 파라미터를 이용한 수식으로 정의할 수 있다. 어파인 변환에 의해 입력 영상의 좌표 (x, y)가 결과 영상의 좌표 (x′, y′)로 이동하는 수식은 다음과 같이 1차 다항식으로 표현한다.

a, b, c, d, e, f가 어파인 변환을 결정하는 여섯 개의 파라미터이다.

위과 같이 두 개의 수식으로 표현된 어파인 변환은 행렬을 이용하여 하나의 수식으로 표현할 수 있습니다.

즉, 입력 영상의 좌표를 나타내는 행렬 

 앞에 2×2 행렬 

를 곱하고, 그 뒤에 2×1 행렬 

을 더하는 형태로 어파인 변환을 표현한다. 수학적 편의를 위해 입력 영상의 좌표 (x, y)에 가상의 좌표 1을 하나 추가하여 (x, y, 1) 형태로 바꾸면, 앞 행렬 수식을 다음과 같이 하나의 행렬 곱셈 형태로 바꿀 수 있다.

 

여기에서 여섯 개의 파라미터로 구성된 2×3 행렬을 어파인 변환 행렬이라고 부른다.

 즉, 어파인 변환은 2×3 실수형 행렬 하나로 표현할 수 있다.

 

 

 

 

입력 영상과 어파인 변환 결과 영상으로부터 어파인 변환 행렬을 구하기 위해서는

최소 세 점의 이동 관계를 알아야 한다.

 

점 하나의 이동 관계로부터 x 좌표와 y 좌표에 대한 변환 수식 두 개를 얻을 수 있으므로, 점 세 개의 이동 관계로부터 총 여섯 개의 방정식을 구할 수 있기 때문이다. 그러므로 점 세 개의 이동 관계를 알고 있다면 여섯 개의 원소로 정의되는 어파인 변환 행렬을 구할 수 있다.

 

 

 

OpenCV는 어파인 변환 행렬을 구하는 함수(getAffineTransform())와 어파인 변환 행렬을 이용하여 실제 영상을 어파인 변환하는 함수(warpAffine())를 모두 제공한다.

 

- getAffineTransform()

  : 어파인 변환 행렬을 구하는 함수

    입력 영상에서 세 점의 좌표(src)와 이 점들이 이동한 결과 영상의 좌표 세 개(dst)를 입력으로 받아

     2X3 어파인 변환 행렬을 계산

    

Mat getAffineTransform(InputArray src, InputArray dst)
 src 입력 영상에서 세 점의 좌표
 dst 결과 영상에서 세 점의 좌표
 반환값 2×3 어파인 변환 행렬. CV_64FC1

 

- warpAffine()

  : 2X3 어파인 변환 행렬을 가지고 있을 때, 어파인 변환한 결과 영상을 생성하는 함수

 

void warpAffine(InputArray src, OutputArray dst,
                     InputArray M, Size dsize,
                     int flags = INTER_LINEAR,
                     int borderMode = BORDER_CONSTANT,
                     const Scalar&borderValue = Scalar())
 src 입력 영상
 dst 결과 영상. src와 같은 타입이고, 크기는 dsize에 의해 결정됩니다.
 M 2×3 어파인 변환 행렬
 dsize 결과 영상 크기
 flags 보간법 알고리즘. 만약 OR 연산자를 이용하여 WARP_INVERSE_MAP 플래그를 함께 지정하면 역방향으로 변환을 수행합니다.
 borderMode 가장자리 픽셀 확장 방식. BorderTypes 열거형 상수 중 하나를 지정합니다. 만약 BORDER_TRANSPARENT를 지정하면 입력 영상의 픽셀 값이 복사되지 않는 영역은 dst 픽셀 값을 그대로 유지합니다.
 borderValue borderMode BORDER_CONSTANT일 때 사용할 상수 값. 기본값으로 검은색이 지정되어 있습니다.

 

    src 영상을 어파인 변환하여 dst 영상을 생성

    dsize 인자에 Size()를 전달하면 입력 영상과 같은 크기의 결과 영상 생성

 


* transform()

: 어파인 변환 행렬을 갖고 있을 때, 영상 전체를 어파인 변환하는 것이 아니라 일부 점들이 어느 위치로 이동하는지 알고싶다면 사용.

void transform(InputArray src, OutputArray dst, InputArray m)
 src 입력 행렬 또는 vector<Point2f>. 점의 좌표를 다채널로 표현합니다.
 dst 출력 행렬 또는 vector<Point2f>
 m 변환 행렬. 2×2 또는 2×3 실수형 행렬

 

 

출처: https://thebook.io/006939/ch08/01/