可変フレームレートの映像ファイルのいくつかは CV_CAP_PROP_FRAME_COUNT のプロパティが 0 になるけど云々

フレーム数計測をやった.

まとめ

マシンは Dell Vostro 400,Core2 Quad,Q6600.コンパイラVC++ 2008 EE.

number name frame count property grab() ループ operator >>
1 test 90 90 90 90
2 1.avi 200 200 200 200
3 1.flv 200 0 200 200
4 fez 27292 27292 27291 27291

遊び半分で処理時間を計測した.operator >> よりは grab() が速いね.operator >> と grab() は一致するから,grab() を使おうね.fez は何が災いしたのか,計測してみると 1 小さい.不思議だ.

やってから気づいた.

    // grab() + retrieve(image, 0); と等価です.
    virtual VideoCapture& operator >> (Mat& image);
http://opencv.jp/opencv-2.0svn/cpp/reading_and_writing_images_and_video.html?highlight=retrieve#videocapture

こういう仕様なら,フレームを数えるには grab() だけでいい.

各映像ファイル詳細

[test.avi]
256x256 24Bit 無圧縮 5.00fps 90f 7864.64kb/s
[RIFF(AVI1.0)] 00:00:18.000 (18.000sec) / 17,701,376Bytes

[1.avi]
256x256 24Bit 不明VP6F 0.00fps 200f 297.77kb/s
[RIFF(AVI1.0)] 00:00:40.000 (40.000sec) / 1,492,272Bytes

[1.flv]
256x256 On2 VP6 5.00fps 400.00kb/s
[FlashVideo] 00:00:39.799 (39.799sec) / 1,490,734Bytes

[fez20091005-185827[000].avi]
640x400 24Bit H.264 15.00fps 27292f 842.23kb/s
MPEG1-LayerIII 44.10kHz 96.00kb/s CBR Mono
[RIFF(AVI1.0)] 00:30:19.466 (1819.466sec) / 214,263,802Bytes

真空波動研Lite 090902 / DLL 090902

画面出力

さっきの表の映像を順に,空行区切りで.

elapsed time [ms]: 0.000710517
frameCount (property): 90
elapsed time [ms]: 23.4078
frameCount (grab()): 90
elapsed time [ms]: 27.1176
frameCount (operator >>): 90

elapsed time [ms]: 0.000778186
frameCount (property): 200
elapsed time [ms]: 313.559
frameCount (grab()): 200
elapsed time [ms]: 407.356
frameCount (operator >>): 200

elapsed time [ms]: 0.00198494
frameCount (property): 0
elapsed time [ms]: 312.889
frameCount (grab()): 200
elapsed time [ms]: 401.504
frameCount (operator >>): 200

elapsed time [ms]: 0.00178945
frameCount (property): 27292
elapsed time [ms]: 94552.4
frameCount (grab()): 27291
elapsed time [ms]: 143904
frameCount (operator >>): 27291

コード

タイム計測は http://wiki.livedoor.jp/mikk_ni3_92/d/OpenCV::%BB%FE%B4%D6%B7%D7%C2%AC から頂戴した.

#include <iostream>
#include <opencv/cv.h>
#include <opencv/highgui.h>

#ifdef _DEBUG
#pragma comment( lib, "cv200d.lib" )
#pragma comment( lib, "cxcore200d.lib" )
#pragma comment( lib, "highgui200d.lib" )
#else
#pragma comment( lib, "cv200.lib" )
#pragma comment( lib, "cxcore200.lib" )
#pragma comment( lib, "highgui200.lib" )
#endif

using namespace std;

double start, finish;
#define stopWatchStart start = static_cast<double>(cv::getTickCount())
#define stopWatchStop  finish = static_cast<double>(cv::getTickCount()); \
	cout << "elapsed time [ms]: " << (finish - start)/cv::getTickFrequency()*1000 << endl

int main ( int argc, char *argv[] )
{
	if ( argc < 2 )
	{
		cout << "execute it: " << "numofframeFORvfr.exe a-video-file" << endl;
		return 0;
	}

	cv::VideoCapture cap = argv[1];
	
	if ( cap.isOpened() == false )
	{
		cout << "loading was failed: " << argv[1] << endl;
		return 0;
	}

	// property
	stopWatchStart;
	int frameCount = (int)cap.get(CV_CAP_PROP_FRAME_COUNT);
	stopWatchStop;
	cout << "frameCount (property): " << frameCount << endl;

	// grab() loop
	frameCount = 0;
	stopWatchStart;
	while ( cap.grab() )
		frameCount++;
	stopWatchStop;
	cout << "frameCount (grab()): " << frameCount << endl;

	// load frames
	frameCount = 0;
	cap.set(CV_CAP_PROP_POS_MSEC, 0.0);
	cv::Mat still;
	stopWatchStart;
	for ( ;; )
	{
		cap >> still;
		if ( still.empty() )
			break;
		frameCount++;
	}
	stopWatchStop;
	cout << "frameCount (operator >>): " << frameCount << endl;
	return 0;
}