1

以下のコードを使用して、カメラから各フレームを読み取り、それをベクトルにプッシュします。後でベクター内の収集されたすべてのフレームを処理するためにこれを行っています。

以下のコードを使用して、カメラからフレームを収集しました。しかし、2005 フレームの後、コードは以下のエラーをスローします。

OpenCV エラー: OutOfMemoryError、ファイル D:\Opencv\modules\core\src\alloc.cpp、行 52 のメモリ不足 (921604 バイトの割り当てに失敗)

以下は、フレームを収集してベクターにプッシュするために使用したコードです。

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/contrib/contrib.hpp"

#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <stdlib.h>

 using namespace std;
 using namespace cv; 


 int main()
 {     

     VideoCapture capture(0); 
     if(!capture.isOpened()) 
         return -1; 
     vector <Mat>  frame;       
     int delay = 10;  
         int count = 0;

                Mat src;     

                while(true) { 
                    capture >> src;                                     
                    frame.push_back(src.clone());                                                            

                    imshow("VIDEO", src);
                    if( waitKey( delay ) >= 0) break; 
                    count = count+1;
                    cout << count << endl;
                } 


                /* I need to process each frame stored inside the vector*/

      destroyWindow("VIDEO");
      capture.release();

   return 0;
 }
4

3 に答える 3

5

エラーが示唆するように、おそらくメモリが不足しています。各フレームが 640*480 (つまり非常に低い解像度) の場合、2005 * 640 * 480 * 3 (ピクセルあたりのバイト数) = 1,847,808,000 (つまり、1.8GB の RAM が連続したブロックに割り当てられます)。

同様に、ベクトルのサイズを変更する必要があるたびに、新しいデータを保持するのに十分な大きさの割り当てを作成し、古いデータを新しいベクトルにコピーしてから、古い割り当てを解放し、必要なメモリ量を効果的に 2 倍にする必要があります。

于 2013-05-07T13:05:49.477 に答える
2

エラーが示すように、プログラムは、オペレーティング システムによってプロセス用に予約されている RAM の制限に達しました。この問題を軽減するために、いくつかのことを行うことができます。

1 -画像を.jpg などのよりコンパクトな形式にエンコードします。これにより、フレームで使用されるメモリが削減されます。

2 -バッファーをディスクに保存します。これはおそらく遅く、フレーム レートを下げたくないため、おそらくプロデューサー/コンシューマー スキームで新しいスレッドを使用する必要があります。

3 - 画像の解像度を下げます。特定のユースケースはわかりませんが、縮小された画像は多くのコンピュータービジョンアルゴリズムに適しています。すべての色情報を保存する必要はありません。

4 - 画像の興味深い点だけを保存する: これは、コンピューター ビジョン コミュニティでは非常に一般的なアプローチです。繰り返しますが、あなたが何を達成しようとしているのかわかりませんが、フレームごとに画像を前処理して、関連するポイントだけを保存することはできますか? フレームレートをリアルタイムで維持するために、前処理アルゴリズムの GPU 実装が必要になる場合があります。

フレームごとに保存するメモリの量を大幅に減らしても、最終的にはメモリ不足になることに注意してください。ディスクに情報を保存しなくても、これはほぼ確実です。

于 2013-05-07T13:14:24.443 に答える
2

生のフレームサイズは巨大です。通常、カメラ ソースのジッタの量に応じて、少なくとも 2 フレーム、たとえば 4 フレーム未満を事前に割り当てる必要があります。マルチメディア システムは、常にメモリを事前に割り当てます。

したがって、通常はそうする必要があります..

for(int i=0; i<NUM_FRAMES; i++
    frames.push_back(new Mat()); //handle exceptions from new.

フレームを使ってリサイクル

int i=0;
int curr_frame=i;

while(true) { 
   capture >> *(frames[i]); 

   //show frame

   i = (i+1)%NUM_FRAMES;

   //process frames[curr_frame]..
}

実際には、できれば別のスレッドで、その場で処理を行う必要があります。したがって、処理時間はカメラのキャプチャ レートとほぼ一致する必要があります。つまり、特定のフレームをまだ処理していないにもかかわらず、カメラによって上書きされるということはありません。ビデオ エンコーダーなど、アルゴリズムの処理時間が変動する場合は、ジッター バッファーが役立ちます。十分な数のバッファー (NUM_FRAMES) があるため、エンコーダーは追いつくことができます。

于 2013-05-07T13:24:10.167 に答える