You get a bonus - 1 coin for daily activity. Now you have 1 coin

The Fast Fourier Transform and Image Comparison

Lecture



The classical technique for comparing a current image with a reference image is based on treating images as two-dimensional brightness functions (discrete two-dimensional intensity matrices). Here, either the distance between the images or a measure of their similarity is computed.

As a rule, the following formula is used to compute the distance between images, being the sum of the absolute values or squares of the intensity differences:

The Fast Fourier Transform and Image Comparison


If, in addition to simply comparing two images, one needs to solve the problem of detecting the position of a fragment of one image within another, the classical "entry-level" method, which consists of iterating over all coordinates and computing the distance using the formula above, as a rule fails in practical use because of the large amount of computation required.

One of the methods that allows the amount of computation to be significantly reduced is the use of Fourier transforms and discrete Fourier transforms to calculate a measure of match between two images at various offsets relative to each other. In this case, the computation takes place simultaneously for different combinations of image shifts relative to one another.


Problem statement

  • Let there be two images X and Y – the image and the template, of sizes (N1,N2) and (M1,M2) respectively, with Ni > Mi
  • It is required to find the coordinates of the template Y within the full image X and to compute an estimated value — a measure of similarity.


For example, find:

the template


The Fast Fourier Transform and Image Comparison

in the image


The Fast Fourier Transform and Image Comparison

Correlation as a measure between images


By definition, the correlation <F,G> of two functions F and G is the quantity:

The Fast Fourier Transform and Image Comparison


This quantity is well known from the course on linear spaces in mathematics and geometry, where it is called the dot product. We will use the following formula as a measure between images:

The Fast Fourier Transform and Image Comparison


or

The Fast Fourier Transform and Image Comparison


This quantity is obtained from the dot product of vectors (treating images as vectors in a multidimensional space). Moreover, this same formula also represents the standard statistical test formula for the hypothesis that two probability distributions coincide.

Note:
When computing the correlation between image fragments, if one image is smaller than the other, we will divide only by the value of the norms of the overlapping parts.

Convolution of two functions


By definition, the convolution of two functions F and G is the function F×G:

The Fast Fourier Transform and Image Comparison

The Fast Fourier Transform and Image Comparison


It is also obvious that F×G'(t) is equal to the correlation obtained as a result of shifting one vector relative to the other by a step t (this is easy to verify by direct substitution of values into the correlation formula).

Fourier transform


The Fourier transform (ℱ) is an operation that maps one function of a real variable to another function, also of a real variable. This new function describes the coefficients ("amplitudes") in the expansion of the original function into elementary components — harmonic oscillations with different frequencies.

The Fourier transform of a function f of a real variable is an integral transform given by the following formula:

The Fast Fourier Transform and Image Comparison

Different sources may give definitions differing from the one above in the choice of the coefficient in front of the integral, as well as in the sign "−" in the exponent. But all the properties remain the same, although the form of some formulas may change.

In addition, there are various generalizations of this concept.

Multidimensional Fourier transform


The Fourier transform of functions defined on the space ℝ^n is given by the formula:

The Fast Fourier Transform and Image Comparison

The inverse transform in this case is given by the formula:

The Fast Fourier Transform and Image Comparison

As before, in different sources the definitions of the multidimensional Fourier transform may differ in the choice of the constant in front of the integral.

Discrete Fourier transform


The discrete Fourier transform (DFT in the English-language literature) is one of the Fourier transforms widely used in digital signal processing algorithms (its modifications are applied in MP3 audio compression, JPEG image compression, etc.), as well as in other fields related to frequency analysis of a discrete (for example, digitized analog) signal. The discrete Fourier transform requires a discrete function as input. Such functions are often created by sampling (taking values from continuous functions). Discrete Fourier transforms help solve partial differential equations and perform operations such as convolutions. Discrete Fourier transforms are also actively used in statistics, in time series analysis. Multidimensional discrete Fourier transforms also exist.

Formulas for discrete transforms


Forward transform:

The Fast Fourier Transform and Image Comparison

Inverse transform:

The Fast Fourier Transform and Image Comparison

The discrete Fourier transform is a linear transform that maps a vector of time samples to a vector of spectral samples of the same length. Thus the transform can be implemented as the multiplication of a symmetric square matrix by a vector:

The Fast Fourier Transform and Image Comparison

Fourier transforms for computing convolution


One of the remarkable properties of Fourier transforms is the ability to quickly compute the correlation of two functions defined either on a real argument (using the classical formula) or on a finite ring (using discrete transforms).

And although similar properties are inherent to many linear transforms, for practical application, to compute the convolution operation, according to the definition we have given, the following formula is used

The Fast Fourier Transform and Image Comparison


Where

  • FFT – the forward Fourier transform operation
  • BFT – the inverse Fourier transform operation


Verifying the correctness of the equality is fairly easy – by explicitly substituting into the Fourier transform formulas and simplifying the resulting formulas

Fourier transforms for computing correlation



Let <F,G>(t) be equal to the correlation obtained as a result of shifting one vector relative to the other by a step t
Then, as already shown earlier, the following holds

