opencvを用いて、カメラから静止画を一定間隔で保存しようとしています。
プログラムを書いてみたのですが、cキーを押しても保存できません。
アドバイスや改善点、新しいプログラムを教えていただけたらと思います。
以下にプログラムを示します。よろしくお願いします。
// メインループ
// 画像表示と保存
int bSelf = 0;
int nCnt = 0;
while ( 1 )
{
// カメラからの入力画像1フレームをframeImageに格納する
frameImage = cvQueryFrame( capture );
printf("フレームの問い合わせ\n");
// 画像を表示する
cvShowImage( windowNameCapture, frameImage );
printf("フレームの描画中\n");
// 'q'キーが入力されたらループを抜ける
key = cvWaitKey( 1 );
if ( key == 'q' )
{
printf("終了します\n");
break;
}
// 'c'キーが入力されったら画像を保存する
else if(key=='c')
{
// フラグ更新
bSelf = ( bSelf == 0 );
nCnt = 0;
}
if ( bSelf && key == 0 )
{
nCnt++;
if ( nCnt >= 1000 )
{
sprintf_s(str,"testmovie%4d.bmp",counter++);
cvSaveImage(str,frameImage);
printf("%s\n",str);
// 次回のためにカウンタを初期化
nCnt = 0;
}
}
// キャプチャ解放
cvReleaseCapture( &capture );
// ウィンドウ破棄
cvDestroyWindow( windowNameCapture );
return 0;
}
A 回答 (9件)
- 最新から表示
- 回答順に表示
No.9
- 回答日時:
>しかし、保存することはできませんでした。
関数仕様はちゃんし確認しないとダメですな……。
http://opencv.jp/opencv-1.0.0/document/opencvref …
http://bicycle.life.coocan.jp/takamints/index.ph …
というわけで、タイムアウト(キー未入力)はkey == -1で判定する必要があります。
>aを押しながらcを押すと撮影開始となるように変更するには
>どのようにしたらよいのでしょうか?
複数のキー押下を検出できない…んじゃないですかね。
SHIFTキーやCtrlキー、Altキーとの複合の場合に検出できるのかは…どうなんだろう?
「cvWaitKey Ctrl」とかで検索するとなにか見つかりますかねぇ。
No.6
- 回答日時:
>例えば1秒を10秒に変更しようとすると、
if ( nCnt >= 1000 )
が1000ms以上という判定なので、ここの値を修正してください。
ただし、先の回答通り1000msになるとは保証できません。
# PCのスペック次第でしょうかねぇ…。
>この部分に
>beforekey = key;
>key = cvWaitKey( 1 );
>を追加するのがベストなのでしょうか?
元々の
key = cvWaitKey( 1 );
がある行の前に
beforekey = key;
を挿入です。
当たり前ですが変数の型はよろしく処理してください。
で、その部分は「1秒を10秒に変更」とはなんの関係もありません。
キーの押下と解放で正しく状態を変更できるか。
と、1秒を意味(したい)カウンタの値。
は別です。(変更された状態によってカウントするかどうかの挙動は変わりますけど。)
カウンタでやるのではなく、timeGettime()でミリ秒取得して比較…の方がズレが出にくいと思いますけどね。
あらかじめマルチメディアタイマの制度を変更するのと、ミリ秒取得のオーバーフローに注意は必要ですが。
# Windowsの49.7日問題で検索すると出てくるかな?
詳しく、親切にありがとうございます。
ここからは自力で調整していきたいと思います。
また、わからないことがあると聞くかもしれませんがよろしくお願いします。
No.5
- 回答日時:
コピペでミスした。
>・ループ3回目
>'c'キー離しました。(2msで離すのは難しいかもしれんが)
4回目ね。
大変わかりやすくありがとうございます!
ミスの原因をわかりやすく伝えてくださりありがとうございます。
ミスの原因がわかりました
まだ余力があれば協力してもらいたいのですが、
例えば1秒を10秒に変更しようとすると、
bSelf = ( bSelf == 0 );
nCnt = 0;
}
if ( bSelf && key == 0 )
{
nCnt++;
if ( nCnt >= 1000 )
{
sprintf_s(str,"testmovie%4d.bmp",counter++);
cvSaveImage(str,frameImage);
printf("%s\n",str);
この部分に
beforekey = key;
key = cvWaitKey( 1 );
を追加するのがベストなのでしょうか?
あまりにも操作が面倒くさいプログラムだと気づきまして…
ボタンを押しただけで、10秒おきに撮影は無理なのでしょうか?
No.4
- 回答日時:
>if ( bSelf && key == 0 )
>この部分をどれだけ検索してもわからなくて、
if ( bSelf != 0 && key == 0 )
だったら判りますか?
bSelf = ( bSelf == 0 );
は、実行するたびに
・bSelfが0だったらbSelfを真(非0)にする。
・bSelfが0じゃなかったらbSelfを偽(0)にする。
という動作になります。
説明を簡単にするために
>while ( 1 )
>{
> // カメラからの入力画像1フレームをframeImageに格納する
:
>}
>// キャプチャ解放
のループは1回回すのに1ms未満で終わるもの…とします。
cvQueryFrame()やprintf()、cvShowImage()も面倒なので説明から省きます。
・ループ1回目
なにもキーが押されていないので
>key = cvWaitKey( 1 );
で1ms待ってkeyには0が入ります。
>if ( key == 'q' )
'q'じゃないのでスルー。
>else if(key=='c')
'c'でもないのでスルー。
>if ( bSelf && key == 0 )
keyは0だけどbSelfが0なのでスルー…ということで2回目へ。
・ループ2回目
'c'キーを押下。
>key = cvWaitKey( 1 );
で押下を検出してkeyに'c'が入る。
>if ( key == 'q' )
'q'じゃないのでスルー。
>else if(key=='c')
'c'なので条件一致。
>bSelf = ( bSelf == 0 );
先の説明通りbSelfに真(非0)を設定。
>nCnt = 0;
そのままnCntに0設定。
>if ( bSelf && key == 0 )
bSelfが非0だけどkeyは0ではないのでスルー…ということで3回目へ。
・ループ3回目
'c'キーは押下状態のまま。(前回のループから1ms経過してないからね)
>key = cvWaitKey( 1 );
で押下を検出してkeyに'c'が入る。
>if ( key == 'q' )
'q'じゃないのでスルー。
>else if(key=='c')
'c'なので条件一致。
>bSelf = ( bSelf == 0 );
先の説明通りbSelfに偽(0)を設定。
>nCnt = 0;
そのままnCntに0設定。
>if ( bSelf && key == 0 )
bSelfが0なのでスルー…ということで4回目へ。
・ループ3回目
'c'キー離しました。(2msで離すのは難しいかもしれんが)
>key = cvWaitKey( 1 );
で1ms待ってkeyには0が入ります。
>if ( key == 'q' )
'q'じゃないのでスルー。
>else if(key=='c')
'c'でもないのでスルー。
>if ( bSelf && key == 0 )
keyは0だけどbSelfが0なのでスルー…ということで次のループへ。
あれれ?
'c'キー押して離したのにキャプチャするルートに入ってくれねぇです。
バグじゃね?
いいえ、『書かれたコードに従っている』ので間違っていません。
というワケで設計ミスです。
'c'キー押下を検出している間、bSelfはおおよそ1ms単位で真(非0)と偽(0)に変化しているので
'c'キーを離すタイミングでキャプチャの処理に入ることができます。
確率50%のルーレット。(たたしキャプチャが実行される(結果がわかる)のは1000ms後)
bSelfは'c'を押して『離したら』状態が変化する。
というように処理しないと、
・キャプチャ動作していないときに'c'を押して(離したら)キャプチャ処理開始。
・キャプチャ動作しているときにに'c'を押して(離したら)キャプチャ動作中止。
になりません。
方法はいくつかありますが…
beforekey = key;
key = cvWaitKey( 1 );
として1つ前のキーの状態を記憶するようにして、
else if(beforekey=='c' && key == 0)
として、『1回前のループの時に'c'キー押下を検出して、今回は検出できなかった場合』として判定する。
ってところでしょうかね。
ただし、コレでもダメな場合があるのでご注意を。
# 'c'キー押したまま'a'キー押して、'c'キー離す。とか……。
んで……実際のところは
cvQueryFrame( capture );
やら
printf();
やら
cvShowImage( windowNameCapture, frameImage );
などの諸々の処理の合計が1ms以内に終わることはまずないでしょうから、
>nCnt++;
も1ms間隔では実行されないでしょう。
よって、
>cvSaveImage(str,frameImage);
が1秒間隔で…ということもない。かと。
# ストレージへの書き込みはそれなりに時間がかかる。ライトキャッシュに突っ込むだけならまだ軽いとはいえ。
No.3
- 回答日時:
>bselfがなにかもわからないような初心者には難しいことでしょうか?
元にしたコードのどこに問題があるのか把握できない。
という状態で改造しようとするのは無理でしょう。
>この部分をなくしてしまっても問題ないのでしょうか?
目の前ある時限爆弾を解除して、目覚まし時計だけ利用したい。
って状況で、いきなり配線を切ってみますか?
まぁこのコードで削除したところで死にはしませんが。
# ある意味で空き容量は死ぬかも知れんが。
>教えていただけたらと思います。
出先…というか帰宅途中なのでスマホで細かく回答する気にはなりません。
自宅着いて落ち着いたあとで余力があれば…になるでしょうね。
# 早くて21時過ぎでしょうかねぇ。真っ直ぐ帰宅するわけでもないですし。
その前に他の人から回答付くかもしれませんが。
ちなみにWindowsの挙動の関係で『1秒後に1秒毎』は保証できませんよ。
現状のコードを修正しても誤差が出るはずです。
申し訳ございません。
if ( bSelf && key == 0 )
この部分をどれだけ検索してもわからなくて、
全ての部分をなくすわけではなく変更するという意味です。
timeGettimeを用いたりしてやってみたのですが、やはり保存が出来なく、
私も勉強しているのですが、余力があればお手伝いしてもらいたいと思います。
ありがとうございます。
No.2
- 回答日時:
>こちらのプログラムも先人のを参考に作りました。
ここの過去のやつですかね。
知恵袋にも似たやつありましたけど。
>こちらの部分ですが、調べてみてもよくわかりません。
printf()でbSelfの値を表示するようにして試してください。
コードの意図としては「cキーを押して、離してから1秒後に1秒毎にキャプチャ画像を保存。もう一度cキーを押して離したら保存を終了」としたかったんだろうな…とは思いますが。
もちろん、そういう風には動きません。
ここの過去の質問ではその部分が解決しないまま終わったようですが。
そのとおりです。
bselfがなにかもわからないような初心者には難しいことでしょうか?
私としては、cキーを押して離してから1秒毎にに保存されるものを作りたいのですが、
// フラグ更新
bSelf = ( bSelf == 0 );
nCnt = 0;
}
if ( bSelf && key == 0 )
{
nCnt++;
この部分をなくしてしまっても問題ないのでしょうか?
教えていただけたらと思います。
No.1
- 回答日時:
opencv使ったことありませんけど……
>// 'c'キーが入力されったら画像を保存する
>else if(key=='c')
>{
>// フラグ更新
>bSelf = ( bSelf == 0 );
>nCnt = 0;
>}
'c'キーを「押してから離すまで」にbSelfがどういう遷移をするか確認してみてはどうでしょう?
「'c'キーが押されている間」、bSelfが0と1を繰り返しているんじゃないかと思いますが…。
離したタイミングでbSelfが0だったら
>if ( bSelf && key == 0 )
の判定はどうなりますかね?
アドバイスありがとうございます。
すいませんが、プログラム初心者なためよくわかりません。
こちらのプログラムも先人のを参考に作りました。
>// 'c'キーが入力されったら画像を保存する
>else if(key=='c')
>{
>// フラグ更新
>bSelf = ( bSelf == 0 );
>nCnt = 0;
>}
こちらの部分ですが、調べてみてもよくわかりません。
図々しいですが、詳しく教えていただけたらと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語 3 2022/11/09 13:27
- C言語・C++・C# 【C++】IDirect3DSurfaceのディープコピーは可能ですか? 1 2022/07/06 02:47
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
For文の終了値を関数にしても問...
-
break文でループを一気に抜ける...
-
Excel VBAで年度をまたぐ期間の...
-
ループを途中で抜けたいのですが。
-
do-while文が禁止される理由
-
__asm int 3でのブレイクポイン...
-
C言語forループが完結した場合...
-
C言語に関する質問
-
While文の終わりにセミコロンが...
-
if文の中にfor文なのか、for文...
-
Cプログラムが終了しない
-
無限ループ対策
-
独習C 素数テスタ・・・分から...
-
入力した数値を倍々するプログラム
-
エクセルVBAで Do While (1)って?
-
入力した文字列から母音だけを...
-
他言語で言うcontinue文
-
繰り返し文の利点について
-
桁数を求めるプログラム。
-
H8/3048マイコンAD/DA変換について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
break文でループを一気に抜ける...
-
do-while文が禁止される理由
-
ループを途中で抜けたいのですが。
-
入力した数値を倍々するプログラム
-
入力した文字列から母音だけを...
-
if文の中にfor文なのか、for文...
-
C言語forループが完結した場合...
-
エクセルでC言語のfor文と同じ...
-
Excel VBAで年度をまたぐ期間の...
-
For文の終了値を関数にしても問...
-
エクセルVBAで Do While (1)って?
-
C言語、whileループを抜け出す...
-
PAD図の書き方
-
Cプログラムが終了しない
-
PIC のプログラムについて ど...
-
他言語で言うcontinue文
-
C言語のプログラムみてください...
-
ループの特定入力終了
-
COBOLのEVALUATE文
-
for文while文の無限ループの違...
おすすめ情報
beforekeyを定義しようしてるんですが、初期化されていませんとなります。
自分の知識不足だとは思いますが、
int beforekey を定義するのでは間違いなのでしょうか?