OpenCVで動画読み込み&書き込み --- C++/CLIでラップ
下記記事にてOpenCVで動画を読み書きする方法を調べました。
OpenCVで動画読み込み&書き込み - 何でもプログラミング
今回は.Netで利用できるよう、C++/CLIでラップしてみたいと思います。
尚、Matクラス(Mat8UC1クラス)は下記記事のものを利用しています。
OpenCVをC++/CLIでラップ - 何でもプログラミング
VideoCapture
FourccはStringで返すようにしてみました。
Mat8UC1を利用しているため、Captureの中で8UC1に変換しています。ここは適宜変更してください。
using namespace msclr::interop; using namespace System; public ref class VideoCapture { public: property int Width { int get() { return (int)_capture->get(CV_CAP_PROP_FRAME_WIDTH); } } property int Height { int get() { return (int)_capture->get(CV_CAP_PROP_FRAME_HEIGHT); } } property double Fps { double get() { return _capture->get(CV_CAP_PROP_FPS); } } property int Count { int get() { return (int)_capture->get(CV_CAP_PROP_FRAME_COUNT); } } property String^ Fourcc { String^ get() { int i = (int)_capture->get(CV_CAP_PROP_FOURCC); char fourcc[] = { (char)(i & 0XFF), (char)((i & 0XFF00) >> 8), (char)((i & 0XFF0000) >> 16), (char)((i & 0XFF000000) >> 24), 0 }; return gcnew String(fourcc); } } property bool IsOpened { bool get() { return _capture->isOpened(); } } VideoCapture(String^ path) { _capture = new cv::VideoCapture(marshal_as<std::string>(path)); } !VideoCapture() { if (_capture != nullptr) { delete _capture; _capture = nullptr; } } ~VideoCapture() { this->!VideoCapture(); } Mat8UC1^ Capture() { cv::Mat src; *_capture >> src; auto dst = gcnew Mat8UC1(src.rows, src.cols); if (src.channels() == 1) src.copyTo(*dst->_mat); else if (src.channels() == 3 || src.channels() == 4) cv::cvtColor(src, *dst->_mat, CV_RGB2GRAY); return dst; } void Seek(int frame) { _capture->set(CV_CAP_PROP_POS_FRAMES, frame); } private: cv::VideoCapture* _capture; };
VideoWriter
Fourcc文字列からIntに変換するにはcv::VideoWriter::fourccを利用します。
Write関数内でカラー化していますが、ここは適宜変更してください。
public ref class VideoWriter { public: property bool IsOpened { bool get() { return _writer->isOpened(); } } VideoWriter(String^ path, int width, int height, String^ fourcc, double fps) { _writer = new cv::VideoWriter( marshal_as<std::string>(path), cv::VideoWriter::fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]), fps, cv::Size(width, height)); } !VideoWriter() { if (_writer != nullptr) { delete _writer; _writer = nullptr; } } ~VideoWriter() { this->!VideoWriter(); } void Write(Mat8UC1^ mat) { cv::Mat color; cv::cvtColor(*mat->_mat, color, CV_GRAY2BGR); *_writer << color; } private: cv::VideoWriter* _writer; };
F#で利用
動画はopenCVのサンプルMegamind.aviを利用しています。
動画をそのまま保存しているだけですが、Mat8UC1を介しているため出力はグレースケールになっています。
[<EntryPoint>] let main argv = let capture = new CV.VideoCapture(@"C:\lib\opencv3.2\sources\samples\data\megamind.avi") let writer = new CV.VideoWriter(@"output.avi", capture.Width, capture.Height, capture.Fourcc, capture.Fps); capture |> Seq.unfold (fun x -> Some(x.Capture(), x)) |> Seq.takeWhile (fun x -> not x.IsEmpty) |> Seq.iter writer.Write 0