Criar uma matriz de tampão para medições contínuas
Pergunta
Estou começando a programação em MATLAB e tenho alguns problemas criando uma matriz de buffer. Eu estou tentando fazer o seguinte:
Eu estou obtendo continuamente uma imagem de uma webcam e depois de segmentação I obter o centróide de um alvo em movimento. Eu preciso armazenar os dados centróide para processamento, mas eu não quero que ocupam muita memória. Por exemplo, se eu fosse um t=inf
tempo, eu estava pensando de armazenar 10 pontos temporais de dados em uma matriz, como um buffer circular, em seguida, escrever e apagar os dados mais velhos, porque eu preciso trabalhar com ambos, os dados reais no tempo ( t) e um conjunto de dados anterior no tempo (t-1).
Solução
buffSize = 10;
circBuff = nan(1,buffSize);
for newest = 1:1000;
circBuff = [newest circBuff(1:end-1)]
end
Eu testei isso, não tem tempo apreciável para ser executado no MATLAB. O profiler não encontrou os gargalos com o código.
Outras dicas
UPDATE:
Uma vez que agora eu entendo que você precisa de um circular de buffer para armazenar dados, aqui está uma solução que você pode usar. Desde que disse que foram armazenar dados centróide de objectos numa imagem, que vai dar-lhe um processo geral para o armazenamento de um número arbitrário de medições (quer um valor de índice de pixel para cada centróide, ou 2 valores de coordenadas x e y, etc) ...
Em primeiro lugar, inicializar o 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
Em seguida, você vai ter o seu ciclo contínuo. Você pode usar um enquanto loop e uma variável de sinalizador que inicialmente tem o valor VERDADEIRO (e que você pode definir a FALSE para parar o 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
Isso funciona da seguinte forma: em cada ponto de tempo, a primeira coluna (ou seja, os dados anteriores) em
Se você não quiser realizar o processamento em cada passo de tempo, mas em vez disso só depois de todos os nBuffer pontos tempo para que ele está operando em um novo conjunto de dados de cada vez, em seguida, substituir o acima de código com o seguinte:
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:
Há uma série de variações que você pode fazer com o código acima. Por exemplo, se você deseja armazenar dois conjuntos de dados com 10 pontos no tempo cada um, você pode mudar nBuffer a 20 para armazenar o antigo conjunto nos primeiros 10 colunas e o novo conjunto nos últimos 10 colunas . Em seguida, altere a declaração se a:
...
if (processTime == nBuffer/2),
...
E agora você pode realizar o seu processamento usando tanto o conjunto mais antigo de 10 pontos de dados (em centroidBuffer (:, 1:10) ) e o conjunto mais recente de 10 pontos de dados (em centroidBuffer (:, 11:20). )
Quando você está falando de grandes conjuntos de dados em cada iteração, o shuffle de dados pode começar a tomar um pouco de tempo. A maneira que eu lidar com isso para grandes conjuntos de dados é usar algo como:
circBuff (:,:, modificação (contador, numFrames)) = newData; Desta forma, você apenas os dados de substituição uma vez, ao invés de mover todos os pontos de dados em todo o seu tampão em cada ciclo. Você apenas tem que ser um pouco mais esclarecido sobre como você acessar seus dados.
HTH, Dan
centroidBuffer = [centroidBuffer(:,2:end) centroidData(:)];
Esta é uma solução agradável e simples, mas é lento. Toda vez que você adicionar um novo vetor, Matlab tem que copiar os dados inteiros de idade, exceto a primeira entrada. Se você pensar em tempo real, isso não é uma boa idéia.
circBuff(:,:,mod(counter,numFrames)) = newData
Esta ideia não tem a cópia de problemas, mas agora você não tem uma boa subarray mais, o que representa desde o primeiro índice para o último índice os dados em ordem cronológica.
I acabou de enviar minha solução para um buffer rápido circular que evita os dois problemas para
http://www.mathworks.com/matlabcentral/fileexchange/47025 -circvbuf-m
A idéia principal deste buffer circular é constante e rápido desempenho e evitando operações de cópia ao usar o tampão em um 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 a tela para ver, que este buffer circular tem vantagens se o buffer é grande, mas o tamanho dos dados para acrescentar cada vez é pequeno como o desempenho de circVBuf não depende do tamanho do buffer, em comparação com uma cópia simples tampão.
O buffer duplo Garanties um tempo previsível para um acréscimo acordo com os dados para anexar em qualquer situação. No futuro, esta classe deve dar-lhe uma escolha para sim buffer duplo ou não - as coisas vão speedup, se você não precisa o tempo garantied.