Hatena::ブログ(Diary)

BiBoLoG

2009-11-21

OpenCV 2.0 用サンプル - 画像入出力,映像入出力

Win32 コンソールアプリケーションプロジェクトで作っていく.C++ Interface なんて未知の分野だが,OpenCV2.0\doc\opencv.pdf を参考にしたら何とかなるようだ.

環境と内容

内容は4つある.

  1. 画像読み込みと保存と表示
  2. 映像読込と再生
  3. 映像ファイルの情報を画面に表示
  4. AVI ファイルを AVI ファイルに書き出す

画像読み込みと保存と表示 via VS2008 集成openCV过程

解放はデストラクタに書いてあるんだろう.きっと.

#include "stdafx.h"
#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

const char *FILENAME = "c:/data/image/lena.png";
const char *WINDOW_NAME = "lena.png";

int _tmain(int argc, _TCHAR* argv[])
{
	cv::Mat image = cv::imread(FILENAME);
	if ( !image.empty() )
	{
		cv::imwrite("test.png", image);
		cv::namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
		cv::imshow(WINDOW_NAME, image);
		cv::waitKey();
	}

	return 0;
}

f:id:Guernsey:20091121110123j:image

映像読込と再生

映像終端を超えると cv::imshow が例外を投げる.追っかけてみたら,image が空になっていたから empty() を試してみたらビンゴ.次に示すのは,cv:VideoCapture からフレーム数を取得し,カウンタを回して止めた.

長い映像に暇をもてあまして閉じるボタンをクリックした.ウインドウが消えたが,次のフレームから復活した.この挙動,以前とは違うよな.カチカチカチ.途中終了をつけてやりたいので ESC キーをスイッチにしてやった.

#include "stdafx.h"
#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

const char *FILENAME = "c:/data/video/fez20091005-185827[000].avi";
//const char *FILENAME = "c:/data/video/90frame.avi";
const char *WINDOW_NAME = "play window";
const int KEYCODE_ESC = 0x1b;

int _tmain(int argc, _TCHAR* argv[])
{
	cv::VideoCapture capture(FILENAME);
	if( capture.isOpened() )
	{
		cv::Mat image;
		cv::namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
		double frame_count = capture.get(CV_CAP_PROP_FRAME_COUNT);
		int key;
		int i = 0;
		while( frame_count-- )
		{
			capture >> image;
			cv::imshow( WINDOW_NAME, image);
			key = cv::waitKey(1);
			if( key == KEYCODE_ESC )
			{
				break;
			}
		}
	}

	return 0;
}

無限ループにするなら,capture >> image; 後に image.empty() をチェックするといいだろう.

if( image.empty() )
{
	break;
}

f:id:Guernsey:20091121110220j:image

映像終端で画像読み込みするとこんな状態になる.このとき,empty() は真を返す.

f:id:Guernsey:20091121110219p:image

映像ファイルの情報を画面に表示

映像プロパティの ID リストは highgui.h 287行から.二次元配列の行数取得は BohYoh.com?C/C++ FAQ 2次元配列の要素数を取得するにはどうすればよいですか。 から.

#include "stdafx.h"
#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

//const char *FILENAME = "c:/data/video/90frame.avi";
const char *FILENAME = "c:/data/video/fez20091005-185827[000].avi";
const char *HIGHGUI_PROPID[] = {
	"CV_CAP_PROP_POS_MSEC     ",
	"CV_CAP_PROP_POS_FRAMES   ",
	"CV_CAP_PROP_POS_AVI_RATIO",
	"CV_CAP_PROP_FRAME_WIDTH  ",
	"CV_CAP_PROP_FRAME_HEIGHT ",
	"CV_CAP_PROP_FPS          ",
	"CV_CAP_PROP_FOURCC       ",
	"CV_CAP_PROP_FRAME_COUNT  ",
	"CV_CAP_PROP_FORMAT       ",
	"CV_CAP_PROP_MODE         ",
	"CV_CAP_PROP_BRIGHTNESS   ",
	"CV_CAP_PROP_CONTRAST     ",
	"CV_CAP_PROP_SATURATION   ",
	"CV_CAP_PROP_HUE          ",
	"CV_CAP_PROP_GAIN         ",
	"CV_CAP_PROP_EXPOSURE     ",
	"CV_CAP_PROP_CONVERT_RGB  ",
	"CV_CAP_PROP_WHITE_BALANCE",
	"CV_CAP_PROP_RECTIFICATION",
};
const int HIGHGUI_PROPID_COUNT = sizeof( HIGHGUI_PROPID ) / sizeof( HIGHGUI_PROPID[0] ) ;

