2016-06-01 7 views
-1

顔のデータセットを作成したい。だから私は60 fpsのWindows用のkinectの色/深度/赤外線とその他のデータを取得し、それらをハードディスクに保存するグラバープログラム(Visual C++)を書いています。それは私が秒に10フレーム以上を保存することはできませんので、多くの時間がかかり、多くのフレームが落とされます。私はfileStorage(opencv)を使ってyamlのデータを保存しようとしていますが、それも遅いです。私は2つのスレッドを使用することについて考えています.1つはデータを取得するため、もう1つは保存することです。 2つの独立したスレッド間のデータ通信が主な問題です。 フレームを失うことなくデータを保存する最適なソリューションは何ですか?ハードディスクにFast kinectデータを書き込む

+1

が必要な帯域幅(60fpsの* sizeOfAFrame)を計算し、帯域幅を書き、ハードウェアと比較します。理論的にすべてのフレームを書き込むことができる場合は、キャッシュしてから別のスレッドから書き込んで最適化することができます。いくつかの遅延が数秒後に発生したファイルシステムを見てきましたが、これはマルチスレッドで修正されました。 fileStorageでの書き出しは、おそらくデータサイズが大幅に増加し、フォーマット/変換に時間がかかるため、生データを書き込むよりもはるかに時間がかかります。 – Micka

+0

OP:60FPSは確実ですか? 1920x1080のRGB画像は6075 KiB、16ビットの奥行き、512x424のIRは424 KiBです.30 Hzでフレームあたり6923 KiBを超えると、〜203 MiB/sが得られます。 Mickaの言うとおり、ハードウェアによって異なります。生データを確実に書き込む必要があります。これは、リアルタイムに近い場所で圧縮することはできません(少なくともCPUのみではない)。いくつかのコードを表示し、HWと実際にどれくらい保存したいかを詳細に説明します(1つの連続したフレームシーケンスの時間的長さ)。 –

答えて

-1

感謝を読み取ることができます。 私は、共有メモリ(キュー)とmutexという2つのスレッドを定義することでこの問題を解決します。

//I have a passenger class that store all data including images in it 
#include "passenger.h" 
//I define a queue from passenger class 
queue<passenger> passengerQueue; 
//and a mutex 
std::mutex myMutex; 
void GrabberThreadFunc() 
{ 
    //get the data and store it in a passenger object 
    if (nearPassenger.valid) 
    { 
     std::lock_guard<std::mutex> guard(myMutex); 
     passengerQueue.push(nearPassenger); 
    } 
} 
void SavetThreadFunc() 
{ 
    if (!passengerQueue.empty()) 
    { 
     std::lock_guard<std::mutex> guard(myMutex); 
     passengerQueue.front().SaveData(); 
     passengerQueue.pop(); 
    } 
} 

のint _tmain(int型のargc、_TCHAR * ARGV []) {

thread GrabberThread(GrabberThreadFunc); 
thread SaverThread(SaverThreadFunc); 

if (GrabberThread.joinable()) 
    GrabberThread.join(); 

if (SaverThread.joinable()) 
    SaverThread.join(); 

return 0; 

}

+0

R.y.z、あなたのソリューションを共有できますか? – Geucimar

-1

mmap()でメモリに60以上のフレームをキャッシュし、ファイルを保存するためにsendfileを使用します。もちろん、キャッシュと保存の間には何らかの同期が必要です。

定義済みの要素数が600(60 * number_of_sec_which_are_cached)であるvector<JOB>を使用しているとします。

struct JOB 
{ 
    int second_number; //second related to time 
    int frame_number; //frame number in second specified by "JOB::second_number" 
    unsigned char *buf; //frame buffer 
    unsigned int buf_length; //number of bytes in frame which would be a fixed number. 
    int valid; 
}; 

グラバーは、フレームをフェッチするときにJOB::valid = 1になります。

FileSavingThreadは、JOB::valid==1と保存後にフレームが保存可能かどうかを確認するためにを使用して、JOB::valid=0となります。

JOB::validAtomic operations libraryを使用すると、簡単に同期のためのmutexを回避できます。

次に、グラバーはベクトル内の要素(すべての要素を調べることによって)を見つけ、JOB::valid==0とし、その特定の要素にフレームを格納する必要があります。

同様に、FileSavingThreadはベクトル内でJOB::valid==1の要素を見つけ、その要素で指定されたフレームをファイルに保存する必要があります。

パフォーマンスに応じて、ベクトルの要素の数を増やしたり、FileSavingThreadの数を増やしたり、その両方を増やしたりすることができます。

//-------------------------------------------------------------------------

  • 新しい方法2:メモリマップされている既存のファイルを使用して
  • 参考:ここでMemory Mapped File

、我々は我々が手やメモリマップする前に、そのくらいのサイズのファイルを作成することができます保存するフレーム数やどのくらいの時間を秒数に対応したデータを知っていればそのファイル。次に、フレームを保存することは、連続した方法でメモリに書き込むのと同じくらい簡単です。キャッシングとI/Oは、最適な方法でOSによって自動的に管理されます。

これは、計算に含まれるすべてのパラメータw.r.tフレームが固定されているために可能です。

フレームの読み込みは、保存されたファイルをメモリマッピングすることによっても行うことができます。単一のフレームが再び必要とされる場合、特定のフレームのオフセットを計算するのに必要なすべてのパラメータが固定されるので、保存されたファイルの開始からのオフセットの計算は容易に計算できます。

は今の利点は、このような方法で、読み取り/書き込みにあるものをすべてのあなたの助けのためにここにWhat Do Memory-Mapped Files Have to Offer?

+1

残念ながら、 'std :: vector'にmutexが必要です。ベクトルのメンバ上のアトミックライブラリを使用すると助けになりません。 Grabberがベクトルにジョブを追加すると、既存のすべてのジョブとそれらのアトミック変数を**移動する**再割り当てが行われる可能性があります。したがって、FileSavingThreadはベクトルを読み込み中にロックする必要があります。 – MSalters

+0

Visual StudioはWindowsを意味します - Windowsには 'senfile()'はありません。メモリマッピングは 'mmap()'ではなく、別のAPIも使用します。 mmapの使用法について詳しく説明する必要があります(匿名の共有メモリを使用しているようですが、明らかではありません)。同期は些細な問題ではなく、少なくともいくつかの擬似コードを持つ具体的な例や、関連する回答への参照が役立つでしょう。一般的な考え方は悪くありませんが、答えはより詳細になる可能性があります。 –

+0

@MSalters:答えを慎重に読んでいれば、「要素数があらかじめ定義されたベクトル」という行が見つかります。したがって、再割り当ての機会がなく、ロックを必要とする新しい要素をベクトルに追加することさえありません。私がすでにあなたが言及した問題については、あんたのことを言った。また、Grabberは 'JOB :: valid = 1'を' JOB :: buf'に記入した後、FileSavingThreadが 'JOB:valid == 0'を見つけるまで行います。そして、原子操作(TestAndSet())は 'JOB:valid'をセットするために使用されるので、実際には同期のためにロックする必要はありません。 – sameerkn

関連する問題