
ゆうき( @BASEBALLY15 )です^^
今回はどうしたんじゃ?
C++でOpenCVを使う練習をしているのですが,動画の読み込みや表示方法について教えて欲しいです.
任せておきなさい!

目次
具体的に何が出来るの?
今回紹介する方法を使うことで,以下の動画のように,画像を2値化したり輪郭を抽出したりすることができます.
元動画
2値化した動画
画素値50で閾値をとっています.

輪郭を抽出した動画
Canny法を使っています.

開発環境を載せておくよ!
始めに,今回用いたOSやエディタ等のバージョンについて載せておきます.
エディタ :Visual Studio2015
ライブラリ:OpenCV 3.4.10
言語 :C++
Visual StudioでOpenCVを使うためには…
Visual Studio上でOpenCVを使うためには,あらかじめ設定を行っておく必要があります.
以下の記事で設定方法について紹介しているので,設定を行っていない方は先にこちらの記事をご覧ください.
それでは早速,C++とOpenCVを使って,動画の読み込みと表示を行っていきたいと思います!
C++とOpenCVを使って,動画の読み込みと表示を行ってみた!
先に全体のコードを載せて,後半で解説を行いたいと思います.
全体のコード
#include <iostream>
#include <opencv2/opencv.hpp>//OpenCVのインクルード
#include "opencv2/highgui/highgui.hpp" //動画を表示する際に必要
using namespace cv;
int main(int argc, const char* argv[]) {
Mat img(Size(640, 360), CV_8UC3);
Mat gray_img(Size(640, 360), CV_8UC1);
Mat gaussian_img(Size(640, 360), CV_8UC1);
Mat bin_img(Size(640, 360), CV_8UC1);
Mat canny_img(Size(640, 360), CV_8UC1);
//動画ファイルを指定
std::cout << "FileName=" << std::flush;
//文字型のファイルを用意
std::string VideoFile = argv[argc - 1];
//コマンドプロンプからファイル名を入力
std::cin >> VideoFile;
//動画読み込み用のオブジェクトを生成
VideoCapture cap(VideoFile);
//動画書き込み用のオブジェクトを生成
VideoWriter writer_bin_img("C:\\〇〇\\bin_img.mov", VideoWriter::fourcc('m', 'p', '4', 'v'), 100, Size(640, 360), false);
VideoWriter writer_canny_img("C:\\〇〇\\canny_img.mov", VideoWriter::fourcc('m', 'p', '4', 'v'), 100, Size(640, 360), false);
// cv::VideoCaptureが正常に動作しているかをチェック!
if (!cap.isOpened())
{
std::cerr << "cannot open this movie file!" << std::endl;
return -1;
}
// cv::VideoWriterが正常に動作しているかをチェック!
if (!writer_bin_img.isOpened() & !writer_canny_img.isOpened())
{
std::cerr << "failed to record" << std::endl;
return -1;
}
double max_frame = cap.get(CAP_PROP_FRAME_COUNT);//フレーム数
for (int i = 0; i < int(max_frame); i++)
{
cap >> img;//1フレーム分取り出してimgに保存させる
//グレイスケール化
cvtColor(img, gray_img, CV_BGR2GRAY);
//平滑化
GaussianBlur(gray_img, gaussian_img, Size(7, 7), 0.0);
//2値化
threshold(gaussian_img, bin_img, 50, 255, THRESH_BINARY);
//輪郭抽出
Canny(img, canny_img, 60.0, 150.0);
//録画(動画ファイルに画像を出力)
writer_bin_img << bin_img; //2値化
writer_canny_img << canny_img; //canny法によるエッジ検出
//もし,Enterキーが押されたら強制終了
if (waitKey(1) == 13)
{
break;
}
}
cap.release();//読み込み用のオブジェクトを解放
writer_bin_img.release();//書き込み用のオブジェクトを解放
writer_canny_img.release();
destroyAllWindows();//ウィンドウを破棄
return 0;
}
解説
1. C++で標準入出力を行うために,『iostream』をインクルードします.
そして,OpenCVを使うために,『opencv2/opencv.hpp』と『opencv2/highgui/highgui.hpp』もインクルードします.
あと,『using namespace cv』と書くことで,OpenCVを使うたびに,『cv』を書く必要が無くなります.
(例:cv::imread() → imread()と書けばよい)
#include <iostream>
#include <opencv2/opencv.hpp>//OpenCVのインクルード
#include "opencv2/highgui/highgui.hpp" //動画を表示する際に必要
using namespace cv;
2. Mat型で画像ファイルを用意します.
『Size(〇, △)』で画像の横幅と縦幅を指定します.
そして,『CV_8UC3』で3チャンネル(カラー画像),『CV_8UC1』で1チャンネルと宣言します.
Mat img(Size(640, 360), CV_8UC3);
Mat gray_img(Size(640, 360), CV_8UC1);
Mat gaussian_img(Size(640, 360), CV_8UC1);
Mat bin_img(Size(640, 360), CV_8UC1);
Mat canny_img(Size(640, 360), CV_8UC1);
3. 以下の3行で,標準入力を行っています.
(※標準入力・・・コマンドプロンプト上からファイルを読み込む)
//動画ファイルを指定
std::cout << "FileName=" << std::flush;
//文字型のファイルを用意
std::string VideoFile = argv[argc - 1];
//コマンドプロンプからファイル名を入力
std::cin >> VideoFile;
4. 『VideoCapture』で動画を読み込む用のオブジェクトを生成し,『VideoWriter』で動画を書き込む用のオブジェクトを生成します.
『VideoWriter』内にある,『false』はグレイスケール時に使います.カラー画像を書き込みたい場合は,『true』にします.
また,正常に読み込めたか,書き込めたかを確認するために,エラー時の処理も書いておきます.
//動画読み込み用のオブジェクトを生成
VideoCapture cap(VideoFile);
//動画書き込み用のオブジェクトを生成
VideoWriter writer_bin_img("C:\\〇〇\\bin_img.mov", VideoWriter::fourcc('m', 'p', '4', 'v'), 100, Size(640, 360), false);
VideoWriter writer_canny_img("C:\\〇〇\\canny_img.mov", VideoWriter::fourcc('m', 'p', '4', 'v'), 100, Size(640, 360), false);
// cv::VideoCaptureが正常に動作しているかをチェック!
if (!cap.isOpened())
{
std::cerr << "cannot open this movie file!" << std::endl;
return -1;
}
// cv::VideoWriterが正常に動作しているかをチェック!
if (!writer_bin_img.isOpened() & !writer_canny_img.isOpened())
{
std::cerr << "failed to record" << std::endl;
return -1;
}
5. まず,『double max_frame = cap.get(CAP_PROP_FRAME_COUNT)』で動画の全フレーム数を取得します.
そして,for文で0番目から最後の画像までを1まいずつ処理していきます.
今回の場合だと,最初に『cap >> img』で,動画から画像ファイルに代入し,グレイスケール化や平滑化など,それぞれの処理を行います.
そして,『writer_bin_img << bin_img』,『writer_canny_img << canny_img』と書くことで,2値化の画像と輪郭を抽出した画像をそれぞれの動画書き込みオブジェクトに代入していきます.
最後に動画を強制終了するためのコードを書きます.
(※『waitKey(1) == 13』でエンターキーを押された場合に,終了させることができます.)
double max_frame = cap.get(CAP_PROP_FRAME_COUNT);//フレーム数
for (int i = 0; i < int(max_frame); i++)
{
cap >> img;//1フレーム分取り出してimgに保存させる
//グレイスケール化
cvtColor(img, gray_img, CV_BGR2GRAY);
//平滑化
GaussianBlur(gray_img, gaussian_img, Size(7, 7), 0.0);
//2値化
threshold(gaussian_img, bin_img, 50, 255, THRESH_BINARY);
//輪郭抽出
Canny(img, canny_img, 60.0, 150.0);
//表示
imshow("Video1", img);
imshow("Video2", bin_img);
imshow("Video3", canny_img);
//録画(動画ファイルに画像を出力)
writer_bin_img << bin_img; //2値化
writer_canny_img << canny_img; //canny法によるエッジ検出
//もし,Enterキーが押されたら強制終了
if (waitKey(1) == 13)
{
break;
}
}
6. 『release()』と書くことで,読み込み用と書き込み用のオブジェクトを閉じる作業を行います.
また,『destroyAllWindows()』で開いているウィンドウを閉じます.
そして,最後に『return 0』と書くことで,正常に終了したことを意味します.
cap.release();//読み込み用のオブジェクトを解放
writer_bin_img.release();//書き込み用のオブジェクトを解放
writer_canny_img.release();
destroyAllWindows();//ウィンドウを破棄
return 0;
終わりに
今回は,C++とOpenCVで動画の読み込みと書き込みを行う方法についてご紹介しました.
この方法を使うことで,動画を2値化したり輪郭を抽出したり,またまた様々なことが出来るので,是非使ってみて下さい!
それでは,goodbye.