Обнаружение движения по дисперсии
Урок-практикум: ловим движение по тому, что сигнал датчика начинает «гулять» сильнее обычного.
Детектор движения по дисперсии объявляет движение, когда разброс (стандартное отклонение) сигнала в окне превышает порог, заданный с запасом над уровнем шума покоя.
Многие движения проще обнаружить не по среднему уровню, а по изменчивости. В покое датчик (PIR, акселерометр, освещённость) даёт почти постоянный сигнал с малым шумом; при движении сигнал начинает колебаться сильнее. Сравним дисперсию окна с порогом.
Дисперсия как мера активности
Стандартное отклонение окна из $N$ отсчётов:
$$ \sigma = \sqrt{\frac{1}{N}\sum_{i=1}^{N}(x_i - \bar{x})^2} $$
Если $\sigma \gt \sigma_{thr}$ — фиксируем движение. Порог берут заметно выше шума покоя.
import statistics
def is_motion(window, thr):
return statistics.pstdev(window) > thr
quiet = [100, 101, 99, 100, 102] # покой
moving = [100, 140, 99, 100, 30] # движение
print("покой:", round(statistics.pstdev(quiet), 2),
"-> движение?", is_motion(quiet, 5.0))
print("движение:", round(statistics.pstdev(moving), 2),
"-> движение?", is_motion(moving, 5.0))Вывод:
покой: 1.02 -> движение? False движение: 28.0 -> движение? True
Скользящее окно и удержание
На потоке дисперсию считают по скользящему окну. Чтобы событие не дёргалось, к нему применяют тот же гистерезис, что и к порогам (раздел 7): включаем по высокому порогу, держим состояние «движение» ещё несколько отсчётов после спада.
import statistics
def motion_stream(signal, w=4, thr=5.0):
out = []
for i in range(len(signal)):
lo = max(0, i - w + 1)
window = signal[lo:i+1]
sd = statistics.pstdev(window) if len(window) > 1 else 0.0
out.append(1 if sd > thr else 0)
return out
sig = [100, 100, 101, 130, 90, 105, 100, 100, 100]
print(motion_stream(sig))Вывод:
[0, 0, 0, 1, 1, 1, 1, 1, 0]
Как работает под капотом
Детектор по дисперсии нечувствителен к постоянному смещению: его волнует не уровень, а изменчивость, поэтому медленный дрейф нуля его не обманет. Порог $\sigma_{thr}$ калибруют, замерив дисперсию покоя и взяв запас в несколько раз. Слишком низкий порог даст ложные срабатывания от шума, слишком высокий пропустит слабое движение. Это та же логика «сигнал против шума», что пронизывает весь курс: мы отделяем полезное событие от фоновой дрожи, зная статистику покоя.
Частые ошибки
- Ставить порог близко к шуму покоя — детектор будет ложно срабатывать.
- Детектировать движение по среднему уровню — дрейф нуля собьёт его.
- Брать слишком короткое окно — дисперсия станет неустойчивой и шумной.
Итог
- Движение надёжно ловится по росту дисперсии (разброса) сигнала.
- Порог берут с запасом над дисперсией покоя; помогает гистерезис.
- Метод нечувствителен к смещению — реагирует на изменчивость, а не на уровень.