Я пытаюсь сформировать спектрограмму из 8-минутной волны акустики дельфина и сохранить ее в виде файла изображения. Цель состоит в том, чтобы использовать алгоритмы удаления шума и выделения, упомянутые в следующей статье: https://pdfs.semanticscholar.org/9cbf/d5b23600d4976f27ea454329f183b1fe6166.pdf
Основная идея заключается в том, что щелчки дельфинов почти всегда представлены в виде вертикальных широкополосных всплесков на спектрограмме, в то время как свистки разлетаются по диагональной кривой. Алгоритмы ищут пиксели максимальной интенсивности, а затем смотрят на соседние пиксели. Если пиксельные окрестности являются вертикальными, то они ослабляются, если они не поддерживаются.
Этот код был получен из http://www.frank -zalkow.de / en / code-snippets / create-audio-спектрограммы-с-python.html? Ckattempt = 1 Я использую его, потому что мне нравится Легко настраиваемый коэффициент размера в plotstft def.
Код создает спектрограмму, в которую я могу масштабировать и находить сигналы с достаточной четкостью, но когда я смотрю на сформированный файл .png, при масштабировании разрешение оказывается недостаточным. Свистки обычно имеют длину 0,4-1,3 секунды, а каждый щелчок - около 0,1 секунды. Поэтому мне нужно иметь возможность увеличить разрешение, достаточное для того, чтобы увидеть время, подходящее под эти длины.
Кроме того, я пытаюсь выяснить, как отфильтровать все частоты> = 5000 Гц и <= 16000 Гц, но я не слишком уверен, что настроить в моем коде. </p>
Я настроил fig1.savefig ('Spectrogram.png', dpi = 500) для увеличения dpi. Я получаю ошибки памяти на 1000 точек на дюйм.
Также я увеличил размер бина в def plotstft (audiopath, binsize = 2xx12, plotpath = None, colormap = "Grays"): до 2xx12, что обеспечивает отличное разрешение при использовании функции масштабирования на рисунке.
AS для фильтрации частот. Я пытался выяснить, какой массив содержит сами частоты, чтобы я мог удалить из массива те, которые находятся за пределами моих границ, но мне не слишком повезло.
import numpy as np
from matplotlib import pyplot as plt
import scipy.io.wavfile as wav
from numpy.lib import stride_tricks
def stft(sig, frameSize, overlapFac=0.5, window=np.hanning):
win = window(frameSize)
hopSize = int(frameSize - np.floor(overlapFac * frameSize))
# zeros at beginning (thus center of 1st window should be for sample nr. 0)
samples = np.append(np.zeros(int(np.floor(frameSize/2.0))), sig)
# cols for windowing
cols = np.ceil( (len(samples) - frameSize) / float(hopSize)) + 1
# zeros at end (thus samples can be fully covered by frames)
samples = np.append(samples, np.zeros(frameSize))
frames = stride_tricks.as_strided(samples, shape=(int(cols), frameSize), strides=(samples.strides[0]*hopSize, samples.strides[0])).copy()
frames *= win
return np.fft.rfft(frames)
def logscale_spec(spec, sr=44100, factor=20.):
timebins, freqbins = np.shape(spec)
scale = np.linspace(0, 1, freqbins) ** factor
scale *= (freqbins-1)/max(scale)
scale = np.unique(np.round(scale))
# create spectrogram with new freq bins
newspec = np.complex128(np.zeros([timebins, len(scale)]))
for i in range(0, len(scale)):
if i == len(scale)-1:
newspec[:,i] = np.sum(spec[:,int(scale[i]):], axis=1)
else:
newspec[:,i] = np.sum(spec[:,int(scale[i]):int(scale[i+1])], axis=1)
# list center freq of bins
allfreqs = np.abs(np.fft.fftfreq(freqbins*2, 1./sr)[:freqbins+1])
freqs = []
fmin = 5000
fmax = 16000
for i in range(0, len(scale)):
if i == len(scale)-1:
freqs += [np.mean(allfreqs[int(scale[i]):])]
else:
freqs += [np.mean(allfreqs[int(scale[i]):int(scale[i+1])])]
return newspec, freqs
def plotstft(audiopath, binsize=2**12, plotpath=None, colormap="Greys"):
samplerate, samples = wav.read(audiopath)
s = stft(samples, binsize)
sshow, freq = logscale_spec(s, factor=1.0, sr=samplerate)
ims = 20.*np.log10(np.abs(sshow)/10e-6) # amplitude to decibel
timebins, freqbins = np.shape(ims)
print("timebins: ", timebins)
print("freqbins: ", freqbins)
plt.figure(figsize=(15, 7.5))
plt.imshow(np.transpose(ims), origin="lower", aspect="auto", cmap=colormap, interpolation="none")
plt.colorbar()
plt.xlabel("time (s)")
plt.ylabel("frequency (hz)")
plt.xlim([0, timebins-1])
plt.ylim([0, freqbins])
xlocs = np.float32(np.linspace(0, timebins-1, 5))
plt.xticks(xlocs, ["%.02f" % l for l in ((xlocs*len(samples)/timebins)+(0.5*binsize))/samplerate])
ylocs = np.int16(np.round(np.linspace(0, freqbins-1, 10)))
plt.yticks(ylocs, ["%.02f" % freq[i] for i in ylocs])
if plotpath:
plt.savefig(plotpath, bbox_inches="tight")
else:
fig1 = plt.gcf()
plt.show()
fig1.savefig('Spectrogram.png', dpi=500)
plt.clf()
return ims
ims = plotstft('8min.wav')
Вывод изображения спектрограммы с высоким разрешением с той же степенью разрешения в пикселях, что и при увеличении в fi