2016-05-26 10 views
1

私は、通常100 HZまたは10 msのスキャン時間を実行し、時間が重要なタスクを実行しているシステムを持っています。私はopencvでカメラを追加しようとしています(ユーザーがシステムとやりとりした時に応じて、10秒から数分の間でどこにでも入ることができます)、品質管理のために画像をキャプチャします。ここ は私のコードがやっていることです。カメラフレームのキャプチャ

int main(int, char**) 
{ 
    VideoCapture cap(0); // open the default camera 
    if(!cap.isOpened()) // check if we succeeded 
     return -1; 

    UMat frame; 
    for(;;){ 
     if (timing_variable_100Hz){ 
      cap >> frame; // get a new frame from camera 

      *Do something time critical* 
      if(some_criteria_is_met){ 
       if(!frame.empty()) imwrite("Image.jpg", frame); 
      } 
     } 
    } 
    return 0; 
} 

今私がいる問題がcap >> frameは、多くの時間を要することです。

スキャン時間は定期的に3msぐらいですが、現在は40msです。今私の質問は、とにかくカメラを開いて、キャプチャし、その後、すべてのフレームをキャプチャする必要はないですか?私はif(some_criteria_is_met)の中でcap >> frameを動かして、最初の画像を正しく取り込めましたが、数分後に撮られた2番目の画像は、最初の取り込まれた画像を1フレーム過ぎていました。

おかげ

+0

あなたは[グラブ](HTTPを見ませんでした。 opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=videocapture#videocapture-grab)と[retrieve](http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html)を参照してください。 ?ハイライト= videocapture#videocapture-retrieve)関数?ドキュメントからは、あなたが探しているものだけであるようです。 – AldurDisciple

+0

私はこれを試してみましたが、vcap >> frame vs vcap、grab()を使用した場合、大きな違いは見られませんでした。彼らは両方とも完了するのに約32ミリ秒かかりました。多分グラブ()は1ミリ秒か2秒かかりました。 これは面白いのですが、データシートにはretrieve()が遅いメソッドであることが記載されていますが、私のテストではそうでないことが示されています。 –

+0

私はスレッドの答えに同意します –

答えて

2

問題は、カメラのフレームレートが100fps未満、おそらく30fps(測定した32msに相当)であるため、新しいフレームが利用可能になるのを待つことです。

opencvでブロックされていない読み込みを行う方法はないので、私はあなたの最善の選択肢は別のスレッドでビデオを取得することだと思います。

このような何か、あなたが使用している場合、C++ 11(これは、わからないことは全く正しい例です)://ドキュメント:

void camera_loop(std::atomic<bool> &capture, std::atomic<bool> &stop) 
{ 
    VideoCapture cap(0); 
    Mat frame; 
    while(!stop) 
    { 
     cap.grab(); 
     if(capture) 
     { 
      cap.retrieve(frame); 
      // do whatever you do with the frame 
      capture=false; 
     } 
    } 
} 

int main() 
{ 
    std::atomic<bool> capture=false, stop=false; 
    std::thread camera_thread(camera_loop, std::ref(capture), std::ref(stop)); 
    for(;;) 
    { 
     // do something time critical 
     if(some_criteria_is_met) 
     { 
      capture=true; 
     } 
    } 
    stop=true; 
    camera_thread.join(); 
} 
1

それはare there anyway to open the camera, capture, then not have to capture every frame after until I have to?のあなたの質問に答えていませんが、提案

あなたがしようとするとフレームだけをキャプチャするための責任があるバックグラウンドスレッドでcap >> frameを持つことができます。

フレームがメモリに格納されたら、それをメインスレッドからアクセスする共有サイクリックキューにプッシュします。

+0

ええ、あなたの答えは理にかなっています。私はこれを実装します。ありがとう –

関連する問題