Question

I'm starting programming in MATLAB and I have some problems creating a buffer matrix. I'm trying to do the following:

I'm continuously obtaining an image from a webcam and after segmentation I obtain the centroid of a moving target. I need to store the centroid data for processing but I don't want it to occupy too much memory. For example, if I was a time t=inf, I was thinking of storing 10 time points of data in a matrix, like a circular buffer, then writing and erasing the older data, because I need work with both, the actual data in time (t) and a previous data in time (t-1).

Was it helpful?

Solution

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

I have tested this, it takes no appreciable time to run in MATLAB. The profiler did not find any bottlenecks with the code.

OTHER TIPS

UPDATE:

Since I now understand that you need a circular buffer to store data, here's a solution you can use. Since you said you were storing centroid data of objects in an image, I will give you a general case for storing an arbitrary number of measurements (either 1 pixel index value for each centroid, or 2 values for x and y coordinates, etc.)...

First, initialize the buffer:

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

Next, you will have your continuous loop. You can use a while loop and a flag variable that initially has the value TRUE (and which you can set to FALSE to stop the loop):

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

This works in the following way: at each time point, the first column (i.e. the oldest data) in centroidBuffer is removed and a new column (i.e. the new data) is appended to the end. In this way, the buffer matrix is always the same size.

If you don't want to perform your processing at every time step, but instead only after every nBuffer time points so that it is operating on a new set of data each time, then replace the above code with the following:

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

EDIT:

There are a number of variations you can make with the above code. For example, if you want to store two sets of data with 10 time points each, you can change nBuffer to 20 to store the old set in the first 10 columns and the new set in the last 10 columns. Then, change the if statement to:

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

And now you can perform your processing using both the older set of 10 data points (in centroidBuffer(:,1:10)) and the newer set of 10 data points (in centroidBuffer(:,11:20)).

When you're talking about large data sets on each iteration, the data shuffle can start taking up some time. The way I handle it for large data sets is to use something like:

circBuff(:,:,mod(counter,numFrames)) = newData; This way you only overwrite data once, rather than moving every data point in your entire buffer on each cycle. You just have to be a bit more savvy about how you access your data.

HTH, Dan

centroidBuffer = [centroidBuffer(:,2:end) centroidData(:)];

This is a nice and simple solution, but it is slow. Every time you add a new vector, matlab has to copy the whole old data except the first entry. If you think about real-time, this is not a good idea.

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

This idea does not have the copy-problem, but now you do not have a nice subarray any more, which represents from the first index to the last index the data in chronological order.

I just uploaded my solution for a fast circular buffer which avoids the two problems to

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

The main idea of this circular buffer is constant and fast performance and avoiding copy operations when using the buffer in a program:

% 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));

Check the screenshot to see, that this circular buffer has advantages if the buffer is large, but the size of data to append each time is small as the performance of circVBuf does NOT depend on the buffer size, compared to a simple copy buffer.

The double buffering garanties a predictive time for an append depending on the data to append in any situation. In future this class shall give you a choice for double buffering yes or no - things will speedup, if you do not need the garantied time. enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top