質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

7764閲覧

opencv 動画 再生

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2017/07/07 09:25

編集2017/07/08 09:18

c

1#include <stdio.h> 2#include <cv.h> 3#include <highgui.h> 4 5int main(int argc, char* argv[]) { 6int i; 7float *p; 8double w = 320, h = 240; 9IplImage *src_img = 0, *gray_img = 0; 10CvMemStorage *storage; 11CvSeq *circles = 0; 12CvCapture *capture = 0; 13 14capture = cvCaptureFromCAM (0); 15//capture = cvCaptureFromFile(argv[1]); 16 17cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, w); 18cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h); 19cvNamedWindow ("circles", CV_WINDOW_AUTOSIZE); 20while(1) { 21src_img = cvQueryFrame (capture); 22CvSize sizeOfImage = cvGetSize(src_img); 23//IplImage *gray_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1); 24gray_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1); 25 26cvCvtColor(src_img, gray_img, CV_BGR2GRAY); 27//src_img_gray = cvQueryFrame (capture); 28 29cvSmooth (gray_img, gray_img, CV_GAUSSIAN, 11, 11, 0, 0); 30storage = cvCreateMemStorage (0); 31 32circles = cvHoughCircles (gray_img, storage, CV_HOUGH_GRADIENT, 331, 100, 20, 50, 10, MAX (gray_img->width, gray_img->height)); 34for (i = 0; i < circles->total; i++) { 35p = (float *) cvGetSeqElem (circles, i); 36cvCircle (src_img, cvPoint (cvRound (p[0]), cvRound (p[1])), 3, CV_RGB (0, 255, 0), -1, 8, 0); 37cvCircle (src_img, cvPoint (cvRound (p[0]), cvRound (p[1])), cvRound (p[2]), CV_RGB (255, 0, 0), 3, 8, 0); 38} 39 40cvShowImage ("circles", src_img); 41cvWaitKey (10); 42} 43cvDestroyWindow ("circles"); 44cvReleaseImage (&src_img); 45cvReleaseImage (&gray_img); 46cvReleaseMemStorage (&storage); 47return 0; 48}

このプログラムでカメラで円検出をしました。opencvのCaptureFromFileという関数でカメラの部分をデスクトップにある動画に変えたいのですが、どうすればいいでしょうか

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2017/07/07 09:31