void print_videinfo(cv::VideoCapture capture)
{
	if ( capture.isOpened() )
	{
		for( int i = 0; i < HIGHGUI_PROPID_COUNT; i++ )
		{
			printf("%s: %lf\n", HIGHGUI_PROPID[i], capture.get(i));
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	cv::VideoCapture capture(FILENAME);
	printf("%s\n", FILENAME);
	print_videinfo(capture);

	getchar();

	return 0;
}

f:id:Guernsey:20091121110251p:image

AVI ファイルを AVI ファイルに書き出す

while( frame_count-- ); と書いていて,デバッグを20分続けていた.

#define CV_FOURCC_PROMPT -1  /* Open Codec Selection Dialog (Windows only) */
#define CV_FOURCC_DEFAULT CV_FOURCC('I', 'Y', 'U', 'V') /* Use default codec for specified filename (Linux only) */
#include "stdafx.h"
#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

const char *IN_VIDEO = "c:/data/video/fez20091005-185827[000].avi";
//const char *IN_VIDEO = "c:/data/video/90frame.avi";
const char *OUT_VIDEO = "c:/data/video/test.avi";
const char *WINDOW_NAME = "preview window";
const int KEYCODE_ESC = 0x1b;

class video_property
{
private:
	int count;
	int width;
	int height;
	double  fps;
public:
	int get_count(void)  { return this->count;  }
	int get_width(void)  { return this->width;  }
	int get_height(void) { return this->height; }
	double get_fps(void)    { return this->fps; }
	video_property( cv::VideoCapture capture ) { set(capture); };
	void set( cv::VideoCapture capture)
	{
		if ( capture.isOpened() )
		{
			this->count  = (int) capture.get( CV_CAP_PROP_FRAME_COUNT  );
			this->width  = (int) capture.get( CV_CAP_PROP_FRAME_WIDTH  );
			this->height = (int) capture.get( CV_CAP_PROP_FRAME_HEIGHT );
			this->fps    = capture.get( CV_CAP_PROP_FPS );
		}else{
			this->count = this->width = this->height = 0;
			this->fps = 0.0;
		}
	}
	void print(void)
	{
		printf("%-26s: %d\n",  "CV_CAP_PROP_FRAME_COUNT",  this->count );
		printf("%-26s: %d\n",  "CV_CAP_PROP_FRAME_WIDTH",  this->width );
		printf("%-26s: %d\n",  "CV_CAP_PROP_FRAME_HEIGHT", this->height);
		printf("%-26s: %lf\n", "CV_CAP_PROP_FPS",         this->fps   );
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	cv::VideoCapture capture(IN_VIDEO);
	printf("%s\n", IN_VIDEO);
	if( capture.isOpened() )
	{
		video_property prop(capture);
		prop.print();
		cv::VideoWriter writer(
			OUT_VIDEO, CV_FOURCC_DEFAULT,
			prop.get_fps(), cv::Size(prop.get_width(), prop.get_height()));
		
		if( writer.isOpened() )
		{
			cv::namedWindow(WINDOW_NAME, CV_WINDOW_AUTOSIZE);
			int frame_count = prop.get_count();
			cv::Mat image;
			int key;
			while( frame_count )
			{
				capture >> image;
				cv::imshow( WINDOW_NAME, image);
				key = cv::waitKey(1);
				writer << image;
				if( key == KEYCODE_ESC )
					break;
			}
		}
	}

	return 0;
}

f:id:Guernsey:20091121110315j:image

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

リンク元
Connection: close