Skip to main content Link Menu Expand (external link) Document Search Copy Copied

동영상 입출력

Table of contents

  1. VideoCapture
    1. 사전 정의된 VideoCapture 클래스의 속성들
    2. VideoCapture 클래스와 멤버 함수
    3. 동영상 파일로 부터 영상 데이터 가져오기
    4. 카메라로 부터 영상 데이터 가져오기
  2. VideoWriter
    1. 동영상 파일 저장하기

VideoCapture

OpenCV에서는 카메라와 동영상으로부터 프레임(Frame)을 받아오는 작업을 VideoCapture 클래스 하나로 처리한다. Read()grab()retrieve() 두 함수로 구성된다. grab은 캡쳐을 시작해라라는 명령, retrieve()는 캠쳐된 영상을 프로그램으로 받아오는 역할을 수행한다. open()의 인자는 정수와 문자열을 받을 수 있는데 정수의 경우 연결되 카메라 장치의 번호를 입력하고 문자열의 경우 동영상 파일의 경로를 입려한다. 인터넬 주소를 입력하는 경우 스트림 동영상 데이터도 읽을 수 있다. 또한 영상 뿐만 아니라 정지 영상인 이미지도 가능하다.

사전 정의된 VideoCapture 클래스의 속성들

get(), set()은 카메라 혹은 동영상 데이터의 속성을 가져오거나 설정하는데 사용된다.

enum VideoCaptureProperties {
       CAP_PROP_POS_MSEC       =0, //!< Current position of the video file in milliseconds.
       CAP_PROP_POS_FRAMES     =1, //!< 0-based index of the frame to be decoded/captured next.
       CAP_PROP_POS_AVI_RATIO  =2, //!< Relative position of the video file: 0=start of the film, 1=end of the film.
       CAP_PROP_FRAME_WIDTH    =3, //!< Width of the frames in the video stream.
       CAP_PROP_FRAME_HEIGHT   =4, //!< Height of the frames in the video stream.
       CAP_PROP_FPS            =5, //!< Frame rate.
       CAP_PROP_FOURCC         =6, //!< 4-character code of codec. see VideoWriter::fourcc .
       CAP_PROP_FRAME_COUNT    =7, //!< Number of frames in the video file.
       CAP_PROP_FORMAT         =8, //!< Format of the %Mat objects (see Mat::type()) returned by VideoCapture::retrieve().
                                   //!< Set value -1 to fetch undecoded RAW video streams (as Mat 8UC1).
       CAP_PROP_MODE           =9, //!< Backend-specific value indicating the current capture mode.
       CAP_PROP_BRIGHTNESS    =10, //!< Brightness of the image (only for those cameras that support).
       CAP_PROP_CONTRAST      =11, //!< Contrast of the image (only for cameras).
       CAP_PROP_SATURATION    =12, //!< Saturation of the image (only for cameras).
       CAP_PROP_HUE           =13, //!< Hue of the image (only for cameras).
       CAP_PROP_GAIN          =14, //!< Gain of the image (only for those cameras that support).
       CAP_PROP_EXPOSURE      =15, //!< Exposure (only for those cameras that support).
       CAP_PROP_CONVERT_RGB   =16, //!< Boolean flags indicating whether images should be converted to RGB. <br/>
                                   //!< *GStreamer note*: The flag is ignored in case if custom pipeline is used. It's user responsibility to interpret pipeline output.
                                   ...
}

VideoCapture 클래스와 멤버 함수

VideoCapture(const String& filename, int apiPreference = CAP_ANY);
bool open(const String& filename, int apiPreference = CAP_ANY);

VideoCapture(int index, int apiPreference, const std::vector<int>& params);
bool open(int index, int apiPreference, const std::vector<int>& params);


bool isOpened() const;
void release();
bool grab();
bool retrieve(OutputArray image, int flag = 0);
VideoCapture& operator >> (CV_OUT Mat& image);
virtual bool read(OutputArray image);
virtual bool set(int propId, double value);
virtual double get(int propId) const;

동영상 파일로 부터 영상 데이터 가져오기

