OpenCV를 이용하여 비디오 저장/녹화하기 [C++]

OpenCV를 이용하여 USB 카메라 영상을 출력, 저장, 녹화하는 코드

이전 OpenCV 설치, PC & Visual Studio 환경설정 이라는 글을 통해 OpenCV를 사용하기 위한 PC 환경과 Visual Studio의 환경을 구성하는 방법에 대해 설명 하였다. 이번 글을 통해서는 OpenCV를 이용하여 PC에 연결되어 있는 USB 카메라로 부터 비디오를 획득하여 모니터에 출력하고, 이미지를 저장하거나 동영상 파일을 생성하는 방법을 Visual Studio와 C++을 활용하여 구현해 본다. 우선 아래쪽의 전체 코드를 살펴보자.

#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")		

#define TRUE	1
#define FALSE	0

int main(int, char**)
{
    Mat frame;

    bool bRec = FALSE;

    VideoCapture   cap;							
    VideoWriter    outputVideo;					

    namedWindow("Live", WINDOW_NORMAL);			
		
    cap.open(0);									
    cap.set(CAP_PROP_FRAME_WIDTH, 1280);
    cap.set(CAP_PROP_FRAME_HEIGHT, 720);
	
    if (!cap.isOpened()) {							
        cerr << "ERROR! Unable to open camera\n";
        return -1;
    }

    /***************************************
   		    Main Routine
    ***************************************/
    for (;;)
    {
        cap.read(frame);							

        if(frame.empty()) {						
            cerr << "ERROR! No Video\n";
            break;
        }
	
        imshow("Live", frame);		    // Live Display					

        char ch = waitKey(33);							

        if(getWindowProperty("Live", WND_PROP_VISIBLE) <= 0) {
            destroyAllWindows();
            break;
        }

        if(ch == 83 || ch == 115)	    // "s", Save Image
            imwrite("Image.jpg", frame);

        if(ch == 82 || ch == 114)	    // "r", Recording Video		
        {
            if(!bRec) {
                outputVideo.open("Video.avi", 
                                  VideoWriter::fourcc('X','V','I','D'), 
                                  30.0, Size(1280, 720), true);
                bRec = TRUE;
            }
            else {
                outputVideo.release();
                bRec = FALSE;
            }
        }
		
        if(bRec)
            outputVideo.write(frame);
    }
	
    return 0;
}

알아 두어야 할 라인에 대한 간략한 설명

이제부터 위 코드 중에 알아두면 유용한 코드블럭 들에 대해 설명한다.

#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")

위 라인은 Visual Studio에서 실행하는 경우에 항상 나타나는 콘솔창이 표시되는 것을 막는다.

Mat frame;

frame이라는 이름으로 Mat 객체를 생성한다.
Mat은 Matrix의 약자로 가로세로 픽셀들을 2차원 좌표로 표현하기 위한 일종의 2차원 배열이다.

VideoCapture   cap;							
VideoWriter     outputVideo;	

비디오를 읽기 위한 cap 객체와 비디오 파일을 생성하기 위한 outputVideo 객체를 생성한다.

namedWindow("Live", WINDOW_NORMAL);

비디오를 화면에 표시하기 위해 “Live”라는 이름으로 창을 만든다.
이름 뒤에는 3가지 종류의 플래그를 포함할 수 있으며, 각각의 의미는 다음과 같다.

  • WINDOW_NORMAL : 창 크기를 수동으로 변경할 수 있다.
  • WINDOW_AUTOSIZE : 창 크기를 자동으로 지정해 준다. (기본값)
  • WINDOW_FULLSCREEN : 창 크기를 전체화면으로 고정한다.
cap.open(0);									
cap.set(CAP_PROP_FRAME_WIDTH, 1280);
cap.set(CAP_PROP_FRAME_HEIGHT, 720);

VideoCaptrue 객체인 cap을 이용하여 0번째 카메라 장치를 연다.
USB 카메라가 1개만 연결되어 있는 경우라면, 카메라는 0번으로 할당된다. 또한, cap 객체의 가로 및 세로 사이즈를 1920 x 1080으로 지정한다. 이 사이즈는 USB 카메라가 제공할 수 있는 해상도를 초과하지 않도록 설정해 주어야 한다.

cap.read(frame);

Mat 객체인 frame으로 영상 이미지를 읽어온다.

imshow("Live", frame);	

비디오를 화면에 표시하기 위해 생성한 창에 읽어온 영상을 디스플레이 한다.

if (ch == 83 || ch == 115)				
	imwrite("Image.jpg", frame);

“s” 또는 “S”의 키보드 자판이 클릭되면, “Image.jpg”라는 이름으로 현재의 영상을 저장한다.

if (ch == 82 || ch == 114) {			// Recording Video - "R"
     if (!bRec) {
          outputVideo.open("Video.avi", VideoWriter::fourcc('X', 'V', 'I', 'D'), 30.0, Size(1280, 720), true);              
          bRec = TRUE;
     }
}
else {
     outputVideo.release();
     bRec = FALSE;
}

“r” 또는 “R”의 키보드 자판이 클릭되면, VideoWriter 클래스의 객체인 outputVideo를 통해 “Video.avi”라는 이름으로 동영상 파일을 생성한다. 다시 한번 “r” 또는 “R”의 키보드 자판이 클릭되면, Video.avi 파일을 닫고, 동영상 생성을 중지한다.

outputVideo.open("Video.avi", VideoWriter::fourcc('X','V','I','D'), 30.0, Size(1280, 720), true);

초당 30장, 1280 x 720사이즈로 “Video.avi”라는 이름의 동영상 파일을 생성한다.

if (bRec)
     outputVideo.write(frame);

처음 ‘r’ 또는 “R”의 키보드 자판이 눌리면, bRec 변수는 True 값을 가지며, 다시 한번 ‘r’ 또는 “R”의 키보드 자판이 눌려서 bRec이 False 값을 갖기 전까지 outputVideo 객체에 카메라로 부터 읽어온 영상 이미지를 저장한다.

outputVideo.write(frame);

“Video.avi” 파일에 읽어온 영상을 Write 한다

마지막으로, C++ 대신에 Python으로 동일한 기능을 구현한 코드는 “OpenCV를 이용하여 비디오 저장/녹화하기 [Python]” 를 참조할 수 있다.