Domanda

Sto iniziando a programmare in MATLAB e ho dei problemi con la creazione di una matrice buffer. Sto provando a fare quanto segue:

Ricevo continuamente un'immagine da una webcam e dopo la segmentazione ottengo il centroide di un bersaglio in movimento. Devo archiviare i dati del centroide per l'elaborazione ma non voglio che occupi troppa memoria. Ad esempio, se fossi un tempo t = inf , stavo pensando di memorizzare 10 punti temporali di dati in una matrice, come un buffer circolare, quindi scrivere e cancellare i dati più vecchi, perché ho bisogno di lavoro con entrambi, i dati effettivi nel tempo (t) e i dati precedenti nel tempo (t-1).

È stato utile?

Soluzione

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

Ho provato questo, non ci vuole tempo apprezzabile per funzionare in MATLAB. Il profiler non ha riscontrato colli di bottiglia con il codice.

Altri suggerimenti

UPDATE:

Dato che ora capisco che è necessario un buffer circolare per archiviare i dati, ecco una soluzione che è possibile utilizzare. Poiché hai detto che stavi memorizzando i dati del centroide degli oggetti in un'immagine, ti fornirò un caso generale per la memorizzazione di un numero arbitrario di misurazioni (o un valore di indice di 1 pixel per ciascun centroide o 2 valori per le coordinate xey, ecc.) ...

Innanzitutto, inizializza il 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

Successivamente, avrai il tuo ciclo continuo. Puoi utilizzare un while loop e una variabile flag che inizialmente ha il valore TRUE (e che tu può impostare su FALSE per interrompere il 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

Funziona nel modo seguente: in ogni momento, la prima colonna (ovvero i dati più vecchi) in centroidBuffer viene rimossa e una nuova colonna (cioè i nuovi dati) viene aggiunta alla fine . In questo modo, la matrice del buffer ha sempre le stesse dimensioni.

Se non si desidera eseguire l'elaborazione in ogni passaggio, ma solo dopo ogni nBuffer in modo che operi su un nuovo insieme di dati ogni volta, sostituire il sopra il codice con il seguente:

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

Modifica

Esistono diverse varianti che è possibile apportare con il codice sopra. Ad esempio, se si desidera archiviare due set di dati con 10 punti temporali ciascuno, è possibile modificare nBuffer su 20 per memorizzare il vecchio set nelle prime 10 colonne e il nuovo set nelle ultime 10 colonne . Quindi, modifica l'istruzione if in:

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

E ora puoi eseguire l'elaborazione utilizzando sia il set precedente di 10 punti dati (in centroidBuffer (:, 1:10) ) sia il set più recente di 10 punti dati (in centroidBuffer. (:, 11:20) )

Quando si parla di set di dati di grandi dimensioni su ogni iterazione, la riproduzione casuale dei dati può iniziare a richiedere del tempo. Il modo in cui lo gestisco per set di dati di grandi dimensioni è utilizzare qualcosa del tipo:

circBuff (:,:, mod (counter, numFrames)) = newData; In questo modo si sovrascrivono i dati una sola volta, anziché spostare ogni punto di dati nell'intero buffer su ogni ciclo. Devi solo essere un po 'più esperto su come accedere ai tuoi dati.

HTH, Dan

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

Questa è una soluzione piacevole e semplice, ma è lenta. Ogni volta che aggiungi un nuovo vettore, matlab deve copiare tutti i vecchi dati tranne la prima voce. Se pensi al tempo reale, questa non è una buona idea.

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

Questa idea non ha il problema della copia, ma ora non hai più un buon subarray, che rappresenta dal primo indice all'ultimo indice i dati in ordine cronologico.

Ho appena caricato la mia soluzione per un buffer circolare veloce che evita i due problemi

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

L'idea principale di questo buffer circolare è la prestazione costante e veloce ed evitare le operazioni di copia quando si utilizza il buffer in un programma:

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

Controlla lo screenshot per vedere che questo buffer circolare ha dei vantaggi se il buffer è grande, ma la dimensione dei dati da aggiungere ogni volta è piccola poiché le prestazioni di circVBuf NON dipendono dalle dimensioni del buffer, rispetto a una semplice copia tampone.

Il doppio buffering garantisce un tempo predittivo per un'appendice a seconda dei dati da aggiungere in qualsiasi situazione. In futuro questa classe ti darà una scelta per il doppio buffering sì o no - le cose accelereranno se non hai bisogno del tempo garantito. inserisci qui la descrizione dell'immagine

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top