/// <summary> /// Двумерное обратное быстрое преобразование фурье /// </summary> /// <param name="source">входная матрица</param> /// <param name="height">The height.</param> /// <param name="width">The width.</param> /// <returns> /// Выходной ряд /// </returns> public static Complex[,] IFastTransform(Complex[,] source, int height, int width) { if (source.GetLength(0) != source.GetLength(1)) { return(null); } int size = source.GetLength(0); Complex[,] outC = new Complex[size, size]; //преобразуем столбцы for (int i = 0; i < size; i++) //проходим по столбцам { Complex[] raw = new Complex[size]; for (int j = 0; j < size; j++) //проходим внутри столбца, собирая его { raw[j] = source[j, i]; } raw = Fourier.IFastTransform(raw); //получаем фурье образ столбца for (int j = 0; j < size; j++) //записываем его в массив { outC[j, i] = raw[j]; } } //преобразуем строки for (int i = 0; i < size; i++) //проходим по строкам { Complex[] str = new Complex[size]; for (int j = 0; j < size; j++) //проходим внутри строки, собирая её { str[j] = outC[i, j]; } str = Fourier.IFastTransform(str); //получаем фурье образ строки for (int j = 0; j < size; j++) //записываем его в массив { outC[i, j] = str[j]; } } Complex[,] value = new Complex[height, width]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { value[i, j] = outC[i, j]; } } return(value); }
/// <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); }