C# FFT相关系数的计算
我想用RGE 2.2.5计算两个声音样本的相关系数 我已经阅读了计算互相关的公式。C# FFT相关系数的计算,c#,image-processing,fft,correlation,cross-correlation,C#,Image Processing,Fft,Correlation,Cross Correlation,我想用RGE 2.2.5计算两个声音样本的相关系数 我已经阅读了计算互相关的公式。 我读过计算相关系数的公式 这就是我目前拥有的: 在调用CrossCorrelation()之前,已执行FFT 静态复数[]互相关(复数[]ffta,复数[]fftb) { var conj=ffta.Select(i=>newcomplex(i.Re,-i.Im)).ToArray(); for(int a=0;ai.squaredmagnity).Max(); var Denominora=a.Select(i
我读过计算相关系数的公式 这就是我目前拥有的:
在调用CrossCorrelation()之前,已执行FFT
静态复数[]互相关(复数[]ffta,复数[]fftb)
{
var conj=ffta.Select(i=>newcomplex(i.Re,-i.Im)).ToArray();
for(int a=0;ai.squaredmagnity).Max();
var Denominora=a.Select(i=>i.magnity).Max();
var denominorb=b.Select(i=>i.magnificate).Max();
返回分子/(分母*分母);
}
我不确定这是否是实现功能(或处理数据)的正确方法,因为我对DSP非常陌生。如果有人能为我指出正确的方向,我将不胜感激。要与FFTs和Afrog进行互相关:
- 用零填充信号: 根据fft的正式文件: 该方法只接受2n大小的数据数组,其中n可能在[1,14]范围内变化
- 对两个信号进行FFT
- 将一个与另一个的共轭相乘(按元素相乘)
- 进行逆FFT
- 取最大值作为共振系数,其指数作为延迟(信号滞后)
//same as OP
public Complex[] CrossCorrelation(Complex[] ffta, Complex[] fftb)
{
var conj = ffta.Select(i => new Complex(i.Re, -i.Im)).ToArray();
conj = conj.Zip(fftb, (v1, v2) => Complex.Multiply(v1, v2)).ToArray();
FourierTransform.FFT(conj, FourierTransform.Direction.Backward);
//get that data and plot in Excel, to show the max peak
Console.WriteLine("---------rr[i]---------");
double[] rr = new double[conj.Length];
rr = conj.Select(i => i.Magnitude).ToArray();
for (int i = 0; i < conj.Length; i++)
Console.WriteLine(rr[i]);
Console.WriteLine("----end-----");
return conj;
}
//tuble.Item1: Cor. Coefficient
//tuble.Item2: Delay of signal (Lag)
public Tuple<double, int> CorrelationCoefficient(Complex[] ffta, Complex[] fftb)
{
Tuple<double, int> tuble;
var correlation = CrossCorrelation(ffta, fftb);
var seq = correlation.Select(i => i.Magnitude);
var maxCoeff = seq.Max();
int maxIndex = seq.ToList().IndexOf(maxCoeff);
Console.WriteLine("max: {0}", maxIndex);
tuble = new Tuple<double, int>(maxCoeff, maxIndex);
return tuble;
}
// Pad signal with zeros up to 2^n and convert to complex
public List<Complex> ToComplexWithPadding(List<double> sample, int padding = 1)
{
//As per AForge documentation:
// The method accepts data array of 2n size only, where n may vary in the [1, 14] range
//So you would need to make sure the input size is correctly padded to a length that is a power of 2, and in the specified range:
double logLength = Math.Ceiling(Math.Log(sample.Count * padding, 2.0));
int paddedLength = (int)Math.Pow(2.0, Math.Min(Math.Max(1.0, logLength), 14.0));
Complex[] complex = new Complex[paddedLength];
var samples = sample.ToArray();
// copy all input samples
int i = 0;
for (; i < sample.Count; i++)
{
complex[i] = new Complex(samples[i], 0);
Console.WriteLine(complex[i].Re);
}
// pad with zeros
for (; i < paddedLength; i++)
{
complex[i] = new Complex(0, 0);
Console.WriteLine(complex[i].Re);
}
return complex.ToList();
}
// extra for signal generation for testing. You can find in the link of the life demo.
你用测试数据试过了吗?它是否返回了预期的结果?为每个传递特定输入的函数编写一些单元测试,并将实际结果与预期值进行比较。您不需要传递整个声音文件,只需创建一些可以手动计算(或使用其他程序)的小数组。我同意Panagiotis Kanavos的观点。例如,你知道两个相同信号之间的相关性将为1。我认为在返回结果之前需要一个平方根(在第二个链接公式中给出),这里是平方系数
//same as OP
public Complex[] CrossCorrelation(Complex[] ffta, Complex[] fftb)
{
var conj = ffta.Select(i => new Complex(i.Re, -i.Im)).ToArray();
conj = conj.Zip(fftb, (v1, v2) => Complex.Multiply(v1, v2)).ToArray();
FourierTransform.FFT(conj, FourierTransform.Direction.Backward);
//get that data and plot in Excel, to show the max peak
Console.WriteLine("---------rr[i]---------");
double[] rr = new double[conj.Length];
rr = conj.Select(i => i.Magnitude).ToArray();
for (int i = 0; i < conj.Length; i++)
Console.WriteLine(rr[i]);
Console.WriteLine("----end-----");
return conj;
}
//tuble.Item1: Cor. Coefficient
//tuble.Item2: Delay of signal (Lag)
public Tuple<double, int> CorrelationCoefficient(Complex[] ffta, Complex[] fftb)
{
Tuple<double, int> tuble;
var correlation = CrossCorrelation(ffta, fftb);
var seq = correlation.Select(i => i.Magnitude);
var maxCoeff = seq.Max();
int maxIndex = seq.ToList().IndexOf(maxCoeff);
Console.WriteLine("max: {0}", maxIndex);
tuble = new Tuple<double, int>(maxCoeff, maxIndex);
return tuble;
}
// Pad signal with zeros up to 2^n and convert to complex
public List<Complex> ToComplexWithPadding(List<double> sample, int padding = 1)
{
//As per AForge documentation:
// The method accepts data array of 2n size only, where n may vary in the [1, 14] range
//So you would need to make sure the input size is correctly padded to a length that is a power of 2, and in the specified range:
double logLength = Math.Ceiling(Math.Log(sample.Count * padding, 2.0));
int paddedLength = (int)Math.Pow(2.0, Math.Min(Math.Max(1.0, logLength), 14.0));
Complex[] complex = new Complex[paddedLength];
var samples = sample.ToArray();
// copy all input samples
int i = 0;
for (; i < sample.Count; i++)
{
complex[i] = new Complex(samples[i], 0);
Console.WriteLine(complex[i].Re);
}
// pad with zeros
for (; i < paddedLength; i++)
{
complex[i] = new Complex(0, 0);
Console.WriteLine(complex[i].Re);
}
return complex.ToList();
}
// extra for signal generation for testing. You can find in the link of the life demo.
correlation Coef: 0.33867796353274 | Delay: 11| actual delay: 11