Wednesday 22 November 2017

Moving Average Filter Cpp


¿Es posible implementar una media móvil en C sin necesidad de una ventana de muestras? He encontrado que puedo optimizar un poco, eligiendo un tamaño de ventana que es una potencia de dos para permitir el cambio de bits en lugar de dividir, pero no necesitar Un buffer sería bueno. ¿Existe una manera de expresar un nuevo promedio móvil sólo como una función del resultado anterior y la nueva muestra Definir un ejemplo de media móvil, a través de una ventana de 4 muestras para ser: Agregar nueva muestra e: Un promedio móvil se puede implementar recursivamente , Pero para un cálculo exacto de la media móvil tiene que recordar la más antigua muestra de entrada en la suma (es decir, el a en su ejemplo). Para una longitud N de media móvil se calcula: donde yn es la señal de salida y xn es la señal de entrada. Eq. (1) se puede escribir recursivamente como Así que siempre necesita recordar la muestra xn-N para calcular (2). Como señaló Conrad Turner, puede usar una ventana exponencial (infinitamente larga), que le permite calcular la salida sólo de la salida pasada y la entrada actual: pero esto no es una media móvil estándar (no ponderada) sino exponencial (Por lo menos en teoría) nunca se olvida nada (los pesos sólo se hacen más pequeños y más pequeños para las muestras en el pasado). Inicializar total 0, count0 (cada vez que se ve un nuevo valor Entonces una entrada (scanf), una suma totalnewValue, un incremento (count), un promedio de división (total / count) Esta sería una media móvil sobre todas las entradas Para calcular el promedio Sobre sólo las 4 últimas entradas, requeriría 4 variables de entrada, tal vez copiando cada entrada a una variable de entrada más antigua, luego calculando la nueva media móvil como suma de las 4 variables de entrada, dividida por 4 (el desplazamiento a la derecha 2 sería bueno si todas las entradas fueran Positivo para hacer el cálculo promedioIm que codifica algo en el momento donde Im que toma un manojo de valores sobre tiempo de una brújula del hardware. Esta brújula es muy exacta y se pone al día muy a menudo, con el resultado que si sacude levemente, termino para arriba con el impar Valor que es salvajemente inconsistente con sus vecinos. Quiero suavizar esos valores. Habiendo hecho algo de lectura alrededor, parece que lo que quiero es un filtro de paso alto, un filtro de paso bajo o un promedio móvil. Mejor media que puedo Consiga abajo con, apenas mantenga una historia de los 5 últimos valores o lo que, y utilice el promedio de esos valores corriente abajo en mi código donde estaba una vez apenas usando el valor más reciente. Eso debería, creo, suavizar los jiggles muy bien, pero me parece que su probablemente bastante ineficiente, y este es probablemente uno de los problemas conocidos a los programadores adecuados a lo que theres una solución de Mate Clever realmente ordenada. Sin embargo, soy uno de esos horribles programadores autodidacta sin una pizca de educación formal en algo que ni siquiera esté vagamente relacionado con CompSci o Matemáticas. Leer un poco sugiere que esto puede ser un filtro de paso alto o bajo, pero no puedo encontrar nada que explique en términos comprensibles a un hack como yo cuál sería el efecto de estos algoritmos en una matriz de valores, y mucho menos cómo la matemática trabajos. La respuesta dada aquí. Por ejemplo, técnicamente responde a mi pregunta, pero sólo en términos comprensibles para aquellos que probablemente ya saben cómo resolver el problema. Sería una persona muy encantadora e inteligente que pudiera explicar el tipo de problema que es, y cómo funcionan las soluciones, en términos comprensibles para un graduado de Artes. Si su promedio móvil tiene que ser largo para lograr el suavizado requerido, y usted realmente no necesita ninguna forma particular de kernel, entonces youre mejor si utiliza una media móvil exponencialmente decadente: donde usted Elegir minúscula para ser una constante apropiada (por ejemplo, si usted elige minúsculo 1- 1 / N, tendrá la misma cantidad de promediar que una ventana de tamaño N, pero se distribuye de manera diferente sobre puntos más antiguos). De todos modos, ya que el siguiente valor de la media móvil sólo depende de la anterior y sus datos, usted no tiene que mantener una cola o nada. Y usted puede pensar en esto como hacer algo así como, Bueno, tengo un nuevo punto, pero no confío en él, así que voy a mantener 80 de mi antigua estimación de la medición, y sólo confiar en este nuevo punto de datos 20. Eso es Casi lo mismo que decir, Bueno, yo sólo confío en este nuevo punto 20, y mal uso 4 otros puntos que confío en la misma cantidad, excepto que en lugar de tomar explícitamente los otros 4 puntos, está asumiendo que el promedio que hizo la última vez Era razonable para que pueda utilizar su trabajo anterior. Respondió Sep 21 10 at 14:27 Oye, sé que esto es 5 años de retraso, pero gracias por una respuesta impresionante. I39m trabajando en un juego donde el sonido cambia en función de su velocidad, pero debido a correr el juego en una computadora lenta-asno, la velocidad fluctuaría salvajemente, que estaba bien para la dirección, pero súper molesto en términos de sonido. Esta fue una solución realmente simple y barata para algo que pensé que sería un problema muy complejo. Ndash Adam Mar 16 15 at 20:20 Si está intentando eliminar el valor extraño ocasional, un filtro de paso bajo es la mejor de las tres opciones que ha identificado. Los filtros de paso bajo permiten cambios de baja velocidad como los causados ​​por la rotación de una brújula con la mano, mientras que rechazan cambios de alta velocidad como los causados ​​por golpes en la carretera, por ejemplo. Un promedio móvil probablemente no será suficiente, ya que los efectos de un solo golpe en sus datos afectarán a varios valores subsiguientes, dependiendo del tamaño de su ventana de promedio móvil. Si los valores impares son fácilmente detectados, incluso puede ser mejor con un algoritmo de eliminación de glitch que los ignora completamente: Aquí hay un gráfico guick para ilustrar: El primer gráfico es la señal de entrada, con un fallo desagradable. El segundo gráfico muestra el efecto de un promedio móvil de 10 muestras. El gráfico final es una combinación del promedio de 10 muestras y el algoritmo de detección de fallos simple mostrado anteriormente. Cuando se detecta el fallo, se utiliza el promedio de 10 muestras en lugar del valor real. Respondió Sep 21 10 at 13:38 Muy bien explicado, y puntos de bonificación para el gráfico) ndash Henry Cooke Sep 22 10 at 0:50 Wow. Rara vez vio una respuesta tan agradable ndash Muis Jun 4 13 at 9:14 La media móvil es un filtro de paso bajo. Ndash nomen Oct 21 13 at 19:36 Pruebe con una media de ejecución / streaming en su lugar. Ndash kert Apr 25 14 at 22:09 Media móvil que puedo bajar con. Pero me parece que su probablemente bastante ineficiente. Theres realmente ninguna razón una media móvil debe ser ineficiente. Usted mantiene el número de puntos de datos que desea en algún búfer (como una cola circular). En cada nuevo punto de datos, se extrae el valor más antiguo y se resta de una suma, y ​​se empuja el más reciente y se agrega a la suma. Así que cada punto de datos nuevos realmente sólo implica un pop / push, una adición y una sustracción. Su promedio móvil es siempre esta suma cambiante dividida por el número de valores en su búfer. Se vuelve un poco más complicado si está recibiendo datos simultáneamente de múltiples hilos, pero ya que sus datos provienen de un dispositivo de hardware que me parece muy dudoso. Oh, y también: programadores autodidactos horribles se unen) El promedio móvil me parecía ineficiente porque tienes que almacenar un búfer de valores - mejor hacer sólo algunas Matemáticas Inteligentes con tu valor de entrada y valor de trabajo actual Creo que eso es como el promedio móvil exponencial trabajos. Una optimización que se ha observado para este tipo de media móvil implica el uso de un amplificador de cola de longitud fija, un puntero a donde se encuentra en esa cola, y simplemente envolver el puntero alrededor (con o un si). Voila No hay costosos empujones / pop. Poder para los aficionados, hermano ndash Enrique: Para un promedio móvil directo, usted necesita el búfer simplemente para que usted sepa qué valor se disparó cuando el siguiente valor se empuja. Dicho esto, la fila de longitud fija en fila, un puntero que está describiendo es exactamente lo que quise decir por cola circular. Eso es lo que decía que no era eficiente. ¿Qué pensaste que quería decir Y si tu respuesta es quotan matriz que cambia sus valores de nuevo en cada removalquot indexado (como std :: vector en C). Bueno, entonces, I39m tan herido que don39t incluso quiero hablar con usted más) ndash Dan Tao Sep 22 10 a las 1:58 Henry: No sé acerca de AS3, pero un programador de Java tiene colecciones como CircularQueue a su disposición (I39m No un desarrollador de Java, así que estoy seguro de que hay mejores ejemplos por ahí que es lo que encontré de una búsqueda rápida de Google), que implementa precisamente la funcionalidad que estamos hablando. Estoy bastante seguro de que la mayoría de los lenguajes de nivel medio y bajo con bibliotecas estándar tienen algo similar (por ejemplo, en QueueltTgt). De todos modos, yo también fui filosofía. Todo está perdonado. Ndash Dan Tao Sep 22 10 at 12:44 Una media móvil exponencialmente decaying se puede calcular a mano con sólo la tendencia si se utilizan los valores adecuados. Vea www. fourmilab. ch/hackdiet/e4/ para una idea sobre cómo hacer esto rápidamente con un lápiz y papel si está buscando un promedio móvil suavizado exponencialmente con 10 suavizado. Pero dado que usted tiene una computadora, es probable que desee realizar un cambio binario en lugar de un cambio decimal) De esta manera, todo lo que necesita es una variable para su valor actual y otra para el promedio. El siguiente promedio se puede calcular a partir de eso. Responde Sep 21 10 at 14:39 theres una técnica llamada una puerta de rango que funciona bien con muestras espurias de baja ocurrencia. Suponiendo el uso de una de las técnicas de filtro mencionadas anteriormente (promedio móvil, exponencial), una vez que haya suficiente historia (una Constante de Tiempo) puede probar la nueva muestra de datos entrantes para determinar si es razonable antes de que se agregue a la computación. Se requiere cierto conocimiento de la tasa de cambio razonable máxima de la señal. La muestra bruta se compara con el valor suavizado más reciente, y si el valor absoluto de esa diferencia es mayor que el intervalo permitido, esa muestra es expulsada (o reemplazada por alguna heurística, por ejemplo, una predicción basada en el diferencial de pendiente o la tendencia Valor de predicción de doble exponencial suavizado) respondió 30 de abril a las 6:56 sé que esto es alcanzable con el impulso como por: Pero realmente me gustaría evitar el uso de impulso. He googled y no he encontrado ningún ejemplo adecuado o legible. Básicamente, quiero seguir el promedio móvil de una corriente en curso de una corriente de números de punto flotante utilizando los números 1000 más recientes como una muestra de datos. ¿Cuál es la manera más fácil de lograr esto experimenté con el uso de una matriz circular, media móvil exponencial y una media móvil más simple y encontró que los resultados de la matriz circular se adapta a mis necesidades mejor. Si sus necesidades son simples, puede intentar usar una media móvil exponencial. Puesto simplemente, usted hace una variable del acumulador, y como su código mira cada muestra, el código actualiza el acumulador con el nuevo valor. Usted escoge un alfa constante que está entre 0 y 1, y calcule esto: Usted apenas necesita encontrar un valor del alfa donde el efecto de una muestra dada dura solamente cerca de 1000 muestras. Hmm, no estoy realmente seguro de que esto es adecuado para usted, ahora que he puesto aquí. El problema es que 1000 es una ventana bastante larga para un promedio móvil exponencial No estoy seguro de que haya un alpha que se extendería el promedio en los últimos 1000 números, sin subflujo en el cálculo de punto flotante. Pero si usted quisiera un promedio más pequeño, como 30 números o tan, esto es una manera muy fácil y rápida de hacerla. Respondió 12 de junio 12 en 4:44 1 en su puesto. El promedio móvil exponencial puede permitir que el alfa sea variable. Así, esto permite que se utilice para calcular promedios de base de tiempo (por ejemplo, bytes por segundo). Si el tiempo transcurrido desde la última actualización del acumulador es de más de 1 segundo, deje que alfa sea 1.0. De lo contrario, puede permitir que alpha be (usecs desde la última actualización / 1000000). Ndash jxh 12 de junio a las 6:21 Básicamente, quiero seguir el promedio móvil de una corriente en curso de una corriente de números de punto flotante usando los números 1000 más recientes como una muestra de datos. Tenga en cuenta que el siguiente actualiza el total como elementos añadidos / reemplazados, evitando costosos recorridos O (N) para calcular la suma - necesaria para el promedio - a la demanda. Total se hace un parámetro diferente de T a soporte, p. Usando un largo largo cuando totalizan 1000 long s, un int para char s, o un doble a total float s. Esto es un poco defectuoso en que numsamples podría ir más allá de INTMAX - si te importa que podría utilizar un unsigned mucho tiempo. O utilice un miembro de datos de bool extra para grabar cuando el contenedor se rellena primero mientras cicla numsamples alrededor de la matriz (mejor entonces cambia el nombre de algo inocuo como pos). Respondió el 12 de Junio ​​12 a las 5:19 se supone que el operador quotvoid (T sample) quot es realmente operador quotvoid (T sample) quot. Ndash oPless Jun 8 14 at 11:52 oPless ahhh. bien descrito. En realidad quería que fuera para ser operador vacío () (T muestra), pero por supuesto, usted podría utilizar cualquier notación que te gustaba. Se arreglará, gracias. Ndash Tony D Jun 8 14 at 14: 27Intro Una de las principales aplicaciones de la placa Arduino es la lectura y registro de datos de sensores. Por ejemplo uno monitorea la presión cada segundo del día. Como frecuencias de muestreo altas a menudo generan picos en los gráficos, también se quiere tener un promedio de las mediciones. Como las mediciones no son estáticas en el tiempo lo que a menudo se necesita es un promedio de funcionamiento. Éste es el promedio de un cierto período y muy valioso al hacer análisis de la tendencia. La forma más simple de un promedio de ejecución se puede hacer por el código que se basa en el promedio anterior de ejecución: Si uno no quiere utilizar matemáticas punto flotante - como esto ocupa la memoria y disminuye la velocidad - uno puede hacer lo mismo completamente en el dominio entero. La división por 256 en el código de ejemplo es un desplazamiento a la derecha 8, que es más rápido que decir división por ejemplo. 100. Esto es cierto para cada potencia de 2 como divisor y sólo uno debe tener cuidado la suma de los pesos es igual a la potencia de 2. Y por supuesto uno debe tener cuidado no hay desbordamiento intermedio (considere el uso de unsigned largo) Si necesita Un promedio de ejecución más preciso, in concreto de las últimas 10 mediciones, se necesita una matriz (o lista vinculada) para mantenerlos. Esta matriz actúa como un amortiguador circular y con cada nueva medida se elimina la más antigua. El promedio de ejecución se calcula como la suma de todos los elementos divididos por el número de elementos de la matriz. El código para el promedio de ejecución será algo como esto: Desventaja de este código es que la matriz para contener todos los valores puede llegar a ser bastante grande. Si usted tiene una medición por segundo y desea un promedio de ejecución por minuto que necesita una matriz de 60 un promedio por hora necesitaría una matriz de 3600. Eso no podría hacerse de esta manera en un Arduino, ya que sólo tiene 2 K de RAM. Sin embargo, mediante la construcción de un promedio de 2 etapas se puede abordar bastante bien (renuncia: no para todas las mediciones). En el código psuedo: Como una nueva matriz estática interna es necesaria para cada función runningAverage, esto grita para ser implementado como una clase. Biblioteca RunningAverage La biblioteca runningAverage crea una clase de la función anterior para que pueda usarse varias veces en un boceto. Desacopla la función add () y avg () para que sea un poco más flexible, p. Uno puede llamar al promedio varias veces sin agregar nada. Tenga en cuenta que cada instancia de la clase añade su propia matriz para realizar mediciones, y que esto se suma al uso de la memoria. La interfaz de la clase se mantiene lo más pequeña posible. Nota: con la versión 0.2 los nombres de los métodos se hacen más descriptivos. Uso Un pequeño bosquejo muestra cómo se puede utilizar. Un generador aleatorio se utiliza para imitar un sensor. En setup () el myRA se borra para que podamos empezar a agregar nuevos datos. En loop () primero se genera un número aleatorio y se convierte en un flotador que se agregará a myRA. A continuación, el valor de ejecución se imprime en el puerto serie. También se puede mostrar en algunos LCD o enviar a través de Ethernet, etc Cuando se añaden 300 elementos myRA se borra para empezar de nuevo. Notas Para utilizar la biblioteca, cree una carpeta en su SKETCHBOOKPATHlibaries con el nombre RunningAverage y coloque allí. h y. cpp. Opcionalmente, haga un subdirectorio de ejemplos para colocar la aplicación de ejemplo. Historia 2011-01-30: inicial versión 2011-02-28: fijo desaparecido destructor en archivo. h 2011-02-28: eliminado por defecto constructor 2012--. Añadido fillValue () refactorizado para la publicación 2017-07-03: agregó código de protección de la memoria - si la matriz interna no se puede asignar tamaño Se convierte en 0. Esto es para solucionar el problema descrito aquí - forum. arduino. cc/indextopic50473.msg1790086msg1790086 - Todo Pruebe extensivamente. Clase de plantilla EjecuciónActiva. h EjecuciónActividad. cppAmedios / Promedio móvil simple Promedios / Promedio móvil simple Se le anima a que resuelva esta tarea de acuerdo con la descripción de la tarea, utilizando cualquier idioma que conozca. Calculando el promedio móvil simple de una serie de números. Crear una función / clase / instancia con estado que toma un punto y devuelve una rutina que toma un número como argumento y devuelve una media móvil simple de sus argumentos hasta ahora. Un promedio móvil simple es un método para calcular un promedio de una corriente de números haciendo sólo el promedio de los últimos 160 P 160 números de la corriente 160, donde 160 P 160 se conoce como el período. Se puede implementar llamando a una rutina de iniciación con 160 P 160 como su argumento, 160 I (P), 160 que debe devolver una rutina que cuando se llama con miembros individuales sucesivos de un flujo de números, calcula la media de (arriba A), los últimos 160 P 160 de ellos, permite llamar a este 160 SMA (). La palabra 160 estado 160 en la descripción de la tarea se refiere a la necesidad de 160 SMA () 160 para recordar cierta información entre las llamadas a ella: 160 El período, 160 P 160 Un contenedor ordenado de al menos los últimos 160 P 160 números de cada uno de Sus llamadas individuales. El estado 160 también significa que las llamadas sucesivas a 160 I (), 160 el inicializador, 160 deben devolver rutinas separadas que no 160 comparten el estado guardado para que puedan ser utilizadas en dos flujos independientes de datos. El pseudo-código para una implementación de 160 SMA 160 es: Esta versión utiliza una cola persistente para contener los valores p más recientes. Cada función devuelta desde init-moving-average tiene su estado en un átomo que contiene un valor de cola. Esta implementación utiliza una lista circular para almacenar los números dentro de la ventana al principio de cada indicador de iteración se refiere a la celda de lista que contiene el valor que acaba de salir de la ventana y que se reemplazará con el valor simplemente añadido. Uso de un cierre En la actualidad, este sma no puede ser nogc porque asigna un cierre en el montón. Algún análisis de escape podría eliminar la asignación de montón. Uso de una edición de estructura Esta versión evita la asignación de montón del cierre manteniendo los datos en el marco de pila de la función principal. La misma salida: Para evitar que las aproximaciones de punto flotante sigan acumulándose y creciendo, el código podría realizar una suma periódica en toda la matriz de cola circular. Esta implementación produce dos objetos (de función) compartiendo estado. Es idiomático en E separar la entrada de la salida (leer de la escritura) en lugar de combinarlos en un objeto. La estructura es la misma que la implementación de la Desviación EstándarE. El programa de elixir siguiente genera una función anónima con un período incrustado p, que se utiliza como el período de la media móvil simple. La función run lee la entrada numérica y la pasa a la función anónima recién creada, y luego inspecciona el resultado a STDOUT. La salida se muestra a continuación, con el promedio, seguido por la entrada agrupada, formando la base de cada media móvil. Erlang tiene cierres, pero variables inmutables. Una solución entonces es utilizar procesos y un mensaje simple que pasa la API basada. Los lenguajes de matriz tienen rutinas para calcular los avarages de deslizamiento para una secuencia dada de ítems. Es menos eficiente realizar bucle como en los siguientes comandos. Pide continuamente una entrada I. Que se añade al final de una lista L1. L1 se puede encontrar pulsando 2ND / 1, y la media se puede encontrar en List / OPS Pulse ON para terminar el programa. Función que devuelve una lista que contiene los datos promediados del argumento suministrado Programa que devuelve un valor simple en cada invocación: list es la lista que se promedia: p es el período: 5 devuelve la lista promedio: Ejemplo 2: Utilizando el programa movinav2 , 5) - Inicializando el cálculo del promedio móvil, y definir el período de 5 movinav2 (3, x): x - nuevos datos en la lista (valor 3), y el resultado se almacenará en la variable x, y se muestra movinav2 (4, : X - nuevos datos (valor 4), y el nuevo resultado se almacenará en la variable x, y se mostrará (43) / 2. Descripción de la función movinavg: variable r - es el resultado (la lista de promedios) que se devolverá variable i - es la variable de índice, y apunta al final de la sub-lista de la lista de promediar. Variable z - una variable auxiliar La función utiliza la variable i para determinar qué valores de la lista serán considerados en el siguiente cálculo promedio. En cada iteración, la variable i apunta al último valor de la lista que se utilizará en el cálculo promedio. Así que sólo tenemos que averiguar cuál será el primer valor en la lista. Por lo general, hay que tener en cuenta los elementos p, por lo que el primer elemento será el indexado por (i-p1). Sin embargo, en las primeras iteraciones, el cálculo será normalmente negativo, por lo que la siguiente ecuación evitará los índices negativos: max (i-p1,1) o, ordenando la ecuación, max (i-p, 0) 1. Pero el número de elementos en las primeras iteraciones también será menor, el valor correcto será (índice final - comenzar índice 1) o, ordenando la ecuación, (i - (max (ip, 0) 1), y luego , (I - max (ip, 0)). La variable z tiene el valor común (max (ip), 0) así que el beginindex será (z1) y los numberofelements serán (iz) mid (list, z1, iz) devolverá la lista de valor que será la suma promedio .) Los sumará sum (.) / (Iz) ri los medirá y almacenará el resultado en el lugar apropiado en la lista de resultados Usando un cierre y creando una función

No comments:

Post a Comment