Memang mungkin untuk melakukan seperti yang Anda sarankan tetapi tidak tanpa beberapa efek samping. Katakanlah kita membentuk sinyal uji sederhana mana:s(t)=slow(t)+shigh(t)
slow(t)=cos(2πf0t)+cos(2πf1t+π3)
shigh(t)=12⋅cos(2πf2t+0.2)
di mana kami mengatakan bahwa kedua berada di bawah frekuensi cut-off lowpass yang dipilih sedemikian rupa sehingga , dan kami memilih . Kita tentu saja dapat memilih amplitudo seperti yang kita inginkan dan saya baru saja memilih yang di atas untuk menjaga hal-hal sederhana. Dengan memiliki dua kontribusi frekuensi di bawah frekuensi cut-off dan satu di atas membuatnya mudah untuk mengikuti dan membandingkan sinyal.f0,f1fcutf0<f1<fcutf2>fcut
Berikut ini saya berasumsi bahwa kami memiliki sampel diambil dengan frekuensi . Pada kenyataannya, kami memilih untuk membuat sinyal yang diamati menjadi halus. Juga diasumsikan bahwa kami hanya mempertimbangkan satu kumpulan sampel data. Jika Anda perlu menangani beberapa kerangka waktu, periksa kertas karya Fred Harris bernama "Pada Penggunaan Windows untuk Analisis Harmonik dengan Transformasi Fourier Diskrit" dari Proc. IEEE pada tahun 1978.Nfs>2⋅f2fs≫2⋅f2
Saya telah menggabungkan program Python kecil untuk menggambarkan beberapa konsep - kodenya cukup buruk tetapi saya hanya mengambil beberapa kode lama yang saya miliki untuk masalah yang sama. Meskipun hampir tidak ada komentar, itu harus cukup mudah diikuti karena modul kecil. Ada dua fungsi dft / idft ; dua fungsi fshiftn / fshiftp untuk mengubah frekuensi sinyal i DFT domain untuk penyaringan; sebuah fungsi dftlpass untuk melakukan pemfilteran dalam domain DFT; fungsi zpblpass untuk melakukan penyaringan dengan menggunakan filter Butterworth; fungsi bbdftsig untuk membentuk sinyal uji dan melakukan penyaringan; dan akhirnya sebuah fungsi plot keciluntuk merencanakan sinyal. Di akhir skrip, parameter yang berbeda diatur dan angka yang berbeda dibuat.
"""
Test of DFT versus scipy.signal.butter filtering with respect to
signal reconstruction.
"""
# import ############################################################ import #
import matplotlib as mpl; mpl.rcParams['backend'] = 'Agg'
import matplotlib.pyplot as mplpp
import matplotlib.mlab as mplml
import numpy as np
import scipy.signal as sps
# initialize #################################################### initialize #
try:
mpl.rc('text', usetex=False)
mpl.rc('font', family='serif')
mpl.rc('font', serif='STIXGeneral')
mpl.rc('font', size=8)
except AttributeError:
None
# dft ################################################################## dft #
def dft(xt, fs, t0):
N, d = len(xt), -2j*np.pi/len(xt)
w = np.arange(N, dtype=np.float).reshape((N,1))
c = np.exp(d*t0*fs*w)
W = np.exp(d*np.dot(w,np.transpose(w)))
xf = np.multiply(c,np.dot(W,xt)) / float(N)
f = w*fs/float(N)
return xf, f
# idft ################################################################ idft #
def idft( X, FS, T0 ):
N, d = len(X), 2j*np.pi/len(X)
w = np.arange(N, dtype=float).reshape((N,1))
cc = np.exp(d*T0*FS*w)
Wc = np.exp(d*np.dot(w, np.transpose(w)))
Y = np.dot(Wc, np.multiply(cc, X))
return Y
# fshiftn ########################################################## fshiftn #
def fshiftn( xf, f ):
assert type(f) == np.ndarray, "f must be a np.ndarray"
assert f.shape[1] == 1, "f must be a column array"
assert xf.shape[1] == 1, "xf must be a column array"
assert sum(f<0) == 0, "All frequency components must be 0 or positive"
# Determine sampling rate, tolerance, and allocate output array
fs, tol = len(f)*(np.abs(f[1,0]-f[0,0])), 1.E-2
fshift = np.zeros((len(f),1), dtype=float)
xfshift = np.zeros((len(f),1), dtype=complex)
# Determine index where f > fs/2
Nm = np.floor(len(f)/2.0)
Np = np.floor((len(f)-1.0)/2.0)
# Compute output frequency array such that -fs/2 <= f < fs/2 and the
# corresponding Fourier coefficients
fshift[:Nm,0] = f[Np+1:,0] - fs
fshift[Nm,0] = f[0,0]
fshift[Nm+1:,0] = f[1:Np+1,0]
xfshift[:Nm,0] = xf[Np+1:,0]
xfshift[Nm,0] = xf[0,0]
xfshift[Nm+1:,0] = xf[1:Np+1,0]
return xfshift, fshift
# fshiftp ########################################################## fshiftp #
def fshiftp(xf, f):
assert type(f) == np.ndarray, "f must be a np.ndarray"
assert f.shape[1] == 1, "f must be a column array"
assert xf.shape[1] == 1, "xf must be a column array"
assert sum(f<0) > 0, "Some input frequencies must be negative"
# Determine sampling rate, tolerance, and allocate output array
fs, tol = len(f)*(np.abs(f[1,0]-f[0,0])), 1.E-2
fshift = np.zeros((len(f),1), dtype=float)
xfshift = np.zeros((len(f),1), dtype=complex)
# Determine index where f > fs/2
#Nx = np.floor((len(f)+1+tol)/2)
Nm = np.floor(len(f)/2.0)
Np = np.floor((len(f)-1.0)/2.0)
# Compute output frequency array such that -fs/2 <= f < fs/2 and the
# corresponding Fourier coefficients
fshift[Np+1:,0] = f[:Nm:,0] + fs
fshift[0,0] = f[Nm,0]
fshift[1:Np+1:,0] = f[Nm+1:,0]
xfshift[Np+1:,0] = xf[:Nm:,0]
xfshift[0,0] = xf[Nm,0]
xfshift[1:Np+1:,0] = xf[Nm+1:,0]
return xfshift, fshift
# dftlpass ######################################################## dftlpass #
def dftlpass(xt, fs, fcut):
# Perform Discrete Fourier Transform
xf, f = dft(xt, fs, 0.0)
# Shift frequencies to -fs/2 <= f < fs/2 ... and coefficients
xfshift, fshift = fshiftn(xf, f)
# Perform filtration
xfshift = xfshift * (np.abs(fshift) <= fcut)
# Re-shift frequencies to 0 <= f < fs ... and coefficients
xfrecon, frecon = fshiftp(xfshift, fshift)
# Perform inverse Discrete Fourier Transform
yt = idft(xfrecon, fs, 0.0)
return yt.real
# zpblpass ######################################################## zpblpass #
def zpblpass(xn, fcal, fs, fcut):
bz, az = sps.butter(5, fcut/(fs/2))
# Gain calibration
Ncal = np.max([np.int(20*fs/fcal), 30000])
Nguard = np.int(0.1*Ncal)
t = np.arange(Ncal) / fs
x0_cal = 1.0 * np.cos(2*np.pi*fcal*t)
yi_cal = sps.filtfilt(bz, az, 2.0*x0_cal*np.cos(2*np.pi*fcal*t))
k = 1.0/np.mean(yi_cal[Nguard:Ncal-Nguard])
# Scaled output
yn = k * sps.filtfilt(bz, az, xn)
return yn
# bbdftsig ######################################################## bbdftsig #
def bbdftsig(f0, f1, f2, fcut, fs, N):
t = np.arange(N).reshape((N,1)) / fs
s0 = np.sin(2*np.pi*f0*t)
s1 = np.sin(2*np.pi*f1*t + 0.2)
s2 = 0.7 * np.sin(2*np.pi*f2*t + np.pi/3.0)
slow = s0 + s1
s = slow + s2
sf = dftlpass(s, fs, fcut)
sfdftv = sf.reshape((N))
sv = s.reshape((N))
slowv = slow.reshape((N))
sv = s.reshape((N))
sfzpbv = zpblpass(sv, f1, fs, fcut)
#sfzpbv = sfzpb.reshape((N))
return sv, slowv, sfdftv, sfzpbv
# plotsigs ######################################################## plotsigs #
def plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname):
n = np.arange(s.shape[0])
# Plot results
mplpp.figure(1, (5.0,2.25))
mplpp.clf()
mplpp.plot(n[Nstart:Nstop], s[Nstart:Nstop], 'm-',
n[Nstart:Nstop:4], s[Nstart:Nstop:4], 'mx',
n[Nstart:Nstop], slow[Nstart:Nstop], 'g-',
n[Nstart:Nstop:10], slow[Nstart:Nstop:10], 'gx',
n[Nstart:Nstop], sfdft[Nstart:Nstop], 'r-',
n[Nstart:Nstop:15], sfdft[Nstart:Nstop:15], 'rx',
n[Nstart:Nstop], sfzpb[Nstart:Nstop], 'b-',
linewidth=1.5)
mplpp.legend([r'$s$', r'$s$', r'$s_{\rm low}$', r'$s_{\rm low}$',
r'DFT', r'DFT', r'ZPB'], loc='upper right')
mplpp.ylabel(r'Signal')
mplpp.xlabel(r'$n$')
#mplpp.axis([-10.0, 10.0, 1.0E-2, 1.0E2])
mplpp.grid(True)
mplpp.savefig(fname, dpi=600,
bbox_inches='tight', pad_inches=0.05)
mplpp.close()
# __main__ ######################################################## __main__ #
if __name__ == '__main__':
# Initialize
f0 = 3.0
f1 = 11.5
f2 = 20.0
fcut = 15.0
fs = 1000.0
N = 5000
s, slow, sfdft, sfzpb = bbdftsig(f0, f1, f2, fcut, fs, N)
n = np.arange(s.shape[0])
# Fig. 1: full data set
Nstart = 0
Nstop = N
fname = 'full.pdf'
plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)
# Fig. 2: beginning
Nstart = 0
Nstop = 150
fname = 'beginning.pdf'
plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)
# Fig. 3: middle
Nstart = np.floor(N/2.0) - 75
Nstop = Nstart + 100
fname = 'middle.pdf'
plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)
# Fig. 4: ending
Nstart = N - 150
Nstop = N
fname = 'ending.pdf'
plotsigs(s, slow, sfdft, sfzpb, Nstart, Nstop, fname)
Memilih dan memberi kita resolusi frekuensi Hz. Jika kita memilih sesuai dengan ini kita bisa mendapatkan persetujuan sempurna dengan memilih frekuensi seperti yang ditunjukkan di atas. Jika kita pertama-tama memilih frekuensi yang ada di grid sebagai , , dan kita memiliki kita mendapatkan set hasil pertama. Bagian pertama, tengah dan terakhir dari sinyal yang relevan ditunjukkan di bawah ini:N=5000fs=1000fs/N=0.2f0,f1,f2f0=3f1=11f2=21fcut=15
Seperti yang terlihat dari gambar, kita memiliki input gabungan sebagai sinyal magenta; sinyal hijau seperti yang hanya bisa kita lihat dari tanda 'x' adalah (sinyal input mentah ketika kita hanya memasukkan sinyal input di bawah frekuensi cut-off); sinyal merah adalah sinyal yang kami dapatkan saat menggunakan filter DFT; dan sinyal biru adalah yang kita dapatkan dari filter Butterworth. Seperti yang terlihat di atas, kami memperoleh persetujuan sempurna antara dan sinyal DFT yang difilter - tetapi filter Butterworth memiliki beberapa dampak pada sinyal in-band (khususnya komponen disslowslowf1. Seperti yang cukup tipikal untuk jenis pengolahan ini, kami memiliki beberapa perbedaan di awal dan akhir urutan karena efek tepi dan kesepakatan yang cukup baik antara kedua jenis penyaringan di bagian tengah.
Jika kita mengubah frekuensi menjadi yang tidak ada di kisi frekuensi (dan lebih jauh itu cukup dekat dengan frekuensi cut-off), kita melihat beberapa hasil yang berbeda seperti yang ditunjukkan di bawah ini.f1f1=11.5
Sekarang kita melihat perbedaan besar antara sinyal hijau, biru dan merah yang dalam situasi ideal harus identik. Di tengah-tengah sinyal mereka semua setuju dengan cukup baik - DFT dan referensi setuju dengan yang terbaik.slow
Jadi kesimpulannya adalah mungkin untuk menggunakan penyaringan langsung dengan memaksa koefisien Fourier ke nol yang juga kadang-kadang dilakukan dalam penginderaan tekan untuk mengurangi dukungan sinyal untuk memaksa sparsity pada sinyal. Namun, ada konsekuensi dari ini sebagai peningkatan kesalahan khususnya di tepi sinyal. Selanjutnya, di atas adalah kasus terbaik di mana seluruh sinyal diperlakukan sebagai satu urutan. Jika sinyal harus dipecah dalam kerangka waktu maka akan menjadi rumit karena kita perlu mempertimbangkan beberapa teknik windowing atau lainnya untuk memastikan kontinuitas sinyal di antara frame. Jadi saran saya mirip dengan beberapa posting lain dalam merekomendasikan untuk menggunakan Butterworth / Elliptic / .. atau filter apa pun secara normal.