【OpenCV】視頻製作

視頻

  視頻文件本身就是一個容器,包含視頻feeds、音頻feeds和其他軌道如字幕。視頻格式有avi、mov或mkv。

  由於OpenCV提供的視頻容器只能支持avi擴展,限制了保存的視頻文件不能大於2 GB。當然,還可以使用其他更專業的視頻編寫庫如HuffYUV, CorePNG and LCL。常用視頻編解碼器有XVID, DIVX or H264。

  本節的測試視頻下載地址:https://github.com/opencv/opencv/blob/master/samples/data/Megamind.avi


代碼示例

#include <iostream>
#include <string>

#include <opencv2/core.hpp>
#include <opencv2/videoio.hpp>

using namespace std;
using namespace cv;

int main()
{
    string source = "../data/Megamind.avi";
    VideoCapture inputVideoB(source), inputVideoG(source), inputVideoR(source);
    if (!inputVideoB.isOpened() || !inputVideoG.isOpened() || !inputVideoR.isOpened()) { return -1; }

    // 四個字符的編解碼器代碼,get獲得8字符的double,static_cast<int>
    int ex = static_cast<int>(inputVideoB.get(CAP_PROP_FOURCC));

    char EXT[] = { (char)(ex & 0XFF) , (char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24), 0 };

    Size S = Size((int)inputVideoB.get(CAP_PROP_FRAME_WIDTH), (int)inputVideoB.get(CAP_PROP_FRAME_HEIGHT));

    cout << "Input frame resolution: Width=" << S.width << "  Height=" << S.height
        << " of nr#: " << inputVideoB.get(CAP_PROP_FRAME_COUNT) << endl;
    cout << "Input codec type: " << EXT << endl;

    Mat srcB, srcG, srcR, resB, resG, resR;
    VideoWriter outputVideoB, outputVideoG, outputVideoR;
    vector<Mat> spB, spG, spR;

    // 查找字符串中最後一個出現的c。有匹配,則返回匹配位置;否則返回-1
    string::size_type pAt = source.find_last_of('.');
    string NameB = source.substr(0, pAt) + 'B' + ".avi";
    string NameG = source.substr(0, pAt) + 'G' + ".avi";
    string NameR = source.substr(0, pAt) + 'R' + ".avi";

    bool outputType = 0;  // 若爲 0 則與輸入的編解碼器相同
    if (outputType)
    {
        outputVideoB.open(NameB, ex = -1, inputVideoB.get(CAP_PROP_FPS), S, true);
        outputVideoG.open(NameG, ex = -1, inputVideoG.get(CAP_PROP_FPS), S, true);
        outputVideoR.open(NameR, ex = -1, inputVideoR.get(CAP_PROP_FPS), S, true);
    }
    else
    {
        outputVideoB.open(NameB, ex, inputVideoB.get(CAP_PROP_FPS), S, true);
        outputVideoG.open(NameG, ex, inputVideoG.get(CAP_PROP_FPS), S, true);
        outputVideoR.open(NameR, ex, inputVideoR.get(CAP_PROP_FPS), S, true);
    }
    if (!outputVideoB.isOpened() || !outputVideoG.isOpened() || !outputVideoR.isOpened()) { return -1; }

    for (;;)
    {
        inputVideoB >> srcB;                        // 矩陣形式讀取視頻
        if (srcB.empty())   break;
        split(srcB, spB);                           // 分離BGR三個通道
        spB[1] = Mat::zeros(S, spB[1].type());
        spB[2] = Mat::zeros(S, spB[2].type());
        merge(spB, resB);                           // 合併BGR三個通道
        outputVideoB << resB;
    }   
    for (;;)
    {
        inputVideoG >> srcG;                        // 矩陣形式讀取視頻
        if (srcG.empty())   break;
        split(srcG, spG);                           // 分離BGR三個通道
        spG[0] = Mat::zeros(S, spG[0].type());
        spG[2] = Mat::zeros(S, spG[2].type());
        merge(spG, resG);                           // 合併BGR三個通道
        outputVideoG << resG;
    }   
    for (;;)
    {
        inputVideoR >> srcR;                        // 矩陣形式讀取視頻
        if (srcR.empty())   break;
        split(srcR, spR);                           // 分離BGR三個通道
        spR[0] = Mat::zeros(S, spR[0].type());
        spR[1] = Mat::zeros(S, spR[1].type());
        merge(spR, resR);                           // 合併BGR三個通道
        outputVideoR << resR;
    }

    cout << "視頻製作完成" << endl;
    return 0;
}

運行結果

這裏寫圖片描述

發佈了99 篇原創文章 · 獲贊 210 · 訪問量 40萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章