Monday, 20 November 2017

Applying a Median Filter

public static Bitmap MedianFilter(this Bitmap sourceBitmap, 
                                            int matrixSize,   
                                              int bias = 0, 
                                    bool grayscale = false) 
{
    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); 

 
    if (grayscale == true) 
    { 
        float rgb = 0; 

 
        for (int k = 0; k < pixelBuffer.Length; k += 4) 
        { 
            rgb = pixelBuffer[k] * 0.11f; 
            rgb += pixelBuffer[k + 1] * 0.59f; 
            rgb += pixelBuffer[k + 2] * 0.3f; 

 
            pixelBuffer[k] = (byte )rgb; 
            pixelBuffer[k + 1] = pixelBuffer[k]; 
            pixelBuffer[k + 2] = pixelBuffer[k]; 
            pixelBuffer[k + 3] = 255; 
        } 
    } 

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

 
    int byteOffset = 0; 
 
    List<int> neighbourPixels = new List<int>(); 
    byte[] middlePixel; 

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

 
            neighbourPixels.Clear(); 

 
            for (int filterY = -filterOffset; 
                filterY <= filterOffset; filterY++) 
            { 
                for (int filterX = -filterOffset; 
                    filterX <= filterOffset; filterX++) 
                { 

 
                    calcOffset = byteOffset + 
                                 (filterX * 4) + 
                        (filterY * sourceData.Stride); 

 
                    neighbourPixels.Add(BitConverter.ToInt32( 
                                     pixelBuffer, calcOffset)); 
                } 
            } 

 
            neighbourPixels.Sort(); 
 
            middlePixel = BitConverter.GetBytes( 
                               neighbourPixels[filterOffset]); 

 
            resultBuffer[byteOffset] = middlePixel[0]; 
            resultBuffer[byteOffset + 1] = middlePixel[1]; 
            resultBuffer[byteOffset + 2] = middlePixel[2]; 
            resultBuffer[byteOffset + 3] = middlePixel[3]; 
        } 
    }

 
    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