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