Пример #1
0
        /// <summary>
        /// Two dimensional Fast Fourier Transform.
        /// </summary>
        /// <param name="width">Image width.</param>
        /// <param name="height">Image height.</param>
        /// <param name="stride">Image stride.</param>
        /// <param name="data">Data to transform.</param>
        /// <param name="direction">Transformation direction.</param>
        ///
        /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size
        /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array
        /// is valid, but 15x15 is not.</note></para></remarks>
        ///
        /// <exception cref="ArgumentException">Incorrect data length.</exception>
        ///
        public unsafe static void FFT2(ComplexF *data, int width, int height, int stride, Direction direction)
        {
            int k = height;
            int n = width;

            // check data size
            if (
                (!AForge.Math.Tools.IsPowerOf2(k)) ||
                (!AForge.Math.Tools.IsPowerOf2(n)) ||
                (k < minLength) || (k > maxLength) ||
                (n < minLength) || (n > maxLength)
                )
            {
                throw new ArgumentException("Incorrect data length.");
            }

            // process rows
            ComplexF *dataPtr = data; //get row

            for (int i = 0; i < height; i++)
            {
                // transform it
                FourierTransform.FFT(dataPtr, n, direction);

                dataPtr += stride / sizeof(ComplexF);
            }

            // process columns
            dataPtr = data; //get column

            fixed(ComplexF *_col = new ComplexF[k])
            {
                ComplexF *col = _col;

                for (int j = 0; j < height; j++)
                {
                    // copy column
                    ComplexF *dataColPtr = &dataPtr[j];
                    for (int i = 0; i < k; i++)
                    {
                        col[i]      = *dataColPtr;
                        dataColPtr += stride / sizeof(ComplexF);
                    }

                    // transform it
                    FourierTransform.FFT(col, k, direction);

                    // copy back
                    dataColPtr = &dataPtr[j];
                    for (int i = 0; i < k; i++)
                    {
                        *dataColPtr = col[i];
                        dataColPtr += stride / sizeof(ComplexF);
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Two dimensional Fast Fourier Transform.
        /// </summary>
        ///
        /// <param name="data">Data to transform.</param>
        /// <param name="direction">Transformation direction.</param>
        ///
        /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size
        /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array
        /// is valid, but 15x15 is not.</note></para></remarks>
        ///
        /// <exception cref="ArgumentException">Incorrect data length.</exception>
        ///
        public static void FFT2(ComplexF[,] data, Direction direction)
        {
            int k = data.GetLength(0);
            int n = data.GetLength(1);

            // check data size
            if (
                (!Tools.IsPowerOf2(k)) ||
                (!Tools.IsPowerOf2(n)) ||
                (k < minLength) || (k > maxLength) ||
                (n < minLength) || (n > maxLength)
                )
            {
                throw new ArgumentException("Incorrect data length.");
            }

            // process rows
            ComplexF[] row = new ComplexF[n];

            for (int i = 0; i < k; i++)
            {
                // copy row
                for (int j = 0; j < n; j++)
                {
                    row[j] = data[i, j];
                }
                // transform it
                FourierTransform.FFT(row, direction);
                // copy back
                for (int j = 0; j < n; j++)
                {
                    data[i, j] = row[j];
                }
            }

            // process columns
            ComplexF[] col = new ComplexF[k];

            for (int j = 0; j < n; j++)
            {
                // copy column
                for (int i = 0; i < k; i++)
                {
                    col[i] = data[i, j];
                }
                // transform it
                FourierTransform.FFT(col, direction);
                // copy back
                for (int i = 0; i < k; i++)
                {
                    data[i, j] = col[i];
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Two dimensional Fast Fourier Transform.
        /// </summary>
        /// <param name="width">Image width.</param>
        /// <param name="height">Image height.</param>
        /// <param name="stride">Image stride.</param>
        /// <param name="data">Data to transform.</param>
        /// <param name="direction">Transformation direction.</param>
        ///
        /// <remarks><para><note>The method accepts <paramref name="data"/> array of 2<sup>n</sup> size
        /// only in each dimension, where <b>n</b> may vary in the [1, 14] range. For example, 16x16 array
        /// is valid, but 15x15 is not.</note></para></remarks>
        ///
        /// <exception cref="ArgumentException">Incorrect data length.</exception>
        ///
        public unsafe static void FFT2(ComplexF *data, int width, int height, int stride, Direction direction)
        {
            const int MIN_PATCH_SIZE = 32; //how much rows/columns should one thread process

            int k = height;
            int n = width;

            // check data size
            if (
                (!AForge.Math.Tools.IsPowerOf2(k)) ||
                (!AForge.Math.Tools.IsPowerOf2(n)) ||
                (k < minLength) || (k > maxLength) ||
                (n < minLength) || (n > maxLength)
                )
            {
                throw new ArgumentException("Incorrect data length.");
            }

            // process rows
            var procRow = new ParallelProcessor <bool, bool>(new Size(1 /*does not matter*/, height),
                                                             () => true,
                                                             (_, __, area) =>
            {
                ComplexF *dataPatchPtr = data + area.Y * stride / sizeof(ComplexF);                                                 //get row

                for (int i = 0; i < area.Height; i++)
                {
                    // transform it
                    FourierTransform.FFT(dataPatchPtr, n, direction);

                    dataPatchPtr += stride / sizeof(ComplexF);
                }
            },
                                                             new ParallelOptions2D {
                ParallelTrigger = (size) => size.Height >= MIN_PATCH_SIZE
                                  /*,ForceSequential = true*/ }
                                                             );

            // process columns
            //(y and x are swaped => proc thinks it is diving horizontal pacthes but instead we are using them as vertical ones)
            var procCol = new ParallelProcessor <bool, bool>(new Size(1 /*does not matter*/, width),
                                                             () => true,
                                                             (_, __, area) =>
            {
                ComplexF *dataPatchPtr = &data[area.Y];                                                 //get column

                fixed(ComplexF * _col = new ComplexF[k])
                {
                    ComplexF *col = _col;

                    for (int j = 0; j < area.Height; j++)
                    {
                        // copy column
                        ComplexF *dataColPtr = &dataPatchPtr[j];
                        for (int i = 0; i < k; i++)
                        {
                            col[i]      = *dataColPtr;
                            dataColPtr += stride / sizeof(ComplexF);
                        }

                        // transform it
                        FourierTransform.FFT(col, k, direction);

                        // copy back
                        dataColPtr = &dataPatchPtr[j];
                        for (int i = 0; i < k; i++)
                        {
                            *dataColPtr = col[i];
                            dataColPtr += stride / sizeof(ComplexF);
                        }
                    }
                }
            },
                                                             new ParallelOptions2D {
                ParallelTrigger = (size) => size.Height >= MIN_PATCH_SIZE
                                  /*,ForceSequential = true */ }
                                                             );

            procRow.Process(true);
            procCol.Process(true);
        }