コードはバッククオート三つ(```)で括ってください。よくわからないようであれば、マークダウン記法について少し調べてみてください。
guest

回答3

0

ベストアンサー

cvCaptureFromFiledeprecatedになっています。またC API自体もメンテナンスされていません。代わりにcv::VideoCaptureクラスを利用してください。どうしてもC APIを利用する場合はcvCreateFileCaptureを利用してください。

cpp

1#include <opencv2/core.hpp> 2#include <opencv2/videoio.hpp> 3#include <opencv2/highgui.hpp> 4#include <iostream> 5#include <thread> 6#include <chrono> 7 8int main() 9{ 10 namespace ch = std::chrono; 11 cv::VideoCapture video("/Users/pbl2017/Desktop/baseball.mp4"); 12 if(!video.isOpened()) { 13 std::cerr << "Fail to open video" << std::endl; 14 return 1; 15 } 16 cv::namedWindow("Live", cv::WINDOW_AUTOSIZE); 17 const double fps = video.get(cv::VideoCaptureProperties::CAP_PROP_FPS); 18 const double mspf = 1000.0 / fps; 19 const auto begin_time = ch::steady_clock::now(); 20 std::size_t frame_count = 0; 21 for(cv::Mat frame; video.read(frame) && !frame.empty(); ++frame_count) { 22 cv::imshow("Live", frame); 23 if('q' == cv::waitKey(1)) break;//qキーで脱出 24 std::this_thread::sleep_until(begin_time + ch::milliseconds(frame_count * mspf)); 25 } 26}

注意点

cv::VideoCapture::getの信憑性

cv::VideoCapture::getの値は信用できないという話もある。例えばdecoderがIntelMFX, GPhoto2の場合、内部実装はガバガバで信用できない。

ref:

CFR(固定フレームレート)の場合のループ制御

多くのサンプルでcv::waitKey(30)としているが、これは明確な誤りである。動画のフレームレートは多くの場合29.9724fpsであることが多いが、動画を開いてみるまでFPSは確定しない。30fps決め打ちはやってはいけない。

またcv::VideoCapture::read, cv::imshowの実行時間も無視してはいけない。つまりcv::waitKeyはあくまでキー入力を受けるために使うべきであり、フレームレート制御に用いてはならない
cv::waitKeyはドキュメントによると引数はミリ秒単位であり、0以下の値(どういうわけかこいつ負の値もとる、頭がおかC)が渡されるとキー入力があるまで動かないので、キー入力を待たない最小時間である1msec.を渡す。

ではどうやってフレームレート制御するかというと、C++11で追加された時間ライブラリとスレッドライブラリを利用する。つまりstd::chrono::steady_clock,
std::chrono::milliseconds, std::this_thread::sleep_untilを利用する。

steady_clockはたとえプログラム起動中にOSが例えばNTP同期するなどして時刻が逆行した場合でもその影響を受けずに動作する。

VFR(可変フレームレート)の場合のループ制御

上記サンプルはVFRな動画に対しては全く正常に動作しない。

可変フレームレートというくらいだから、各フレームごとに表示時間を決定する必要がある。これを怠るプログラムのなんとまあ多いこと。

ref: 本の虫: VFRはいまだ浸透せず

VFRというのは圧縮効率の観点から極めて合理的でありサポートするべきだというのに。

しかしながら、OpenCVではどのようにしてその情報を手に入れればいいのだろうか?

  1. cv::VideoCaptureProperties::CAP_PROP_POS_MSECを利用してcv::VideoCapture::readのあとにこの値をcv::VideoCapture::getで読み、std::this_thread::sleep_untilなどでwaitする
  2. cv::VideoCaptureProperties::CAP_PROP_FPSを利用してcv::imshowのあとにこの値をcv::VideoCapture::getで読み、std::this_thread::sleep_untilなどでwaitする

しかしながらすでに述べたとおり、cv::VideoCapture::get

正しい値が返ってくるといいなぁ(願望)

程度の信憑性であり、実用に耐えない。唯一信頼が置ける場合は、コーデックが事前に決め打ちでき、かつOpenCVでのそのコーデックの実装が正しい場合のみである。

つまり、OpenCVの動画再生機能はまともにVFRな動画を再生することができない。FFmpegやそのラッパーであるL-SMASH Worksでdecodeするべきである。

投稿2017/07/08 02:31

編集2017/07/09 06:09
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/07/08 04:39

コンパイルするとtreating 'c' input as 'c++' when in C++ mode, this behavior is deprecatedという警告が出るのですがこれは関係がありますかね?写真を表示させたりするときは、この警告が出ても実行できるんですけど、、、
yumetodo

2017/07/08 04:53

C言語としてコンパイルしていませんか?
yumetodo

2017/07/08 04:59

名前マングリングをC++でするので、C++としてコンパイルするファイルから読み込まれるヘッダーファイルで宣言されている関数の実体がCとしてコンパイルされる場合、linkできないと思います。
yumetodo

2017/07/08 05:21

あれ・・・`video.get(cv::VideoCaptureProperties::CAP_PROP_FPS)`って実装覗きに行ったらこれ信用度が・・・
退会済みユーザー

退会済みユーザー

2017/07/08 05:21

ファイルの拡張子を.cにしているのですが、.ccや.cppにしたら良いということでしょうか?
退会済みユーザー

退会済みユーザー

2017/07/08 05:37

ありがとうございます!
guest

0

  • コードの中に書き込む

capture = cvCaptureFromFile("C:\\Users\\name\\Desktop\\hoge.avi");

  • コマンドライン引数を指定する (以下はWindowsの場合)

> programname.exe C:\Users\name\Desktop\hoge.avi

のどちらかでしょう。

投稿2017/07/07 09:35

LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C++

1#include <stdio.h> 2#include <cv.h> 3#include <highgui.h> 4 5 6int main(int agrc, char* argv[]){ 7 cvNamedWindow("Example",CV_WINDOW_AUTOSIZE); 8 CvCapture *capture = cvCreateFileCapture("baseball.mp4"); 9 IplImage *frame ; 10 while(1){ 11 frame = cvQueryFrame(capture); 12 if(!frame) break; 13 cvShowImage("Example" , frame); 14 char c = cvWaitKey(33); 15 if(c == 27) break; 16 } 17 cvReleaseCapture(&capture); 18 cvDestroyWindow("Example"); 19}

C++

1#include <opencv2/core.hpp> 2#include <opencv2/videoio.hpp> 3#include <opencv2/highgui.hpp> 4#include <iostream> 5 6int main(int argc, const char* argv[]) 7{ 8 cv::VideoCapture cap("baseball.mp4"); 9 if (!cap.isOpened()) 10 return -1; 11 cv::namedWindow("image", cv::WINDOW_AUTOSIZE); 12 cv::Mat frame; 13 for (;;) 14 { 15 cap >> frame; 16 if (frame.empty()) break; 17 cv::imshow("image", frame); 18 cv::waitKey(30); 19 } 20 return 0; 21} 22

この二つの方法で動画を読み込み表示させることができた

投稿2017/07/08 09:21

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2017/07/08 09:24

ベストアンサーをyumetodoさんにつけるべきじゃないですか?
退会済みユーザー

退会済みユーザー

2017/07/08 09:28

どうやったらベストアンサーを付けれるんですか?一度未解決にしたほうがいいですか?
退会済みユーザー

退会済みユーザー

2017/07/08 09:30

すいませんできました。ありがとうございました。
LouiS0616

2017/07/08 09:34

いえいえ。回答欄は回答者のためにあるので、本当の本当に自力で解決したとき以外は使わないでくださいね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問