視頻
視頻文件本身就是一個容器,包含視頻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;
}
運行結果