예제 #1
0
        /// <summary>
        /// Перевод оператора искажения из пространственной в частотную область. Размерность не меняется.
        /// </summary>
        /// <param name="filter">Оператор искажения PSF (Point Spread Function)</param>
        /// <returns>OTF (Optical Transfer Function)</returns>
        public static Complex[,] Psf2otf(ConvolutionFilter filter)
        {
            double[,] filterMatrix = filter.normalizedFilterMatrix;
            int FilterSize = filterMatrix.GetLength(0);
            int halfSize   = (FilterSize - 1) / 2;
            int ost        = FilterSize - halfSize;

            double[,] newFilter = new double[FilterSize, FilterSize];
            //+ + -
            //+ + -
            //- - -
            for (int i = 0; i < ost; i++)
            {
                for (int j = 0; j < ost; j++)
                {
                    newFilter[i, j] = filterMatrix[i + halfSize, j + halfSize];
                }
            }
            //- - +
            //- - +
            //- - -
            for (int i = 0; i < ost; i++)
            {
                for (int j = ost; j < FilterSize; j++)
                {
                    newFilter[i, j] = filterMatrix[i + halfSize, j - ost];
                }
            }
            //- - -
            //- - -
            //+ + -
            for (int i = ost; i < FilterSize; i++)
            {
                for (int j = 0; j < ost; j++)
                {
                    newFilter[i, j] = filterMatrix[i - ost, j + halfSize];
                }
            }
            //- - -
            //- - -
            //- - +
            for (int i = ost; i < FilterSize; i++)
            {
                for (int j = ost; j < FilterSize; j++)
                {
                    newFilter[i, j] = filterMatrix[i - ost, j - ost];
                }
            }

            return(Fourier.Transform(Converter.ToComplexMatrix(newFilter)));
        }
예제 #2
0
        /// <summary>
        /// Двумерное прямое преобразование фурье
        /// </summary>
        /// <param name="source">входная матрица</param>
        /// <returns>Выходной ряд</returns>
        public static Complex[,] Transform(Complex[,] source)
        {
            int M = source.GetLength(0);    //строк
            int N = source.GetLength(1);    //столбцов

            Complex[,] outC = new Complex[M, N];

            //преобразуем строки
            for (int i = 0; i < M; i++) //проходим по строкам
            {
                Complex[] str = new Complex[N];
                for (int j = 0; j < N; j++) //проходим внутри строки, собирая её
                {
                    str[j] = source[i, j];
                }
                str = Fourier.Transform(str); //получаем фурье образ строки
                for (int j = 0; j < N; j++)   //записываем его в массив
                {
                    outC[i, j] = str[j];
                }
            }

            //преобразуем столбцы
            for (int i = 0; i < N; i++) //проходим по столбцам
            {
                Complex[] raw = new Complex[M];
                for (int j = 0; j < M; j++) //проходим внутри столбца, собирая его
                {
                    raw[j] = outC[j, i];
                }
                raw = Fourier.Transform(raw); //получаем фурье образ столбца
                for (int j = 0; j < M; j++)   //записываем его в массив
                {
                    outC[j, i] = raw[j];
                }
            }

            return(outC);
        }
예제 #3
0
        /// <summary>
        /// Двумерное прямое быстрое преобразование фурье
        /// </summary>
        /// <param name="source">входная матрица</param>
        /// <returns>Выходной ряд</returns>
        public static Complex[,] FastTransform(Complex[,] source)
        {
            int m = source.GetLength(0);    //строк
            int n = source.GetLength(1);    //столбцов

            int size = n;

            if (m > n)
            {
                size = m;
            }

            double log = Math.Log(size, 2);

            Complex[,] x;

            if (log - Math.Round(log) != 0)
            {
                size = (int)Math.Pow(2, (int)log + 1);
            }
            x = new Complex[size, size];
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    x[i, j] = source[i, j];
                }
            }

            Complex[,] outC = new Complex[size, size];

            //преобразуем строки
            for (int i = 0; i < size; i++) //проходим по строкам
            {
                Complex[] str = new Complex[size];
                for (int j = 0; j < size; j++) //проходим внутри строки, собирая её
                {
                    str[j] = x[i, j];
                }
                str = Fourier.UnsafeFastTransform(str); //получаем фурье образ строки
                for (int j = 0; j < size; j++)          //записываем его в массив
                {
                    outC[i, j] = str[j];
                }
            }

            //преобразуем столбцы
            for (int i = 0; i < size; i++) //проходим по столбцам
            {
                Complex[] raw = new Complex[size];
                for (int j = 0; j < size; j++) //проходим внутри столбца, собирая его
                {
                    raw[j] = outC[j, i];
                }
                raw = Fourier.UnsafeFastTransform(raw); //получаем фурье образ столбца
                for (int j = 0; j < size; j++)          //записываем его в массив
                {
                    outC[j, i] = raw[j];
                }
            }

            return(outC);
        }
