c#實現影象影象卷積與濾波——高斯平滑
阿新 • • 發佈:2019-02-06
使用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; }