[函數名稱]php
高斯平滑濾波器 GaussFilter(WriteableBitmap src,int radius,double sigma)html
[算法說明]算法
高斯濾波器實質上是一種信號的濾波器,其用途是信號的平滑處理。它是一類根據高斯函數的函數
形狀來選擇權重的線性平滑濾波器,該濾波器對於抑制服從正態分佈的噪聲很是有效。高斯函數網站
的公式以下所示:spa
private static double[,] GaussFuc(int r, double sigma) { int size = 2 * r + 1; double[,] gaussResult = new double[size, size]; double k = 0.0; for (int y = -r, h = 0; y <= r; y++, h++) { for (int x = -r, w = 0; x <= r; x++, w++) { gaussResult[w, h] = (1.0 / (2.0 * Math.PI * sigma * sigma)) * (Math.Exp(-((double)x * (double)x + (double)y * (double)y) / (2.0 * sigma * sigma))); k += gaussResult[w, h]; } } return gaussResult; }
咱們設置參數r=1,sigma=1.0,則獲得一個3*3的高斯模板以下:.net
這個公式能夠理解爲先對圖像按行進行一次一維高斯濾波,在對結果圖像按列進行一次一維高斯濾波,這樣速度將大大提升。code
一維高斯濾波代碼以下(包含歸一化):htm
private static double[] GaussKernel1D(int r, double sigma) { double[] filter = new double[2 * r + 1]; double sum = 0.0; for (int i = 0; i < filter.Length; i++) { filter[i] = Math.Exp((double)(-(i - r) * (i - r)) / (2.0 * sigma * sigma)); sum += filter[i]; } for (int i = 0; i < filter.Length; i++) { filter[i] = filter[i] / sum; } return filter; }
[函數代碼]blog
private static double[] GaussKernel(int radius, double sigma) { int length=2*radius+1; double[] kernel = new double[length]; double sum = 0.0; for (int i = 0; i < length; i++) { kernel[i] = Math.Exp((double)(-(i - radius) * (i - radius)) / (2.0 * sigma * sigma)); sum += kernel[i]; } for (int i = 0; i < length; i++) { kernel[i] = kernel[i] / sum; } return kernel; } /// <summary> /// Gauss filter process /// </summary> /// <param name="src">The source image.</param> /// <param name="radius">The radius of gauss kernel,from 0 to 100.</param> /// <param name="sigma">The convince of gauss kernel, from 0 to 30.</param> /// <returns></returns> public static WriteableBitmap GaussFilter(WriteableBitmap src,int radius,double sigma) ////高斯濾波 { if (src != null) { int w = src.PixelWidth; int h = src.PixelHeight; WriteableBitmap srcImage = new WriteableBitmap(w, h); byte[] srcValue = src.PixelBuffer.ToArray(); byte[] tempValue=(byte[])srcValue.Clone(); double[] kernel = GaussKernel(radius, sigma); double tempB = 0.0, tempG = 0.0, tempR = 0.0; int rem = 0; int t = 0; int v = 0; double K = 0.0; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { tempB = tempG = tempR = 0.0; for (int k = -radius; k <= radius; k++) { rem = (Math.Abs(x + k) % w); t = rem * 4 + y * w * 4; K=kernel[k+radius]; tempB += srcValue[t] * K; tempG += srcValue[t + 1] * K; tempR += srcValue[t + 2] * K; } v = x * 4 + y * w * 4; tempValue[v] = (byte)tempB; tempValue[v + 1] = (byte)tempG; tempValue[v + 2] = (byte)tempR; } } for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { tempB = tempG = tempR = 0.0; for (int k = -radius; k <= radius; k++) { rem = (Math.Abs(y + k) % h); t = rem * w * 4 + x * 4; K = kernel[k + radius]; tempB += tempValue[t] * K; tempG += tempValue[t + 1] * K; tempR += tempValue[t + 2] * K; } v = x * 4 + y * w * 4; srcValue[v] = (byte)tempB; srcValue[v + 1] = (byte)tempG; srcValue[v + 2] = (byte)tempR; } } Stream sTemp = srcImage.PixelBuffer.AsStream(); sTemp.Seek(0, SeekOrigin.Begin); sTemp.Write(srcValue, 0, w * 4 * h); return srcImage; } else { return null; } }