Monday, 20 November 2017

Implementing Morphological Filters

public static Bitmap DilateAndErodeFilter(this Bitmap sourceBitmap, 
                                        int matrixSize,
                                        MorphologyType morphType,
                                        bool applyBlue = true,
                                        bool applyGreen = true,
                                        bool applyRed = true,
                                        MorphologyEdgeType edgeType =
                                        MorphologyEdgeType.None) 
{
    BitmapData sourceData = 
               sourceBitmap.LockBits(new Rectangle (0, 0,
               sourceBitmap.Width, sourceBitmap.Height),
               ImageLockMode.ReadOnly, 
               PixelFormat.Format32bppArgb);

 
    byte[] pixelBuffer = new byte[sourceData.Stride * 
                                  sourceData.Height];

 
    byte[] resultBuffer = new byte[sourceData.Stride * 
                                   sourceData.Height];

 
    Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, 
                               pixelBuffer.Length);

 
    sourceBitmap.UnlockBits(sourceData);

 
    int filterOffset = (matrixSize - 1) / 2;
    int calcOffset = 0;

 
    int byteOffset = 0;

 
    int blue = 0;
    int green = 0;
    int red = 0;

 
    byte morphResetValue = 0;

 
    if (morphType == MorphologyType.Erosion)
    {
        morphResetValue = 255;
    }

 
    for (int offsetY = filterOffset; offsetY < 
        sourceBitmap.Height - filterOffset; offsetY++)
    {
        for (int offsetX = filterOffset; offsetX < 
            sourceBitmap.Width - filterOffset; offsetX++)
        {
            byteOffset = offsetY * 
                         sourceData.Stride + 
                         offsetX * 4;

 
            blue = morphResetValue;
            green = morphResetValue;
            red = morphResetValue;

 
            if (morphType == MorphologyType.Dilation)
            {
                for (int filterY = -filterOffset;
                    filterY <= filterOffset; filterY++)
                {
                    for (int filterX = -filterOffset;
                        filterX <= filterOffset; filterX++)
                    {
                        calcOffset = byteOffset +
                                     (filterX * 4) +
                        (filterY * sourceData.Stride);

 
                        if (pixelBuffer[calcOffset] > blue)
                        {
                            blue = pixelBuffer[calcOffset];
                        }

 
                        if (pixelBuffer[calcOffset + 1] > green)
                        {
                            green = pixelBuffer[calcOffset + 1];
                        }

 
                        if (pixelBuffer[calcOffset + 2] > red)
                        {
                            red = pixelBuffer[calcOffset + 2];
                        }
                    }
                }
            }
            else if (morphType == MorphologyType.Erosion)
            {
                for (int filterY = -filterOffset;
                    filterY <= filterOffset; filterY++)
                {
                    for (int filterX = -filterOffset;
                        filterX <= filterOffset; filterX++)
                    {
                        calcOffset = byteOffset +
                                     (filterX * 4) +
                        (filterY * sourceData.Stride);

 
                        if (pixelBuffer[calcOffset] < blue)
                        {
                            blue = pixelBuffer[calcOffset];
                        }

 
                        if (pixelBuffer[calcOffset + 1] < green)
                        {
                            green = pixelBuffer[calcOffset + 1];
                        }

 
                        if (pixelBuffer[calcOffset + 2] < red)
                        {
                            red = pixelBuffer[calcOffset + 2];
                        }
                    }
                }
            }

 
            if (applyBlue == false )
            {
                blue = pixelBuffer[byteOffset];
            }

 
            if (applyGreen == false )
            {
                green = pixelBuffer[byteOffset + 1];
            }

 
            if (applyRed == false )
            {
                red = pixelBuffer[byteOffset + 2];
            }

 
            if (edgeType == MorphologyEdgeType.EdgeDetection || 
                edgeType == MorphologyEdgeType.SharpenEdgeDetection)
            {
                if (morphType == MorphologyType.Dilation)
                {
                    blue = blue - pixelBuffer[byteOffset];
                    green = green - pixelBuffer[byteOffset + 1];
                    red = red - pixelBuffer[byteOffset + 2];
                }
                else if (morphType == MorphologyType.Erosion)
                {
                    blue = pixelBuffer[byteOffset] - blue;
                    green = pixelBuffer[byteOffset + 1] - green;
                    red = pixelBuffer[byteOffset + 2] - red;
                }

 
                if (edgeType == MorphologyEdgeType.SharpenEdgeDetection)
                {
                    blue += pixelBuffer[byteOffset];
                    green += pixelBuffer[byteOffset + 1];
                    red += pixelBuffer[byteOffset + 2];
                }
            }

 
            blue = (blue > 255 ? 255 : (blue < 0 ? 0 : blue));
            green = (green > 255 ? 255 : (green < 0 ? 0 : green));
            red = (red > 255 ? 255 : (red < 0 ? 0 : red));

 
            resultBuffer[byteOffset] = (byte)blue;
            resultBuffer[byteOffset + 1] = (byte)green;
            resultBuffer[byteOffset + 2] = (byte)red;
            resultBuffer[byteOffset + 3] = 255;
        }
    }

 
    Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, 
                                     sourceBitmap.Height);

 
    BitmapData resultData = 
               resultBitmap.LockBits(new Rectangle(0, 0,
               resultBitmap.Width, resultBitmap.Height),
               ImageLockMode.WriteOnly,
               PixelFormat.Format32bppArgb);

 
    Marshal.Copy(resultBuffer, 0, resultData.Scan0, 
                               resultBuffer.Length);

 
    resultBitmap.UnlockBits(resultData);

 
    return resultBitmap;
}

No comments:

Post a Comment