The Fast Fourier Transform and Image Comparison


If implementations of the Fourier transform algorithm using complex numbers are used, then such transforms have yet another remarkable property:

The Fast Fourier Transform and Image Comparison


Where CONJUGATE ( FFT(G) ) – is the matrix made up of the conjugate elements of the matrix FFT(G)
Thus, we obtain

The Fast Fourier Transform and Image Comparison


Fourier transforms for solving the problem


Using the formula for estimating the distance between images under a shift (i,j) relative to one another

The Fast Fourier Transform and Image Comparison


we obtain that

The Fast Fourier Transform and Image Comparison


Where

  • <X,Y>(i,j) – the scalar product of two images obtained under a shift (i,j) of images X and Y relative to one another
  • E – an image of size equal to the minimum dimensions of X and Y, filled with unit values (that is, the “frame” within which X and Y are compared)
  • |X|(i,j) – the norm of the common part of image X under a shift (i,j)
  • |Y|(i,j) – the norm of the common part of image Y under a shift (i,j)
  • FFT – the operation of the direct two-dimensional discrete Fourier transform
  • BFT – the operation of the inverse two-dimensional discrete Fourier transform
  • CONJUGATE – the operation of computing a matrix of conjugate elements
  • SQUAREMAGNITUDE– the operation of computing a matrix of squared amplitudes of the elements

Simplifying the formulas for solving the problem


When solving the problem of searching for a single sample, additional normalization of the sample is unnecessary, and also the computation of the norm of the common part can be replaced by the sum of pixel brightness values in that common part, or by the sum of squares of brightness values in that common part
Using the formula for estimating the distance between images under a shift (i,j) relative to one another

The Fast Fourier Transform and Image Comparison


we obtain that

The Fast Fourier Transform and Image Comparison


Where

  • <X,Y>(i,j) – the scalar product of two images obtained under a shift (i,j) of images X and Y relative to one another
  • E – an image of size equal to the minimum dimensions of X and Y, filled with unit values (that is, the “frame” within which X and Y are compared)
  • <X,X>(i,j) – the norm (sum of pixel brightness values) of the common part of image X under a shift (i,j)
  • FFT – the operation of the direct two-dimensional discrete Fourier transform
  • BFT – the operation of the inverse two-dimensional discrete Fourier transform
  • CONJUGATE – the operation of computing a matrix of conjugate elements
  • SQUAREMAGNITUDE– the operation of computing a matrix of squared amplitudes of the elements


Algorithm for finding a fragment within a full image

  • Let there be two images X and Y – the image and the sample, of sizes (N1,N2) and (M1,M2) respectively, with Ni > Mi
  • It is required to find the coordinates of sample Y within the full image X and compute an estimated value — a measure of closeness.

  1. Expand image Y to size (N1,N2), padding it with zeros
  2. Form image E of ones of size (M1,M2) and expand it to size (N1,N2), padding it with zeros
  3. Compute <X,Y> = BFT ( FFT(X) * CONJUGATE ( FFT(Y) ) )
  4. Compute <X,X> = BFT ( SQUAREMAGNITUDE( FFT(X) ) * CONJUGATE ( FFT(E) ) )
  5. Compute M[i,j] = (f + <X,Y> [i,j])/(f + <X,X> [i,j])
  6. Find the element with the maximum value in matrix M – the coordinates of this element are the sought position of the sample within the full image, and the value equals the comparison measure estimate.


Note:
When using the discrete Fourier transform, matrix M also contains elements from a cyclic shift of the images relative to each other. Therefore, if it is not necessary to analyze cyclic frame shift, the search for the maximum element in matrix M should be limited to the region (0,0)-(N1-M1, N2-M2).

Implementation examples


The implemented algorithms are part of the open-source library FFTTools. Web address: github.com/dprotopopov/FFTTools

Software used

  • Microsoft Visual Studio 2013 C# — development environment and programming language
  • EmguCV/OpenCV – C++ library of structures and algorithms for image processing
  • FFTWSharp/FFTW – C++ library implementing fast discrete Fourier transform algorithms

