You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#中基于Accord Framework计算归一化互相关系数?

Great to hear you’ve got the basic FFT-based cross-correlation working smoothly with Accord Framework! Let’s break down how to compute normalized cross-correlation (NCC) coefficients, which will scale your results to a [-1, 1] range for easier interpretation.

First, Let’s Recap the Normalization Formula

The core idea of NCC is to divide the raw cross-correlation results by the product of the L2 norms (Euclidean norms) of your two input arrays. For global normalization (applying the same scaling factor to all correlation values), the formula is:

NCC(a, b) = corr(a, b) / (||a||₂ * ||b||₂)

If you’re working with template matching or need sliding-window normalization (where each correlation value is scaled based on the local window of a aligned with b), we’ll cover that too.

Step 1: Formalize Your Existing Cross-Correlation Code

First, let’s lock in the cross-correlation implementation you already have (using Accord’s FFT utilities for efficiency):

using Accord.Math;
using Accord.Math.Transforms;

public static double[] CrossCorrelateFFT(double[] a, double[] b)
{
    int corrLength = a.Length + b.Length - 1;
    int fftLength = FourierTransform.NextPowerOfTwo(corrLength);

    // Pad both arrays to the next power of two for optimized FFT computation
    double[] aPadded = a.Pad(fftLength, 0);
    double[] bPadded = b.Pad(fftLength, 0);

    // Compute FFTs, multiply by the conjugate of b's FFT, then inverse FFT
    Complex[] fftA = FourierTransform.FFT(aPadded, FourierTransform.Direction.Forward);
    Complex[] fftB = FourierTransform.FFT(bPadded, FourierTransform.Direction.Forward);
    Complex[] fftProduct = fftA.Multiply(fftB.Conjugate());

    // Extract real values from inverse FFT and trim to the actual correlation length
    double[] rawCorr = FourierTransform.IFFT(fftProduct, FourierTransform.Direction.Backward).Real;
    return rawCorr.Take(corrLength).ToArray();
}

Step 2: Add Global Normalization

Now, wrap this in a method that calculates the L2 norms and applies the scaling to get normalized coefficients:

public static double[] NormalizedCrossCorrelateFFT(double[] a, double[] b)
{
    double[] rawCorr = CrossCorrelateFFT(a, b);

    // Calculate L2 norms of the original input arrays
    double normA = Vector.Norm2(a);
    double normB = Vector.Norm2(b);

    // Guard against division by zero (handle near-zero values for numerical stability)
    if (normA < 1e-10 || normB < 1e-10)
        throw new ArgumentException("One or both input arrays have near-zero norm; normalization is undefined.");

    double normProduct = normA * normB;

    // Normalize each element of the raw correlation result
    return rawCorr.Select(value => value / normProduct).ToArray();
}

Step 3: Sliding-Window (Template-Match) Normalization (Optional)

If you need NCC for tasks like template matching (where you want to compare local regions of a to b), you’ll want to center both arrays by subtracting their means first. This removes bias from constant offsets (like brightness differences) and gives a more robust match score:

public static double[] NormalizedCrossCorrelateSlidingFFT(double[] a, double[] b)
{
    int corrLength = a.Length + b.Length - 1;
    int fftLength = FourierTransform.NextPowerOfTwo(corrLength);

    // Center the arrays by subtracting their respective means
    double meanA = a.Mean();
    double meanB = b.Mean();
    double[] aCentered = a.Subtract(meanA);
    double[] bCentered = b.Subtract(meanB);

    // Compute cross-correlation of the centered arrays
    double[] centeredCorr = CrossCorrelateFFT(aCentered, bCentered);

    // Calculate the denominator: product of square roots of sum-of-squares for centered arrays
    double sumSqA = aCentered.Select(x => x * x).Sum();
    double sumSqB = bCentered.Select(x => x * x).Sum();
    double denominator = Math.Sqrt(sumSqA * sumSqB);

    if (denominator < 1e-10)
        throw new ArgumentException("Centered arrays have near-zero variance; normalization is undefined.");

    // Normalize and trim to the correct correlation length
    return centeredCorr.Take(corrLength).Select(value => value / denominator).ToArray();
}

Key Notes

  • Global normalization scales all correlation values to [-1, 1], where 1 means perfect positive alignment, -1 means perfect negative alignment, and 0 means no correlation.
  • Sliding-window (centered) normalization is ideal for template matching, as it ignores constant brightness or offset differences between the target array and template.

内容的提问来源于stack exchange,提问作者Trion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:42:53