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

[Python/OpenCV] Perspective Transform(투시 변환)

by 꿀개 2022. 5. 6.

Perspective Transform

- 직사각형 형태의 영상을 임의의 볼록 사각형 형태로 변경할 수 있는 변환

- 원본 영상에 있던 직선은 결과 영상에서 그대로 유지되지만, 두 직선의 평행 관계는 깨질 수 있음

- 어파인 변환보다 자유도가 높음

 

 

위 그림은 점 네 개의 이동 관계에 의해 결정되는 투시 변환을 나타낸다.

 

투시 변환은 직선의 평행 관계가 유지되지 않기 때문에 결과 영상의 형태가 임의의 사각형으로 나타난다.

 

점 하나의 이동 관계로부터 x 좌표에 대한 방정식 하나와 y 좌표에 대한 방정식 하나를 얻을 수 있으므로, 점 네 개의 이동 관계로부터 여덟 개의 방정식을 얻을 수 있다.

 

이 여덟 개의 방정식으로부터 투시 변환을 표현하는 파라미터 정보를 계산할 수 있다.

 

그러나, 투시 변환은 좌표 계산의 편의상 보통 3X3 크기의 실수 행렬로 표현된다. 

 

투시 변환을 표현하는 행렬을 MP라고 하면,

입력 영상의 픽셀 좌표 (x, y)가 행렬 MP에 의해 이동하는 결과 영상 픽셀 좌표 (x′, y′)는 다음과 같다.


* 입력 좌표와 출력 좌표를 (x, y, 1), (wx′, wy′, w) 형태로 표현한 것을

  동차 좌표계(homogeneous coordinates)라고 하며, 좌표 계산의 편의를 위해 사용한 것이다.

* w는 결과 영상의 좌표를 표현할 때 사용되는 비례 상수, w=p31x+p32y+p33 형태로 계산


그러므로 x', y'은 다음과 같다.

 

 

 

OpenCV는 투시 변환 행렬을 구하는 함수(getPerspectiveTransform())와 투시 변환 행렬을 이용하여 실제 영상을 투시 변환하는 함수를 모두 제공한다.

 

- getPerspectiveTransform()

  : 입력 영상에서 네 점의 좌표와 결과 영상의 좌표 네 개를 입력으로 받아 3X3 투시 변환 행렬을 계산

 

Mat getPerspectiveTransform(InputArray src, InputArray dst, 
                                      int solvedMethod = DECOMP_LU)
 src 입력 영상에서 네 점의 좌표
 dst 결과 영상에서 네 점의 좌표
 solveMethod 계산 방법 지정. DecompTypes 열거형 상수 중 하나를 지정합니다.
 반환값 3×3 크기의 투시 변환 행렬

 

- warpPerspective()

  : 3X3 투시 변환을 갖고 있을 때, 투시 변환한 결과 영상을 생성하는 함수

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

 

   dsize 위치에 Size()를 지정하면 입력 영상과 같은 크기의 결과 영상을 생성한다.

 

다음 사진은 K 카드의 모서리를 반듯한 직사각형 형태로 투시 변환했을 때의 결과를 보여준다.

 


* perspectiveTransform()

: 3X3 투시 변환 행렬을 갖고있을 때, 일부 점들이 투시 변환에 의해 어느 위치로 이동할 것인지 알 수 있음

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

 

 

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