React Native中如何将运动电压数据通过FFT转换为频幅图
用FFT处理传感器数据生成频率-振幅图(React Native实现)
一、FFT核心概念先理清
- size参数:指参与FFT变换的样本点总数,必须是2的幂(如128、256、512)——这是FFT算法的优化要求,能大幅提升计算效率。如果你的原始数据长度不是2的幂,需要补零或截断到最近的2的幂值。
二、fft.js 完整使用示例
1. 安装依赖
npm install fft.js # 或 yarn add fft.js
2. 完整代码实现
import FFT from 'fft.js'; // 采样率:根据你的传感器实际采样频率修改(示例为每秒100个样本) const SAMPLE_RATE = 100; // 预处理原始数据:调整为2的幂长度,转成FFT需要的复数格式 function preprocessRawData(rawVoltageList) { // 找到大于等于原始数据长度的最小2的幂 let fftSize = 1; while (fftSize < rawVoltageList.length) { fftSize *= 2; } // 生成复数数组:[实部(电压值), 虚部(设为0)],超出原始长度的补0 const complexData = new Array(fftSize).fill(0).map((_, index) => [ rawVoltageList[index] || 0, 0 ]); return { complexData, fftSize }; } // 执行FFT并计算频率-振幅数据 function calculateFrequencyAmplitude(rawVoltageList) { const { complexData, fftSize } = preprocessRawData(rawVoltageList); const fftInstance = new FFT(fftSize); // 执行FFT变换(直接修改输入的complexData数组) fftInstance.transform(complexData); // 提取有效数据:FFT结果对称,仅取前半段即可 const result = []; const halfSize = Math.floor(fftSize / 2); for (let i = 0; i < halfSize; i++) { const [realPart, imagPart] = complexData[i]; // 计算振幅:复数模长,除以fftSize做归一化,让结果和原始电压幅度匹配 const amplitude = Math.sqrt(realPart ** 2 + imagPart ** 2) / fftSize; // 计算对应频率:(采样率 × 索引) / FFT大小 const frequency = (SAMPLE_RATE * i) / fftSize; result.push({ frequency, amplitude }); } return result; } // 调用示例 const rawVoltageData = [1023, 300, 200, 500, ...]; // 你的传感器原始数据 const freqAmpResult = calculateFrequencyAmplitude(rawVoltageData); console.log(freqAmpResult); // 输出[{frequency: 0, amplitude: x}, {frequency: 0.39, amplitude: y}, ...]
三、绘制频率-振幅图
React Native中可以用victory-native或react-native-chart-kit实现图表,以下是victory-native的示例:
1. 安装依赖
npm install victory-native react-native-svg
2. 图表组件实现
import { VictoryLine, VictoryChart, VictoryAxis, VictoryLabel } from 'victory-native'; function FrequencyAmplitudeChart({ data }) { return ( <VictoryChart domainPadding={{ x: 20, y: 10 }} style={{ parent: { width: '100%', height: 300 }, xAxis: { label: { fontSize: 12 } }, yAxis: { label: { fontSize: 12 } } }} > <VictoryAxis dependentAxis label="振幅" labelComponent={<VictoryLabel dy={-20} />} /> <VictoryAxis label="频率(Hz)" labelComponent={<VictoryLabel dy={20} />} /> <VictoryLine data={data} x="frequency" y="amplitude" style={{ data: { stroke: '#2196F3', strokeWidth: 2 } }} /> </VictoryChart> ); } // 调用:<FrequencyAmplitudeChart data={freqAmpResult} />
四、其他可选方案
- dsp.js:封装更上层的FFT方法,无需手动处理复数格式,直接传入实数组即可:
import * as dsp from 'dsp.js'; const fft = new dsp.FFT(256, SAMPLE_RATE); fft.forward(rawVoltageData); const amplitudes = fft.spectrum; // 直接得到振幅数组 - 积分方法:如果动作标准度判断依赖位移/速度变化,可对原始电压数据(需先转成加速度)做积分计算,但FFT更适合分析动作的周期性特征。
注意事项
- 采样率必须准确:频率计算完全依赖采样率,需和传感器实际采样频率保持一致,否则结果会偏差。
- 噪声处理:传感器数据通常带噪声,可先用低通滤波(如dsp.js的
dsp.LP12)预处理后再做FFT,结果更可靠。 - 非平稳信号:如果动作是阶段性的(如启动-持续-结束),可考虑用**短时傅里叶变换(STFT)**分析局部频率特征,dsp.js也支持相关方法。
内容的提问来源于stack exchange,提问作者asdzxsad
相关产品推荐
相关产品推荐

