프로그래밍 언어 및 IT 정보/opencv_python

[opencv_python] 4.1 기하학적 변환 (대칭, 회전, 확대, 축소 )

Himer_torr 2022. 7. 21. 11:54
반응형

저번 포스팅에 이어 opencv로 기하학적 변환을 진행해보도록 하겠습니다. 
기하학적 변환(geo-metric transform)은 영상의 좌표에 기하학적인 연산을 가해서 변환된 새로운 좌표를
얻는 것을 말합니다. 쉽게 말해 이미지를 구성하는 픽셀 좌표값이 위치를 재배치하는 과정이라고 보시면 됩니다 :)

 

저는 Visual studio code와opencv 4.5.5 버전을 이용하였습니다.

 

 

대칭(Flip, Symmetry)

대칭은 상하대칭 or 좌우 대칭 2가지 방법이 있는데, 변환할 행렬(이미지)에 대해 2x2 행렬을 왼쪽곱샘을 진행해하면 됩니다.

즉 '->' 형태의 물체에 Y축 대칭을 적용한다면 '<-' 형태를 가지게 되는 것이죠

변환 좌표 수식은 아래와 같습니다.

수식에서 (x,y)는 입력영상의 픽셀 좌표이고, (x',y')는 결과 영상의 픽셀좌표, w는 입력영상의 가로크기 입니다.

수식을 해석하자면 x축방향으로 -1배 크기를 변환한 후 x축 방향으로 w-1만큼 이동 변환과 같습니다. 

 

cv2.flip(src,flipcode,dst=None)

Parameters

  • src: 입력영상
  • filpcode: 대칭 방향 지정( 1 = 좌우대칭, 0 = 상하 대칭 , -1 = 좌우&상하대칭 )
  • dst: 출력영상

 

import cv2

img = cv2.imread('img/torr.jpg')


cv2.imshow('img',img)

dst = cv2.flip(img,-1)  
dst2 = cv2.flip(img,1)
dst3 = cv2.flip(img,0)

cv2.imshow('flip',dst)
cv2.imshow('filp2',dst2)
cv2.imshow('flip3',dst3)

cv2.waitKey()
cv2.destroyAllWindows()

결과값

저는 3가지의 대칭을 모두 진행해보았습니다. 이처럼 원하는 방향으로 filpcode를 지정하여 대칭을 진행할 수 있습니다.

 

회전(Rotate)

회전은 회전 변환 행렬(Rotation matrix)를 통해 변환이 진행됩니다.

행렬식은 아래와 같습니다. 영상을 회전하려면 삼각함수를 써야 하는데, 삼각함수와 관계는 

자세히 설명하지 않겠습니다!

 

cv2.getRotationMatrix2D(center, angle, scale)
cv2.rotate(src, rotateCode)

Parameters

  • ceter: 회전 중심 좌표
  • angle: 회전 각도, 양수는 반시계, 음수는 시계방향을 의미합니다.
  • scale: 회전 후 추가적으로 확대 또는 축소할 비율

Parameters

  • src: 입력 영상
  • rotateCode: cv2.ROTATE_90_CLOCKWISE : 시계방향 90도 회전
                         cv2.ROTATE_180 : 180도 회전
                     cv2.ROTATE_90_COUNTERCLOCKWISE: 반시계 반향 90도 회전

 

# getRotationMatrix2D 사용시

import cv2

img = cv2.imread('img/torr.jpg')

height, width, channel = img.shape


height, width, channel = img.shape
matrix = cv2.getRotationMatrix2D((width/2, height/2), 90, 1)
dst = cv2.warpAffine(img, matrix, (width, height)) 

 
cv2.imshow("img", img)
cv2.imshow("dst", dst)

cv2.waitKey()
cv2.destroyAllWindows()

 

# rotate를 이용한 코드

import cv2

img = cv2.imread('img/torr.jpg')
img90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE) # 시계방향으로 90도 회전
img180 = cv2.rotate(img, cv2.ROTATE_180) # 180도 회전
img270 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE) # 반시계방향으로 90도 회전 
                                                         # = 시계방향으로 270도 회전
 
cv2.imshow('original', img)
cv2.imshow('rotate90', img90)
cv2.imshow('rotate180', img180)
cv2.imshow('rotate270', img270)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.waitKey()
cv2.destroyAllWindows()

 

 

확대 축소(resize,  Image Pyramid)

