본문으로 바로가기

# Spectrogram_python

category Domain/Audio 2020. 9. 16. 10:40

Spectrogram(시간, 주파수) 구하는 파이썬 코드에 대해 기술한다.

 

[50Hz, 20Hz 짜리 합성된 신호(z)]

- Sampling rate(Fs) : 1초 당 2000개 

#-*- coding:utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

Fs = 2000.
Ts = 1 / Fs
te = 1.0
t = np.arange(0.0, te, Ts)

# Signal x (20Hz) + Signal y (50Hz)
x = np.cos(2 * np.pi * 20 * t)
y = np.cos(2 * np.pi * 50 * t)

# Signal z
z = x + y

N = len(z)

k = np.arange(N)
T = N / Fs
freq = k / T
freq = freq[range(int(N/2))]

# FFT 적용
yfft = np.fft.fft(z)
yf = yfft / N
yf = yf[range(int(N/2))]

plt.rcParams["figure.figsize"] = (15,4)

# FFT 출력
plt.plot(freq, abs(yf), 'b')
plt.xlabel('Frequency')
plt.ylabel('Amplitude')
plt.xlim(0, Fs / 20)
plt.show()

FFT 출력

 

FFT 결과를 보면 주파수 성분 50Hz, 20Hz가 존재하는 것을 확인 할 수 있다.

 

하지만 이 그림에서는 어느 시점에 해당 주파수 성분이 존재하는지 알 수 없다.

따라서, STFT (고정된 시간 길이로 분할 및 FFT 수행)을 통해 해당 시점에 주파수성분을 알 수 있게 된다.

 

 

[신호(z)에 대한 Spectrogram 분석]

Spectgrogram 구하는 4가지 방법 

- pylab

- matplotlib.specgram

- scipy의 signal

- librosz의 stft

import pylab 
from scipy import signal


## Spectrogram type 1
f, tt, Sxx = signal.spectrogram(z, Fs)

plt.pcolormesh(tt, f, Sxx, shading='gouraud')
plt.title('Spectrogram type 1')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.ylim(0, 200)
plt.show()
    
## Spectrogram type 2
pp, ff, tt, pplot = pylab.specgram(
z,
NFFT=256,
Fs=2000,
detrend=pylab.detrend_none, 
window=pylab.window_hanning,
noverlap=int(128 * 0.5))
pylab.title('Spectrogram type 2')
pylab.ylim(0, 200)


## Spectrogram type 3
fig, (ax1, ax2) = plt.subplots(nrows=2)

ax1.plot(t, z)
ax1.set_xlabel('Time(s)')
ax1.set_ylabel('Amplitude')
fig.tight_layout()

Pxx, freqs, bins, im = ax2.specgram(z, NFFT=256, Fs=Fs, noverlap=int(128 * 0.5))
ax2.set_title('Spectrogram type 3')
ax2.set_xlabel('Time(s)')
ax2.set_ylabel('Frequency')
fig.tight_layout()

plt.show()

 

signal.spectrogram

- 해당 결과를 y축 0~200으로 확대시키면 다음과 같이 50Hz, 20Hz에서의 변화를 감지할 수 있다.

pylab.specgram

plt.specgram

원 z 신호(위)와 스펙트로그램(아래)

 

librosa.stft

- 파이썬 STFT를 사용한 Spectrogram

import librosa.display

# STFT power spectrum
D_octave = np.abs(librosa.stft(z))
librosa.display.specshow(librosa.amplitude_to_db(D_octave, ref=np.max), sr=Fs, y_axis='linear', x_axis='time')
plt.title('Spectrogram type 4')
plt.ylim(0, 200)
plt.show()

 

 

 

'Domain > Audio' 카테고리의 다른 글

# Band pass Filter + Low pass Filter + High pass Filter_python  (3) 2020.09.17
# FFT_python  (0) 2020.07.05