Я обнаружил, что моя машина борется со сверткой, поэтому я предлагаю следующее решение:
Быстрое вычисление окна RMS с быстрым вычислением
Предположим, у нас есть аналоговые выборки напряжения a0 ...99 (сто отсчетов), и нам нужно пройти через них среднеквадратичное отклонение из 10 отсчетов.
Окно будет первоначально сканировать элементы от a0 до a9 (десять отсчетов), чтобы получить rms0.
# rms = [rms0, rms1, ... rms99-9] (total of 91 elements in list):
(rms0)^2 = (1/10) (a0^2 + ... + a9^2) # --- (note 1)
(rms1)^2 = (1/10) (... a1^2 + ... + a9^2 + a10^2) # window moved a step, a0 falls out, a10 comes in
(rms2)^2 = (1/10) ( a2^2 + ... + a10^2 + a11^2) # window moved another step, a1 falls out, a11 comes in
...
Упрощение: у нас есть a = [a0, ... a99]
Чтобы создать скользящее среднеквадратичное значение из 10 выборок, мы можем взять sqrt сложения 10 a^2
и умножить на 1/10.
Другими словами, если мы имеем
p = (1/10) * a^2 = 1/10 * [a0^2, ... a99^2]
Чтобы получить rms^2
, просто добавьте группу из 10 человек.
Давайте получим acummulator acu:
acu = p0 + ... p8 # (as in note 1 above)
Тогда мы можем иметь
rms0^2 = p0 + ... p8 + p9
= acu + p9
rms1^2 = acu + p9 + p10 - p0
rms2^2 = acu + p9 + p10 + p11 - p0 - p1
...
мы можем создать:
V0 = [acu, 0, 0, ... 0]
V1 = [ p9, p10, p11, .... p99] -- len=91
V2 = [ 0, -p0, -p1, ... -p89] -- len=91
V3 = V0 + V1 + V2
, если мы запустим itertools.accumulate(V3)
, мы получим rms-массив
Код:
import numpy as np
from itertools import accumulate
a2 = np.power(in_ch, 2) / tm_w # create array of p, in_ch is samples, tm_w is window length
v1 = np.array(a2[tm_w - 1 : ]) # v1 = [p9, p10, ...]
v2 = np.append([0], a2[0 : len(a2) - tm_w]) # v2 = [0, p0, ...]
acu = list(accumulate(a2[0 : tm_w - 1])) # get initial accumulation (acu) of the window - 1
v1[0] = v1[0] + acu[-1] # rms element #1 will be at end of window and contains the accumulation
rmspw2 = list(accumulate(v1 - v2))
rms = np.power(rmspw2, 0.5)
Я могу вычислитьмассив из 128 мегапикселей менее чем за 1 минуту.