입력 이미지는 항상 동일 크기가 아니므로 너무 크거나 너무 작을 수 있습니다.

그럴 때, 입력 이미지 크기를 변경해야 하는데, 2가지 방법이 있습니다.

resize, 이미지 피라미드(Image pyramid)를 활용해 이미지의 크기를 원하는 단계까지
샘플링하는 작업입니다.

dst = cv2.resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)

Parameters

  • src: 입력 영상
  • dsize: 결과 영상크기(w,h) 튜플, (0,0)이면 fx, fy값을 이용하여 결정
  • dst: 출력 영상
  • fx, fy: x와 y방향의 스케일 비율 (dsize값이 0일때)
  • interpolation: 보간법 지정, 기본값은 cv2.INTER_LINEAR

cv2.INTER_NEAREST : 최근방 이웃 보간법 -  가장 빠르지만 성능이 다소 떨어집니다. 잘 쓰이지 않습니다.

cv2.INTER_LINEAR : 쌍 선형 보간법 - 효율이 뛰어납니다. 속도와 성능도 준수하여 가장 많이 사용됩니다.

                                   영상 확대 시 주로 이용됩니다.

cv2.INTER_CUBIC : 바이큐빅 보간법 - 쌍 선형보다 느리지만 성능이 더 우수합니다. 영상 확대 시 주로 이용됩니다.

cv2.INTER_LANCZOS4 : Lanczos 보간법 - 좀 더 복잡해서 오래 걸리지만 훨씬 성능이 우수합니다.

cv2.INTER_AREA : 영역 보간법 - 영역의 특징을 추출하여 결과를 지정합니다. 영상 축소 시 주로 이용됩니다.

 

import cv2

img = cv2.imread('img/torr.jpg')
height, width, channel = img.shape

dst = cv2.resize(img, dsize=(0, 0), fx=1.5, fy=1.5)
dst2 = cv2.resize(img, dsize=(500, 500))
dst3 = cv2.resize(img, dsize=(840, 720))


cv2.imshow("img", img)
cv2.imshow("dst", dst)
cv2.imshow("dst2", dst2)
cv2.imshow("dst3", dst3)

cv2.waitKey() 
cv2.destroyAllWindows()

 

2번째로 이미지 피라미드(Image pyramid)를 활용하는 것입니다.

이미지 피라미드의 의미는 이미지의 크기를 확대하거나 축소했을 때 이미지들의 형태가 피라미드같이 표현됩니다.

원본 이미지에서 크기를 확대하는 것을 업 샘플링이라고 하며 하위 단계의 이미지를 생성하게 됩니다.

반대로 원본 이미지에서 크기를 축소하는 것을 다운 샘플링이라 하며, 상위 단계의 이미지를 생성하게 됩니다.

이미지 피라미드는 가우시안 피라미드(Gaussian Pyramid)라플라시안 피라미드(Laplacian Pyramid)를 활용합니다.

 

cv.pyrUp(src[, dst[, dstsize[, borderType]]])

Parameters

  • src: 입력 영상
  • dst: 출력 이미지. 지정된 크기와 src와 같은 유형을 갖습니다.
  • dstsize: 출력 이미지의 크기 - 매우 세밀한 크기 조정을 필요할 때 사용
  • borderType: 픽셀 외삽 방법, BorderTypes 참조 (BORDER_DEFAULT  지원됨 )
cv.pyrDown(src[,dst[,dstsize[,borderType]]])

Parameters

  • src: 입력 영상
  • dst: 출력 이미지. 지정된 크기와 src와 같은 유형을 갖습니다.
  • dstsize: 출력 이미지의 크기 - 매우 세밀한 크기 조정을 필요할 때 사용
  • borderType: 픽셀 외삽 방법, BorderTypes 참조 (BORDER_DEFAULT  지원됨 ) - opencv 홈페이지 참조
import cv2

img = cv2.imread('img/torr.jpg')

height, width, channel = img.shape

dst = cv2.pyrUp(img, dstsize=(width * 2, height * 2), borderType=cv2.BORDER_DEFAULT)
dst2 = cv2.pyrDown(img)

cv2.imshow("src", img)
cv2.imshow("dst", dst)
cv2.imshow("dst2", dst2)
cv2.waitKey()
cv2.destroyAllWindows()

cv2.waitKey() 
cv2.destroyAllWindows()

 

반응형