我开始在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中运行没有多少时间。分析器没有找到代码的任何瓶颈。

其他提示

<强>更新

由于我现在明白你需要一个循环缓冲区来存储数据,这里有一个你可以使用的解决方案。既然你说你在图像中存储了物体的质心数据,我将给你一个存储任意数量测量值的一般情况(每个质心的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个时间点,则可以将 nBuffer 更改为20,以将旧集合存储在前10列中,将新集合存储在最后10列中。然后,将if语句更改为:

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

现在,您可以使用较旧的10个数据点(在 centroidBuffer(:,1:10))和较新的10个数据点(在中)执行处理centroidBuffer(:,11:20)

当您在每次迭代中讨论大型数据集时,数据随机播放可能会占用一些时间。我为大型数据集处理它的方法是使用类似的东西:

circBuff(:,:,mod(counter,numFrames))= newData; 这样,您只需覆盖一次数据,而不是在每个循环中移动整个缓冲区中的每个数据点。您只需要更加了解如何访问数据。

HTH, 丹

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

这是一个很好而简单的解决方案,但速度很慢。每次添加新向量时,matlab都必须复制除第一个条目之外的所有旧数据。如果你考虑实时,这不是一个好主意。

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

这个想法没有复制问题,但现在你不再有一个好的子阵列,它从时间顺序表示从第一个索引到最后一个索引的数据。

我刚刚上传了我的解决方案,用于快速循环缓冲区,避免了两个问题

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

这种循环缓冲区的主要思想是持续快速的性能 在程序中使用缓冲区时避免复制操作:

% 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的性能不依赖于缓冲区大小,与简单的副本相比缓冲液中。

双缓冲可以根据要在任何情况下附加的数据来确定追加的预测时间。将来这个课程会给你一个双重缓冲的选择是或否 - 如果你不需要保证时间,事情就会加速。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top