You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 07:24:18