算法简介
从幅度、频率、相位三个维度对一维信号进行正弦拟合,从而达到去燥及输出标准波形的目的。可以根据实际需求修改分段长度、拟合带宽,其中分段长度的选取是假定信号在分段时间内平稳且必须大于一个信号周期。
算法效果如下:
完整代码(java)
//参数说明:input为输入的一维信号,fr为输入信号采样率。算法默认使用32点的分段长度,即要求信号在32点的时间内是平稳的且信号单周期长度小于32点,用户可根据实际需求修改分段长度。算法默认拟合带宽为0.8~3Hz,用户同样可以按需修改带宽。
float[] CurveFittingAlgorithm(float[] input, float fr){
ArrayList resultList=new ArrayList();
float[] seg=new float[32];
double[] y=new double[32];
double scale=3;
double best_freq=0;
double best_phase=0;
for(int p=0;p<input.length/32;p++) {
//数据分段,每32点拟合一次
for (int q = 32 * p; q < 32 * (p + 1); q++) {
seg[q - 32 * p] = input[q];
}
//分段拟合,实现幅度、相位、频率对齐
double max=0;
//double scale=findMax(seg);
for (int k = 0; k < 45; k++) {
double phase = (Math.PI) * k / 22.5; //相位分辨率8度
for (int j = 0; j < 44; j++) {
double freq = 0.8 + 0.05 * j; //0.8~3Hz带宽等间隔切成44份,频率分辨率0.05Hz
for (int i = 0; i < seg.length; i++) {
double t = (double) i / fr;
y[i] = scale * Math.sin(2 * (Math.PI) * freq * t + phase);
}
double sum = 0;
for (int m = 0; m < seg.length; m++) {
sum = sum + seg[m] * y[m];
}
if (sum > max) {
max = sum;
best_freq = freq;
best_phase = phase;
}
}
}
//找到最佳匹配后进行存储
for (int r = 0; r < seg.length; r++) {
double t = (double) r / fr;
y[r] =scale*Math.sin(2 * (Math.PI) *best_freq* t+best_phase);
resultList.add(y[r]);
}
}
float[] output =new float[resultList.size()];
for(int i=0;i<output.length;i++){
output[i]=Float.parseFloat(resultList.get(i).toString());
}
System.out.println("拟合曲线:"+Arrays.toString(output));
return output;
}