Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# FFT相关系数的计算_C#_Image Processing_Fft_Correlation_Cross Correlation - Fatal编程技术网

C# FFT相关系数的计算

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

我想用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=>i.magnity).Max();
var denominorb=b.Select(i=>i.magnificate).Max();
返回分子/(分母*分母);
}

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

要与FFTs和Afrog进行互相关:

  • 用零填充信号: 根据fft的正式文件: 该方法只接受2n大小的数据数组,其中n可能在[1,14]范围内变化
因此,您需要确保输入大小正确填充到2的幂的长度,并且在指定的范围内: 考虑到至少一半的波形为“空白”(零)

参考:

  • 对两个信号进行FFT
  • 将一个与另一个的共轭相乘(按元素相乘)
  • 进行逆FFT
  • 取最大值作为共振系数,其指数作为延迟(信号滞后)
为什么生成IFFT的最大值:

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

参考:

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

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