반응형

OpenCV로 끊김이 적은 동영상 재생

코드

배경이야기가 너무 길어서 두괄식으로 본론인 코드를 먼저 기록한다.

import cv2
import time
import ipywidgets as widgets
import IPython.display as display
import copy

cap = cv2.VideoCapture(video_file)
wImg = widgets.Image(
    layout = widgets.Layout(border="solid")
)
display.display( wImg)

if cap.isOpened():
    ret, img = cap.read()
    while ret:
        # 동영상 파일에서 캡쳐된 이미지를 이미지 파일 스트림으로 다시 인코딩을 한다.
        tmpStream = cv2.imencode(".jpeg", img)[1].tostring()
        wImg.value = tmpStream
        # 20 프레임이 되기 위한 딜레이 다만, 실제로 입력한 것보다 조금 더 딜레이가 있다
        time.sleep(0.05)
        ret, img = cap.read()
cap.release()

배경(도입)

이직을 하고 딥러닝 관련 프로젝트를 하게 되면서 3년만에 IPython notebook을 사용하게 되었다. 지금은 통상 jupyter로 많이 불리기는 하지만, 여전히 IPython notebook의 흔적이 남아 있다. 암튼 jupyter에서는 OpenCV에서 기본적으로 제공하는 imshow()가 정상적으로 작동이 되지 않는다. 이는 초기 OpenCV가 python에서도 동작하게 지원을 할때 독특하게 자체 자료구조인 Mat를 사용하지 않고 numpy.ndarray 자료구조를 사용하게 되면서 IPython Notebook에서 자주 사용하는 matplotlib를 사용하면서 굳이 따로 지원할 필요성을 못 느껴서 그런 것 같다. 게다가 python에 전통적으로 사용하던 IPL 라이브러리 역시 numpy.ndarray구조를 이용하여 이미지 데이터를 관리 하기 때문에 호환도 비교적 쉽다.

OpenCV의 기초인 IO(입출력) 부분에서는 기본적으로 이미지를 화면에 띄우는 것과 동영상을 재생하는 것을 기본적인 과정이다. 이 과정에서 동영상은 여러장의 이미지를 갱신하면서 재생이 된다는 것을 원리로 배울 수 있다. 문제는 matplotlib 의 pyplot 모듈을 이용해서 이미지를 화면에 보여주는데, 이 모듈은 이름에서 볼 수 있듯이 원래는 그래프와 약간이 이미지를 처리하기 위한 모듈이다. 그러다 보니 로컬에서 사용하는 OpenCV에서 처럼 동일한 윈도우에 imshow() 메서드를 호출해서 이미지만 바꿔서 동영상이 재생되는 것을 보여줄 수 없다.

필자는 구글링을 했을 때 스택오버 플로워에서는 다양한 방법들을 제시된 것을 확인 했었는데, 크게 2가지 방법이 있었다. 첫번째 방법은 IPython Notebook에 html 태그 삽입하는 방식을 사용해서 작성하는 방법, 두번째 방법은 webGL 관련 모듈을 설치하여 해당 모듈에 연결하는 방법이다. 필자는 두번째 방법을 시도했었는데, 생각보다. 프래임 드랍이 심했다.

일반적으로 사람이 실시간으로 딜레이를 못느끼는 프래임은 약 20정도인 것을 과거 다른 프로젝트를 통해서 경험을 했었다. 당연히 20프레임 이하였으니 상당한 딜레이를 느꼈던 것이다. 한동안 실망하고 잊고 있었다.

그러던 우연히 ipywidgets 이라는 IPython 자체 지원 모듈중 Image 위젯을 사용해서 이미지를 보는 보조 툴을 만들 일이 있었는데, 생각보다 이미지 파일 전환에 딜레이가 적다는 생각이 들었다. Image 위잿의 파일의 바이너리 스트림을 입력하는 부분에 동영상에서 읽은 이미지를 인코딩을 해서 연속적으로 렌더링을 하게 하면 WebGL보다 부드럽게 이미지 재생이 되지 않을까? 하는 발상으로 테스트를 해보니 생각보다 20프레임 이상 재생이 되는 것을 확인 했었다.

여기서 추가로 테스트 할 점은 코덱을 jpeg 외에 png, bmp 각각 변경해서 시도를 해봤는데, 인코딩시 스트림의 크기 클 수로 느려지는 것을 확인했다. 즉 압축률이 좋을 수록 동영상 재생의 딜레이가 적어지는 것을 알 수 있었다.

반응형

+ Recent posts