Create a buffer matrix for continuous measurements

后端 未结 4 1197
野趣味
野趣味 2020-12-06 14:56

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 w

相关标签:
4条回答
  • 2020-12-06 15:28

    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

    0 讨论(0)
  • 2020-12-06 15:37
    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.

    0 讨论(0)
  • 2020-12-06 15:41

    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)).

    0 讨论(0)
  • 2020-12-06 15:54
    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

    0 讨论(0)
提交回复
热议问题