OpenCV - 기하학적 변환

항니·2021년 12월 29일
0
post-thumbnail

✏️ 요즘은 딥러닝에 대해 공부를 하는 중입니다!
그중에서 최근 opencv(cv2)를 이용하여 ,
이미지/영상에 필터를 입히고, 다양한 변환을 하는 방법에 대해 배웠는데 굉장히 재미있었습니다!ㅎㅎ


공간에서의 기하학적 변환에는 translation, affine, Euclidean, similarity, projective 등이 있으며, 이러한 다양한 변환을 opencv를 통해 구현할 수 있는데요.
이미지를 이동시키고, 확대/축소, 회전시키고, 대칭 변환을 하는등 다양한 변환이 가능합니다.
뿐만 아니라, 이를 응용하여 어파인 변환과 투시변환도 가능한데요.

문서를 스캔해주는 어플을 다들 써보신 적이 있을 것 같은데, 이렇게 왜곡된 형태를 직사각형 형태로 똑바로 펴주는 원리가 이러한 투시변환의 원리였다는 것을 깨달을 수 있었습니다.


이를 응용하여 친구와 카톡을 하다가 친구가 보낸 루피 이모티콘을 보고 루피의 찌그러진 얼굴을 펴줄 수 있을까? 하는 궁금증이 생겨 직접 시도해보았습니다!
(사실 오늘 글을 쓰게 된 이유ㅋㅋㅋ)

과연 결과는...! (두구두구두구)

하하하하😂😂😂
얼굴 형태는 그래도 예쁜 형태가 되었지만, 한번의 시술(?)로는 이목구비마저 예쁘게 원위치 시켜줄 수는 없었습니다...🥲
좀 더 레벨업을 하여 기술을 연마한 뒤에 다시 수술을 집도해보는 것으로 하겠습니다!

import sys
import numpy as np
import cv2


def drawROI(img, corners):
    cpy = img.copy()

    c1 = (192, 192, 255)
    c2 = (128, 128, 255)

    for pt in corners:
        cv2.circle(cpy, (int(pt[0]), int(pt[1])), 25, c1, -1, cv2.LINE_AA)

    cv2.line(cpy, (int(corners[0][0]), int(corners[0][1])), (int(corners[1][0]), int(corners[1][1])), c2, 2, cv2.LINE_AA)
    cv2.line(cpy, (int(corners[1][0]), int(corners[1][1])), (int(corners[2][0]), int(corners[2][1])), c2, 2, cv2.LINE_AA)
    cv2.line(cpy, (int(corners[2][0]), int(corners[2][1])), (int(corners[3][0]), int(corners[3][1])), c2, 2, cv2.LINE_AA)
    cv2.line(cpy, (int(corners[3][0]), int(corners[3][1])), (int(corners[0][0]), int(corners[0][1])), c2, 2, cv2.LINE_AA)
   
    disp = cv2.addWeighted(img, 0.3, cpy, 0.7, 0)

    return disp

def onMouse(event, x, y, flags, param):
    global srcQuad, dragSrc, ptOld, src

    if event == cv2.EVENT_LBUTTONDOWN:
        for i in range(4):
            if cv2.norm(srcQuad[i] - (x, y)) < 25:
                dragSrc[i] = True
                ptOld = (x, y)
                break

    if event == cv2.EVENT_LBUTTONUP:
        for i in range(4):
            dragSrc[i] = False
   
    if event == cv2.EVENT_MOUSEMOVE:
        for i in range(4):
            if dragSrc[i]:
                dx = x - ptOld[0]
                dy = y - ptOld[1]

                srcQuad[i] += (dx, dy)

                cpy = drawROI(src, srcQuad)
                cv2.imshow('img', cpy)
                ptOld = (x, y)
                break

src = cv2.imread('../data/루피2.png')

if src is None:
    print('Image open failed!')
    sys.exit()

h, w = src.shape[:2]
dw = 300
dh = round(dw * 200 / 200)

srcQuad = np.array([[30, 30], [30, h-30], [w-30, h-30], [w-30, 30]], np.float32)
dstQuad = np.array([[0, 0], [0, dh-1], [dw-1, dh-1], [dw-1, 0]], np.float32)
dragSrc = [False, False, False, False]

disp = drawROI(src, srcQuad)

cv2.imshow('img', disp)
cv2.setMouseCallback('img', onMouse)

while True:
    key = cv2.waitKey()
    if key == 13: # Enter
        break
    elif key == 27: # esc
        cv2.destroyWindow('img')
        sys.exit()

pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
dst = cv2.warpPerspective(src, pers, (dw, dh), flags=cv2.INTER_CUBIC)

cv2.imshow('dst', dst)

while True:
    if cv2.waitKey()==27:
        break

cv2.destroyAllWindows()
profile
3D 모델 플랫폼에서 데이터 분석을 하고 있습니다

0개의 댓글