DY N DY

opencv를 이용한 영상 합치기 본문

PARK/영상처리 관련

opencv를 이용한 영상 합치기

손세지 2016. 11. 17. 21:35

이걸 사용할 일이 그다지 많지는 않을 것 같으나... 실험할 때 많이 사용할 수도 있을 것 같다. 

개인적으로는 한가지 영상에 대해 여러가지 알고리즘을 이용해 테스트 한 결과영상 또는 중간영상을 뽑아냈을 때

(동일한 영상이므로 전체프레임 수와 영상의 크기는 동일한 것으로 가정한다.)

프레임별로 확인하고 싶은데 5개 알고리즘을 이용한다면 original영상까지 총 6개쯤 될텐데... 비디오플레이어를 6개 켜고 하기가 귀찮아서

만들게 되었다..  

아마 opencv에서 지원하는 영상은 다 열릴것 같다. (주로 mpeg4 avi사용)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include    <vector>
#include    <iostream>
#include    <math.h>
#include    <opencv/cv.hpp>
using namespace std;
using namespace cv;
 
int main()
{
    vector<string> videoPath;
    videoPath.push_back("drop.avi");
    videoPath.push_back("drop.avi");
    videoPath.push_back("drop.avi");
    videoPath.push_back("drop.avi");
    videoPath.push_back("drop.avi");
    videoPath.push_back("drop.avi");
 
 
    int H = (int)(sqrt(videoPath.size()));
    int W = ceil((videoPath.size()) / (double)H);
    vector<cv::VideoCapture> videoCapture;
    for (int i = 0; i < (int)videoPath.size(); i++)
    {
        videoCapture.push_back(cv::VideoCapture(videoPath[i]));
        if (!videoCapture[i].isOpened())
        {
            cout << "fail to read the video" << endl;
            return EXIT_FAILURE;
        }
    }
 
    // 모든 비디오의 width와 height가 같다고 가정
    double fps = videoCapture[0].get(CV_CAP_PROP_FPS);
    int width = (int)videoCapture[0].get(CV_CAP_PROP_FRAME_WIDTH);
    int height = (int)videoCapture[0].get(CV_CAP_PROP_FRAME_HEIGHT);
    int W_size = width * W;
    int H_size = height * H;
    int loop = 1;
    cv::VideoWriter vw("result.avi", CV_FOURCC('D''I''V''X'), fps, Size(W_size, H_size));
 
    while (loop)
    {
        Mat image = Mat(Size(W_size, H_size), CV_8UC3);
 
        int i = 0;
        for (int c = 0; c < H; ++c)
        {
            for (int r = 0; r < W; ++r)
            {
                Mat frame;
                if (i > videoPath.size() - 1)
                    continue;
                videoCapture[i] >> frame;
                i++;
                if (frame.empty())
                {
                    loop = 0;
                    break;
                }
 
                frame.copyTo(image(Rect((r*width), (c*height), width, height)));
            }
        }
        if (!image.empty())
        {
            vw.write(image);
            imshow("image", image);
            waitKey(1);
        }
    }
 
    vw.release();
    return 0;
}
cs


영상은 주로 4개영상으로 실험하였으나 혹시 몰라서 여러개 영상도 가능하게 하였다. 

영상 순서는 글씨 순서. (raster scan order)


코드는 특별한 것은 없다. 


벡터에 영상을 순서대로 저장한 후에 

영상 개수에 따라 결과영상 크기를 정하기 위해 H, W를 계산하였다. (그냥 최대한 정사각형으로 보여주려고 이런저런 수식을 생각해봤다.)

그 후에는 차례대로 영상을 열고. (24라인)


while loop에서 프레임마다 가져와서 결과영상에 저장해준다. 


결과는 아래와 같다. drop.avi는 프로젝트 폴더 내에 넣어놓았다. 

영상은 구글에서 sample video avi검색해보니 많아서 아무거나 받았다. (검색결과 2번째 링크)

http://www.engr.colostate.edu/me/facil/dynamics/avis.htm

아래 결과는 6개 영상으로 테스트 했을 때. 39라인에 쓴 것 처럼 result.avi로 저장된다.