Monday, 20 November 2017

Applying Gaussian blur to image in frequency domain

private ComplexImage makeGaussKernel(double size, double std, int imgWidth, int imgHeight)
{
    double scale = 2000.0;
    double hsize = size / 2.0;

    Bitmap bmp = new Bitmap(imgWidth, imgHeight, PixelFormat.Format8bppIndexed);
    LockBitmap lbmp = new LockBitmap(bmp);

    lbmp.LockBits();

    double y = -hsize;
    double yStep = hsize / (lbmp.Height / 2.0);
    double xStep = hsize / (lbmp.Width / 2.0);

    for (int i = 0; i < lbmp.Height; ++i)
    {
        double x = -hsize;

        for (int j = 0; j < lbmp.Width; ++j)
        {
            double g = gauss2d(x, y, std) * scale;

            g = g < 0.0 ? 0.0 : g;
            g = g > 255.0 ? 255.0 : g;

            lbmp.SetPixel(j, i, Color.FromArgb((int)g));

            x += xStep;
        }

        y += yStep;
    }

    lbmp.UnlockBits();

    return ComplexImage.FromBitmap(bmp);
}

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)));
}

private void applyGaussToImage(ComplexImage complexImage, ComplexImage filter)
{
    for (int i = 0; i < complexImage.Height; ++i)
    {
        for (int j = 0; j < complexImage.Width; ++j)
        {
            complexImage.Data[i, j] = AForge.Math.Complex.Multiply(complexImage.Data[i, j], filter.Data[i, j]);
        }
    }
}

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.");
    }

    LockBitmap resultLock = new LockBitmap(result);
    resultLock.LockBits();

    LockBitmap red = new LockBitmap(channels[0]);
    LockBitmap green = new LockBitmap(channels[1]);
    LockBitmap blue = new LockBitmap(channels[2]);

    red.LockBits();
    green.LockBits();
    blue.LockBits();

    for (int y = 0; y < result.Height; y++)
    {
        for (int x = 0; x < result.Width; x++)
        {
            resultLock.SetPixel(x, y, Color.FromArgb((int)red.GetPixel(x, y).R, (int)green.GetPixel(x, y).G, (int)blue.GetPixel(x, y).B));
        }
    }

    red.UnlockBits();
    green.UnlockBits();
    blue.UnlockBits();

    resultLock.UnlockBits();

    return result;
}

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];
    LockBitmap[] locks = new LockBitmap[channelCount];
    LockBitmap sourceLock = new LockBitmap(source);
    sourceLock.LockBits();

    for (int i = 0; i < channelCount; ++i)
    {
        result[i] = new Bitmap(source.Width, source.Height, PixelFormat.Format8bppIndexed);
        locks[i] = new LockBitmap(result[i]);
        locks[i].LockBits();
    }

    for (int x = 0; x < source.Width; x++)
    {
        for (int y = 0; y < source.Height; y++)
        {
            switch (channelCount)
            {
                case 3:
                    locks[0].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).R));
                    locks[1].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).G));
                    locks[2].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).B));

                    break;
                case 4:
                    locks[0].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).A));
                    locks[1].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).R));
                    locks[2].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).G));
                    locks[3].SetPixel(x, y, Color.FromArgb(sourceLock.GetPixel(x, y).B));

                    break;
                default:
                    break;
            }
        }
    }

    for (int i = 0; i < channelCount; ++i)
    {
        locks[i].UnlockBits();
    }

    sourceLock.UnlockBits();
}

No comments:

Post a Comment