본문 바로가기

OpenCV

OpenCV 이미지 변환 및 회전

반응형

최근 모바일 기기에 내장된 이미지 편집 기능을 통해 이미지를 자르고, 회전하고, 다양한 작업을 할 수 있게 되면서 이미지 편집이 점점 더 인기를 얻고 있습니다. 이 블로그 게시물에서는 OpenCV를 활용한 이미지 변환 및 회전에 대해 살펴보겠습니다.

 

 

 

 

기본 이미지 변환 작업

 

이미지 이동과 회전은 이미지 편집에서 가장 기본적인 작업 중 하나입니다. 두 작업 모두 더 넓은 의미의 아핀 변환(Affine transformation)에 속합니다. 따라서 더 복잡한 변환을 배우기 전에 먼저 OpenCV에서 제공하는 함수를 사용하여 이미지를 회전하고 이동하는 방법을 익혀야 합니다. 아래 이미지를 확인해 보세요. 이 이미지가 모든 변환 예제에 사용될 것입니다.

 

일출, 물, 화물선, 구름이 있는 애니메이션 이미지입니다. 이 글에서는 이 이미지를 이미지 회전 및 변환의 입력으로 사용합니다.

 

 

이 기사 전체에서 사용될 예시 이미지입니다.

 

목차

  • OpenCV를 사용한 이미지 회전
  • OpenCV를 이용한 이미지 변환
  • 흥미로운 응용 프로그램
  • Streamlit을 사용한 웹 애플리케이션
  • 요약

 

OpenCV를 사용하여 이미지 회전을 수행하는 데 사용되는 아래 코드를 살펴보겠습니다. 이 글의 나머지 부분에서는 각 줄과 이미지 변환에 대해 자세히 살펴보겠습니다. 글을 마치면 아래 코드를 잘 이해하게 될 것입니다.

 

파이썬:

 

import cv2
 
# Reading the image
image = cv2.imread('image.jpg')
 
# dividing height and width by 2 to get the center of the image
height, width = image.shape[:2]
# get the center coordinates of the image to create the 2D rotation matrix
center = (width/2, height/2)
 
# using cv2.getRotationMatrix2D() to get the rotation matrix
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)
 
# rotate the image using cv2.warpAffine
rotated_image = cv2.warpAffine(src=image, M=rotate_matrix, dsize=(width, height))
 
cv2.imshow('Original image', image)
cv2.imshow('Rotated image', rotated_image)
# wait indefinitely, press any key on keyboard to exit
cv2.waitKey(0)
# save the rotated image to disk
cv2.imwrite('rotated_image.jpg', rotated_image)

 

C++:

 

#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
 
int main(int, char**) 
{
    Mat image = imread("image.jpg");
   imshow("image", image);
   waitKey(0);
   double angle = 45;
 
   // get the center coordinates of the image to create the 2D rotation matrix
   Point2f center((image.cols - 1) / 2.0, (image.rows - 1) / 2.0);
   // using getRotationMatrix2D() to get the rotation matrix
   Mat rotation_matix = getRotationMatrix2D(center, angle, 1.0);
 
   // we will save the resulting image in rotated_image matrix
   Mat rotated_image;
   // rotate the image using warpAffine
   warpAffine(image, rotated_image, rotation_matix, image.size());
   imshow("Rotated image", rotated_image);
    // wait indefinitely, press any key on keyboard to exit
   waitKey(0);
   // save the rotated image to disk
   imwrite("rotated_im.jpg", rotated_image);
 
   return 0;
}

 

시스템에 이미 OpenCV가 설치되어 있다고 가정합니다. OpenCV를 설치해야 하는 경우 아래 관련 링크를 방문하세요.

Windows에 OpenCV 설치

MacOS에 OpenCV 설치

Ubuntu에 OpenCV 설치

 

OpenCV를 사용한 이미지 회전

 

θ 세타변환 행렬을 정의하여 이미지를 특정 각도로 회전할 수 있습니다 중. 이 행렬은 일반적으로 다음과 같은 형식을 갖습니다.

 

 

 