void ex_video(){
    VideoCapture cap("../data//test_video.mp4");
    // or
    // VideoCapture cap;
    // cap.open(0);

    if(!cap.isOpened()){
        cerr << "File open failed!" << endl;
        return;
    }


    Mat frame;
    while(true){
        cap >> frame;
        cout << cap.get(CAP_PROP_FRAME_HEIGHT) << endl;
        cout << cap.get(CAP_PROP_FRAME_WIDTH) << endl;
        cout << cap.get(CAP_PROP_FRAME_COUNT) << endl;
        cout << cap.get(CAP_PROP_FPS) << endl;
        cout << cap.get(CAP_PROP_POS_FRAMES) << endl;
        imshow("video", frame);
        if(waitKey(10) == 27){
            break;
        }
    }

    cap.release();
    destroyAllWindows();

}

카메라로 부터 영상 데이터 가져오기

void ex_cam(){
    VideoCapture cap(0);
    if(!cap.isOpened()){
        cerr << "Camera open failed!" << endl;
        return;
    }

    cap.set(CAP_PROP_FRAME_HEIGHT, 1280);
    cap.set(CAP_PROP_FRAME_WIDTH, 720);
    int w = cvRound(cap.get(CAP_PROP_FRAME_WIDTH));
    int h = cvRound(cap.get(CAP_PROP_FRAME_HEIGHT));
    cout << w << " x " << h << endl;

    Mat frame;
    while(true){
        // cap >> frame;
        cap.read(frame);
        // 위 두 줄의 코드는 동일하게 cap으로 부터 한 프레임의 영상 데이터를 받아오는 코드이다.
        // 일반적인 카메라의 FPS는 30으로 초당 30장의 이미지를 가져온다.
        // 33ms의 1 frame을 받아오는 것이며, 해당 loop는 적어도 33ms의 한 번 순회 한다고 볼 수 있다.
        if(frame.empty()){
            cerr << "Fream empty" << endl;
            break;
        }
        imshow("cam", frame);
        cout << cap.get(CAP_PROP_FPS) << endl;
        if(waitKey(1) == 27){
            // waitKey()에 의해서 순회 주기가 33ms보다 길어질 수 있다.
            break;
        }
    }

    cap.release();
    destroyAllWindows();
}

VideoWriter

영상 데이터를 파일로 저장하는 클래스이다.

VideoWriter(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true);

bool open(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true);


bool isOpened() const;
void release();
VideoWriter& operator << (const Mat& image);
void write(InputArray image);
bool set(int propId, double value);
double get(int propId) const;
int fourcc(char c1, char c2, char c3, char c4);
// e.g. 
// int fourcc = VideoWriter::fourcc('R','P','Z','A');

동영상 파일 저장하기

void ex_video_writer(){
    VideoCapture cap(0);
    // VideoCapture cap("../data/test_video.mp4");

    if(!cap.isOpened()){
        cerr << "File open failed!" << endl;
        return;
    }

    // int fourcc = VideoWriter::fourcc('X', 'V', 'I', 'D');
    int fourcc = VideoWriter::fourcc('R','P','Z','A');

    Size size((int)cap.get(CAP_PROP_FRAME_WIDTH), 
              (int)cap.get(CAP_PROP_FRAME_HEIGHT));
    double fps = cap.get(CAP_PROP_FPS);

    cout << "FPS " << fps << endl;
    cout << "Size " << size << endl;
    cout << "Size " << size.width << endl;
    cout << "foucc " << fourcc << endl;

    VideoWriter output("../data/test_video2.mp4", fourcc, fps, size);
    if(!output.isOpened()){
        cout << "test_video_output.avi open failed" << endl;
        return;
    }

    int delay = cvRound(1000/fps);
    Mat frame;
    while(true){
        cap >> frame;
        if(frame.empty()){
            break;
        }
        output << frame;
        imshow("frame", frame);

        if(waitKey(delay) == 27){
            // 한 fream 단위로 원본 영상과 시간을 맞추기 위해 delay를 사용한다.
            break;
        }

        cout << "File save complete!" << endl;

        output.release();
        cap.release();
        destroyAllWindows(); 

    }

}