Pregunta

Estoy empezando a programar en MATLAB y tengo algunos problemas para crear una matriz de búfer. Estoy tratando de hacer lo siguiente:

Obtengo continuamente una imagen de una cámara web y, después de la segmentación, obtengo el centroide de un objetivo en movimiento. Necesito almacenar los datos del centroide para procesar, pero no quiero que ocupen demasiada memoria. Por ejemplo, si era un t = inf de un tiempo, estaba pensando en almacenar 10 puntos de tiempo de datos en una matriz, como un búfer circular, luego escribir y borrar los datos más antiguos, porque necesito trabajar con ambos, los datos reales en el tiempo (t) y los datos anteriores en el tiempo (t-1).

¿Fue útil?

Solución

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

He probado esto, no lleva un tiempo apreciable ejecutarlo en MATLAB. El generador de perfiles no encontró ningún cuello de botella con el código.

Otros consejos

ACTUALIZAR:

Como ahora entiendo que necesita un búfer circular para almacenar datos, aquí hay una solución que puede usar. Como dijo que estaba almacenando datos de centroides de objetos en una imagen, le daré un caso general para almacenar un número arbitrario de mediciones (ya sea un valor de índice de 1 píxel para cada centroide, o 2 valores para las coordenadas x e y, etc.) ...

Primero, inicialice el búfer:

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

A continuación, tendrá su bucle continuo. Puede usar un while loop y una variable de marca que inicialmente tiene el valor TRUE (y que puede configurarlo en FALSE para detener el ciclo):

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

Esto funciona de la siguiente manera: en cada punto de tiempo, la primera columna (es decir, los datos más antiguos) en centroidBuffer se elimina y se agrega una nueva columna (es decir, los nuevos datos) al final . De esta manera, la matriz del búfer es siempre del mismo tamaño.

Si no desea realizar su procesamiento en cada paso de tiempo, sino solo después de cada nBuffer puntos de tiempo para que esté operando en un nuevo conjunto de datos cada vez, entonces reemplace código anterior con lo siguiente:

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:

Hay una serie de variaciones que puedes hacer con el código anterior. Por ejemplo, si desea almacenar dos conjuntos de datos con 10 puntos de tiempo cada uno, puede cambiar nBuffer a 20 para almacenar el conjunto anterior en las primeras 10 columnas y el nuevo conjunto en las últimas 10 columnas . Luego, cambie la instrucción if a:

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

Y ahora puede realizar su procesamiento utilizando el conjunto más antiguo de 10 puntos de datos (en centroidBuffer (:, 1:10) ) y el conjunto más reciente de 10 puntos de datos (en centroidBuffer (:, 11:20) ).

Cuando se habla de grandes conjuntos de datos en cada iteración, la mezcla de datos puede comenzar a tomar algún tiempo. La forma en que lo manejo para grandes conjuntos de datos es usar algo como:

circBuff (:,:, mod (counter, numFrames)) = newData; De esta manera, solo sobrescribe los datos una vez, en lugar de mover cada punto de datos en todo el búfer en cada ciclo. Solo tiene que ser un poco más inteligente sobre cómo acceder a sus datos.

HTH, Dan

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

Esta es una solución agradable y simple, pero es lenta. Cada vez que agrega un nuevo vector, matlab tiene que copiar todos los datos antiguos, excepto la primera entrada. Si piensas en tiempo real, no es una buena idea.

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

Esta idea no tiene el problema de copia, pero ahora ya no tiene un subarreglo agradable, que representa desde el primer índice hasta el último índice los datos en orden cronológico.

Acabo de cargar mi solución para un búfer circular rápido que evita los dos problemas

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

La idea principal de este búfer circular es un rendimiento constante y rápido. y evitar operaciones de copia cuando se utiliza el búfer en un programa:

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

Verifique la captura de pantalla para ver, que este búfer circular tiene ventajas si el búfer es grande, pero el tamaño de los datos a adjuntar es pequeño ya que el rendimiento de circVBuf NO depende del tamaño del búfer, en comparación con una copia simple búfer.

El búfer doble garantiza un tiempo predictivo para un agregado en función de los datos a agregar en cualquier situación. En el futuro, esta clase le dará una opción para el búfer doble sí o no: las cosas se acelerarán, si no necesita el tiempo garantizado. ingrese la descripción de la imagen aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top