OpenCV는 이미지의 회전 중심을 정의하고, 이미지 크기를 조절하기 위한 배율(scale factor)을 정의하는 기능을 제공합니다. 이 경우, 변환 행렬이 수정됩니다.

 

 

위의 매트릭스에서:

 

 

여기서 Cx & Cy는 이미지가 회전하는 좌표입니다.

 

OpenCV는 getRotationMatrix2D()위의 변환 행렬을 생성하는 함수를 제공합니다.

 

2D 회전 행렬을 생성하기 위한 구문은 다음과 같습니다.

 

getRotationMatrix2D(center, angle, scale)

 

이 getRotationMatrix2D()함수는 다음과 같은 인수를 사용합니다.

 

  • center: 입력 이미지의 회전 중심
  • angle: 회전 각도(도)
  • scale: 제공된 값에 따라 이미지를 확대 또는 축소하는 등방성 축척 인자

 

양수이면 angle이미지가 시계 반대 방향으로 회전합니다. 이미지를 시계 방향으로 같은 양만큼 회전하려면 angle음수여야 합니다.

 

회전은 3단계 작업입니다.

 

  1. 먼저 회전 중심을 찾아야 합니다. 이는 일반적으로 회전하려는 이미지의 중심입니다.
  2. 다음으로, 2D 회전 행렬을 생성합니다. OpenCV는 getRotationMatrix2D()위에서 설명한 함수를 제공합니다.
  3. 마지막으로, 이전 단계에서 생성한 회전 행렬을 사용하여 이미지에 아핀 변환을 적용합니다. warpAffine()OpenCV의 함수가 이 작업을 수행합니다.

 

warpAffine() 함수는 이미지에 아핀 변환을 적용합니다. 아핀 변환을 적용한 후에는 원본 이미지의 모든 평행선이 출력 이미지에서도 평행하게 유지됩니다.

 

전체 구문은 warpAffine()아래와 같습니다.

 

warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])

 

함수의 인수는 다음과 같습니다.

 

  • src: 소스 마법사
  • M: 변환 행렬
  • dsize: 출력 이미지의 크기
  • dst: 출력 이미지
  • flags: INTER_LINEAR 또는 INTER_NEAREST와 같은 보간 방법의 조합
  • borderMode: 픽셀 외삽법
  • borderValue: 상수 경계의 경우 사용되는 값으로 기본값은 0입니다.

 

참고 : OpenCV 아핀 변환에 대해 자세히 알아보려면 여기를 클릭 하세요.

 

좋아요, 이제 코드와 함수를 알았으니 OpenCV를 사용하여 구체적인 예를 들어 보겠습니다. 먼저 OpenCV 라이브러리를 임포트하고 이미지를 읽어 봅시다.

 

파이썬

 

import cv2

# Reading the image

image = cv2.imread('image.jpg')

 

참고: include 문 뒤의 모든 C++ 코드는 main()함수 내부에 있습니다.

 

C++

 

#include "opencv2/opencv.hpp"

using namespace cv;

 

# Reading the image

Mat image = imread("image.jpg");

 

다음으로, 회전점을 계산합니다. 이 예시에서는 이미지의 중심이 됩니다. 이를 위해 아래와 같이 이미지의 너비와 높이를 2로 나누면 됩니다.

 

파이썬

 

# Dividing height and width by 2 to get the center of the image

height, width = image.shape[:2]

center = (width/2, height/2)

 

C++

 

// get the center coordinates of the image to create the 2D rotation matrix

Point2f center((image.cols - 1) / 2.0, (image.rows - 1) / 2.0);

 

이미지 중심의 픽셀 좌표를 구한 후, 아래와 같이 getRotationMatrix2D() 함수를 사용하여 회전 행렬을 계산합니다. 이 함수는 다음과 같은 입력값을 받습니다:

 

  • 회전이 발생하는 중심점
  • 회전 각도(도 단위, 양수 값, 반시계 방향 회전에 해당)
  • 이미지 크기를 조정하는 등방성 배율입니다. 이 값은 부동 소수점 값일 수 있습니다. 예를 들어, 1.0 값은 출력 이미지의 크기를 원본 이미지와 동일하게 유지합니다. 2.0 값은 결과 이미지의 크기를 원본 이미지의 두 배로 만듭니다.

 

