Programming/OpenCV

[OpenCV-python] 2. Getting Started with Videos

JinWooHong Dev 2021. 6. 8. 23:24

이번 실습에서는

  • 비디오를 read, display, save 하는 방법
  • 카메라로 부터 비디오를 캡처하고 나타내기
  • cv.VideoCapture(), cv.VideoWriter() 함수에 대해서 배울 것이다.

 

카메라로부터 비디오 캡처

OpenCV는 카메라를 사용한 실시간 스트림 기능을 간단한 인터페이스로 제공한다. 나는 컴퓨터에 웹캠을 연결하여 실습을 진행하였다.

우선 이 실습을 진행하려면 VideoCapture를 생성해야된다. 이것의 argument는 장치 인덱스나 비디오 파일의 이름이 될 수 있다. 장치 인덱스는 카메라를 지정하는 숫자이다. 카메라 한대만 연결되어 있다고 가정하고 실습을 진행한다. 보통 0 이나 -1로 설정을 하면 된다. 카메라가 두 대 이상이면 1이나 다른 숫자로 지정을 할 수가 있다. 그렇게 하면 이제 프레임별로 캡처를 할 수 있게 된다. 마지막에는 장치를 꼭 release 해줘야 한다.

 

소스 코드

import numpy as np
import cv2 as cv

cap = cv.VideoCapture(0)

#print(cap.get(cv.CAP_PROP_FRAME_WIDTH), cap.get(cv.CAP_PROP_FRAME_HEIGHT))

#cap.set(cv.CAP_PROP_FRAME_WIDTH,320)
#cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)

if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame (stream end?). Exiting ...")
        break
    
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    
    cv.imshow('frame', gray)
    if cv.waitKey(1) == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

cap.read() 는 bool 값을 리턴한다. 만약 프레임을 알맞게 읽었다면 True 값을 리턴할 것이다. 이것으로 비디오 연결을 확인할 수 있다. cap이 캡처를 초기화하지 않은 경우도 있어 오류가 날 수 있다. 이럴 때는 cap.isOpened() 대신에 cap.open()을 사용해 open하면 된다.

propId가 0부터 18까지의 숫자인 cap.get(propId) 메서드를 사용하여 비디오의 일부 기능을 액세스 할 수도 있다. 각 숫자는 비디오의 속성을 나타내며 cv::VideoCapture::get() 에서 자세히 확인할 수 있다. 이 값중 일부는 cap.set(propId, value)을 사용하여 수정할 수 있다.

예를 들어, cap.get(cv.CAP_PROP_FRAME_WIDTH)cap.get(cv.CAP_PROP_FRAME_HEIGHT)을 사용하면 너비와 높이를 확인할 수 있다. 이것의 초기값은 640x480 이다. 320x240으로 수정하고싶다면 cap.set(cv.CAP_PROP_FRAME_WIDTH,320)cap.set(cv.CAP_PROP_FRAME_HEIGHT,240)을 하면 된다.

실행 결과

웹캠에 연결되어 흑백으로 출력되는 것을 확인할 수 있으며, q를 누르면 종료되는 것을 확인.

비디오 파일 재생

동영상 파일을 재생하는 방법은 카메라로부터 비디오 캡처하는 방법이랑 같다. 다른 점은 카메라 인덱스에 파일 이름을 넣어줘야 한다. 또한 프레임을 display하는 동안, cv.waitkey()에 적절한 시간을 사용해야한다. 만약 너무 작다면 비디오가 매우 빠르고 너무 높다면 비디오가 너무 느릴 것이다. 일반적으로 25milliseconds 를 사용.

무료 샘플 동영상 링크

소스 코드

import numpy as np
import cv2 as cv

cap = cv.VideoCapture("파일 경로")

while cap.isOpened():
    ret, frame = cap.read()

    if not ret:
        print("Can't receive frame (stream end?). Exiting ... ")
        break
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    cv.imshow("frame",gray)
    if cv.waitKey(1) == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

 

실행 결과

동영상이 재생되는 것을 확인할 수 있다. 배속 설정에 따라 동영상 속도가 달라지는 것을 확인할 수 있다.

 

 

비디오 저장

비디오를 저장하려면 우선 VideoWriter 객체를 생성한다. 저장할 동영상의 이름을 정하고 FoucCC 코드를 지정해야한다. 그러고 난 후 fps를 설정하고 프레임 크기를 보낸다. 마지막은 isColor로 True면 encoder는 컬러 프레임이며 그렇지 않은 경우에는 흑백 프레임이 된다.

FourCC는 비디오 코덱을 지정하는데 사용되는 4byte 코드이다. 사용가능한 코드들을 fourcc.org에서 찾을 수 있다.

  • In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is more preferable. MJPG results in high size video. X264 gives very small size video)
  • In Windows: DIVX (More to be tested and added)
  • In OSX: MJPG (.mp4), DIVX (.avi), X264 (.mkv).

FourCC는 cv.VideoWriter_fourcc('M','J','P','G') 또는 cv.VideoWriter_fourcc(*'MJPG') 이렇게 사용한다.(MJPG 형식의 경우)

아래 코드에서는 카메라에서 캡처한 뒤 수직 방향으로 뒤집은 다음 비디오를 저장한다. cv.flip() 메소드 사용.

소스 코드

import numpy as np
import cv2 as cv

cap = cv.VideoCapture(0)

fourcc = cv.VideoWriter_fourcc(*'DIVX')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640,480))

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        print("Can't receive frame (stream end?). Exiting ... ")
        break
    frame = cv.flip(frame, 0)

    out.write(frame)

    cv.imshow('frame', frame)
    if cv.waitKey(1) == ord('q'):
        break

cap.release()
out.release()
cv.destroyAllWindows()

 

실행 결과

동영상이 filp 되어 나타나는 것을 볼 수 있고 저장또한 되는 것을 확인할 수 있다.