Sunday 15 October 2017

Moving Average Filter Cpp


É possível implementar uma média móvel em C sem a necessidade de uma janela de amostras Ive descobri que eu posso otimizar um pouco, escolhendo um tamanho de janela thats um poder de dois para permitir bit-shifting em vez de dividir, mas não necessitando Um buffer seria bom. Existe uma maneira de expressar um novo resultado da média móvel apenas como uma função do antigo resultado e da nova amostra Definir um exemplo de média móvel, através de uma janela de 4 amostras para ser: Adicionar nova amostra e: Uma média móvel pode ser implementada recursivamente , Mas para um cálculo exato da média móvel você deve se lembrar da amostra de entrada mais antiga na soma (ou seja, o a no seu exemplo). Para um comprimento N média móvel você calcula: onde yn é o sinal de saída e xn é o sinal de entrada. Eq. (1) pode ser escrito recursivamente como Então você sempre precisa lembrar a amostra xn-N para calcular (2). Como indicado por Conrad Turner, você pode usar uma janela exponencial (infinitamente longa), que permite calcular a saída somente da saída anterior e da entrada atual: mas esta não é uma média móvel padrão (não ponderada), mas uma média exponencial Ponderada média móvel, onde as amostras mais no passado obter um peso menor, mas (pelo menos em teoria) você nunca esquecer nada (os pesos apenas ficar menor e menor para amostras no passado). Inicialize total 0, count0 (cada vez que vê um novo valor) Então uma entrada (scanf), uma add totalnewValue, um incremento (count), uma divide average (total / count) Esta seria uma média móvel sobre todas as entradas Para calcular a média Sobre apenas as 4 últimas entradas, exigiria 4 variáveis ​​de entrada, talvez copiando cada entrada para uma variável de entrada mais antiga, calculando a nova média móvel como a soma das 4 variáveis ​​de entrada, dividida por 4 (desvio para a direita 2 seria bom se todas as entradas fossem Positivo para fazer o cálculo médioIm codificação algo no momento em que Im tendo um monte de valores ao longo do tempo de uma bússola de hardware. Esta bússola é muito preciso e atualizações com muita freqüência, com o resultado que, se ele jiggles ligeiramente, eu acabar com o estranho Valor thats descontroladamente inconsistente com seus vizinhos. Eu quero suavizar esses valores. Ter feito alguma leitura ao redor, parece que o que eu quero é um filtro passa-alta, um filtro passa-baixa ou uma média móvel. Em média móvel eu posso Ficar com, basta manter um histórico dos últimos 5 valores ou qualquer outra coisa, e usar a média desses valores a jusante no meu código onde eu estava uma vez apenas usando o valor mais recente. Isso deve, eu acho, suavizar esses jiggles muito bem, mas parece-me que o seu provavelmente bastante ineficiente, e este é provavelmente um daqueles Problemas Conhecidos aos Programadores Adequados para que theres uma solução de Matemática Inteligente realmente limpa. Eu sou, entretanto, um daqueles programadores self-taught terríveis sem um pedaço da instrução formal em qualquer coisa vagamente relacionado a CompSci ou à matemática. Ler em torno de um pouco sugere que este pode ser um filtro de alta ou baixa passagem, mas eu não consigo encontrar nada que explique em termos compreensíveis para um hack como eu o que o efeito desses algoritmos seria sobre uma matriz de valores, muito menos como a matemática Funciona. A resposta dada aqui. Por exemplo, tecnicamente responde à minha pergunta, mas apenas em termos compreensíveis para aqueles que provavelmente já sabem como resolver o problema. Seria uma pessoa muito linda e inteligente quem poderia explicar o tipo de problema que isso é, e como as soluções funcionam, em termos compreensíveis para um graduado em Artes. Se a sua média móvel tem que ser longa, a fim de alcançar a suavização necessária, e você realmente não precisa de qualquer forma especial de kernel, então você está melhor se você usar uma média móvel exponencial decadência: onde você Escolha minúscula para ser uma constante apropriada (por exemplo, se você escolher minúsculo 1- 1 / N, ele terá a mesma quantidade de média como uma janela de tamanho N, mas distribuídos de forma diferente sobre pontos mais antigos). Enfim, uma vez que o próximo valor da média móvel depende apenas do anterior e seus dados, você não tem que manter uma fila ou qualquer coisa. E você pode pensar nisso como fazendo algo como, Bem, eu tenho um novo ponto, mas eu realmente não confio, então eu vou manter 80 da minha antiga estimativa da medição, e só confiar neste novo ponto de dados 20. Isso é Praticamente o mesmo que dizer, Bem, eu só confio neste novo ponto 20, e eu uso 4 outros pontos que eu confio na mesma quantidade, exceto que em vez de tomar explicitamente os 4 outros pontos, você está supondo que a média que você fez na última vez Era sensato para que você possa usar seu trabalho anterior. Resposta Eu sei que isso é 5 anos de atraso, mas obrigado por uma resposta incrível. I39m trabalhando em um jogo onde o som muda com base na sua velocidade, mas devido à execução do jogo em um computador lento ass, a velocidade flutuaria descontroladamente, o que era bom para a direção, mas super irritante em termos de som. Esta foi uma solução realmente simples e barata para algo que eu pensei que seria um problema muito complexo. Ndash Adam Mar 16 15 at 20:20 Se você estiver tentando remover o valor estranho ocasional, um filtro passa-baixa é a melhor das três opções que você identificou. Os filtros passa-baixa permitem mudanças de baixa velocidade, como as causadas pela rotação de uma bússola à mão, ao mesmo tempo em que rejeitam mudanças de alta velocidade, como as causadas por solavancos na estrada, por exemplo. Uma média móvel provavelmente não será suficiente, uma vez que os efeitos de um único blip em seus dados afetarão vários valores subseqüentes, dependendo do tamanho de sua janela de média móvel. Se os valores ímpares forem facilmente detectados, você pode até estar melhor com um algoritmo de remoção de glitch que ignora completamente eles: Aqui está um gráfico guick para ilustrar: O primeiro gráfico é o sinal de entrada, com uma falha desagradável. O segundo gráfico mostra o efeito de uma média móvel de 10 amostras. O gráfico final é uma combinação da média de 10 amostras e do algoritmo de detecção de falhas simples mostrado acima. Quando a falha é detectada, a média de 10 amostras é usada em vez do valor real. Respondeu Sep 21 10 at 13:38 Bem explicado, e pontos de bônus para o gráfico) ndash Henry Cooke Sep 22 10 at 0:50 Uau. Seldomly viu uma resposta tão agradável ndash Muis Jun 4 13 at 9:14 A média móvel é um filtro passa-baixa. Ndash nomen Oct 21 13 at 19:36 Experimente uma mediana de execução / streaming em vez disso. Ndash kert Apr 25 14 at 22:09 Movendo média, eu posso descer com. Mas parece-me que o seu provavelmente bastante ineficaz. Não há realmente nenhuma razão uma média móvel deve ser ineficiente. Você mantém o número de pontos de dados desejados em algum buffer (como uma fila circular). Em cada novo ponto de dados, você pop o valor mais antigo e subtraí-lo de uma soma, e empurrar o mais novo e adicioná-lo à soma. Assim, cada novo ponto de dados realmente só envolve um pop / push, uma adição e uma subtração. A sua média móvel é sempre esta soma deslocada dividida pelo número de valores no seu buffer. Ele fica um pouco mais complicado se você está recebendo dados simultaneamente a partir de vários segmentos, mas desde que seus dados vem de um dispositivo de hardware que parece altamente duvidoso para mim. Oh e também: programadores autodidacta terríveis se unem) A média móvel parecia ineficiente para mim porque você tem que armazenar um buffer de valores - melhor apenas fazer algumas Matemática Inteligente com seu valor de entrada e valor de funcionamento atual Eu acho que é como média móvel exponencial Funciona. Uma otimização que eu tenho visto para esse tipo de média móvel envolve o uso de um amplificador de fila de comprimento fixo, um ponteiro para onde você está nessa fila, e apenas envolver o ponteiro ao redor (com ou um if). Voila Nenhum impulso caro / pop. Poder para os amadores, irmão Henry: Para uma média móvel em linha reta você precisa do buffer simplesmente para que você saiba o valor obtém estourou quando o próximo valor ser empurrado. Dito isto, o amplificador de fila de comprimento fixo que você está descrevendo é exatamente o que eu quis dizer com fila quotcircular. Isso é porque eu estava dizendo que ele não é eficiente. O que você acha que eu quis dizer E se sua resposta é quotan array que muda seus valores de volta em cada remoção indexada (como std :: vector em C). Bem, então, I39m tão machucar eu don39t ainda quero falar com você mais) ndash Dan Tao Sep 22 10 às 1:58 Henry: Eu don39t saber sobre AS3, mas um programador Java tem coleções como CircularQueue à sua disposição (I39m Não um desenvolvedor Java, então tenho certeza de que há melhores exemplos lá fora que é exatamente o que eu encontrei a partir de uma pesquisa rápida do Google), que implementa precisamente a funcionalidade que estamos falando. I39m bastante confiante a maioria das linguagens de médio e baixo nível com bibliotecas padrão têm algo semelhante (por exemplo, em QueueltTgt lá). Enfim, eu era filosofia, então. tudo é perdoado. Ndash Dan Tao Sep 22 10 em 12:44 Uma média móvel decrescente exponencialmente pode ser calculada manualmente com apenas a tendência se você usar os valores adequados. Veja fourmilab. ch/hackdiet/e4/ para obter uma idéia sobre como fazer isso rapidamente com uma caneta e papel, se você está procurando exponencialmente suavizada média móvel com 10 suavização. Mas desde que você tem um computador, você provavelmente quer fazer deslocamento binário ao contrário de deslocamento decimal) Desta forma, tudo que você precisa é uma variável para o seu valor atual e um para a média. A média seguinte pode então ser calculada a partir daí. Há uma técnica chamada uma porta de intervalo que funciona bem com amostras espúrias de baixa ocorrência. Supondo o uso de uma das técnicas de filtro mencionadas acima (média móvel, exponencial), uma vez que você tenha histórico suficiente (uma Constante de Tempo) você pode testar a nova amostra de dados para razoabilidade antes de ser adicionada à computação. É necessário algum conhecimento da taxa máxima de mudança razoável do sinal. A amostra bruta é comparada com o valor mais recente suavizado e se o valor absoluto dessa diferença for maior do que o intervalo permitido, essa amostra é descartada (ou substituída por alguma heurística, por exemplo, uma previsão baseada no diferencial de inclinação ou na tendência Valor de predição de dupla exponencial suavização) respondeu Apr 30 at 6:56 sei que isso é possível com o impulso como por: Mas eu realmente gostaria de evitar usar impulso. Eu tenho googled e não encontrei qualquer exemplos adequados ou legível. Basicamente, eu quero acompanhar a média móvel de um fluxo em andamento de um fluxo de números de ponto flutuante usando os mais recentes números de 1000 como uma amostra de dados. Qual é a maneira mais fácil de conseguir isso que eu experimentei com o uso de uma matriz circular, média móvel exponencial e uma média móvel mais simples e descobriu que os resultados da matriz circular adequado às minhas necessidades. Se suas necessidades são simples, você pode apenas tentar usar uma média móvel exponencial. Simplificando, você faz uma variável de acumulador, e como seu código olha para cada amostra, o código atualiza o acumulador com o novo valor. Você escolhe um alfa constante que está entre 0 e 1 e calcula isso: Você só precisa encontrar um valor de alfa onde o efeito de uma determinada amostra só dura cerca de 1000 amostras. Hmm, Im realmente não tenho certeza que isso é adequado para você, agora que Ive colocá-lo aqui. O problema é que 1000 é uma janela muito longa para uma média móvel exponencial Não tenho certeza se há um alfa que estenderia a média nos últimos 1000 números, sem subfluxo no cálculo do ponto flutuante. Mas se você quisesse uma média menor, como 30 números ou assim, esta é uma maneira muito fácil e rápida de fazê-lo. Respondeu 12 de junho 12 em 4:44 1 em seu borne. A média móvel exponencial pode permitir que o alfa seja variável. Portanto, isso permite que ele seja usado para calcular médias de base de tempo (por exemplo, bytes por segundo). Se o tempo desde a última actualização do acumulador for superior a 1 segundo, deixe alfa ser 1.0. Caso contrário, você pode deixar alfa ser (usecs desde a última atualização / 1000000). Ndash jxh Jun 12 12 at 6:21 Basicamente, eu quero acompanhar a média móvel de um fluxo em curso de um fluxo de números de ponto flutuante usando os mais recentes números de 1000 como uma amostra de dados. Observe que o abaixo atualiza o total como elementos como adicionado / substituído, evitando costal O (N) traversal para calcular a soma - necessária para a média - on demand. Total é feito um parâmetro diferente de T para suporte, e. Usando um longo longo quando totalizando 1000 s longos, um int para char s, ou um dobro ao total float s. Este é um pouco falho em que numsamples poderia ir passado INTMAX - se você se importa que você poderia usar um unsigned longo longo. Ou usar um membro de dados bool extra para gravar quando o recipiente é preenchido pela primeira vez enquanto ciclismo numsamples em torno da matriz (melhor então renomeado algo inócuo como pos). Respondida em 12 de junho de 12 às 5:19, assume-se que o operador quotvoid (amostra T) é, na verdade, operador quotvoid (T amostra) quot. Ndash oPless Jun 8 14 at 11:52 oPless ahhh. Bem manchado. Na verdade, eu quis dizer para ser void operador () (T amostra), mas é claro que você poderia usar qualquer nota que você gostava. Vai corrigir, obrigado. Ndash Tony D Jun 8 14 at 14: 27Intro Uma das principais aplicações para a placa Arduino é a leitura e registro de dados de sensores. Por exemplo, um monitora a pressão a cada segundo do dia. Como altas taxas de amostragem geralmente gera picos nos gráficos, também se deseja ter uma média das medições. Como as medições não são estáticas no tempo o que muitas vezes precisamos é de uma média de corrida. Esta é a média de um determinado período e muito valioso quando se faz análise de tendências. A forma mais simples de uma média em execução pode ser feita por um código que se baseia na média anterior: Se não se deseja usar matemática em ponto flutuante - como isso ocupa a memória e diminui a velocidade - pode-se fazer o mesmo completamente no domínio inteiro. A divisão por 256 no código de exemplo é um deslocamento-direito 8, que é mais rápido do que digamos divisão por, e. 100. Isso é verdade para cada poder de 2 como divisor e um só deve ter cuidado a soma dos pesos é igual ao poder de 2. E, claro, deve-se tomar cuidado não há transbordamento intermediário (considere usar unsigned longo) Se você precisar Uma média de execução mais precisa, in concreto das últimas 10 medições, você precisa de uma matriz (ou lista vinculada) para mantê-los. Esta matriz age como um buffer circular e com cada nova medição a mais antiga é removida. A média de execução é calculada como a soma de todos os elementos divididos pelo número de elementos na matriz. O código para a média em execução será algo como isto: Desvantagem deste código é que a matriz para armazenar todos os valores pode se tornar bastante grande. Se você tem uma medição por segundo e você quer uma média de execução por minuto que você precisa de uma matriz de 60 uma média por hora precisaria de uma matriz de 3600. Isso não poderia ser feito desta maneira em um Arduino como ele só tem 2K de RAM. No entanto, através da construção de uma média de 2 estágios que pode ser abordado muito bem (renúncia: não para todas as medições). No código psuedo: Como uma nova matriz estática interna é necessária para cada função runningAverage, este grita para ser implementado como uma classe. Biblioteca RunningAverage A biblioteca runningAverage cria uma classe da função acima para que ela possa ser usada várias vezes em um sketch. Desacopla a função add () e avg () para ser um pouco mais flexível, e. Um pode chamar a média várias vezes sem adicionar uma coisa. Observe que cada instância da classe adiciona sua própria matriz para realizar medições e que isso adiciona até o uso de memória. A interface da classe é mantida o menor possível. Nota: com a versão 0.2 os nomes dos métodos são todos mais descritivos. Uso Um pequeno esboço mostra como ele pode ser usado. Um gerador aleatório é usado para imitar um sensor. Em setup () o myRA é limpo para que possamos começar a adicionar novos dados. Em loop () primeiro um número aleatório é gerado e convertido em um flutuador a ser adicionado ao myRA. Em seguida, o runningAverage é impresso para a porta serial. Pode-se também exibi-lo em algum LCD ou enviar mais ethernet etc Quando 300 itens são adicionados myRA é limpo para começar de novo. Notas Para utilizar a biblioteca, crie uma pasta no SKETCHBOOKPATHlibaries com o nome RunningAverage e coloque o. h e. cpp lá. Opcionalmente, faça um subdiretório de exemplos para colocar o aplicativo de exemplo. Histórico 2011-01-30: versão inicial 2011-02-28: fixa destrutor em falta no arquivo. h 2011-02-28: construtor padrão removido 2012--. Adicionado fillValue () refactored para publicação 2014-07-03: adicionado código de proteção de memória - se matriz interna não pode ser alocada tamanho Torna-se 0. Isso é para resolver o problema descrito aqui - forum. arduino. cc/indextopic50473.msg1790086msg1790086 - Todo Test extensivamente. Classe de modelo CorridaAventual. h CorrenteActiv. cppA média / Média móvel simples Médias / Média móvel simples Você é encorajado a resolver esta tarefa de acordo com a descrição da tarefa, usando qualquer idioma que você conheça. Calculando a média móvel simples de uma série de números. Criar uma função stateful / classe / instância que leva um período e retorna uma rotina que leva um número como argumento e retorna uma média móvel simples de seus argumentos até agora. Uma m�ia m�el simples �um m�odo para calcular uma m�ia de um fluxo de n�eros calculando apenas a m�ia dos �timos n�eros de 160 P 160 a partir do fluxo 160, em que 160 P 160 �conhecido como o per�do. Ele pode ser implementado chamando uma rotina de iniciação com 160 P 160 como argumento, 160 I (P), 160 que deve retornar uma rotina que, quando chamada com membros individuais, sucessivos de um fluxo de números, calcula a média de Para), os últimos 160 P 160 deles, vamos chamar este 160 SMA (). A palavra 160 estado 160 na descrição da tarefa refere-se à necessidade de 160 SMA () 160 lembrar determinadas informações entre as chamadas para ele: 160 O período, 160 P 160 Um recipiente ordenado de pelo menos os últimos 160 P 160 números de cada um dos Suas chamadas individuais. Stateful 160 também significa que chamadas sucessivas para 160 I (), 160 o inicializador, 160 devem retornar rotinas separadas que não 160 não compartilham o estado salvo para que possam ser usadas em dois fluxos de dados independentes. Pseudo-código para uma implementação de 160 SMA 160 é: Esta versão usa uma fila persistente para conter os valores p mais recentes. Cada função retornada de init-moving-average tem seu estado em um átomo contendo um valor de fila. Esta implementação usa uma lista circular para armazenar os números dentro da janela no início de cada ponteiro de iteração refere-se à célula de lista que mantém o valor apenas movendo para fora da janela e para ser substituído com o valor apenas adicionado. Usando um fechamento editar Atualmente este sma não pode ser nogc porque ele aloca um encerramento no heap. Alguma análise de escape pode remover a alocação de heap. Usando uma edição de estrutura Esta versão evita a alocação de heap do fechamento mantendo os dados no quadro de pilha da função principal. Mesmo resultado: Para evitar que as aproximações de ponto flutuante sigam se acumulando e crescendo, o código poderia executar uma soma periódica em toda a matriz de filas circulares. Esta implementação produz dois estados de compartilhamento de objetos (função). É idiomático em E separar a entrada da saída (ler a partir da escrita) em vez de combiná-los em um objeto. A estrutura é a mesma que a implementação do Desvio PadrãoE. O programa elixir abaixo gera uma função anônima com um período embutido p, que é usado como o período da média móvel simples. A função de execução lê entrada numérica e passa para a função anônima recém-criada e, em seguida, inspeciona o resultado para STDOUT. A saída é mostrada abaixo, com a média, seguida pela entrada agrupada, formando a base de cada média móvel. Erlang tem fechamentos, mas variáveis ​​imutáveis. Uma solução então é usar processos e uma simples mensagem passando API baseada. As linguagens de matriz têm rotinas para calcular os avarages deslizando para uma determinada seqüência de itens. É menos eficiente para loop como nos comandos a seguir. Solicita continuamente uma entrada I. Que é adicionado ao final de uma lista L1. L1 pode ser encontrado pressionando 2ND / 1, e a média pode ser encontrada em List / OPS Pressione ON para terminar o programa. Função que retorna uma lista contendo os dados médios do argumento fornecido Programa que retorna um valor simples em cada invocação: list é a média da lista: p é o período: 5 retorna a lista média: Exemplo 2: Usando o programa movinav2 (i , 5) - Inicializando o cálculo da média móvel e definindo o período de 5 movinav2 (3, x): x - novos dados na lista (valor 3), e o resultado será armazenado na variável x e exibido movinav2 (4, x) : X - novos dados (valor 4), eo novo resultado será armazenado na variável x, e exibido (43) / 2. Descrição da função movinavg: variável r - é o resultado (a lista média) que será retornada variável i - é a variável de índice, e aponta para o fim da sub-lista a lista sendo calculada a média. Variável z - uma variável auxiliar A função usa a variável i para determinar quais valores da lista serão considerados no cálculo da média seguinte. Em cada iteração, a variável i aponta para o último valor na lista que será utilizado no cálculo médio. Portanto, só precisamos descobrir qual será o primeiro valor na lista. Geralmente bem tem que considerar p elementos, então o primeiro elemento será o indexado por (i-p1). No entanto, nas primeiras iterações, esse cálculo será normalmente negativo, de modo que a seguinte equação evitará índices negativos: max (i-p1,1) ou, arranjar a equação, max (i-p, 0) 1. Mas o número de elementos nas primeiras iterações também será menor, o valor correto será (índice final - índice de início 1) ou, arranjar a equação, (i - (max (ip, 0) 1) e então , (I-max (ip, 0)). A variável z detém o valor comum (max (ip), 0) então o beginindex será (z1) e os numberofelements serão (iz) mid (list, z1, iz) retornará a lista de valor que será a soma média .) Irá somá-los soma (.) / (Iz) ri irá média deles e armazenar o resultado no lugar apropriado na lista de resultados Usando um fecho e criando uma função

No comments:

Post a Comment