이 함수는 다음 단계에서 이미지를 회전하는 데 사용될 2D 회전 행렬을 반환합니다.

 

파이썬

 

# the above center is the center of rotation axis

# use cv2.getRotationMatrix2D() to get the rotation matrix

rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=45, scale=1)

 

C++

 

// create the rotation matrix using the image center

Mat rotation_matix = getRotationMatrix2D(center, angle=45, 1.0);

 

이제 계산된 회전 행렬을 warpAffine() 함수를 사용하여 이미지에 적용합니다. 이 함수는 세 가지 입력값을 요구합니다: 

 

  1. 소스 이미지
  2. 회전 행렬
  3. 출력 이미지의 크기

 

회전된 이미지는 rotated_image아래에 표시될 곳에 저장됩니다.

 

파이썬

 

# Rotate the image using cv2.warpAffine

rotated_image = cv2.warpAffine(src=image, M=rotate_matrix, dsize=(width, height))

 

C++

 

// we will save the resulting image in rotated_image matrix
Mat rotated_image;
// apply affine transformation to the original image using the 2D rotation matrix
warpAffine(image, rotated_image, rotation_matix, image.size());

 

이제 imshow()함수를 사용하여 회전된 이미지를 표시합니다.

 

파이썬

 

# visualize the original and the rotated image
cv2.imshow('Original image', image)
cv2.imshow('Rotated image', rotated_image)
# wait indefinitely, press any key on keyboard to exit
cv2.waitKey(0)
# write the output, the rotated image to disk
cv2.imwrite('rotated_image.jpg', rotated_image)

 

C++

 

imshow("Rotated image", rotated_image);
waitKey(0);
// save the rotated image to disk
imwrite("rotated_im.jpg", rotated_image);

 

 

 

 

OpenCV의 회전 함수를 적용한 후의 출력 이미지입니다.

 

 

OpenCV를 이용한 이미지 변환

 

컴퓨터 비전에서 이미지 변환은 x축과 y축을 따라 지정된 픽셀 수만큼 이미지를 이동하는 것을 의미합니다. 이미지를 이동해야 하는 픽셀 수를 와 tx라고 가정하면 ty, 다음과 같이 변환 행렬을 정의할 수 있습니다 중.

 

 

 

이제 tx 및 ty 값으로 이미지를 이동할 때 유의해야 할 몇 가지 사항이 있습니다.

 

  • 양수 값을 제공하면 tx이미지가 오른쪽으로 이동하고, 음수 값을 제공하면 이미지가 왼쪽으로 이동합니다.
  • 마찬가지로, 양의 값은 ty이미지를 아래로 이동시키고, 음의 값은 이미지를 위로 이동합니다.

 

OpenCV를 사용하여 이미지를 변환하려면 다음 단계를 따르세요.

 

  1. 먼저, 이미지를 읽고 너비와 높이를 구합니다.
  2. 다음으로, 회전과 마찬가지로 2차원 배열인 변환 행렬을 만듭니다. 이 행렬에는 이미지를 x축과 y축을 따라 이동하는 데 필요한 정보가 들어 있습니다.
  3. 회전과 마찬가지로 warpAffine()이 마지막 단계에서도 함수를 사용하여 아핀 변환을 적용합니다.

 

다음 코드를 살펴보고 얼마나 간단한지 직접 확인해 보세요.

 

파이썬

 

import cv2 
import numpy as np
 
# read the image 
image = cv2.imread('image.jpg')
# get the width and height of the image
height, width = image.shape[:2]

 

C++

 

#include "opencv2/opencv.hpp"
using namespace cv
// read the image 
Mat image = imread("image.jpg");
// get the height and width of the image
int height = image.cols;
int width = image.rows;

 

위의 코드 블록에서 이미지를 읽고 높이와 너비를 구합니다.

 

다음으로, 변환 행렬을 만듭니다.

 

파이썬

 

# get tx and ty values for translation
# you can specify any value of your choice
tx, ty = width / 4, height / 4
 
# create the translation matrix using tx and ty, it is a NumPy array 
translation_matrix = np.array([
    [1, 0, tx],
    [0, 1, ty]
], dtype=np.float32)

 

