Как вывести спектрограмму высокого разрешения в формате .png для шумоподавления и выделения сигнала на основе спектрограммы - PullRequest
0 голосов
/ 13 апреля 2019

Я пытаюсь сформировать спектрограмму из 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

...