3

MATLAB でプログラミングを開始していますが、バッファー マトリックスの作成に問題があります。私は次のことをしようとしています:

私は継続的にウェブカメラから画像を取得しており、セグメンテーションの後、移動するターゲットの重心を取得しています。処理のために重心データを保存する必要がありますが、メモリを占有しすぎないようにします。たとえば、私が time だった場合t=inf、データの 10 時点のデータを循環バッファーのようなマトリックスに保存し、古いデータを書き込んで消去することを考えていました。これは、時間内の実際のデータ (t ) と時間内の前のデータ (t-1)。

4

4 に答える 4

7
buffSize = 10;
circBuff = nan(1,buffSize);
for newest = 1:1000;
    circBuff = [newest circBuff(1:end-1)]
end

私はこれをテストしました。MATLABで実行するのにそれほど時間はかかりません。プロファイラーは、コードのボトルネックを検出しませんでした。

于 2009-05-05T15:57:26.767 に答える
2

反復ごとに大きなデータセットについて話している場合、データシャッフルに時間がかかることがあります。大規模なデータセットに対して私がそれを処理する方法は、次のようなものを使用することです。

circBuff(:、:、mod(counter、numFrames))= newData; このように、各サイクルでバッファ全体のすべてのデータポイントを移動するのではなく、データを1回だけ上書きします。データへのアクセス方法についてもう少し精通している必要があります。

HTH、ダン

于 2009-05-05T16:31:30.570 に答える
2

アップデート:

データを格納するには循環バッファーが必要であることを理解したので、使用できるソリューションを次に示します。オブジェクトの重心データを画像に保存していると言ったので、任意の数の測定値を保存する一般的なケースを示します (各重心に対して 1 つのピクセル インデックス値、または x 座標と y 座標に対して 2 つの値など)。 ...

まず、バッファを初期化します。

nBuffer = 10;  % You can set this to whatever number of time points
               %   you want to store data for
nSamples = 2;  % You can set this to the number of data values you
               %   need for each point in time
centroidBuffer = zeros(nSamples,nBuffer);  % Initialize the buffer to zeroes

次に、連続ループを作成します。while ループと、初期値がTRUEのフラグ変数を使用できます(ループを停止するためにFALSEに設定できます)。

keepLooping = true;
while keepLooping,
  % Capture your image
  % Compute the centroid data and place it in the vector "centroidData"
  centroidBuffer = [centroidBuffer(:,2:end) centroidData(:)];
  % Do whatever processing you want to do on centroidBuffer
  % Choose to set keepLooping to false, if you want
end

これは次のように機能します。各時点で、centroidBufferの最初の列 (つまり、最も古いデータ)が削除され、新しい列 (つまり、新しいデータ) が末尾に追加されます。このように、バッファ行列は常に同じサイズです。

すべてのタイム ステップで処理を実行するのではなく、毎回新しいデータ セットで動作するようにnBuffer時点ごとにのみ処理を実行する場合は、上記のコードを次のように置き換えます。

keepLooping = true;
processTime = 0;
while keepLooping,
  % Capture your image
  % Compute the centroid data and place it in the vector "centroidData"
  centroidBuffer = [centroidBuffer(:,2:end) centroidData(:)];
  processTime = processTime+1;
  if (processTime == nBuffer),
    % Do whatever processing you want to do on centroidBuffer
    processTime = 0;
  end
  % Choose to set keepLooping to false, if you want
end

編集:

上記のコードを使用して、さまざまなバリエーションを作成できます。たとえば、それぞれ 10 時点の 2 つのデータ セットを格納する場合、nBufferを 20 に変更して、最初の 10 列に古いセットを格納し、最後の 10 列に新しいセットを格納できます。次に、if ステートメントを次のように変更します。

  ...
  if (processTime == nBuffer/2),
  ...

これで、古い 10 個のデータ ポイントのセット ( centroidBuffer(:,1:10)内) と新しい 10 個のデータ ポイントのセット ( centroidBuffer(:,11:20)内)の両方を使用して処理を実行できます。

于 2009-05-04T20:00:45.240 に答える
1
centroidBuffer = [centroidBuffer(:,2:end) centroidData(:)];

これは素晴らしくシンプルなソリューションですが、遅いです。新しいベクトルを追加するたびに、matlab は最初のエントリを除く古いデータ全体をコピーする必要があります。リアルタイムを考えると、これは得策ではありません。

circBuff(:,:,mod(counter,numFrames)) = newData

このアイデアにはコピーの問題はありませんが、最初のインデックスから最後のインデックスまでのデータを時系列で表す素敵なサブ配列はもうありません。

2つの問題を回避する高速循環バッファのソリューションをアップロードしました

http://www.mathworks.com/matlabcentral/fileexchange/47025-circvbuf-m

この循環バッファーの主なアイデアは、プログラムでバッファーを使用するときに一定の高速パフォーマンスとコピー操作を回避することです。

% create a circular vector buffer
    bufferSz = 1000;
    vectorLen= 7;
    cvbuf = circVBuf(int64(bufferSz),int64(vectorLen));

% fill buffer with 99 vectors
    vecs = zeros(99,vectorLen,'double');
    cvbuf.append(vecs);

% loop over lastly appended vectors of the circVBuf:
    new = cvbuf.new;
    lst = cvbuf.lst;
    for ix=new:lst
       vec(:) = cvbuf.raw(:,ix);
    end

% or direct array operation on lastly appended vectors in the buffer (no copy => fast)
    new = cvbuf.new;
    lst = cvbuf.lst;
    mean = mean(cvbuf.raw(3:7,new:lst));

スクリーンショットを確認してください。バッファが大きい場合、この循環バッファには利点がありますが、単純なコピー バッファと比較して、circVBuf のパフォーマンスはバッファ サイズに依存しないため、毎回追加するデータのサイズは小さいことがわかります。

ダブルバッファリングは、どのような状況でも追加するデータに応じて、追加の予測時間を保証します。将来、このクラスは、ダブル バッファリングの yes または no を選択できるようになります。 ここに画像の説明を入力

于 2014-06-21T15:23:48.800 に答える