C++

 

// get tx and ty values for translation
float tx = float(width) / 4;
float ty = float(height) / 4;
// create the translation matrix using tx and ty
float warp_values[] = { 1.0, 0.0, tx, 0.0, 1.0, ty };
Mat translation_matrix = Mat(2, 3, CV_32F, warp_values);

 

 

위에서 논의한 바와 같이 변환 행렬을 위해 tx와 ty가 필요합니다. 이 예시에서는 너비와 높이의 1/4을 변환 값으로 사용합니다. 다양한 값을 시도해보고 그 출력 결과를 살펴보시길 권장합니다. 

 

 

warpAffine()이제 회전에 적용했던 것과 같은 함수를 사용하여 이미지에 변환 행렬을 적용합니다 .

 

파이썬

 

# apply the translation to the image
translated_image = cv2.warpAffine(src=image, M=translation_matrix, dsize=(width, height))

 

C++

 

// save the resulting image in translated_image matrix
Mat translated_image;
// apply affine transformation to the original image using the translation matrix
warpAffine(image, translated_image, translation_matrix, image.size());

 

참고: warpAffine() 는 이미지에 모든 유형의 아핀 변환을 적용하는 데 사용할 수 있는 일반 함수입니다. 행렬 M을 적절하게 정의하기만 하면 됩니다.

 

이 마지막 코드 블록은 변환된 이미지를 시각화하여 디스크에 기록합니다. 이제 완료되었습니다!

 

파이썬

 

# display the original and the Translated images
cv2.imshow('Translated image', translated_image)
cv2.imshow('Original image', image)
cv2.waitKey(0)
# save the translated image to disk
cv2.imwrite('translated_image.jpg', translated_image)

 

C++

 

//display the original and the Translated images
imshow("Translated image", translated_image);
imshow("Original image", image);
waitKey(0);
// save the translated image to disk
imwrite("translated_image.jpg", translated_image);

 

다음 그림은 번역된 이미지를 보여줍니다.

 

 

OpenCV를 이용한 이미지 변환 결과

 

 

흥미로운 응용 프로그램

 

장면을 조감도로 보여주는 애플리케이션을 만들고 싶으신가요? 먼저 OpenCV의 원근 변환에 대한 정보를 얻으세요. 그리고 변환에 대해 배운 모든 내용을 추가하세요. 그러면 앱을 만들어 보세요!

 

아핀 변환에 대해 자세히 알아보려면 여기 튜토리얼을 살펴보는 것도 좋습니다 .

 

Streamlit을 사용한 웹 애플리케이션

 

여기에서 살펴볼 수 있는 간단한 웹 애플리케이션을 만들었는데, 이를 통해 이미지를 회전하고 변환할 수 있습니다.

 

요약

 

이 게시물에서는 OpenCV를 이용한 이미지 이동 및 회전에 대해 알아보았습니다. 먼저 OpenCV를 사용하여 이미지를 회전하는 것부터 시작했는데, 이 getRotationMatrix2D()함수는 2D 회전 행렬을 구하는 데 사용되었습니다. 그런 다음 이 회전 행렬을 함수에 전달하여 warpAffine()이미지를 중심점을 기준으로 원하는 각도만큼 회전시켰습니다.

 

다음으로, OpenCV를 사용하여 이미지를 변환하는 방법을 알아보았습니다. 이를 위해 이미지를 변환할 x 및 y 값을 포함하는 변환 행렬을 명시적으로 정의했습니다. 변환을 위해 warpAffine()함수를 사용하여 변환을 적용했습니다.

 

이미지 회전과 이동은 가장 기본적인 기하학적 변환 중 하나이며, OpenCV를 사용하여 수행할 수 있는 다른 변환에 대해 배우는 데 좋은 기반이 될 것입니다. 입력을 변경하고 결과를 확인하면서 이 예제들을 직접 실험해 보시기 바랍니다.

 

이 게시물에서 논의된 모든 코드는 이 링크에서 찾을 수 있습니다 → 이미지 회전 및 변환 콜랩 노트북

 

 

 

 

 

 

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^