이미지 위에 임의의 4점을 선택하면 그 구역 내 이미지를 원근 변환하는 코드를 작성해보았다. homograpyTransformation 함수를 통해 4점을 입력받으면 calPoint 함수로 상하좌우를 지정해주기 때문에 전처럼 "좌상 → 좌하 → 우상 → 우하" 순으로 점을 찍지 않아도 되며, 변형 후 각 점의 좌표와 원근 변환한 이미지 크기도 같이 계산해준다.

img = cv2.imread('athletic-field-1867053_1920.jpg')
count = 0
blue, green, red, yellow = (255, 0, 0), (0, 255, 0), (0, 0, 255), (0, 255, 255)
point_array = []

def calPoint(ary):
    total = np.sum(ary, axis=1)
    differ = np.diff(ary, axis=1)

    left_top = ary[np.argmin(total)]
    left_bottom = ary[np.argmax(differ)]
    right_top = ary[np.argmin(differ)]
    right_bottom = ary[np.argmax(total)]
    src = [left_top, left_bottom, right_top, right_bottom]
    src = np.float32(src)
    
    width1 = abs(left_top[0] - right_top[0])
    width2 = abs(left_bottom[0] - right_bottom[0])
    width = max(width1, width2)
    height1 = abs(left_top[1] - left_bottom[1])
    height2 = abs(right_top[1] - right_bottom[1])
    height = max(height1, height2)
    dst = np.float32([[0, 0], [0, height -1], [width -1, 0], [width -1, height -1]])
    return (src, dst, width, height)


def homograpyTransformation(event, x, y, flags, param):
    global count, point_array
    
    if event == cv2.EVENT_LBUTTONDOWN:
        count = count + 1
        point_array.append([x, y])
        
    elif event == cv2.EVENT_LBUTTONUP:
        if count == 1:
            cv2.circle(img, (x, y), 5, blue, -1)
            cv2.imshow('Original', img)

        elif count == 2:
            cv2.circle(img, (x, y), 5, green, -1)
            cv2.imshow('Original', img)

        elif count == 3:
            cv2.circle(img, (x, y), 5, red, -1)
            cv2.imshow('Original', img)

        elif count == 4:
            count = 0
            cv2.circle(img, (x, y), 5, yellow, -1)
            cv2.imshow('Original', img)

            src, dst, width, height = calPoint(point_array)
            M = cv2.getPerspectiveTransform(src, dst)
            transformImage = cv2.warpPerspective(img, M, (width, height))
            cv2.imshow('Transform', transformImage)
            cv2.imwrite('Perspective_Transformation.jpg', transformImage)

cv2.namedWindow('Original')
cv2.setMouseCallback('Original', homograpyTransformation, param = img)

while True:
    cv2.imshow('Original', img)
    if cv2.waitKey(0) & 0xFF:
        transformImage = cv2.imread('Perspective_Transformation.jpg')

        b, g, r = cv2.split(transformImage)
        transformImage = cv2.merge([r, g, b])
        plt.imshow(transformImage)
        break

cv2.destroyAllWindows()

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기