• 締切済み

OpenCVを用いて任意の時間で静止画を保存したい。

OpenCVを用いて"s"キーを押したら静止画保存が始まり、再度"s"キーを押したら保存が終了しるプログラムを作成しています。(保存レートは1秒間で30フレームの静止画保存で考えています)また、保存する静止画を指定したフォルダに保存するプログラムを作成していますが、プログラム作成の経験が浅く、なかなかうまく作れず困っております。どのようにプログラムを組めばこのようなプログラムが作れるのでしょうか。下記のプログラムは作成でき、これを基礎にして作り上げていこうと考えています。プログラムの内容としては"c"キーを押した分だけ、連番でbip形式で画像を保存するプログラムです。精度の関係上timegettime関数を使用したいと考えているのですが、、。 <ソースプログラム> #include <stdio.h> #include <highgui.h> int main( int argc, char** argv ){ int key; // キー入力用変数 int counter = 0; CvCapture *capture; // キャプチャ用構造体 IplImage *frameImage; // キャプチャ画像用IplImage char str[32]; char windowNameCapture[] = "CMOS Camera Image"; // ウィンドウネーム // カメラの初期化 if( ( capture = cvCreateCameraCapture(-1)) == NULL ){ // カメラデバイスが検出できない場合 printf("カメラデバイスを検出できません\n"); return -1; } // ウィンドウ生成 cvNamedWindow( windowNameCapture, CV_WINDOW_AUTOSIZE ); // メインループ while(1){ // カメラからの1フレームをframeImageに格納 frameImage = cvQueryFrame( capture ); // 画像表示 cvShowImage( windowNameCapture, frameImage ); // 'ESC'キーが入力されたらループを抜ける key = cvWaitKey(1); if( key == '\x1b' ){ break; // 静止画保存 } else if( key == 'c'){ sprintf_s(str, "cmosview%04d.bmp",counter++); cvSaveImage(str, frameImage ); } } // キャプチャ解放 cvReleaseCapture( &capture ); // ウィンドウ破棄 cvDestroyWindow( windowNameCapture ); return 0; }

みんなの回答

回答No.2

 こんばんは。補足いただきました。遅れてしまってすんません。  常にカメラデバイスから、映像が上がってくるのだと思います・・・。チョッと勘違いしてしまいました。  今回、コンソールに対してprintfで動きを追っています。  映像が写されながら、Sキーが押された瞬間に録画開始、もう一回押すと録画停止です(カメラデバイスからの映像は映り続ける筈)。  修正を入れましたので以下を参考にされて下さい。 +----------------------------------------------------------------------- // メインループ while(1){ /*----------追加プログラム----------*/ // カメラから1フレームをframeImageに格納 frameImage = cvQueryFrame( capture ); printf("フレームの問い合わせ\n"); // 画像表示 cvShowImage( windowNameCapture, frameImage ); printf("フレームの描画中\n"); key = cvWaitKey(1); // 静止撮影ボタンが押された if(key =='c') { sprintf_s( str, "cmosview%04.bmp", counter++ ); cvSaveImage( str, frameImage ); } // 録画ボタンが押された else if(key == 's') { // トグルする bCapture ^=TRUE; ::printf("%s\n", bCapture?"録画開始":"録画停止"); // キャプチャーの開始を命じられたので開始時刻を取得 if(bCapture) { dwCurrentTime = dwLastTime = ::timeGetTime(); } } // 'ESC'キーが入力されたらループを抜ける else if(key == '\x1b') { printf("終了します\n"); break; } //キャプチャーしていないので引き返す if(!bCapture) continue; // 最新時間を取得 dwCurrentTime = ::timeGetTime(); // 経過時間がレートに満たないので引き返す if(dwCurrentTime - dwLastTime <= 30) continue; // 現在のタイムを最新のタイムにする dwLastTime = dwCurrentTime; // 保存 sprintf_s( str, "cmosview%4d.bmp", counter++ ); cvSaveImage( str, frameImage ); printf("%s\n", str); } -----------------------------------------------------------------------+

