代码之家  ›  专栏  ›  技术社区  ›  user366312

灰度与彩色fft

  •  3
  • user366312  · 技术社区  · 6 年前

    以下代码将彩色图像转换为灰度,然后计算其fft:

        private void button1_Click(object sender, EventArgs e)
        {
            Bitmap source = pictureBox1.Image as Bitmap;
    
            Bitmap gray = Grayscale.ToGrayscale(source);
    
            Complex[,] cpxImage = ImageDataConverter.ToComplex(gray);
    
            Complex[,] fftCpxImage = FourierTransform.ForwardFFT(cpxImage);
    
            Complex[,] shiftedFftCpxImage = FourierShifter.ShiftFft(fftCpxImage);
    
            Bitmap mag = FourierPlot.FftMagnitudePlot(shiftedFftCpxImage, PixelFormat.Format8bppIndexed);
            Bitmap phase = FourierPlot.FftPhasePlot(shiftedFftCpxImage, PixelFormat.Format8bppIndexed);
    
            pictureBox2.Image = gray;
    
            pictureBox3.Image =  mag;
    
            pictureBox4.Image = phase;
        }
    

    下面的代码将彩色图像分割为三个通道,计算它们的fft并将它们合并在一起,形成fft的rgb图像。

        private void button2_Click(object sender, EventArgs e)
        {
            Bitmap source = pictureBox1.Image as Bitmap;
    
            int [,,] array3d = ImageDataConverter.ToInteger3d(source);
    
            int[,] red = ArrayTools<int>.Split(array3d, 0);
            int[,] green = ArrayTools<int>.Split(array3d, 1);
            int[,] blue = ArrayTools<int>.Split(array3d, 2);
    
            Complex [,] cpxRed = ImageDataConverter.ToComplex(red);
            Complex [,] cpxGreen = ImageDataConverter.ToComplex(green);
            Complex [,] cpxBlue = ImageDataConverter.ToComplex(blue);
    
            Complex[,] fftCpxRed = FourierTransform.ForwardFFT(cpxRed);
            Complex[,] fftCpxGreen = FourierTransform.ForwardFFT(cpxGreen);
            Complex[,] fftCpxBlue = FourierTransform.ForwardFFT(cpxBlue);
    
            Complex[,] shiftedFftCpxRed = FourierShifter.ShiftFft(fftCpxRed);
            Complex[,] shiftedFftCpxGreen = FourierShifter.ShiftFft(fftCpxGreen);
            Complex[,] shiftedFftCpxBlue = FourierShifter.ShiftFft(fftCpxBlue);
    
            int[,] fftRed = ImageDataConverter.ToIntegerMagnitude(shiftedFftCpxRed);
            int[,] fftGreen = ImageDataConverter.ToIntegerMagnitude(shiftedFftCpxGreen);
            int[,] fftBlue = ImageDataConverter.ToIntegerMagnitude(shiftedFftCpxBlue);
    
            int [,,] dest = ArrayTools<int>.Merge(fftRed, fftGreen, fftBlue);
    
            Bitmap mag = ImageDataConverter.ToBitmap3d(dest, PixelFormat.Format8bppIndexed);
            Grayscale.SetPalette(mag);
    
            pictureBox3.Image = mag;
        }
    

    输出

    enter image description here enter image description here

    在第一个案例中,结果非常好,正如预期的那样。在第二种情况下,输出完全是黑色的。

    再来一个测试: 如果我只使用一个通道,输出同样很酷:

            ... ... ...
    
            Complex[,] shiftedFftCpxRed = FourierShifter.ShiftFft(fftCpxRed);
            Complex[,] shiftedFftCpxGreen = FourierShifter.ShiftFft(fftCpxGreen);
            Complex[,] shiftedFftCpxBlue = FourierShifter.ShiftFft(fftCpxBlue);
    
            Bitmap mag = FourierPlot.FftMagnitudePlot(shiftedFftCpxRed, PixelFormat.Format8bppIndexed);
            Bitmap phase = FourierPlot.FftPhasePlot(shiftedFftCpxRed, PixelFormat.Format8bppIndexed);
    
            pictureBox2.Image = ImageDataConverter.ToBitmap2d(red, PixelFormat.Format8bppIndexed);
            pictureBox3.Image = mag;
            pictureBox4.Image = phase;
    
            ... ... ...
    

    enter image description here

    我觉得有个问题

        public static int[,] ToIntegerMagnitude(Complex[,] image)
        {
            int Width = image.GetLength(0);
            int Height = image.GetLength(1);
    
            int[,] integer = new int[Width, Height];
    
    
            for (int j = 0; j <= Height - 1; j++)
            {
                for (int i = 0; i <= Width - 1; i++)
                {
                    integer[i, j] = ((int)image[i, j].Magnitude);
                }
            }
    
            return integer;
        }
    

    这只是数量部分,因此在这个过程中会丢失数据。

    有什么建议吗?

    是的。

    相关源代码

    public static class FourierPlot
    {
        public static Bitmap FftMagnitudePlot(Complex[,] fftImage, PixelFormat pixelFormat)
        {
            int[,] FourierMagnitudeNormalizedInteger = FourierNormalizer.Normalize(fftImage, NormalizeType.Magnitude);
    
            Bitmap color = ImageDataConverter.ToBitmap2d(FourierMagnitudeNormalizedInteger, pixelFormat);
    
            Grayscale.SetPalette(color);
    
            return color;
        }
    
        public static Bitmap FftPhasePlot(Complex[,] fftImage, PixelFormat pixelFormat)
        {
            int[,] FourierPhaseNormalizedInteger = FourierNormalizer.Normalize(fftImage, NormalizeType.Phase);
    
            Bitmap color = ImageDataConverter.ToBitmap2d(FourierPhaseNormalizedInteger, pixelFormat);
    
            Grayscale.SetPalette(color);
    
            return color;
        }
    }
    
    public partial class FourierNormalizer
    {
        public static int[,] Normalize(Complex[,] Output, NormalizeType normalizeType)
        {
            int Width = Output.GetLength(0);
            int Height = Output.GetLength(1);
    
            double[,] FourierDouble = new double[Width, Height];
            double[,] FourierLogDouble = new double[Width, Height];
            int[,] FourierNormalizedInteger = new int[Width, Height];
    
            double max = 0;
    
            if (normalizeType == NormalizeType.Magnitude)
            {
                for (int i = 0; i <= Width - 1; i++)
                {
                    for (int j = 0; j <= Height - 1; j++)
                    {
                        FourierDouble[i, j] = Output[i, j].Magnitude;
                        FourierLogDouble[i, j] = (double)Math.Log(1 + FourierDouble[i, j]);
                    }
                }
    
                max = FourierLogDouble[0, 0];
            }
            else
            {
                for (int i = 0; i <= Width - 1; i++)
                {
                    for (int j = 0; j <= Height - 1; j++)
                    {
                        FourierDouble[i, j] = Output[i, j].Phase;
                        FourierLogDouble[i, j] = (double)Math.Log(1 + Math.Abs(FourierDouble[i, j]));
                    }
                }
    
                FourierLogDouble[0, 0] = 0;
                max = FourierLogDouble[1, 1];
            }
    
            for (int i = 0; i <= Width - 1; i++)
            {
                for (int j = 0; j <= Height - 1; j++)
                {
                    if (FourierLogDouble[i, j] > max)
                    {
                        max = FourierLogDouble[i, j];
                    }
                }
            }
    
            for (int i = 0; i <= Width - 1; i++)
            {
                for (int j = 0; j <= Height - 1; j++)
                {
                    FourierLogDouble[i, j] = FourierLogDouble[i, j] / max;
                }
            }
    
            if (normalizeType == NormalizeType.Magnitude)
            {
                for (int i = 0; i <= Width - 1; i++)
                {
                    for (int j = 0; j <= Height - 1; j++)
                    {
                        FourierNormalizedInteger[i, j] = (int)(2000 * FourierLogDouble[i, j]);
                    }
                }
            }
            else
            {
                for (int i = 0; i <= Width - 1; i++)
                {
                    for (int j = 0; j <= Height - 1; j++)
                    {
                        FourierNormalizedInteger[i, j] = (int)(255 * FourierLogDouble[i, j]);
                    }
                }
            }
    
            return FourierNormalizedInteger;
        }
    }
    
        public static Bitmap ToBitmap3d(int[, ,] image, PixelFormat pixelFormat)
        {
            int Width = image.GetLength(1);
            int Height = image.GetLength(2);
    
            Bitmap bmp = new Bitmap(Width, Height, pixelFormat);
    
            BitmapLocker locker = new BitmapLocker(bmp);
            locker.Lock();
    
            int [,] red = ArrayTools<int>.Split(image, 0);
            int [,] green = ArrayTools<int>.Split(image, 1);
            int [,] blue = ArrayTools<int>.Split(image, 2);
    
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    int r = red[x,y];
                    int g = green[x,y];
                    int b = blue[x,y];
    
                    Color clr = Color.FromArgb(r,g,b);
    
                    locker.SetPixel(x, y, clr);
                }
            }
    
            locker.Unlock();
    
            return bmp;
        } 
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   user366312    6 年前

    enter image description here

    这句话解决了我的问题。

        private void button2_Click(object sender, EventArgs e)
        {
            Bitmap source = (Bitmap)(pictureBox1.Image as Bitmap).Clone();
    
            int[, ,] array3d = ImageDataConverter.ToInteger3d(source);
    
            int[,] red = ArrayTools<int>.Split(array3d, 0);
            int[,] green = ArrayTools<int>.Split(array3d, 1);
            int[,] blue = ArrayTools<int>.Split(array3d, 2);
    
            Complex[,] cpxRed = ImageDataConverter.ToComplex(red);
            Complex[,] cpxGreen = ImageDataConverter.ToComplex(green);
            Complex[,] cpxBlue = ImageDataConverter.ToComplex(blue);
    
            Complex[,] fftCpxRed = FourierTransform.ForwardFFT(cpxRed);
            Complex[,] fftCpxGreen = FourierTransform.ForwardFFT(cpxGreen);
            Complex[,] fftCpxBlue = FourierTransform.ForwardFFT(cpxBlue);
    
            Complex[,] shiftedFftCpxRed = FourierShifter.ShiftFft(fftCpxRed);
            Complex[,] shiftedFftCpxGreen = FourierShifter.ShiftFft(fftCpxGreen);
            Complex[,] shiftedFftCpxBlue = FourierShifter.ShiftFft(fftCpxBlue);
    
            int[,] normRed = FourierNormalizer.Normalize(shiftedFftCpxRed, NormalizeType.Magnitude);
            int[,] normGreen = FourierNormalizer.Normalize(shiftedFftCpxGreen, NormalizeType.Magnitude);
            int[,] normBlue = FourierNormalizer.Normalize(shiftedFftCpxBlue, NormalizeType.Magnitude);
    
            Bitmap mag = ImageDataConverter.ToBitmap3d(normRed, normGreen, normBlue, PixelFormat.Format8bppIndexed);
            //Grayscale.SetPalette(mag);
            //Bitmap mag = FourierPlot.FftMagnitudePlot(shiftedFftCpxRed, PixelFormat.Format8bppIndexed);
            Bitmap phase = FourierPlot.FftPhasePlot(shiftedFftCpxRed, PixelFormat.Format8bppIndexed);
    
            pictureBox2.Image = mag;
            pictureBox3.Image = mag;
            pictureBox4.Image = phase;
        }