본문 바로가기
ML & DL/OpenCV

[OpenCV] 10. 이동, 확대/축소, 회전

by 홍월이_ 2023. 3. 3.

아래 내용은 파이썬으로 만드는 OpenCV 프로젝트(이세우 저) 를 공부하며 정리한 내용들입니다.

모든 소스 코드를 확인하고 싶으시다면 제일 하단의 저자 GitHub 주소를 참고하시기 바랍니다.


영상의 기하학적 변환은 기존의 영상을 원하는 모양이나 방향 등으로 변환하기 위해 각 픽셀을 새로운 위치로 옮기는 것이 작업의 대부분이다. 각 픽셀의 $x, y$ 좌표에 대해 옮기고자 하는 새로운 좌표 $x', y'$을 구하는 연산이 필요하다. 각 좌표에 대해 연산식을 적용해서 새로운 좌표를 구해야 하는데, 이때 사용할 연신삭을 가장 효과적으로 표현하는 방법이 행렬식이다. 변환행렬을 이용해서 영상 변환에 가장 흔하게 사용하는 이동, 확대/축소, 회전에 대해 알아보자.

 

10.1 이동

2차원 공간에서 물체를 다른 곳으로 이동시키려면 원래 있던 좌표에 이동시키려는 거리만큼 더해서 이동할 새로운 좌표를 구한다.

어떤 점 $p(x, y)$를 $d_x$와 $d_y$만큼 옮기면 새로운 위치의 좌표 $p(x', y')$을 구할 수 있다. 수식으로 표현하면 아래와 같다.

$$ x' = x + d_x \\ y' = y + d_y $$

이 방적식을 행렬식으로 표현하면 아래와 같다.

$$ \begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} 1 & 0 & d_x \\ 0 & 1 & d_y \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$

$$ \begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} x + d_x \\ y + d_y \end{bmatrix} = \begin{bmatrix} 1x + 0y + 1d_x \\ 0x + 1y + 1d_y \end{bmatrix} $$

좌표를 변환하는 과정은 OpenCV가 알아서 해주지만 어떻게 변환할 것인지는 개발자가 표현해야하는데, 변환할 방정식을 함수에 전달할 때 행렬식이 표현하기 가장 적절하다. 2 x 3 변환행렬만 전달되면 연산이 가능하다.

OpenCV는 행렬로 영상의 좌표를 변환시켜 주는 함수를 제공한다.

  • dst = cv2.warpAffine(src, mtrx, dsize [, dst, flags, dorderMode, borderValue])
    • src : 원본 영상, Numpy 배열
    • mtrx : 2 x 3 변환 행렬, Numpy 배열, dtype = float32
    • dsize : 결과 이미지 크기, tuple(width, height)
    • flags : 보간법 알고리즘 선택 플래그
      • cv2.INTER_LINEAR : 기본 값, 인접한 4개 픽셀 값에 거리 가중치 사용
      • cv2.INTER_NEAREST : 가장 가까운 픽셀 값 사용
      • cv2.INTER_AREA : 픽셀 영역 관계를 이용한 재샘플링
      • cv2.INTER_CUBIC : 인접한 16개 픽셀 값에 거리 가중치 사용
      • cv2.INTER_LANCZOS4 : 인접한 8개 픽셀을 이용한 란초의 알고리즘
    • borderMode : 외곽 영상 보정 플래그
      • cv2.BORDER_CONSTANT : 고정 색상 값 (999 | 12345 | 999)
      • cv2.BORDER_REPLICATE : 가장자리 복제 (111 | 12345 | 555)
      • cv2.BORDER_WRAP : 반복 (345 | 12345 | 123)
      • cv2.BORDER_REFLECT : 반사 (321 | 12345 | 543)
    • borderValue : cv2.BORDER_CONSTANT의 경우 사용할 색상 값(기본 값 = 0)
    • dst : 결과 이미지, Numpy 배열

cv2.warpAffine() 함수는 src 영상을 mtrx 행렬에 따라 변환해서 dsize 크기로 만들어서 반환한다.

