저번 포스팅에 이어 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()
'프로그래밍 언어 및 IT 정보 > opencv_python' 카테고리의 다른 글
[opencv_python] 5. 이미지 컬러스페이스 (BGR,HSV,YUV) (0) | 2022.08.03 |
---|---|
[opencv_python] 4.2 기하학적 변환 (자르기(ROI), 어핀변환,원근변환 ) (0) | 2022.07.22 |
[opencv_python] 3. 이벤트 처리 (키보드, 마우스, 트랙바) (0) | 2022.07.13 |
[opencv_python] 2. 도형 및 TEXT 그리기 (0) | 2022.07.07 |
[opencv_python] 1. 이미지 및 동영상(카메라) 읽어오기 (0) | 2022.07.06 |