Потеря данных во время обратного БПФ изображения.
Я использую следующий код для преобразования растрового изображения в сложное и наоборот.
Даже несмотря на то, что они были непосредственно скопированы с аккорда.NET framework, тестируя эти статические методы, я обнаружил, что повторное использование этих статических методов приводит к "потере данных".
В результате конечный результат искажается.[^]
public partial class ImageDataConverter { #region private static Complex[,] FromBitmapData(BitmapData bmpData) private static Complex[,] ToComplex(BitmapData bmpData) { Complex[,] comp = null; if (bmpData.PixelFormat == PixelFormat.Format8bppIndexed) { int width = bmpData.Width; int height = bmpData.Height; int offset = bmpData.Stride - (width * 1);//1 === 1 byte per pixel. if ((!Tools.IsPowerOf2(width)) || (!Tools.IsPowerOf2(height))) { throw new Exception("Imager width and height should be n of 2."); } comp = new Complex[width, height]; unsafe { byte* src = (byte*)bmpData.Scan0.ToPointer(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, src++) { comp[y, x] = new Complex((float)*src / 255, comp[y, x].Imaginary); } src += offset; } } } else { throw new Exception("EightBppIndexedImageRequired"); } return comp; } #endregion public static Complex[,] ToComplex(Bitmap bmp) { Complex[,] comp = null; if (bmp.PixelFormat == PixelFormat.Format8bppIndexed) { BitmapData bmpData = bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); try { comp = ToComplex(bmpData); } finally { bmp.UnlockBits(bmpData); } } else { throw new Exception("EightBppIndexedImageRequired"); } return comp; } public static Bitmap ToBitmap(Complex[,] image, bool fourierTransformed) { int width = image.GetLength(0); int height = image.GetLength(1); Bitmap bmp = Imager.CreateGrayscaleImage(width, height); BitmapData bmpData = bmp.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); int offset = bmpData.Stride - width; double scale = (fourierTransformed) ? Math.Sqrt(width * height) : 1; unsafe { byte* address = (byte*)bmpData.Scan0.ToPointer(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, address++) { double min = System.Math.Min(255, image[y, x].Magnitude * scale * 255); *address = (byte)System.Math.Max(0, min); } address += offset; } } bmp.UnlockBits(bmpData); return bmp; } }
Как вы можете видеть, FFT работает правильно, но I-FFT-нет.
Это происходит потому, что bitmap to complex и наоборот работают не так, как ожидалось.
Что можно сделать, чтобы исправить функции ToComplex() и ToBitmap (), чтобы они не теряли данные?
Что я уже пробовал:
public partial class ImageDataConverter { #region private static Complex[,] FromBitmapData(BitmapData bmpData) private static Complex[,] ToComplex(BitmapData bmpData) { Complex[,] comp = null; if (bmpData.PixelFormat == PixelFormat.Format8bppIndexed) { int width = bmpData.Width; int height = bmpData.Height; int offset = bmpData.Stride - (width * 1);//1 === 1 byte per pixel. if ((!Tools.IsPowerOf2(width)) || (!Tools.IsPowerOf2(height))) { throw new Exception("Imager width and height should be n of 2."); } comp = new Complex[width, height]; unsafe { byte* src = (byte*)bmpData.Scan0.ToPointer(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, src++) { comp[y, x] = new Complex((float)*src / 255, comp[y, x].Imaginary); } src += offset; } } } else { throw new Exception("EightBppIndexedImageRequired"); } return comp; } #endregion public static Complex[,] ToComplex(Bitmap bmp) { Complex[,] comp = null; if (bmp.PixelFormat == PixelFormat.Format8bppIndexed) { BitmapData bmpData = bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); try { comp = ToComplex(bmpData); } finally { bmp.UnlockBits(bmpData); } } else { throw new Exception("EightBppIndexedImageRequired"); } return comp; } public static Bitmap ToBitmap(Complex[,] image, bool fourierTransformed) { int width = image.GetLength(0); int height = image.GetLength(1); Bitmap bmp = Imager.CreateGrayscaleImage(width, height); BitmapData bmpData = bmp.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); int offset = bmpData.Stride - width; double scale = (fourierTransformed) ? Math.Sqrt(width * height) : 1; unsafe { byte* address = (byte*)bmpData.Scan0.ToPointer(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, address++) { double min = System.Math.Min(255, image[y, x].Magnitude * scale * 255); *address = (byte)System.Math.Max(0, min); } address += offset; } } bmp.UnlockBits(bmpData); return bmp; } }
Richard MacCutchan
Без дополнительной информации об этом можно только догадываться. Вам нужно объяснить, где теряются данные.