簡體   English   中英

用於3d傳感器信號的FFT

[英]FFT for 3d sensor signal

我有加速度信號數據的3d數組,其采樣頻率為50赫茲,這意味着時間步長為1/50 = .02。 我的目標是使用Numpy或Scipy計算此傳感器的主頻率。 我的問題是,我應該分別計算每列的頻率,使用多維fft或計算單個Vector,然后計算fft。

我使用以下函數來計算主頻率。


from scipy import fftpack
import numpy as np
def fourier(signal, timestep):
    data = signal - np.mean(signal)
    N = len(data) // 2  # we need half of data
    freq = fftpack.fftfreq(len(data), d=timestep)[:N]
    fft = fftpack.fft(data)[:N]
    amp = np.abs(fft) / N
    order = np.argsort(amp)[::-1]  ## sort based on the importance
    return freq[order][0]

加速計傳感器的3D陣列產生5維的陣列:空間坐標,時間和加速度的分量。

time維度上采用DFT 對應於一次分析一個傳感器:每個傳感器將產生一個主頻率,可能從一個傳感器到另一個傳感器略有不同,就好像傳感器是分開的一樣。

作為替代方案,讓我們考慮在空間坐標和時間上進行DFT。 它對應於將復合信號寫為正弦平面波的總和:

圖片描述

其中Ǹ是通過將點數乘以時間樣本數得到的比例因子。 在續集中,我將從x,y,z,t,k_x,k_y,k_z和w中獨立地刪除此全局縮放。

在這一點上,對產生這種加速度的物理進行建模將是一項重要的資產。 實際上,如果這種現象是分散的,使用這種DFT幾乎沒有意義。 無論如何,均勻材料中的擴散,彈性或聲學是非分散的:每個頻率獨立於其他頻率。 此外,知道物理學是有用的,因為可以定義能量。 例如,與波k_x,k_y,k_z,w相關的動能寫入:

XXX

因此,與給定頻率w相關的動能寫入:

因此,這種推理提供了一種基於物理的方式來合並逐點DFT 確實,根據Parseval的身份:

關於實際考慮因素,如你所做的那樣減去平均數確實是一個好的開始。 如果通過乘以1 / w ^ 2來計算速度,則零頻率(即平均值)將被歸零,以避免無限或Nan的出現。

此外,在計算時間DFT之前應用窗口可以幫助限制與頻譜泄漏相關的問題。 DFT設計用於與幀的周期一致的周期信號。 更具體地說,它計算通過一次又一次地重復幀構建的信號的傅里葉變換。 結果,人為的不連續性可能出現在邊緣處,從而引起誤導的不存在的頻率。 窗口靠近框架邊緣靠近零點,從而減少了不連續性及其影響。 因此,可以建議將窗口應用於空間維度,以保持與物理平面波分解的一致性。 這將導致給3D陣列中心的加速器增加更多的重量。

平面波分解還要求傳感器的空間間隔必須比預期波長小約兩倍。 否則,會出現另一種稱為混疊的現象。 然而,功率譜W(w)對該問題的敏感性可能低於平面波分解。 相反,如果從加速度開始計算彈性應變能量,則混疊可能成為一個真正的問題,因為計算應變需要相對於空間坐標的導數,即乘以k_x,k_y或k_z,並且空間混疊對應於使用錯了k_x。

一旦計算出W(w),就可以通過計算峰值相對於功率密度的平均頻率來估計對應於每個峰值的頻率,如為什么使用FFT在信號中舍入頻率值?

下面是一個示例代碼,生成一些與幀大小(時間和空間)不一致的頻率平面波。 應用漢寧窗,計算動能並且回溯對應於每個峰的頻率。

import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
import scipy



spacingx=1.
spacingy=1.
spacingz=1.
spacingt=1./50.
Nx=5
Ny=5
Nz=5
Nt=512

frequency1=9.5
frequency2=13.7
frequency3=22.3
#building a signal
acc=np.zeros((Nx,Ny,Nz,Nt,3))
for i in range(Nx):
    for j in range(Ny):
        for k in range(Nz):
            for l in range(Nt):

                acc[i,j,k,l,0]=np.sin(i*spacingx+j*spacingy-2*np.pi*frequency1*l*spacingt)
                acc[i,j,k,l,1]=np.sin(i*spacingx+1.5*k*spacingz-2*np.pi*frequency2*l*spacingt)
                acc[i,j,k,l,2]=np.sin(1.5*i*spacingx+k*spacingz-2*np.pi*frequency3*l*spacingt)

#applying a window both in time and space
hanningx=np.hanning(Nx)
hanningy=np.hanning(Ny)
hanningz=np.hanning(Nz)
hanningt=np.hanning(Nt)

for i in range(Nx):
    hx=hanningx[i]
    for j in range(Ny):
        hy=hanningy[j]
        for k in range(Nz):
            hz=hanningx[k]
            for l in range(Nt):
                ht=hanningt[l]
                acc[i,j,k,l,0]*=hx*hy*hz*ht
                acc[i,j,k,l,1]*=hx*hy*hz*ht
                acc[i,j,k,l,2]*=hx*hy*hz*ht


#computing the DFT over time.
acctilde=np.fft.fft(acc,axis=3)


#kinetic energy
print acctilde.shape[3]
kineticW=np.zeros(acctilde.shape[3])
frequencies=np.fft.fftfreq(Nt, spacingt)

for l in range(Nt):
    oneonomegasquared=0.
    if l>0:
        oneonomegasquared=1.0/(frequencies[l]*frequencies[l])
    for i in range(Nx):
        for j in range(Ny):
            for k in range(Nz):
                kineticW[l]+= oneonomegasquared*(np.real(np.vdot(acctilde[i,j,k,l,:],acctilde[i,j,k,l,:])))



plt.plot(frequencies[0:acctilde.shape[3]],kineticW,'k-',label=r'$W(f)$')
#plt.plot(xi,np.real(fourier),'k-', lw=3, color='red', label=r'$f$, Hz')
plt.legend()
plt.show()

# see https://stackoverflow.com/questions/54714169/why-are-frequency-values-rounded-in-signal-using-fft/54775867#54775867
peaks, _= signal.find_peaks(kineticW, height=np.max(kineticW)*0.1)
print "potential frequencies index", peaks

#compute the mean frequency of the peak with respect to power density
powerpeak=np.zeros(len(peaks))
powerpeaktimefrequency=np.zeros(len(peaks))
for i in range(len(kineticW)):
    dist=1000
    jnear=0
    for j in range(len(peaks)):
        if dist>np.abs(i-peaks[j]):
             dist=np.abs(i-peaks[j])
             jnear=j
    powerpeak[jnear]+=kineticW[i]
    powerpeaktimefrequency[jnear]+=kineticW[i]*frequencies[i]


powerpeaktimefrequency=np.divide(powerpeaktimefrequency,powerpeak)
print 'corrected frequencies', powerpeaktimefrequency

在此輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM