c#中實現圖像圖像卷積與濾波-高斯平滑

使用C#語言編寫高斯平滑。

一、線性濾波與卷積的基本概念
2D卷積需要4個嵌套循環4-double loop,所以它並不快,除非我們使用很小的卷積核。這裏一般使用3×3或者5×5。而且,對於濾波器,也有一定的規則要求:

1)濾波器的大小應該是奇數,這樣它纔有一箇中心,例如3×3,5×5或者7×7。有中心了,也有了半徑的稱呼,例如5×5大小的核的半徑就是2。

2)濾波器矩陣所有的元素之和應該要等於1,這是爲了保證濾波前後圖像的亮度保持不變。當然了,這不是硬性要求了。

3)如果濾波器矩陣所有元素之和大於1,那麼濾波後的圖像就會比原圖像更亮,反之,如果小於1,那麼得到的圖像就會變暗。如果和爲0,圖像不會變黑,但也會非常暗。

4)對於濾波後的結構,可能會出現負數或者大於255的數值。對這種情況,我們將他們直接截斷到0和255之間即可。對於負數,也可以取絕對值。

二、卷積核
        private double[,] GaussianBlur;//聲明私有的高斯模糊卷積核函數
 
        /// <summary>
        /// 構造卷積(Convolution)類函數
        /// </summary>
        public Convolution()
        {
            //初始化高斯模糊卷積核
            int k=273;
            GaussianBlur = new double[5, 5]{{(double)1/k,(double)4/k,(double)7/k,(double)4/k,(double)1/k},
                                            {(double)4/k,(double)16/k,(double)26/k,(double)16/k,(double)4/k},
                                            {(double)7/k,(double)26/k,(double)41/k,(double)26/k,(double)7/k},
                                            {(double)4/k,(double)16/k,(double)26/k,(double)16/k,(double)4/k},
                                            {(double)1/k,(double)4/k,(double)7/k,(double)4/k,(double)1/k}};
        }
三、對圖像進行卷積平滑
/// <summary>
        /// 對圖像進行平滑處理(利用高斯平滑Gaussian Blur)
        /// </summary>
        /// <param name="bitmap">要處理的位圖</param>
        /// <returns>返回平滑處理後的位圖</returns>
        public Bitmap Smooth(Bitmap bitmap) 
        {
            int[, ,] InputPicture = new int[3, bitmap.Width, bitmap.Height];//以GRB以及位圖的長寬建立整數輸入的位圖的數組
 
            Color color = new Color();//儲存某一像素的顏色
            //循環使得InputPicture數組得到位圖的RGB
            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    color = bitmap.GetPixel(i, j);
                    InputPicture[0, i, j] = color.R;
                    InputPicture[1, i, j] = color.G;
                    InputPicture[2, i, j] = color.B;
                }
            }
 
            int[, ,] OutputPicture = new int[3, bitmap.Width, bitmap.Height];//以GRB以及位圖的長寬建立整數輸出的位圖的數組
            Bitmap smooth = new Bitmap(bitmap.Width, bitmap.Height);//創建新位圖
            //循環計算使得OutputPicture數組得到計算後位圖的RGB
            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    int R=0;
                    int G=0;
                    int B=0;
 
                    //每一個像素計算使用高斯模糊卷積核進行計算
                    for (int r = 0; r < 5; r++)//循環卷積核的每一行
                    {
                        for (int f = 0; f < 5; f++)//循環卷積核的每一列
                        {
                            //控制與卷積核相乘的元素
                            int row = i - 2 + r;
                            int index = j - 2 + f;
                            
                            //當超出位圖的大小範圍時,選擇最邊緣的像素值作爲該點的像素值
                            row = row < 0 ? 0 : row;
                            index = index < 0 ? 0 : index;
                            row = row >= bitmap.Width ? bitmap.Width - 1 : row;
                            index = index >= bitmap.Height ? bitmap.Height - 1 : index;
 
                            //輸出得到像素的RGB值
                            R += (int)(GaussianBlur[r, f] * InputPicture[0, row, index]);
                            G += (int)(GaussianBlur[r, f] * InputPicture[1, row, index]);
                            B += (int)(GaussianBlur[r, f] * InputPicture[2, row, index]);
                        }
                    }
                    color = Color.FromArgb(R,G,B);//顏色結構儲存該點RGB
                    smooth.SetPixel(i, j, color);//位圖存儲該點像素值
                }
            }
            return smooth;
        }
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章