Esempio n. 1
0
        /// <summary>
        ///     Calculate function self-convolution values
        /// </summary>
        /// <param name="f">Function values</param>
        /// <returns></returns>
        public double[] Build(double[] f)
        {
            int length = (_functionType == FunctionType.Periodic) ? f.Length : (f.Length + f.Length - 1);

            var input = new fftw_complexarray(length);
            var output = new fftw_complexarray(length);
            fftw_plan forward = fftw_plan.dft_1d(length, input, output,
                fftw_direction.Forward,
                fftw_flags.Estimate);
            fftw_plan backward = fftw_plan.dft_1d(length, input, output,
                fftw_direction.Backward,
                fftw_flags.Estimate);

            var complex = new Complex[length];
            for (int i = 0; i < f.Length; i++) complex[i] = f[i];
            input.SetData(complex);
            forward.Execute();
            complex = output.GetData_Complex();
            input.SetData(complex.Select(x => x*x/length).ToArray());
            backward.Execute();
            complex = output.GetData_Complex();

            return complex.Select(x => x.Magnitude).ToArray();
        }
        /// <summary>
        ///     Sharp bitmap with the Fastest Fourier Transform
        /// </summary>
        /// <returns>Sharped bitmap</returns>
        private double[, ,] Sharp(double[, ,] imageData)
        {
            int length = imageData.Length;
                int n0 = imageData.GetLength(0);
                int n1 = imageData.GetLength(1);
                int n2 = imageData.GetLength(2);

                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 doubles = new double[length];
                Buffer.BlockCopy(imageData, 0, doubles, 0, length * sizeof(double));
                double average = doubles.Average();
                double delta = Math.Sqrt(doubles.Average(x => x * x) - average * average);
                switch (_keepOption)
                {
                    case KeepOption.AverageAndDelta:
                        break;
                    case KeepOption.Sum:
                        average = doubles.Sum();
                        break;
                    case KeepOption.Square:
                        average = Math.Sqrt(doubles.Sum(x => x * x));
                        break;
                    case KeepOption.AverageSquare:
                        average = Math.Sqrt(doubles.Average(x => x * x));
                        break;
                    default:
                        throw new NotImplementedException();
                }

                input.SetData(doubles.Select(x => new Complex(x, 0)).ToArray());
                forward.Execute();
                Complex[] complex = output.GetData_Complex();

                Complex level = complex[0];

                var data = new Complex[n0, n1, n2];
                var buffer = new double[length * 2];

                GCHandle complexHandle = GCHandle.Alloc(complex, GCHandleType.Pinned);
                GCHandle dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
                IntPtr complexPtr = complexHandle.AddrOfPinnedObject();
                IntPtr dataPtr = dataHandle.AddrOfPinnedObject();

                Marshal.Copy(complexPtr, buffer, 0, buffer.Length);
                Marshal.Copy(buffer, 0, dataPtr, buffer.Length);
                switch (_mode)
                {
                    case Mode.BlinderSize:
                        Blind(data, _blinderSize);
                        break;
                    case Mode.FilterStep:
                        int filterStep = _filterStep;
                        var blinderSize = new Size(MulDiv(n1, filterStep, filterStep + 1),
                            MulDiv(n0, filterStep, filterStep + 1));
                        Blind(data, blinderSize);
                        break;
                    default:
                        throw new NotImplementedException();
                }
                Marshal.Copy(dataPtr, buffer, 0, buffer.Length);
                Marshal.Copy(buffer, 0, complexPtr, buffer.Length);

                complexHandle.Free();
                dataHandle.Free();

                complex[0] = level;

                input.SetData(complex);
                backward.Execute();
                doubles = output.GetData_Complex().Select(x => x.Magnitude).ToArray();

                double average2 = doubles.Average();
                double delta2 = Math.Sqrt(doubles.Average(x => x * x) - average2 * average2);
                switch (_keepOption)
                {
                    case KeepOption.AverageAndDelta:
                        break;
                    case KeepOption.Sum:
                        average2 = doubles.Sum();
                        break;
                    case KeepOption.Square:
                        average2 = Math.Sqrt(doubles.Sum(x => x * x));
                        break;
                    case KeepOption.AverageSquare:
                        average2 = Math.Sqrt(doubles.Average(x => x * x));
                        break;
                    default:
                        throw new NotImplementedException();
                }
                // a*average2 + b == average
                // a*delta2 == delta
                double a = (_keepOption == KeepOption.AverageAndDelta) ? (delta / delta2) : (average / average2);
                double b = (_keepOption == KeepOption.AverageAndDelta) ? (average - a * average2) : 0;
                Debug.Assert(Math.Abs(a * average2 + b - average) < 0.1);
                doubles = doubles.Select(x => Math.Round(a * x + b)).ToArray();

                Buffer.BlockCopy(doubles, 0, imageData, 0, length * sizeof(double));
                return imageData;
        }
        /// <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(complex.Zip(output.GetData_Complex(), (x, y) => x*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*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;
        }