1

Really I'm trying to apply 3X3 Median Filtering by C# and depending on my understanding the concepts of Median Filtering I wrote the following code but when I'm running it the Form hangs. I think have some problem in the last nested for loop but i don't know where is the error or the wrong in applying the Median concepts!

public static Bitmap MedianFiltering(Bitmap bm)
    {
        List<int> termsList = new List<int>();
        Bitmap res, temp;
        Color c;
        int counter = 0;

        //Convert to Grayscale 
        for (int i = 0; i < bm.Width; i++)
        {
            for (int j = 0; j < bm.Height; j++)
            {
                c = bm.GetPixel(i, j);
                byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
                bm.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
            }
        }

        temp = bm;

       //applying Median Filtering 
        for (int i = 0; i <= temp.Width - 3; i++)
            for (int j = 0; j <= temp.Height - 3; j++)
            {
                for (int x = i; x <= i + 2; x++)
                    for (int y = j; y <= j + 2; y++)
                    {

                        c = temp.GetPixel(x, y);
                        termsList.Add(c.R);
                        counter++;
                    }
                int[] terms = termsList.ToArray();
                Array.Sort<int>(terms);
                Array.Reverse(terms);
                int color = terms[4];
                temp.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
                counter = 0;
            }
        res = temp;

        return res;
    }

Thanks.

diceguyd30
  • 2,742
  • 20
  • 18
Samah Ahmed
  • 419
  • 8
  • 24
  • It is normal for the UI to hang if you are running this code on the UI thread (e.g. from a button handler). But it should only hang until the median filter calculation is complete. You can use an asynchronous method to make the form not hang while the calculation is in progress. – Yacoub Massad Nov 13 '15 at 23:39
  • I tried it now , at this line ! temp.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color)); – Samah Ahmed Nov 13 '15 at 23:40
  • So it completely hangs? If you wait enough time, does it finish? – Yacoub Massad Nov 13 '15 at 23:40
  • I waited 5 minutes and more with the same result – Samah Ahmed Nov 13 '15 at 23:43
  • Is there any progress after 5 minutes? Place `Debug.WriteLine(i + ", " + j);` after the `temp.SetPixel(i + 1, j + 1,....` line. This will output the current pixel coordinates to the output window (View -> Output in visual studio). This way, you can see if the program is still working or not. – Yacoub Massad Nov 13 '15 at 23:49
  • yes it's still working in this case how we can do this process as fast as possible :( – Samah Ahmed Nov 13 '15 at 23:54
  • By the way, why are you reversing the array? – Yacoub Massad Nov 13 '15 at 23:59
  • You should use memory locked bitmaps for tasks of this type (processing all pixels), it is much faster. Btw You may like this grayscale more: Y = 0.299R + 0.587G + 0.114B – Antonín Lejsek Nov 14 '15 at 05:08

1 Answers1

1

You are not clearing the termsList after each pixel processing. This is causing the list to keep growing. Sorting and reversing the list will keep taking longer and longer times. This will also cause incorrect results since you only want to get the median of the 9 pixels related to the current pixel.

Simply clear the list like this:

...
int[] terms = termsList.ToArray();
termsList.Clear();
...

UPDATE:

I did more optimization for the code:

public static void MedianFiltering(Bitmap bm)
{
    List<byte> termsList = new List<byte>();

    byte[,] image = new byte[bm.Width,bm.Height];

    //Convert to Grayscale 
    for (int i = 0; i < bm.Width; i++)
    {
        for (int j = 0; j < bm.Height; j++)
        {
            var c = bm.GetPixel(i, j);
            byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
            image[i, j] = gray;
        }
    }

    //applying Median Filtering 
    for (int i = 0; i <= bm.Width - 3; i++)
        for (int j = 0; j <= bm.Height - 3; j++)
        {
            for (int x = i; x <= i + 2; x++)
                for (int y = j; y <= j + 2; y++)
                {
                    termsList.Add(image[x, y]);
                }
            byte[] terms = termsList.ToArray();
            termsList.Clear();
            Array.Sort<byte>(terms);
            Array.Reverse(terms);
            byte color = terms[4];
            bm.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
        }
}

Please note that in your original method, you returned a Bitmap. I removed this.

Please note that temp = bm; does not create a copy of the Bitmap. It is just pointing the temp variable to the same object (that is pointed by bm). So in your original method, you returned the exact object that is passed in the method parameter. To use the new method pass the Bitmap and then the bitmap it self will be modified (this is also true for your method).

This enhanced performance 4 times on my machine.

What I did is mainly read the bitmap data into a byte array instead of using the Bitmap it self to read/write data multiple times.

If you need to further enhance the performance, take a look at this question.

Community
  • 1
  • 1
Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
  • It's working more fast now I waited maybe 5 minutes to take the result but I want to make something to apply that with more performance , do you have any suggestion ? – Samah Ahmed Nov 14 '15 at 00:14
  • Strange. 5 minutes is too much. How large is the input image? What is the width and height? – Yacoub Massad Nov 14 '15 at 00:16
  • I tied your code (after adding `termsList.Clear()`) on an image with size 1013x699. And it is taking about 8 seconds on my machine. Although there is room for improvement, it is still strange why its taking 5 minutes on your machine. – Yacoub Massad Nov 14 '15 at 00:21
  • I'm working on virtual machine of windows on my mac this is doing any effects ? I tried one image now 500x333 and it takes 2.5 minutes – Samah Ahmed Nov 14 '15 at 00:29
  • And to answer your question: Yes. Virtual machines are almost always slower than real ones. – Yacoub Massad Nov 14 '15 at 00:44