我正在开发一款Android应用程序,需要检测用户的上下文(是否在最小行驶或步行)。
我正在使用加速度计和所有轴的总和来检测加速度矢量。在步行时,它的工作效果相当不错,我可以看到一些周期性的值。但是我需要以编程方式检测这些周期。
请问是否有任何数学函数可以检测一组值中的周期?我听说傅里叶变换可用于此,但我真的不知道如何实现它。它看起来非常复杂:)
请帮帮我
我正在开发一款Android应用程序,需要检测用户的上下文(是否在最小行驶或步行)。
我正在使用加速度计和所有轴的总和来检测加速度矢量。在步行时,它的工作效果相当不错,我可以看到一些周期性的值。但是我需要以编程方式检测这些周期。
请问是否有任何数学函数可以检测一组值中的周期?我听说傅里叶变换可用于此,但我真的不知道如何实现它。它看起来非常复杂:)
请帮帮我
i
处的自相关性,只需将数据中的每个数据点与移位i
的每个数据点相乘即可。以下是一些伪代码:for i = 0 to length( data ) do
autocorrel[ i ] = 0;
for j = 0 to length( data ) do
autocorrel[ i ] += data( j ) * data( ( j + i ) mod length( data ) )
done
done
[1, 2, 1.2, 1.8]
,然后你可以从每个样本中提取1.5,留下[-.5, .5, -.3, .3]
。现在,如果你将其在偏移量为零的位置相乘,负数将与负数相乘,正数将与正数相乘,得到(-.5)^2 + (.5)^2 + (-.3)^2 + (.3)^2=.68
。在偏移量为1的位置,负数将与正数相乘,得到(-.5)*(.5) + (.5)*(-.3) + (-.3)*(.3) + (.3)*(-.5)=-.64
。在偏移量为2的位置,负数再次与负数相乘,正数与正数相乘。在偏移量为3的位置,类似于偏移量为1的情况。你会发现,在偏移量为0和2(周期)时,得到的是正值,在1和4处得到的是负值。McLeodPitchMethod
中的一个方法,使其能够使用FFT优化的自相关算法计算音高:private void normalizedSquareDifference(final double[] data) {
int n = data.length;
// zero-pad the data so we get a number of autocorrelation function (acf)
// coefficients equal to the window size
double[] fft = new double[2*n];
for(int k=0; k < n; k++){
fft[k] = data[k];
}
transformer.ft(fft);
// the output of fft is 2n, symmetric complex
// multiply first n outputs by their complex conjugates
// to compute the power spectrum
double[] acf = new double[n];
acf[0] = fft[0]*fft[0]/(2*n);
for(int k=1; k <= n-1; k++){
acf[k] = (fft[2*k-1]*fft[2*k-1] + fft[2*k]*fft[2*k])/(2*n);
}
// inverse transform
transformerEven.bt(acf);
// the output of the ifft is symmetric real
// first n coefficients are positive lag acf coefficients
// now acf contains acf coefficients
double[] divisorM = new double[n];
for (int tau = 0; tau < n; tau++) {
// subtract the first and last squared values from the previous divisor to get the new one;
double m = tau == 0 ? 2*acf[0] : divisorM[tau-1] - data[n-tau]*data[n-tau] - data[tau-1]*data[tau-1];
divisorM[tau] = m;
nsdf[tau] = 2*acf[tau]/m;
}
}
其中transformer
是来自Java FFTPACK翻译的FFTTransformer
类的私有实例,而transformerEven
是FFTTransformer_Even
类的私有实例。使用您的数据调用McLeodPitchMethod.getPitch()
将给出非常有效的频率估计。
package com.spec.example;
import android.app.Activity;
import android.os.Bundle;
import com.badlogic.gdx.audio.analysis.FFT;
import java.lang.String;
import android.util.FloatMath;
import android.widget.TextView;
public class spectrogram extends Activity {
/** Called when the activity is first created. */
float[] array = {1, 6, 1, 4, 5, 0, 8, 7, 8, 6, 1,0, 5 ,6, 1,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float[] array_hat,res=new float[array.length/2];
float[] fft_cpx,tmpr,tmpi;
float[] mod_spec =new float[array.length/2];
float[] real_mod = new float[array.length];
float[] imag_mod = new float[array.length];
double[] real = new double[array.length];
double[] imag= new double[array.length];
double[] mag = new double[array.length];
double[] phase = new double[array.length];
int n;
float tmp_val;
String strings;
FFT fft = new FFT(32, 8000);
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
fft.forward(array);
fft_cpx=fft.getSpectrum();
tmpi = fft.getImaginaryPart();
tmpr = fft.getRealPart();
for(int i=0;i<array.length;i++)
{
real[i] = (double) tmpr[i];
imag[i] = (double) tmpi[i];
mag[i] = Math.sqrt((real[i]*real[i]) + (imag[i]*imag[i]));
phase[i]=Math.atan2(imag[i],real[i]);
/****Reconstruction****/
real_mod[i] = (float) (mag[i] * Math.cos(phase[i]));
imag_mod[i] = (float) (mag[i] * Math.sin(phase[i]));
}
fft.inverse(real_mod,imag_mod,res);
}
}
更多信息请参见:http://www.digiphd.com/android-java-reconstruction-fast-fourier-transform-real-signal-libgdx-fft/