计算FFT相关系数 [英] Calculating FFT Correlation Coefficient

查看:91
本文介绍了计算FFT相关系数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 AForge 2.2.5 计算2个声音样本的相关系数.

I would like to calculate the correlation coefficient of 2 sound samples using AForge 2.2.5.

我从此处,我已经阅读了有关计算相关系数的公式.

I've read from here the formula to calculate Cross Correlation.
And here I've read about the formula to calculate the correlation coefficient.

这是我目前拥有的:
在调用CrossCorrelation()之前,已执行FFT.

static Complex[] CrossCorrelation(Complex[] ffta, Complex[] fftb)
{
    var conj = ffta.Select(i => new Complex(i.Re, -i.Im)).ToArray();

    for (int a = 0; a < conj.Length; a++)
        conj[a] = Complex.Multiply(conj[a], fftb[a]);

    FourierTransform.FFT(conj, FourierTransform.Direction.Backward);

    return conj;
}

static double CorrelationCoefficient(Complex[] ffta, Complex[] fftb)
{
    var correlation = CrossCorrelation(ffta, fftb);
    var a = CrossCorrelation(ffta, ffta);
    var b = CrossCorrelation(fftb, fftb);

    // Not sure if this part is correct..
    var numerator = correlation.Select(i => i.SquaredMagnitude).Max();
    var denominatora = a.Select(i => i.Magnitude).Max();
    var denominatorb = b.Select(i => i.Magnitude).Max();

    return numerator / (denominatora * denominatorb);
}

我不确定这是否是实现功能(或处理数据)的正确方法,因为我是DSP的新手.如果有人能指出我正确的方向,将不胜感激.

I'm not sure if that is the right way to implement the function (or handling the data) as I'm very new to DSP. Will greatly appreciate it if someone could point me to the right direction.

推荐答案

使用FFT和Afrog进行互相关:

To do Cross-correlation with FFTs and Afrog:

  • 带有零的填充信号:根据fft的AForge文档:该方法仅接受2n大小的数据数组,其中n可能在[1,14]范围内变化.

因此,您需要确保将输入大小正确填充到2的幂的长度,并在指定范围内:考虑到至少有一半的波浪是空白"(零)

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: taking into account at least half of the wave is "blank" (zeros)

参考:

https://dsp.stackexchange.com/questions/741/为什么要在进行傅立叶变换之前先将i-zero-pad-a-signal

https://dsp.stackexchange.com/questions/1919/ficiently-calculating-autocorrelation-using-ffts

  • 对两个信号进行FFT
  • 将一个与另一个的共轭相乘(按元素相乘)
  • 进行逆FFT
  • 将最大值作为一个相关系数,并将其索引作为延迟(信号滞后)

为什么所得IFFT的最大值:

来自维基百科,互相关可用于确定两个之间的时间延迟信号,例如用于确定在麦克风阵列上传播声信号的时间延迟. 2 [3] [需要澄清]在计算两个信号之间的互相关之后,互相关函数的最大值(如果信号为负相关,则为最小值)指示信号最佳对齐的时间点,即,两个信号之间的时间延迟为由互相关的最大值或arg max的参数确定,如

from wikipedia, Cross-correlations are useful for determining the time delay between two signals, e.g. for determining time delays for the propagation of acoustic signals across a microphone array.2[3][clarification needed] After calculating the cross-correlation between the two signals, the maximum (or minimum if the signals are negatively correlated) of the cross-correlation function indicates the point in time where the signals are best aligned, i.e. the time delay between the two signals is determined by the argument of the maximum, or arg max of the cross-correlation, as in

参考: https://math.stackexchange.com/questions/1080709/为什么在相似部分获得互相关的最大价值

基于以上几点,交叉计算使用以下代码进行计算:

Based on the above points, the Cross Calculation is calculated using the following code:

  //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.

您可以使用延迟11生成的两个信号样本运行生活演示结果与信号的实际延迟相符

You can run life demo with sample of two signal generated with delay 11 and the result match the actual delay of the signal

具有两个信号的生活演示

输出结果:

 correlation Coef: 0.33867796353274 | Delay: 11| actual delay: 11

这篇关于计算FFT相关系数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