변환에 대부분 나타나는 픽셀 탈락 현상을 보정해 주는 보간법 알고리즘과 경계 부분의 보정 방법도 선택할 수 있다.

 

10.2 확대/축소

영상을 확대 또는 축소하려면 원래 있던 좌표에 원하는 비율만큼 곱해서 새로운 좌표를 구할 수 있다. 확대/축소 비율을 가로와 세로 방향으로 각각 $\alpha$와 $\beta$라고 하면 변환행렬을 다음과 같다.

$$ \begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} \alpha & 0 & 0 \\ 0 & \beta & 0 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$

확대와 축소는 2 x 2 행렬로도 충분히 표현이 가능하지만 cv2.warpAffine() 함수는 2 x 3 행렬이 아니면 오류가 발생하기 때문에 열을 추가해서 2 x 3 행렬로 표현을 하였다.

 

OpenCV는 변환행렬을 작성하지 않고 확대와 축소 기능을 사용하는 함수를 제공한다.

  • dst = cv2.resize(src, dsize, dst, fx, fy, interpolation)
    • src : 입력 영상, Numpy 배열
    • dsize : 출력 영상 크기(확대/축소 목표 크기), 생략하면 fx, fy를 적용
      • (width, height)
    • fx, fy : 크기 배율, 생략하면 dsize를 적용
    • interpolation : 보간법 알고리즘 선택 플래그(cv2.warpAffine()과 동일)
    • dst : 결과 영상, Numpy 배열

cv2.resize() 함수는 확대 혹은 축소할 때 몇 픽셀로 할지 아니면 몇 퍼센트로 할지 선택할 수 있다. dsize로 변경하고 싶은 픽셀 크기를 직접 지정하거나 fx와 fy로 변경할 배율을 지정할 수 있다. dsize와 fx, fy 모두 값을 전달하면 dsize만 적용된다.

 

10.3 회전

영상을 회전하기 위해서는 삼각함수를 사용해야 한다.

점 $p$를 원을 따라 $p'$으로 옮기는 것을 회전이라고 하고, 새로운 점 $p'$의 좌표 $x', y'$을 구해주면 회전을 할 수 있다.

각 $\theta$만큼 회전한다고 했을 때, 새로운 점의 좌표는 $p'(xcos\theta, xsin\theta)$가 된다. 새로운 점의 사분면에 따라 다르게도 표현할 수 있다. $y$좌표를 기준으로 계산하면 $p'(-ysin\theta, ycos\theta)$로 설명할 수 있다.

행렬식으로 표현하면 아래와 같다.

$$ \begin{bmatrix} x' \\ y' \end{bmatrix} = \begin{bmatrix} cos\theta & -sin\theta & 0 \\ sin\theta & cos\theta & 0 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix} $$

 

회전을 위한 변환행렬 생성은 다소 까다롭고 회전 축까지 반영하려면 일이 복잡해진다.

OpenCV에서는 복잡한 계산을 하지 않고도 변환행렬을 생성할 수 있는 함수를 제공한다.

  • mtrx = cv2.getRotationMatrix2D(center, angle, scale)
    • center : 회전 축 중심 좌표, Tuple(x, y)
    • angle : 회전 각도, 60진법
    • scale : 확대/축소 배율

 

REFERENCE

  • 소스 코드 참고(저자 GitHub 주소)
 

GitHub - dltpdn/insightbook.opencv_project_python

Contribute to dltpdn/insightbook.opencv_project_python development by creating an account on GitHub.

github.com

 

  • OpenCV 공식문서
 

OpenCV: OpenCV modules

OpenCV  4.7.0 Open Source Computer Vision

docs.opencv.org

 

 

'ML & DL > OpenCV' 카테고리의 다른 글

[OpenCV] 12. 렌즈 왜곡  (0) 2023.03.09
[OpenCV] 11. 뒤틀기  (0) 2023.03.06
[OpenCV] 9. 히스토그램  (0) 2023.03.02
[OpenCV] 8. 이미지 연산  (0) 2023.02.27
[OpenCV] 7. 스레시홀딩  (0) 2023.02.22

댓글