Computer Vision/opencv(python)

[62] (실습) AR 비디오 플레이어

jwjwvison 2021. 3. 25. 23:46
  • AR 비디오 플레이어
    • 카메라 프레임이 특정 영상이 나타나면 해당 위치에 동영상을 재생하는 기능

 

  • 구현할 기능
    • 기준 영상과 카메라 프레임 사이의 특징점 검출 및 매칭
    • 호모그래피 계산
    • 동영상 프레임 투시 변환 & 합성
  • 구현 방법

import sys
import numpy as np
import cv2


# 기준 영상 불러오기
src = cv2.imread('box.png', cv2.IMREAD_GRAYSCALE)

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

# 카메라 장치 열기
cap1 = cv2.VideoCapture(0)

if not cap1.isOpened():
    print('Camera open failed!')
    sys.exit()

# 필요할 경우 카메라 해상도 변경
#cap1.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
#cap1.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)

# 카메라 프레임 화면에 출력할 동영상 파일 열기
cap2 = cv2.VideoCapture('korea.mp4')

if not cap2.isOpened():
    print('Video load failed!')
    sys.exit()

# AKAZE 특징점 알고리즘 객체 생성
detector=cv2.AKAZE_create()

# 기준 영상에서 특징점 검출 및 기술자 생성
kp1,desc1=detector.detectAndCompute(src,None)

# 해밍 거리를 사용하는 매칭 객체 생성
matcher= cv2.BFMatcher_create(cv2.NORM_HAMMING)

while True:
    ret1,frame1=cap1.read()

    if not ret1:
        break

    # 매 프레임마다 특징점 검출 및 기술자 생성 특징점이 너무 적으면 뒤에서 에러가 생길수 있음
    gray=cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)
    kp2,desc2=detector.detectAndCompute(gray,None)

    # 특징점이 100개 이상 검출될 경우 매칭 수행
    if len(kp2)>100:
        matches=matcher.match(desc1,desc2)

        # 좋은 매칭 선별
        matches=sorted(matches,key=lambda x: x.distance)
        good_matches=matches[:80]

        pts1=np.array([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1,1,2).astype(np.float32)
        pts2=np.array([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1,1,2).astype(np.float32)

        # 호모그래피 계산 inliners--> 매칭된 쌍들은 1, 사용되지 않은 매칭들은 0으로 된 행렬을 반환해준다
        H,inliers=cv2.findHomography(pts1,pts2,cv2.RANSAC)

        inliers_cnt=cv2.countNonZero(inliers)  # 1인것만 카운트

        # RANSAC 방법에서 정상적으로 매칭된 것의 개수가 20개 이상이면
        if inliers_cnt>20:
            ret2,frame2=cap2.read()

            if not ret2:
                break

            h,w=frame1.shape[:2]

            # 비디오 프레임을 투시 변환
            video_warp=cv2.warpPerspective(frame2,H,(w,h))  # 사이즈 바꿔보기

            white=np.full(frame2.shape[:2],255,np.uint8)
            white=cv2.warpPerspective(white,H,(w,h))
            cv2.imshow('white',white)

            # 비디오 프레임을 카메라 프레임에 합성
            cv2.copyTo(video_warp, white, frame1)

    cv2.imshow('frame', frame1)
    if cv2.waitKey(1) == 27:
        break

cap1.release()
cap2.release()
cv2.destroyAllWindows()