예제 #4
0
        /// <summary>
        /// Конволюция (свёртка) в частотной области
        /// </summary>
        /// <param name="sourceImage">исходное изображение</param>
        /// <returns>искаженное изображение</returns>
        public Image FastConvolution(Image sourceImage)
        {
            int   height         = sourceImage.Height;
            int   width          = sourceImage.Width;
            int   filterSize     = this.filterMatrix.GetLength(0); //размер PSF
            int   filterHalfSize = (filterSize - 1) / 2 + 1;       //центр PSF
            Image expandedImage  = sourceImage.Expand(filterHalfSize);
            int   expHeight      = expandedImage.Height;
            int   expWidth       = expandedImage.Width;

            double[] image = Converter.ToDoubleArray(expandedImage);
            double[,] red   = new double[expHeight, expWidth];
            double[,] green = new double[expHeight, expWidth];
            double[,] blue  = new double[expHeight, expWidth];
            int index = 0;

            for (int i = 0; i < expHeight; i++)
            {
                for (int j = 0; j < expWidth; j++)
                {
                    blue[i, j]  = image[index];
                    green[i, j] = image[index + 1];
                    red[i, j]   = image[index + 2];
                    index      += 4;
                }
            }

            Complex[,] redFourier   = Fourier.FastTransform(Converter.ToComplexMatrix(red));
            Complex[,] greenFourier = Fourier.FastTransform(Converter.ToComplexMatrix(green));
            Complex[,] blueFourier  = Fourier.FastTransform(Converter.ToComplexMatrix(blue));
            int newSize = redFourier.GetLength(0);

            double[,] kernel         = this.ExpendedByZero(newSize);
            Complex[,] kernelFourier = Fourier.FastTransform(Converter.ToComplexMatrix(kernel));
            for (int u = 0; u < newSize; u++)
            {
                for (int v = 0; v < newSize; v++)
                {
                    redFourier[u, v]   *= kernelFourier[u, v];
                    greenFourier[u, v] *= kernelFourier[u, v];
                    blueFourier[u, v]  *= kernelFourier[u, v];
                }
            }
            Complex[,] newRed   = Fourier.IFastTransform(redFourier, expHeight, expWidth);
            Complex[,] newGreen = Fourier.IFastTransform(greenFourier, expHeight, expWidth);
            Complex[,] newBlue  = Fourier.IFastTransform(blueFourier, expHeight, expWidth);

            Complex[,] resRed   = new Complex[height, width];
            Complex[,] resGreen = new Complex[height, width];
            Complex[,] resBlue  = new Complex[height, width];
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    resRed[i, j]   = Math.Round(newRed[i + filterHalfSize + 1, j + filterHalfSize + 1].Real);
                    resGreen[i, j] = Math.Round(newGreen[i + filterHalfSize + 1, j + filterHalfSize + 1].Real);
                    resBlue[i, j]  = Math.Round(newBlue[i + filterHalfSize + 1, j + filterHalfSize + 1].Real);
                }
            }
            Image result = Converter.ToImage(resRed, resGreen, resBlue);

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Перевод оператора искажения из пространственной в частотную область с новой (бОльшей) размерностью.
        /// </summary>
        /// <param name="filter">оператор искажения исходного размера</param>
        /// <param name="newSize">новая размерность</param>
        /// <returns></returns>
        public static Complex[,] Psf2otf(ConvolutionFilter filter, int newSize)
        {
            double[,] filterMatrix = filter.normalizedFilterMatrix;
            int sourceFilterSize = filterMatrix.GetLength(0);
            int halfSize         = (filter.filterMatrix.GetLength(0) - 1) / 2;

            if (newSize < sourceFilterSize)
            {
                return(null);
            }
            double[,] extendedFilter = new double[newSize, newSize];
            //0 0 0
            //0 0 0
            //0 0 0
            for (int i = 0; i < newSize; i++)
            {
                for (int j = 0; j < newSize; j++)
                {
                    extendedFilter[i, j] = 0;
                }
            }
            //- - -
            //- + +
            //- + +
            for (int i = 0; i < halfSize + 1; i++)
            {
                for (int j = 0; j < halfSize + 1; j++)
                {
                    extendedFilter[i, j] = filterMatrix[i + halfSize, j + halfSize];
                }
            }
            //- - -
            //+ - -
            //+ - -
            for (int i = 0; i < halfSize + 1; i++)
            {
                for (int j = newSize - halfSize; j < newSize; j++)
                {
                    extendedFilter[i, j] = filterMatrix[i + halfSize, j - (newSize - halfSize)];
                }
            }
            //- + +
            //- - -
            //- - -
            for (int i = newSize - halfSize; i < newSize; i++)
            {
                for (int j = 0; j < halfSize + 1; j++)
                {
                    extendedFilter[i, j] = filterMatrix[i - (newSize - halfSize), j + halfSize];
                }
            }
            //+ - -
            //- - -
            //- - -
            for (int i = newSize - halfSize; i < newSize; i++)
            {
                for (int j = newSize - halfSize; j < newSize; j++)
                {
                    extendedFilter[i, j] = filterMatrix[i - (newSize - halfSize), j - (newSize - halfSize)];
                }
            }

            return(Fourier.Transform(Converter.ToComplexMatrix(extendedFilter)));
        }