[opencv-python] 이미지 변화주기

2019. 7. 6. 04:22Python-이론/python-opencv

resize 

이번에는 이미지의 사이즈를 조절해보겠습니다. 

코드

import cv2
import numpy as np


def transform():
    baseImage = cv2.imread("../resource/Images/ipad.jpeg")
    h, w = baseImage.shape[:2]

    img2 = cv2.resize(baseImage, None, None, 0.1, 0.1, interpolation=cv2.INTER_AREA)

    cv2.imshow("img2", img2)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


transform()

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

src

이미지 데이터를 넣어주면 됩니다. 

 

dsize

픽셀 사이즈를 설정해서 크기를 조절할 수 있습니다. example(100, 100) 100px, 100px과 같이 바꾸어 줄 수 있습니다. 

 

fx, fy

비율적으로 사이즈를 조절할 수 있습니다. 위에서는 fx는 0.1은 원래의 사이즈의 10% 크기로 바꾸겠다는 의미입니다. 

 

iporation

iporation은 바뀌기 전의 사진과와 바뀐 후의 사진의 데이터를 활용하여 그사이의 값을 예측하는 것입니다. 위의 경우에는 사이즈가 변하고 픽셀 값들이 깨지거나 합쳐지면서 이사앟게 바뀔 경우를 대비해서 이전의 값과 바뀐 이후의 값을 비교하여 이미지를 예측하여 보여주는 것 같습니다. 

 

결과

이미지 이동

한마디로 x와 y의 값을 몇 만큼 이미지를 이동하는 것입니다. cv2.warpAffine() 함수를 이용하면됩니다. 그리고 이동 시킬 값은 2x3 배열로 만들어 주어야 합니다. 

 

[ [ 1, 0, x축의 이동 길이],

[0, 1, y축의 이동 길이] ]

 

import cv2
import numpy as np


def transform():
    img = cv2.imread("../resource/Images/desktop.png")
    img = cv2.resize(img, None, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
    h, w = img.shape[:2]

    M = np.float32([[1, 0, 100], [0, 1, 50]])

    moveImg = cv2.warpAffine(img, M, (w, h))
    cv2.imshow("moveImage", moveImg)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


transform()

WrapAffine을 통해서 옮겨진 이미지의 값을 가져올 수 있습니다. 

결과

이미지 회전

이미지를 회전하기 위해서는 cv2.getRotationMatrix2D를 사용하면 됩니다. 

 

결과

import numpy as np
import cv2


def transform():
    img = cv2.imread("../resource/Images/desktop.png")
    img = cv2.resize(img, None, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)
    h, w = img.shape[:2]

    M1 = cv2.getRotationMatrix2D((w / 2, h / 2), 45, 1)
    M2 = cv2.getRotationMatrix2D((w / 2, h / 2), 90, 1)

    img2 = cv2.warpAffine(img, M1, (w, h))
    img3 = cv2.warpAffine(img, M2, (w, h))

    cv2.imshow("45 rotation", img2)
    cv2.imshow("90 rotation", img3)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


transform()

cv2.getRotationMatrix2D((w/2, h/2) -> 중앙 점, 회전할 각도, scale)

scale은 회전하는 이미지의 크기를 배수 만큼 보이게 합니다. 0.5면 0.5배 작은 이미지가 회전하고 2배면 2배큰 이미지가 회전합니다. 

결과

 

Affine Transformation

평행선은 유지하면서 이미지를 변환하는 작업입니다. 이동, 확대, Scale, 반전까지 포함된 변환입니다. 

이 함수를 사용하기 위해서는 세개의 점을 매칭하여 이동시키면 됩니다. 

 

코드

import cv2
import numpy as np


def transform():
    img = cv2.imread("../resource/Images/trainRoad.jpg")
    h, w = img.shape[:2]

    pts1 = np.float32([[50, 50], [200, 100], [20, 200]])
    pts2 = np.float32([[10, 100], [200, 50], [100, 250]])

    M = cv2.getAffineTransform(pts1, pts2)

    img2 = cv2.warpAffine(img, M, (w, h))

    cv2.imshow("original", img)
    cv2.imshow("perspective", img2)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


transform()

np.float32로 만들어진 배열은 pts1은 변하기 전의 점 pts2는 변화 후의 점입니다.

 

getAffineTransform

변화와 관련된 배열을 만들어줍니다.  

 

 

warpAffine

이미지 데이터를 만들어줍니다.

 

결과

 

Perspective Transform

직선의 성질만 유지하고 선의 평행선은 유지되지 않는 변환입니다. 기차길로 예로 들자면 기차길이 평행스러워 보일 수 있지만 끝으로 갈때 마다 점점 좁아 져도 이번 예제에서 이동 시켜주어도 직선이 유지가 됩니다. 이것은 위의 변환과 다르게 3개의 좌표가 아닌 4개의 좌표를 사용하여 변화를 줍니다. 

 

코드

import numpy as np
import cv2
import matplotlib.pyplot as plt


def transform():
    img = cv2.imread("../resource/Images/trainRoad.jpg")
    h, w = img.shape[:2]

    pts1 = np.float32([[455, 350], [540, 350], [300, h], [730, h]])
    pts2 = np.float32([[0, 0], [1024, 0], [0, h], [1024, h]])

    M = cv2.getPerspectiveTransform(pts1, pts2)

    img2 = cv2.warpPerspective(img, M, (w, h))

    cv2.circle(img, (455, 350), 20, (255, 0, 0), -1)
    cv2.circle(img, (540, 350), 20, (0, 255, 0), -1)
    cv2.circle(img, (300, h), 20, (0, 0, 255), -1)
    cv2.circle(img, (730, h), 20, (0, 0, 0), -1)

    cv2.circle(img2, (0, 0), 20, (255, 0, 0), -1)
    cv2.circle(img2, (1024, 0), 20, (0, 255, 0), -1)
    cv2.circle(img2, (0, h), 20, (0, 0, 255), -1)
    cv2.circle(img2, (1024, h), 20, (0, 0, 0), -1)

    plt.subplot(1, 2, 1), plt.imshow(img), plt.title('image')
    plt.subplot(1, 2, 2), plt.imshow(img2), plt.title('perspective')
    plt.show()


transform()

4개의 점을 perspective로 이동 시킨 것입니다. 저 점들은 기차길의 좌표를 노가다로 찾아서 찍은 것입니다. cv2.circle을 활용하여 사진에 좌표를 찍었습니다. 그리고 pyplot을 사용하여 사진을 보여줬습니다. 

 

plt.subplot(x에서 보여줄 사진 개수, y에서 보여줄 사진 개수, 1) 1은 첫 사진 

plt.subplot(x에서 보여줄 사진 개수, y에서 보여줄 사진 개수, 2) 2은 두번째 사진이라는 의미입니다. 

 

결과

왼쪽사진의 저 점의 가로 길이나 세로 길이가 쫍아 보이고 안맞아 보이지만 오른쪽의 결과를 봤을때는 나름 잘 맞아 보입니다. Perspective transform은 이러한 성질을 갖고 있습니다.