[OpenCV] 영상 이어붙이기 (3)

스윗포테이토·2022년 11월 15일
0

지난 글에서 작성했던 로직을 클래스로 구현해봤다.

코드에 대한 설명은 주석으로 대체한다.

oneVideoWriter.hpp

#ifndef LANE_DETECTION_ONEVIDEOWRITER_HPP //include 꼬임 방지
#define LANE_DETECTION_ONEVIDEOWRITER_HPP

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

/**
 * 영상 합본 저장하는 클래스
 */
class OneVideoWriter {
public:
    int width, height; // 영상 1개의 너비, 높이
    int row, col; // 영상 배치 레이아웃 - 2X3으로 배치한다면 row=2, col=3
    int proc_cnt; // 한 화면에 나올 영상 개수
    std::string file_path; // 비디오 저장 경로
    cv::Mat merged_frame; // 합본
    cv::VideoWriter vw;

    OneVideoWriter() {} // 선언용

	// 생성자 + 초기화
    OneVideoWriter(std::string file_path, int width, int height, int row, int col, int proc_cnt);

	// 프레임 작성
    void writeFrame(cv::Mat frame, int idx);
};

/**
 * 생성자
 * @param file_path 저장 파일 경로
 * @param width 작은 영상 1개 너비
 * @param height 작은 영상 1개 높이
 * @param row 영상 레이아웃 - 몇개의 행으로 배치할건지
 * @param col 영상 레이아웃 - 몇개의 열로 배치할건지
 * @param proc_cnt 프로세수 수 - 영상의 수
 */
OneVideoWriter::OneVideoWriter(std::string file_path, int width, int height, int row, int col, int proc_cnt) {
    this->width = width; // 영상 1개의 너비
    this->height = height; // 영상 1개의 높이
    this->row = row;
    this->col = col;
    this->proc_cnt = proc_cnt;

    vw.open(file_path, cv::VideoWriter::fourcc('a', 'v', 'c', '1'), 30, cv::Size(col * width, row * height), true);
    this->merged_frame = cv::Mat(row * height, col * width, CV_8UC3);
}

/**
 * idx번째 프레임 저장하는 함수
 * @param frame
 * @param idx 0부터 시작하는 인덱스
 */
void OneVideoWriter::writeFrame(cv::Mat frame, int idx) {
    cv::Mat frame_cp = frame.clone();

	// 모든 프레임의 type을 BGR로 통일
    if (frame.type() != CV_8UC3) {
        cvtColor(frame, frame_cp, cv::COLOR_GRAY2BGR);
    }

	//위치 계산
    int r = idx / this->col, c = idx % this->col;

	// roi 영역 잡기
    cv::Mat roi = this->merged_frame(cv::Rect(c * this->width, r * this->height, this->width, this->height));
    // 합본 프레임에 복사
    frame_cp.copyTo(roi);

	// 프레임 합본 완성되면 비디오에 저장
    if (idx + 1 == this->proc_cnt) {
        this->vw << this->merged_frame;
    }
}

#endif //LANE_DETECTION_ONEVIDEOWRITER_HPP

사용 매뉴얼 - 샘플코드

#include "opencv2/opencv.hpp"
#include "./oneVideoWriter.hpp"

using namespace cv;
OneVideoWriter vw;
const string src_path = "../video.avi";
const string dst_path = "../result.mp4";
int main(){
	VideoCapture input_video(src_path);
    
    if (!input_video.isOpened()) {
        cout << "Can't open video\n";
        return;
    }
    
    int width = input_video.get(CAP_PROP_FRAME_WIDTH);
    int height = input_video.get(CAP_PROP_FRAME_HEIGHT);

    vw = OneVideoWriter(dst_path, width, height, 2, 2, 4);

    Mat frame;

    while (true) {
        video >> frame;

        if (frame.empty()) {
            break;
        }
        
        // 4단계 가공을 거친다고 가정했을 때...
        vw.writeFrame(frame, 0); //원본 저장
        
       	frame = proc1(frame);
        vw.writeFrame(frame, 1);
        
        frame = proc2(frame);
        vw.writeFrame(frame, 2);
        
        frame = proc3(frame);
        vw.writeFrame(frame, 3);
    }
}
profile
나의 삽질이 미래의 누군가를 구할 수 있다면...

0개의 댓글