回答No.1

 こんばんは。  チョッと今カメラデバイスが無いので、実行は出来ない状態ですが、こんな感じで出来ませんか。  timeGetTime()を使用する際にはwinmm.libをリンクするのを忘れないで下さい。  録画開始と同時に再生される事を前提に、ループの部分だけ書きます。参考程度に。 #include<windows.h> #include<mmsystem.h> #pragma comment(lib, "winmm.lib") +----------------------------------------------------------------------- DWORD dwCurrentTime = 0; DWORD dwLastTime = ::timeGetTime(); BOOL bCapture = FALSE; //タイマ精度を1ミリ秒にする ::timeBeginPeriod(1); // メインループ while(1) { //現在のタイム dwCurrentTime = ::timeGetTime(); //保存レート30ミリ秒経過しないので引き返す if(dwCurrentTime - dwLastTime < 30) continue; //現在のタイムを最新のタイムにする dwLastTime = dwCurrentTime; // 録画中 if(bCapture) { // カメラからの1フレームをframeImageに格納 frameImage = cvQueryFrame( capture ); // 画像表示 cvShowImage( windowNameCapture, frameImage ); // 保存 sprintf_s(str, "cmosview%04d.bmp",counter++); cvSaveImage(str, frameImage ); } // 'ESC'キーが入力されたらループを抜ける key = cvWaitKey(1); if( key == '\x1b' ) { break; // 静止画保存 } else if( key == 'c') { sprintf_s(str, "cmosview%04d.bmp",counter++); cvSaveImage(str, frameImage ); } // 録画開始/停止 else if( key == 's') { // トグルする bCapture ^= TRUE; ::printf("%s\n", bCapture ? "録画開始" : "録画停止"); } } -----------------------------------------------------------------------+

2378tcdd
質問者

補足

早速のご連絡有難う御座います。下記のようなプログラムにて実行致しました。エラーもなく、デバッグできましたが、プログラムを起動させると一瞬で終了してしまいました。80行目のcvWaitKeyの変数を0にすると表示されたままですが、カメラからの入力がありません。しかし、非常に勉強になったので引き続き、エラー原因を探って行きたいと思います。お忙しい中、有難う御座います。もし、宜しければ引き続き、ご指導宜しくお願い致します。 ----------ソースプログラム---------- #include <stdio.h> #include <highgui.h> #include <windows.h> // 追加 #include <mmsystem.h> // 追加 #pragma comment(lib,"winmm.lib") // 追加 int main( int argc, char** argv ){ int key; // キー入力用変数 int counter = 0; CvCapture *capture; // キャプチャ用構造体 IplImage *frameImage; // キャプチャ画像用IplImage char str[32]; char windowNameCapture[] = "CMOS Camera Image"; // ウィンドウネーム DWORD dwCurrentTime = 0; // 追加 DWORD dwLastTime = ::timeGetTime(); // 追加 BOOL bCapture = FALSE; // 追加 // タイマ精度を1msにする ::timeBeginPeriod(1); // 追加 // カメラの初期化 if( ( capture = cvCreateCameraCapture(-1)) == NULL ){ // カメラデバイスが検出できない場合 printf("カメラデバイスを検出できません\n"); return -1; } // ウィンドウ生成 cvNamedWindow( windowNameCapture, CV_WINDOW_AUTOSIZE ); // メインループ while(1){ // カメラからの1フレームをframeImageに格納 // frameImage = cvQueryFrame( capture ); // 画像表示 // cvShowImage( windowNameCapture, frameImage ); // 'ESC'キーが入力されたらループを抜ける // key = cvWaitKey(1); // if( key == '\x1b' ){ // break; // 静止画保存 // } else if( key == 'c'){ // sprintf_s(str, "cmosview%04d.bmp",counter++); // cvSaveImage(str, frameImage ); // } /*----------追加プログラム----------*/ // 現在の時間 dwCurrentTime = ::timeGetTime(); // 保存レートの30msを経過しないので引き返す if( dwCurrentTime - dwLastTime < 30 ) continue; // 現在のタイムを最新のタイムにする dwLastTime = dwCurrentTime; // 録画中 if(bCapture) { // カメラから1フレームをframeImageに格納 frameImage = cvQueryFrame( capture ); // 画像表示 cvShowImage( windowNameCapture, frameImage ); // 保存 sprintf_s( str, "cmosview%4d.bmp", counter++ ); cvSaveImage( str, frameImage ); } // 'ESC'キーが入力されたらループを抜ける key = cvWaitKey(1); if ( key = '\x1b' ) { break; // 静止画の保存 } else if( key = 'c' ) { sprintf_s( str, "cmosview%04.bmp", counter++ ); cvSaveImage( str, frameImage ); } // 録画の開始/停止 else if ( key = 's' ) { // トグルする bCapture ^=TRUE; ::printf("%s\n", bCapture?"録画開始":"録画停止"); } } /*----------ここまで----------*/ // キャプチャ解放 cvReleaseCapture( &capture ); // ウィンドウ破棄 cvDestroyWindow( windowNameCapture ); return 0; }