Numpy рекомендации по фильтрации звука с использованием байесовского статистического анализа на двумерном массиве - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь создать аудиофильтр, который будет подавлять фоновые шумы в полевых записях, используя байесовский статистический подход. Типичный звук в поле содержит стандартный уровень фонового шума, который в моем случае нежелателен, когда я пытаюсь обнаружить шум переднего плана.

Используя numpy и scipy, можно проанализировать звук, чтобы определить статистическое стандартное отклонение выборки.

В моей среде шумы переднего плана обычно имеют плотность мощности, которая статистически отличается от фоновой. то есть значение плотности> = (2 стандартных отклонения + среднее значение) удельная мощность (на единицу частоты dft)

from scipy.io import wavfile
rate, audio = wavfile.read('test.wav')     

buckets = 64
nperseg = buckets * 2
noverlap = 10

freq, time, density = signal.spectrogram(audio, fs=rate, window='hann',
                                      nperseg=nperseg, noverlap=noverlap,
                                      detrend=False, scaling='density')

stdev = density.std(1)
mean = density.mean(1)

Проблема

Я надеюсь применить функцию на основе двумерного numpy массива звуковой мощности density в results. В результате получается высококонтрастный 2-мерный массив плотности мощности, значения которого равны либо 0,0, либо 1,0.

Используя 2-мерные данные, я обнаруживаю выбранные аудиозаписи (файлы .wav), которые либо содержат или не содержат звук переднего плана интереса. Затем я могу нарезать файл на куски размером с кусочек, когда возникает такая необходимость. У меня есть большое количество файлов wav + 100 МБ, поэтому время важно.

results = np.zeros((w,h))
sampleMean = mean.mean() # Average of averages

w,h = density.shape
for ww in range(w):
    for hh in range(h):

        # power density value
        v0 = density[ww][hh]

        # power density cutoff limit
        v1 = (2 * stdev[ww]) + mean[ww]

        if v0 > v1 and v0 > sampleMean:
            results[ww][hh] = 1.0

Этот l oop работает, но загружается медленно и безобразно. Это должно быть в состоянии быть написанным, избегая петель, но я - что-то вроде numb numpy noob. Могу ли я получить помощь? Еще лучше, если ответ pep8, как я также изучаю.

Существует ли встроенная функция numpy, такая как функция map (), которая передает индексы позиции массива в качестве аргументов? В этом случае меня не волнует манипулирование массивами на месте, так как я также использую density и results.

1 Ответ

1 голос
/ 01 апреля 2020

Один из способов сделать это - расширить матрицу stddev и среднюю матрицу до размера массива плотности с помощью np.repeat. Таким образом, если вы просто векторизуете вместо использования вложенных циклов for, это может значительно ускориться. Тогда вы можете просто сделать это, я предполагаю, что stdev, v1 и означают numpy массивы.

v1 = (2*stdev) + mean
v1_new = np.repeat(np.expand_dims(v1,axis=0), repeats = h, axis=0)
result[density>sampleMean and density>v1_new] = 1

Это будет просто векторизовать операции вместо того, чтобы иметь для l oop. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...