s ( t ) = sl o w( t ) + sh i g h( t )
Sl o w( t ) = cos( 2 πf0t ) + cos( 2 πf1t + π3)
Sh i g h( t ) = 12⋅ cos( 2 πf2t + 0,2 )
f0, f1fc utf0< f1< fc u tf2> fc u t
NfS> 2 ⋅ f2fS≫ 2 ⋅ f2
Tôi đã kết hợp một chương trình Python nhỏ để minh họa một số khái niệm - mã này khá khủng khiếp nhưng tôi chỉ lấy một số mã cũ mà tôi gặp phải cho các vấn đề tương tự. Mặc dù hầu như không có bất kỳ bình luận nào, nhưng nó khá dễ theo dõi do các mô-đun nhỏ. Hai hàm dft / idft ; hai chức năng fshiftn / fshiftp để thay đổi tần số tín hiệu i miền DFT để lọc; một dftlpass chức năng để thực hiện lọc trong miền DFT; một hàm zpblpass để thực hiện quá trình lọc bằng cách sử dụng bộ lọc Butterworth; một hàm bbdraftig để tạo tín hiệu kiểm tra và thực hiện lọc; và cuối cùng là một lô nhỏ chức năngđể vẽ các tín hiệu. Ở cuối tập lệnh, các tham số khác nhau được đặt và các số liệu khác nhau được thực hiện.
"""
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)
N= 5000fS= 1000fS/ N= 0,2f0, f1, f2f0= 3f1= 11f2= 21fc u t= 15
SSl o wSl o wf1. Vì khá điển hình cho kiểu xử lý này, chúng tôi có một số khác biệt ở đầu và cuối chuỗi do hiệu ứng cạnh và thỏa thuận hợp lý tốt giữa cả hai loại lọc trong phần giữa.
f1f1= 11,5
Sl o w
Vì vậy, để kết luận, có thể sử dụng lọc trực tiếp bằng cách buộc các hệ số Fourier về 0, đôi khi cũng được thực hiện trong cảm biến nén để giảm sự hỗ trợ của tín hiệu để buộc độ thưa của tín hiệu. Tuy nhiên, có những hậu quả của điều này khi các lỗi gia tăng đặc biệt ở các cạnh của tín hiệu. Hơn nữa, ở trên là trường hợp tốt nhất trong đó toàn bộ tín hiệu được coi là một chuỗi. Nếu tín hiệu phải được phân chia trong các khung thời gian thì nó trở nên phức tạp vì khi đó chúng ta cần xem xét một số kỹ thuật cửa sổ hoặc kỹ thuật khác để đảm bảo tính liên tục của tín hiệu giữa các khung. Vì vậy, lời khuyên của tôi tương tự như một số bài đăng khác trong việc khuyến nghị sử dụng bình thường Butterworth / Elliptic / .. hoặc bất kỳ bộ lọc nào.