AForge.NET

  :: AForge.NET Framework :: Articles :: Forums ::

Applying Gaussian blur to image in frequency domain

The forum is to discuss topics related to different areas of image processing and computer vision.

Applying Gaussian blur to image in frequency domain

Postby tariel36 » Thu Apr 09, 2015 9:43 pm

I've got torubles with appling gaussian blur to image in frequency domain. For unknown reasons (probably I've dont something wrong) I recieve wired image instead of blurred one.

There's what i do step by step:
  1. Load the image.
  2. Split image into separate channels.

    Code: Select all
    private static Bitmap[] separateColorChannels(Bitmap source, int channelCount)
    {
       if (channelCount != 3 && channelCount != 4)
       {
          throw new NotSupportedException("Bitmap[] FFTServices.separateColorChannels(Bitmap, int): Only 3 and 4 channels are supported.");
       }

       Bitmap[] result = new Bitmap[channelCount];
       BitmapData[] resultData = new BitmapData[channelCount];
       byte[][] dataBytes = new byte[channelCount][];

       for (int i = 0; i < channelCount; ++i)
       {
          result[i] = new Bitmap(source.Width, source.Height, PixelFormat.Format8bppIndexed);
          resultData[i] = result[i].LockBits(new Rectangle(0, 0, result[i].Width, result[i].Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
          dataBytes[i] = new byte[resultData[i].Height * resultData[i].Stride];

          Marshal.Copy(resultData[i].Scan0, dataBytes[i], 0, dataBytes[i].Length);
       }

       for (int x = 0; x < source.Width; x++)
       {
          for (int y = 0; y < source.Height; y++)
          {
             switch (channelCount)
             {
                case 3:
                   dataBytes[0][y * resultData[0].Stride + x] = source.GetPixel(x, y).R;
                   dataBytes[1][y * resultData[1].Stride + x] = source.GetPixel(x, y).G;
                   dataBytes[2][y * resultData[2].Stride + x] = source.GetPixel(x, y).B;

                   break;
                case 4:
                   dataBytes[0][y * resultData[0].Stride + x] = source.GetPixel(x, y).A;
                   dataBytes[1][y * resultData[1].Stride + x] = source.GetPixel(x, y).R;
                   dataBytes[2][y * resultData[2].Stride + x] = source.GetPixel(x, y).G;
                   dataBytes[3][y * resultData[3].Stride + x] = source.GetPixel(x, y).B;

                   break;
                default:
                   break;
             }
          }
       }

       for (int i = 0; i < channelCount; ++i)
       {
          Marshal.Copy(dataBytes[i], 0, resultData[i].Scan0, dataBytes[i].Length);
          result[i].UnlockBits(resultData[i]);
       }

       return result;
    }

  3. Convert every channel into complex images (with AForge.NET).

    Code: Select all
    public static AForge.Imaging.ComplexImage[] convertColorChannelsToComplex(Emgu.CV.Image<Emgu.CV.Structure.Gray, Byte>[] channels)
    {
       AForge.Imaging.ComplexImage[] result = new AForge.Imaging.ComplexImage[channels.Length];

       for (int i = 0; i < channels.Length; ++i)
       {
          result[i] = AForge.Imaging.ComplexImage.FromBitmap(channels[i].Bitmap);
       }

       return result;
    }

  4. Apply Gaussian blur.
    1. First i create the kernel.

      Code: Select all
      private ComplexImage makeGaussKernel(int side, double min, double max, double step, double std)
      {
         double _0x0 = gauss2d(min, min, std);
         double scaler = 1 / _0x0;

         int pow2 = SizeServices.getNextNearestPowerOf2(side);

         Bitmap bitmap = new Bitmap(pow2, pow2, PixelFormat.Format8bppIndexed);
         var result = AForge.Imaging.ComplexImage.FromBitmap(bitmap);

         double w = min;
         double h = min;

         for(int i = 0; i < result.Data.GetLength(0); ++i)
         {
            w = min;

            for(int j = 0; j < result.Data.GetLength(1); ++j)
            {
               result.Data[i, j].Re = (scaler * gauss2d(w, h, std));
               result.Data[i, j].Im = 0;

               w += step;
            }

            h += step;
         }

         return result;
      }

      private double gauss2d(double x, double y, double std)
      {
         return ((1.0 / (2 * Math.PI * std * std)) * Math.Exp(-((x * x + y * y) / (2 * std * std))));
      }

    2. Apply FFT to every channel and kernel.
    3. Multiply center part of every channel by kernel.

      Code: Select all
      void applyFilter(/*shortened*/)
      {
         /*shortened*/
         for (int i = 0; i < 3; ++i)
         {
            applyGauss(complexImage[i], filter, side);
         }
         /*shortened*/
      }

      private void applyGauss(ComplexImage complexImage, ComplexImage filter, int side)
      {
         int width = complexImage.Data.GetLength(1);
         int height = complexImage.Data.GetLength(0);

         for (int i = height / 2 - side / 2, y = 0; i < height / 2 + side / 2; i++, y = (y + 1) < side ? (y + 1) : 0)
         {
            for (int j = width / 2 - side / 2, x = 0; j < width / 2 + side / 2; j++, y = (x + 1) < side ? (x + 1) : 0)
            {
               complexImage.Data[i, j] = AForge.Math.Complex.Multiply(complexImage.Data[i, j], filter.Data[y, x]);
            }
         }
      }

    4. Apply IFFT to every channel.
  5. Convert every channel back to bitmaps (with AForge.NET).

    Code: Select all
    public static System.Drawing.Bitmap[] convertComplexColorChannelsToBitmap(AForge.Imaging.ComplexImage[] channels)
    {
       System.Drawing.Bitmap[] result = new System.Drawing.Bitmap[channels.Length];

       for (int i = 0; i < channels.Length; ++i)
       {
          result[i] = channels[i].ToBitmap();
       }

       return result;
    }

  6. Merge bitmaps into single bitmap

    Code: Select all
    public static Bitmap mergeColorChannels(Bitmap[] channels)
    {
       Bitmap result = null;

       switch (channels.Length)
       {
          case 1:
             return channels[0];
          case 3:
             result = new Bitmap(channels[0].Width, channels[0].Height, PixelFormat.Format24bppRgb);
             break;
          case 4:
             result = new Bitmap(channels[0].Width, channels[0].Height, PixelFormat.Format32bppArgb);
             break;
          default:
             throw new NotSupportedException("Bitmap FFTServices.mergeColorChannels(Bitmap[]): Only 1, 3 and 4 channels are supported.");
       }

       for (int x = 0; x < result.Width; x++)
       {
          for (int y = 0; y < result.Height; y++)
          {
             switch (channels.Length)
             {
                case 1:
                   result.SetPixel
                   (
                      x, y,
                      Color.FromArgb
                      (
                         channels[0].GetPixel(x, y).R
                      )
                   );
                   break;
                case 3:
                   result.SetPixel
                   (
                      x, y,
                      Color.FromArgb
                      (
                         channels[0].GetPixel(x, y).R,
                         channels[1].GetPixel(x, y).G,
                         channels[2].GetPixel(x, y).B
                      )
                   );
                   break;
                case 4:
                   result.SetPixel
                   (
                      x, y,
                      Color.FromArgb
                      (
                         channels[0].GetPixel(x, y).A,
                         channels[1].GetPixel(x, y).R,
                         channels[2].GetPixel(x, y).G,
                         channels[3].GetPixel(x, y).B
                      )
                   );
                   break;
                default:
                   break;
             }
          }
       }

       return result;
    }

And as a result IF I APPLY FFT to filter i get this. If i dont apply FFT to filter, I get this. I dont have clue what's going on. I'm fairly new with image processing (that's school project) and not really familiar with AForge.NET. Any tips?
tariel36
 
Posts: 1
Joined: Thu Apr 09, 2015 9:34 pm



Return to Image Processing and Computer Vision

cron