/// <summary>
        ///     Catch pattern bitmap with the Fastest Fourier Transform
        /// </summary>
        /// <returns>Matrix of values</returns>
        private Matrix<double> Catch(Image<Gray, double> image)
        {
            const double f = 1.0;
            int length = image.Data.Length;
            int n0 = image.Data.GetLength(0);
            int n1 = image.Data.GetLength(1);
            int n2 = image.Data.GetLength(2);

            Debug.Assert(n2 == 1);

            // Allocate FFTW structures
            var input = new fftw_complexarray(length);
            var output = new fftw_complexarray(length);

            fftw_plan forward = fftw_plan.dft_3d(n0, n1, n2, input, output,
                fftw_direction.Forward,
                fftw_flags.Estimate);
            fftw_plan backward = fftw_plan.dft_3d(n0, n1, n2, input, output,
                fftw_direction.Backward,
                fftw_flags.Estimate);

            var matrix = new Matrix<double>(n0, n1);

            double[,,] patternData = _patternImage.Data;
            double[,,] imageData = image.Data;
            double[,] data = matrix.Data;

            var doubles = new double[length];

            // Calculate Divisor
            Copy(patternData, data);
            Buffer.BlockCopy(data, 0, doubles, 0, length*sizeof (double));
            input.SetData(doubles.Select(x => new Complex(x, 0)).ToArray());
            forward.Execute();
            Complex[] complex = output.GetData_Complex();

            Buffer.BlockCopy(imageData, 0, doubles, 0, length*sizeof (double));
            input.SetData(doubles.Select(x => new Complex(x, 0)).ToArray());
            forward.Execute();

            input.SetData(output.GetData_Complex().Zip(complex, (x, y) => x*Complex.Conjugate(y)).ToArray());
            backward.Execute();
            IEnumerable<double> doubles1 = output.GetData_Complex().Select(x => x.Magnitude);

            if (_fastMode)
            {
                // Fast Result
                Buffer.BlockCopy(doubles1.ToArray(), 0, data, 0, length*sizeof (double));
                return matrix;
            }

            // Calculate Divider (aka Power)
            input.SetData(doubles.Select(x => new Complex(x*x, 0)).ToArray());
            forward.Execute();
            complex = output.GetData_Complex();

            CopyAndReplace(_patternImage.Data, data);
            Buffer.BlockCopy(data, 0, doubles, 0, length*sizeof (double));
            input.SetData(doubles.Select(x => new Complex(x, 0)).ToArray());
            forward.Execute();

            input.SetData(complex.Zip(output.GetData_Complex(), (x, y) => x*Complex.Conjugate(y)).ToArray());
            backward.Execute();
            IEnumerable<double> doubles2 = output.GetData_Complex().Select(x => x.Magnitude);

            // Result
            Buffer.BlockCopy(doubles1.Zip(doubles2, (x, y) => (f + x*x)/(f + y)).ToArray(), 0, data, 0,
                length*sizeof (double));
            return matrix;
        }

/// <summary>
        ///     Copy 3D array to 2D array (sizes can be different)
        ///     Flip copied data
        ///     Reduce last dimension
        /// </summary>
        /// <param name="input">Input array</param>
        /// <param name="output">Output array</param>
        private static void Copy(double[,,] input, double[,] output)
        {
            int n0 = output.GetLength(0);
            int n1 = output.GetLength(1);
            int m0 = Math.Min(n0, input.GetLength(0));
            int m1 = Math.Min(n1, input.GetLength(1));
            int m2 = input.GetLength(2);

            for (int i = 0; i < m0; i++)
                for (int j = 0; j < m1; j++)
                    output[i, j] = input[i, j, 0];

            for (int k = 1; k < m2; k++)
                for (int i = 0; i < m0; i++)
                    for (int j = 0; j < m1; j++)
                        output[i, j] += input[i, j, k];
        }

        /// <summary>
        ///     Copy 3D array to 2D array (sizes can be different)
        ///     Replace items copied by value
        ///     Flip copied data
        ///     Reduce last dimension
        /// </summary>
        /// <param name="input">Input array</param>
        /// <param name="output">Output array</param>
        /// <param name="value">Value to replace copied data</param>
        private static void CopyAndReplace(double[,,] input, double[,] output, double value = 1.0)
        {
            int n0 = output.GetLength(0);
            int n1 = output.GetLength(1);
            int m0 = Math.Min(n0, input.GetLength(0));
            int m1 = Math.Min(n1, input.GetLength(1));
            int m2 = input.GetLength(2);

            for (int i = 0; i < m0; i++)
                for (int j = 0; j < m1; j++)
                    output[i, j] = value;
        }

        /// <summary>
        ///     Find a maximum element in the matrix
        /// </summary>
        /// <param name="matrix">Matrix of values</param>
        /// <param name="x">Index of maximum element</param>
        /// <param name="y">Index of maximum element</param>
        /// <param name="value">Value of maximum element</param>
        public void Max(Matrix<double> matrix, out int x, out int y, out double value)
        {
            double[,] data = matrix.Data;
            int n0 = data.GetLength(0);
            int n1 = data.GetLength(1);
            value = data[0, 0];
            x = y = 0;
            for (int i = 0; i < n0; i++)
            {
                for (int j = 0; j < n1; j++)
                {
                    if (data[i, j] < value) continue;
                    value = data[i, j];
                    x = j;
                    y = i;
                }
            }
        }

        /// <summary>
        ///     Catch pattern bitmap with the Fastest Fourier Transform
        /// </summary>
        /// <returns>Array of values</returns>
        public Matrix<double> Catch(Bitmap bitmap)
        {
            using (var image = new Image<Gray, Byte>(bitmap))
                return Catch(image);
        }



See also

  • Convolution of two functions
  • Fourier transform
created: 2014-08-18
updated: 2026-03-08
431



Was this answer useful?
Choose a quick rating so we can improve the next answer for you.
How satisfied are you?


Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Algorithms"

Terms: Algorithms