cX中的3X3中位数过滤但不起作用?

时间:2015-11-13 23:32:22

标签: c# .net image-processing

我真的试图通过C#应用3X3中值过滤,并根据我的理解中位数过滤的概念,我编写了以下代码但是当我运行它时,表单挂起。我认为在最后一个嵌套for循环中有一些问题,但我不知道应用中值概念的错误或错误在哪里!

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

感谢。

1 个答案:

答案 0 :(得分:1)

在每次像素处理后,您没有清除termsList。这导致列表继续增长。对列表进行排序和反转将持续越来越长的时间。这也会导致错误的结果,因为您只想获得与当前像素相关的9个像素的中位数。

只需清除以下列表:

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

<强>更新

我为代码做了更多优化:

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

请注意,在原始方法中,您返回了Bitmap。我删除了这个。

请注意,temp = bm;不会创建Bitmap的副本。它只是将temp变量指向同一个对象(由bm指向)。因此,在原始方法中,您返回了在method参数中传递的确切对象。要使用新方法,请传递Bitmap,然后修改自身的位图(对于您的方法也是如此)。

这在我的机器上增强了4倍的性能。

我所做的主要是将位图数据读入字节数组,而不是使用Bitmap自己多次读/写数据。

如果您需要进一步提升效果,请查看this question