質問

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

ウェブカメラから画像を継続的に取得しています。セグメンテーション後、移動するターゲットの重心を取得しています。処理のために重心データを保存する必要がありますが、あまり多くのメモリを占有したくありません。たとえば、時間 t = inf の場合、10個のデータポイントを循環バッファーなどの行列に保存し、古いデータを書き込んで消去することを考えていました。時間(t)の実際のデータと時間(t-1)の前のデータの両方で。

役に立ちましたか?

解決

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

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

他のヒント

更新:

データを保存するには circular バッファが必要であることを理解したので、使用できるソリューションを次に示します。画像にオブジェクトの重心データを保存すると言ったので、任意の数の測定値(各重心に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))。

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

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

HTH、 ダン

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のダブルバッファリングの選択肢を提供します-保証された時間を必要としない場合は、速度が向上します。 ここに画像の説明を入力

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top