Wednesday 16 May 2018

Moving average filter c code


Filtro médio ou categoria média do filtro. Desenvolvimento de software de processamento digital de sinais e imagens (DSP e DIP). Abstrato. O artigo é um guia prático para filtro de média ou compreensão e implementação de filtro médio. Artigo contém teoria, código-fonte C, instruções de programação e aplicação de amostra. 1. Introdução ao filtro médio ou filtro médio Filtro médio. ou filtro médio é o filtro de janela da classe linear, que suaviza o sinal (imagem). O filtro funciona como um de baixa passagem. A idéia básica por trás do filtro é que qualquer elemento do sinal (imagem) tenha uma média em sua vizinhança. Para entender como isso é feito na prática, vamos começar com uma ideia de janela. 2. Janela de filtro ou máscara Vamos imaginar, você deve ler uma carta e o que você vê no texto restrito por um buraco em estêncil especial como este. Então, o resultado da leitura é som t. Ok, vamos ler a carta novamente, mas com a ajuda de outro stencil: Agora o resultado da leitura é som 240. Vamos fazer a terceira tentativa: Agora você está lendo a letra t como som 952. O que acontece aqui Para dizer isso na linguagem matemática, você está fazendo uma operação (leitura) sobre o elemento (letra t). E o resultado (som) depende da vizinhança do elemento (letras ao lado de t). E esse stencil, que ajuda a pegar a vizinhança do elemento, é a janela Sim, a janela é apenas um estêncil ou padrão, por meio do qual você está selecionando o elemento 0151 para um conjunto de elementos em torno do determinado 0151 para ajudá-lo a tomar decisões. Outro nome para a janela de filtro é máscara 0151 máscara é um estêncil, que esconde elementos que não estão prestando atenção. Em nosso exemplo, o elemento em que estamos operando posicionado à esquerda da janela, na prática, entretanto, sua posição usual é o centro da janela. Vamos ver alguns exemplos de janela. Em uma dimensão. Fig. 4. Janela ou máscara de tamanho 5 em 1D. Em duas dimensões. Fig. 5. Janela ou máscara de tamanho 3x3 em 2D. Em três dimensões. Pense em construir. E agora, sobre o quarto naquele prédio. A sala é como a janela 3D, que corta algum subespaço de todo o espaço do edifício. Você pode encontrar janela 3D no processamento de imagens de volume (voxel). 3. Compreender o filtro médio Agora vamos ver como calcular a média entre os elementos do bairro. A fórmula é simples e soma a soma pelo número de elementos. Por exemplo, vamos calcular uma média para o caso, representada na fig. 7 Fig. 7. Tomando uma média. E isso é tudo. Sim, nós apenas filtramos o sinal 1D pelo filtro médio Vamos resumir e escrever as instruções passo-a-passo para o processamento por meio do filtro. Filtro de média, ou algoritmo de filtro médio: Coloque uma janela sobre o elemento Tome uma média de 0151 soma elementos e divida a soma pelo número de elementos. Agora, quando temos o algoritmo, é hora de escrevermos algum código, vamos descer para a programação. 4. 1D significa programação de filtro Nesta seção, desenvolvemos um filtro de média de 1D com janela de tamanho 5. Vamos ter um sinal 1D de comprimento N como entrada. O primeiro passo é colocar a janela 0151 fazemos isso mudando o índice do elemento principal: Preste atenção, que estamos começando com o terceiro elemento e terminando com o último mas dois. O problema é que não podemos começar com o primeiro elemento, porque neste caso a parte esquerda da janela do filtro está vazia. Vamos discutir abaixo como resolver esse problema. O segundo passo é pegar a média, ok: Agora, vamos escrever o algoritmo como function: O elemento type pode ser definido como: 5. Tratar arestas Para todos os filtros de janelas, há algum problema. Isso é tratamento de borda. Se você colocar a janela sobre o primeiro (último) elemento, a parte esquerda (direita) da janela estará vazia. Para preencher a lacuna, o sinal deve ser estendido. Para o filtro médio, é boa ideia estender o sinal ou a imagem simetricamente, assim: Assim, antes de passar o sinal para a nossa função de filtro médio, o sinal deve ser estendido. Vamos escrever o invólucro, que faz todos os preparativos. Como você pode ver, nosso código leva em consideração alguns problemas práticos. Primeiro de tudo, nós verificamos que nossos sinais de entrada 0151 sinal não deve ser NULL, e o comprimento do sinal deve ser positivo: Segundo passo 0151 nós verificamos o caso N1. Este caso é especial, porque para construir uma extensão precisamos de pelo menos dois elementos. Para o sinal de 1 elemento, o resultado é o próprio sinal. Além disso, preste atenção, nosso filtro médio funciona no local, se o resultado do parâmetro de saída for NULL. Agora vamos alocar memória para extensão de sinal. E verifique a alocação de memória. Eu sei que isso é possível com o aumento como por: Mas eu realmente gostaria de evitar o uso de impulso. Eu pesquisei e não encontrei nenhum exemplo adequado ou legível. Basicamente, quero rastrear a média móvel de um fluxo contínuo de um fluxo de números de ponto flutuante usando os 1000 números mais recentes como amostra de dados. Qual é a maneira mais fácil de conseguir isso, experimentei usar uma matriz circular, média móvel exponencial e uma média móvel mais simples, e descobri que os resultados da matriz circular se adequavam melhor às minhas necessidades. perguntou 12 de junho de 12 às 4:38 Se as suas necessidades são simples, você pode tentar usar uma média móvel exponencial. Simplificando, você cria uma variável de acumulador e, à medida que seu código examina cada amostra, o código atualiza o acumulador com o novo valor. Você escolhe um alfa constante que esteja entre 0 e 1 e calcula isso: você só precisa encontrar um valor de alfa onde o efeito de uma determinada amostra dura apenas cerca de 1000 amostras. Hmmm, eu não tenho certeza se isso é adequado para você, agora que eu coloquei aqui. O problema é que 1000 é uma janela muito longa para uma média móvel exponencial Não tenho certeza se existe um alpha que possa distribuir a média nos últimos 1000 números, sem underflow no cálculo do ponto flutuante. Mas se você quisesse uma média menor, como 30 números ou mais, essa é uma maneira muito fácil e rápida de fazer isso. respondeu 12 de junho às 12:44 1 em seu post. A média móvel exponencial pode permitir que o alfa seja variável. Então, isso permite que ele seja usado para calcular as médias da base de tempo (por exemplo, bytes por segundo). Se o tempo desde a última atualização do acumulador for maior que 1 segundo, você deixa o alpha ser 1.0. Caso contrário, você pode deixar o alpha ser (usecs desde a última atualização / 1000000). Basicamente eu quero acompanhar a média móvel de um fluxo contínuo de um fluxo de números de ponto flutuante usando os 1000 números mais recentes como uma amostra de dados. Observe que o abaixo atualiza o total como elementos adicionados / substituídos, evitando o deslocamento O (N) caro para calcular a soma - necessária para a média - sob demanda. Total é feito um parâmetro diferente de T para suportar, e. usando um longo longo ao totalizar 1000 long s, um int para char s, ou um double para total float s. Isso é um pouco defeituoso, pois as amostras podem passar do INTMAX - se você se importar, pode usar um sinal longo sem assinatura. ou use um membro extra de dados de bool para registrar quando o contêiner é preenchido pela primeira vez enquanto circula números em torno do array (melhor que renomeie algo inócuo como pos). Resposta: 12 de junho, às 5:19, assume-se que o operador "qvoid" (amostra T) é, na verdade, o operador "co-vi" ("amostra T"). ndash oPless Jun 8 14 às 11:52 oPless ahhh. bem manchado. na verdade eu quis dizer que seria void operator () (amostra T), mas é claro que você poderia usar qualquer notação que você gostasse. Vai consertar, obrigado. ndash Tony D Jun 8 14 às 14: 27 Como outros já mencionaram, você deve considerar um filtro IIR (resposta ao impulso infinito) em vez do filtro FIR (resposta ao impulso finito) que está usando agora. Há mais, mas à primeira vista, os filtros FIR são implementados como convoluções explícitas e filtros IIR com equações. O filtro IIR particular que eu uso muito em microcontroladores é um filtro passa-baixa de pólo único. Este é o equivalente digital de um filtro analógico R-C simples. Para a maioria das aplicações, elas terão melhores características do que o filtro de caixa que você está usando. A maioria dos usos de um filtro de caixa que eu encontrei é resultado de alguém não prestar atenção na classe de processamento de sinal digital, não como resultado da necessidade de suas características particulares. Se você quer apenas atenuar altas frequências que você sabe que são ruído, um filtro passa-baixa de polo único é melhor. A melhor maneira de implementar um digitalmente em um microcontrolador é geralmente: FILT lt-- FILT FF (NOVO - FILT) FILT é uma parte do estado persistente. Essa é a única variável persistente que você precisa para calcular esse filtro. NEW é o novo valor que o filtro está sendo atualizado com essa iteração. FF é a fração do filtro. que ajusta o peso do filtro. Veja este algoritmo e veja que, para FF 0, o filtro é infinitamente pesado, pois a saída nunca muda. Para FF 1, realmente não há filtro, pois a saída apenas segue a entrada. Valores úteis estão entre. Em sistemas pequenos, você escolhe FF como 1/2N, de modo que a multiplicação por FF pode ser realizada como um desvio à direita por N bits. Por exemplo, FF pode ser 1/16 e multiplicar por FF, portanto, um deslocamento à direita de 4 bits. Caso contrário, este filtro precisa de apenas um subtrato e um acréscimo, embora os números geralmente precisem ser mais largos do que o valor de entrada (mais na precisão numérica em uma seção separada abaixo). Eu costumo tirar as leituras A / D significativamente mais rápido do que o necessário e aplicar dois desses filtros em cascata. Este é o equivalente digital de dois filtros R-C em série e atenua em 12 dB / oitava acima da frequência de rolloff. No entanto, para leituras A / D, é mais relevante observar o filtro no domínio do tempo, considerando sua resposta em etapas. Isso informa a rapidez com que o sistema verá uma alteração quando a coisa que você está medindo mudar. Para facilitar a criação desses filtros (o que significa apenas escolher o FF e decidir quantos deles serão em cascata), eu uso o meu programa FILTBITS. Você especifica o número de bits de deslocamento para cada FF na série de filtros em cascata e calcula a resposta da etapa e outros valores. Na verdade, eu geralmente executo isso através do meu script wrapper PLOTFILT. Isso executa FILTBITS, que cria um arquivo CSV e, em seguida, plota o arquivo CSV. Por exemplo, aqui está o resultado de PLOTFILT 4 4: Os dois parâmetros para PLOTFILT significam que haverá dois filtros em cascata do tipo descrito acima. Os valores de 4 indicam o número de bits de deslocamento para realizar a multiplicação por FF. Os dois valores de FF são, portanto, 1/16 neste caso. O traço vermelho é a resposta do degrau unitário e é a principal coisa a ser observada. Por exemplo, isso informa que, se a entrada for alterada instantaneamente, a saída do filtro combinado será estabelecida em 90 do novo valor em 60 iterações. Se você se preocupa com o tempo de estabilização de 95, então você tem que esperar cerca de 73 iterações e, para 50, apenas 26 iterações. O traço verde mostra a saída de um único pico de amplitude total. Isso dá uma ideia da supressão aleatória de ruído. Parece que nenhuma amostra única causará mais do que uma mudança de 2,5 na saída. O traço azul é para dar uma sensação subjetiva do que este filtro faz com o ruído branco. Este não é um teste rigoroso, uma vez que não há garantia de qual é exatamente o conteúdo dos números aleatórios escolhidos como a entrada de ruído branco para esta execução de PLOTFILT. É só para lhe dar uma sensação aproximada de quanto será esmagado e quão suave é. PLOTFILT, talvez FILTBITS, e muitas outras coisas úteis, especialmente para o desenvolvimento de firmware PIC, estão disponíveis na versão do software PIC Development Tools, na página de downloads do meu software. Adicionado sobre precisão numérica, vejo a partir dos comentários e agora uma nova resposta que há interesse em discutir o número de bits necessários para implementar este filtro. Observe que a multiplicação por FF criará novos bits do Log 2 (FF) abaixo do ponto binário. Em sistemas pequenos, o FF é geralmente escolhido para ser 1/2 N, de modo que essa multiplicação é realmente realizada por um deslocamento à direita de N bits. FILT é, portanto, geralmente um inteiro de ponto fixo. Note que isso não altera a matemática do ponto de vista dos processadores. Por exemplo, se você estiver filtrando leituras A / D de 10 bits e N 4 (FF 1/16), precisará de 4 bits de fração abaixo das leituras inteiras A / D de 10 bits. Um a maioria dos processadores, você estaria fazendo operações de 16 bits inteiros devido às leituras A / D de 10 bits. Neste caso, você ainda pode fazer exatamente as mesmas operações de inteiros de 16 bits, mas começar com as leituras A / D deixadas deslocadas por 4 bits. O processador não sabe a diferença e não precisa. Fazer as contas em inteiros inteiros de 16 bits funciona se você considerar que eles são 12.4 pontos fixos ou verdadeiros 16 bits inteiros (16.0 ponto fixo). Em geral, você precisa adicionar N bits a cada pólo de filtro se não quiser adicionar ruído devido à representação numérica. No exemplo acima, o segundo filtro de dois teria que ter 1044 18 bits para não perder informação. Na prática, em uma máquina de 8 bits, você usa valores de 24 bits. Tecnicamente, apenas o segundo polo de dois precisaria de um valor mais amplo, mas, para a simplicidade do firmware, geralmente uso a mesma representação e, portanto, o mesmo código, para todos os polos de um filtro. Geralmente eu escrevo uma sub-rotina ou macro para executar uma operação de pólo de filtro, depois aplico isso a cada pólo. Se uma sub-rotina ou macro depende se os ciclos ou memória de programa são mais importantes nesse projeto específico. De qualquer maneira, eu uso um pouco de scratch para passar NEW para a sub-rotina / macro, que atualiza FILT, mas também carrega isso no mesmo estado de scratch em que o NEW estava. Isso facilita a aplicação de múltiplos pólos, já que o FILT atualizado de um pólo é o NOVO do próximo. Quando uma sub-rotina, é útil ter um ponteiro apontando para FILT no caminho, que é atualizado para depois de FILT na saída. Dessa forma, a sub-rotina opera automaticamente em filtros consecutivos na memória, se chamada várias vezes. Com uma macro, você não precisa de um ponteiro, pois você passa no endereço para operar em cada iteração. Exemplos de código Aqui está um exemplo de uma macro como descrito acima para um PIC 18: E aqui está uma macro semelhante para um PIC 24 ou dsPIC 30 ou 33: Ambos os exemplos são implementados como macros usando meu pré-processador montador PIC. que é mais capaz do que qualquer uma das instalações macro integradas. clabacchio: Outro problema que eu deveria ter mencionado é a implementação de firmware. Você pode escrever uma sub-rotina de filtro low-pass de pólo único uma vez e depois aplicá-la várias vezes. Na verdade, eu geralmente escrevo essa sub-rotina para levar um ponteiro na memória para o estado do filtro, então ele avança o ponteiro para que ele possa ser chamado em sucessão facilmente para realizar filtros multipolares. ndash Olin Lathrop Apr 20 12 at 15:03 1. muito obrigado pelas suas respostas - todas elas. Eu decidi usar este Filtro IIR, mas este Filtro não é usado como um Filtro Standard LowPass, uma vez que eu preciso mediar os Valores dos Contadores e compará-los para detectar Mudanças em um determinado Range. Uma vez que esses valores têm dimensões muito diferentes, dependendo do hardware, eu queria ter uma média para poder reagir a essas mudanças específicas de hardware automaticamente. ndash sensslen May 21 12 at 12:06 Se você pode viver com a restrição de uma potência de dois números de itens para média (ou seja, 2,4,8,16,32 etc), em seguida, a divisão pode ser feita de forma fácil e eficiente em um micro de baixo desempenho sem divisão dedicada, porque pode ser feito como uma mudança de bit. Cada turno à direita é uma potência de dois, por exemplo: O OP pensou que ele tinha dois problemas, dividindo-se em um PIC16 e memória para seu buffer de anel. Esta resposta mostra que a divisão não é difícil. É certo que não resolve o problema de memória, mas o sistema SE permite respostas parciais, e os usuários podem pegar algo de cada resposta por si mesmos, ou até mesmo editar e combinar as respostas do outro. Uma vez que algumas das outras respostas exigem uma operação de divisão, elas são igualmente incompletas, pois não mostram como alcançar isso com eficiência em um PIC16. ndash Martin Apr 20 12 at 13:01 Há uma resposta para um verdadeiro filtro de média móvel (também conhecido como filtro de vagão) com menos requisitos de memória, se você não se importar com a redução da resolução. É chamado de filtro integrador-comb em cascata (CIC). A ideia é que você tenha um integrador no qual você tira as diferenças ao longo de um período de tempo, e o dispositivo de economia de memória chave é que, ao reduzir a resolução, você não precisa armazenar todos os valores do integrador. Ele pode ser implementado usando o seguinte pseudocódigo: Seu comprimento médio efetivo é decimationFactorstatesize, mas você só precisa manter as amostras de stateize. Obviamente, você pode obter um desempenho melhor se seu Fator de estado e decimação for potências de 2, de forma que os operadores de divisão e remanescentes sejam substituídos por turnos e máscaras. Postscript: Eu concordo com Olin que você deve sempre considerar filtros IIR simples antes de um filtro de média móvel. Se você não precisar dos nulos de frequência de um filtro de vagão, um filtro passa-baixa de 1 ou 2 polos provavelmente funcionará bem. Por outro lado, se você estiver filtrando para fins de dizimação (tomando uma entrada de alta taxa de amostragem e calculando a média para uso por um processo de baixa taxa), então um filtro CIC pode ser exatamente o que você está procurando. (especialmente se você puder usar o statesize1 e evitar o ringbuffer completamente com apenas um único valor do integrador anterior) Há uma análise profunda da matemática por trás do filtro IIR de primeira ordem que Olin Lathrop já descreveu na troca de pilha do Digital Signal Processing (Inclui muitas fotos bonitas.) A equação para este filtro IIR é: Isso pode ser implementado usando apenas inteiros e sem divisão usando o seguinte código (pode precisar de alguma depuração enquanto eu estava digitando da memória.) Esse filtro se aproxima de uma média móvel de as últimas K amostras, definindo o valor de alfa para 1 / K. Faça isso no código anterior, definindo BITS para LOG2 (K), ou seja, para K 16, defina BITS como 4, K 4 defina BITS como 2, etc. (Eu verificarei o código listado aqui assim que obtiver uma alteração e edite esta resposta se necessário.) Respondeu o 23 de junho 12 no 4:04 Heres um filtro low-pass unipolar (média movente, com freqüência de corte CutoffFrequency). Muito simples, muito rápido, funciona muito bem e quase sem sobrecarga de memória. Nota: Todas as variáveis ​​têm escopo além da função de filtro, exceto o passado em newInput Nota: Este é um filtro de um único estágio. Vários estágios podem ser colocados em cascata para aumentar a nitidez do filtro. Se você usar mais de um estágio, você terá que ajustar o DecayFactor (como relacionado à frequência de corte) para compensar. E obviamente tudo que você precisa é dessas duas linhas colocadas em qualquer lugar, elas não precisam de sua própria função. Este filtro tem um tempo de aceleração antes que a média móvel represente aquela do sinal de entrada. Se você precisar ignorar esse tempo de aceleração, basta inicializar o MovingAverage para o primeiro valor de newInput em vez de 0 e esperar que a primeira nova entrada não seja um valor atípico. (CutoffFrequency / SampleRate) tem um intervalo entre 0 e 0,5. DecayFactor é um valor entre 0 e 1, geralmente próximo de 1. Flutuadores de precisão simples são bons o suficiente para a maioria das coisas, eu prefiro o dobro. Se você precisa ficar com números inteiros, você pode converter DecayFactor e Amplitude Factor em inteiros fracionários, nos quais o numerador é armazenado como o inteiro, e o denominador é uma potência inteira de 2 (assim você pode mudar de bit para a direita como o denominador em vez de ter que dividir durante o loop de filtro). Por exemplo, se DecayFactor 0.99, e você quiser usar números inteiros, você pode definir DecayFactor 0,99 65536 64881. E, a qualquer momento, multiplicar por DecayFactor em seu loop de filtro, basta deslocar o resultado 16. Para obter mais informações sobre isso, um excelente livro online, capítulo 19 em filtros recursivos: dspguide / ch19.htm PS Para o paradigma Moving Average, uma abordagem diferente para definir DecayFactor e AmplitudeFactor que pode ser mais relevante para as suas necessidades, digamos que você queira a média anterior, cerca de 6 itens juntos, fazendo discretamente, adicionar 6 itens e dividir por 6, você pode definir o AmplitudeFactor para 1/6 e DecayFactor para (1.0 - AmplitudeFactor). Todas as outras pessoas comentaram completamente sobre a utilidade do IIR vs. FIR, e na divisão de potência de dois. Id apenas gostaria de dar alguns detalhes de implementação. O abaixo funciona bem em pequenos microcontroladores sem FPU. Não há multiplicação, e se você mantiver N uma potência de dois, toda a divisão será em um único ciclo. Buffer de anel FIR básico: mantenha um buffer de execução dos últimos N valores e uma soma de todos os valores no buffer. Cada vez que uma nova amostra entra, subtraia o valor mais antigo no buffer de SUM, substitua-o pela nova amostra, inclua a nova amostra em SUM e a saída SUM / N. Buffer de anel IIR modificado: mantenha uma soma em execução dos últimos N valores. Cada vez que uma nova amostra chega, SUM - SUM / N, adiciona a nova amostra e produz o SUM / N. Se você está lendo bem, você está descrevendo um filtro IIR de primeira ordem, o valor que você está subtraindo não é o valor mais antigo que está caindo, mas sim a média dos valores anteriores. Filtros IIR de primeira ordem certamente podem ser úteis, mas não tenho certeza do que você quer dizer quando sugere que a saída é a mesma para todos os sinais periódicos. A uma taxa de amostragem de 10KHz, alimentar uma onda quadrada de 100Hz em um filtro de caixa de 20 estágios produzirá um sinal que aumenta uniformemente para 20 amostras, fica alto por 30, cai uniformemente para 20 amostras e fica baixo para 30. Uma primeira ordem Filtro IIR. ndash supercat Ago 28 13 às 15:31 produzirá uma onda que começa a subir acentuadamente e gradualmente se estabiliza próximo (mas não a) da entrada máxima, então começa a cair acentuadamente e gradualmente se estabiliza próximo (mas não a) do mínimo de entrada. Comportamento muito diferente. ndash supercat Ago 28 13 at 15:32 Uma questão é que uma simples média móvel pode ou não ser útil. Com um filtro IIR, você pode obter um bom filtro com relativamente poucos cálculos. O FIR que você descreve só pode lhe dar um retângulo no tempo - um sinc em freq - e você não pode gerenciar os lóbulos laterais. Pode valer a pena lançar algumas multiplicações de números inteiros para torná-lo um FIR sintonizável agradável simétrico se você puder poupar os pulsos de clock. ScottSeidman: Não há necessidade de multiplicidade se simplesmente houver cada estágio do FIR, ou a saída da média da entrada para aquele estágio e seu valor armazenado anterior, e então armazenar a entrada (se houver o intervalo numérico, pode-se usar a soma em vez da média). Se isso é melhor do que um filtro de caixa depende do aplicativo (a resposta de etapa de um filtro de caixa com um atraso total de 1 ms, por exemplo, terá um pico d2 / dt desagradável quando a entrada for alterada e novamente 1 ms depois, mas terá o mínimo possível d / dt para um filtro com um atraso total de 1ms). Como disse o mikeselectricstuff, se você realmente precisa reduzir suas necessidades de memória, e você não se importa com a sua resposta de impulso sendo um pulso exponencial (em vez de um pulso retangular), eu iria para um filtro médio móvel exponencial . Eu os uso extensivamente. Com esse tipo de filtro, você não precisa de nenhum buffer. Você não precisa armazenar N amostras anteriores. Apenas um. Portanto, seus requisitos de memória são reduzidos por um fator N. Além disso, você não precisa de nenhuma divisão para isso. Apenas multiplicações. Se você tiver acesso à aritmética de ponto flutuante, use multiplicações de ponto flutuante. Caso contrário, faça multiplicações inteiras e mude para a direita. No entanto, estamos em 2012, e eu recomendo que você use compiladores (e MCUs) que permitem trabalhar com números de ponto flutuante. Além de ser mais eficiente na memória e mais rápida (você não precisa atualizar itens em qualquer buffer circular), eu diria que também é mais natural. porque uma resposta de impulso exponencial corresponde melhor à maneira como a natureza se comporta, na maioria dos casos. Um problema com o filtro IIR quase tocado por olin e supercat mas aparentemente desconsiderado por outros é que o arredondamento para baixo introduz alguma imprecisão (e potencialmente bias / truncamento). assumindo que N é uma potência de dois, e apenas a aritmética inteira é usada, o desvio à direita elimina sistematicamente os LSBs da nova amostra. Isso significa que quanto tempo a série poderia ser, a média nunca levará isso em conta. Por exemplo, suponha uma série lentamente decrescente (8,8,8,8,7,7,7,7,6,6) e assuma que a média é de fato 8 no começo. A primeira amostra 7 levará a média a 7, independentemente da força do filtro. Apenas por uma amostra. Mesma história para 6, etc. Agora pense no oposto. a serie sobe. A média permanecerá em 7 para sempre, até que a amostra seja grande o suficiente para mudar. Claro, você pode corrigir o viés adicionando 1 / 2N / 2, mas isso não vai realmente resolver o problema de precisão. nesse caso, a série decrescente permanecerá para sempre em 8 até a amostra ser 8-1 / 2 (N / 2). Para N4, por exemplo, qualquer amostra acima de zero manterá a média inalterada. Acredito que uma solução para isso implicaria manter um acumulador dos LSBs perdidos. Mas eu não fiz isso o suficiente para ter código pronto, e eu não tenho certeza se isso não prejudicaria o poder IIR em alguns outros casos de séries (por exemplo, se 7,9,7,9 seria em média 8 então). Olin, sua cascata de dois estágios também precisaria de alguma explicação. Você quer dizer manter dois valores médios com o resultado do primeiro alimentado no segundo em cada iteração. Qual é o benefício deste

No comments:

Post a Comment