c#实现高斯模糊
說說高斯模糊
高斯模糊的理論我這里就不太多費話了,百度下太多,都是抄來抄去。
主要用到二個函數“高斯函數”
一維形式為:
二維形式為:
X,Y對應的一維二維坐標,σ表示模糊半徑(半徑* 2 + 1) / 2)
根據這二個公式獲取對應的權重。
?
先看二維
假設我們現在圖片中的像素點位置為(0,0)
假設我們設置的模糊半徑為1,那么對應的坐標為如下圖
它是以(0,0)這個坐標為標記,向外擴展1個像素。
接下來就是計算各個坐標的權重值,我們采用二維的高斯函數來計算,計算的代碼如下:
/// <summary>/// 獲取權重/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <returns></returns>private double GetWeighing(int x, int y) {double q = (this.BlurRadius * 2 + 1) / 2; return 1 / (2 * Math.PI * Math.Pow(q, 2)) * Math.Exp(-(x * x + y * y) / (2 * q * q));}this.BlurRadius 為我們設置的模糊半徑
上圖是我們計算的結果,這9個值的結果的總和為:0.779483679709388,該值不能大于1。這個時候我們要將上面的9個值 除以0.779483679709388,使他們的和為1.
?除以0.779483679709388之后為:
假設這9個點上的RGB顏色值中的R值乘以上圖矩陣中的值,如下圖
?
計算之后的顏色值
?
求和為:112.14236039551
所以(0,0)坐標的RGB顏色值中的R為112.14236039551
然后我們獲取這9個點的坐標RGB值,讓后將RGB值分別乘以權重值,然和將這9個值相加得到最后的顏色值。
?
using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text;namespace NetShadow {/// <summary>/// 高斯模糊/// </summary>public class GaussianBlur {/// <summary>/// 模糊半徑/// </summary>public int BlurRadius { get; private set; }private Bitmap SourceImage { get; set; }private List<double> BlurArray { get; set; }private int MaxWidth { get; set; }private int MaxHeight { get; set; }public GaussianBlur(int blurRadius) {BlurArray = new List<double>();this.BlurRadius = blurRadius;this.SetBlurArray();}/// <summary>/// 設置需要模糊的圖片/// </summary>/// <param name="img"></param>public void SetSourceImage(Image img) {this.SourceImage = (Bitmap)img;this.MaxWidth = this.SourceImage.Width - 1;this.MaxHeight = this.SourceImage.Height - 1;}/// <summary>/// 獲取模糊之后的圖片/// </summary>/// <returns></returns>public Bitmap GetBlurImage() {if (this.SourceImage == null) return null;Bitmap newImage = new Bitmap(SourceImage.Width, SourceImage.Height);for (int y = 0; y < this.SourceImage.Height; y++) {for (int x = 0; x < this.SourceImage.Width; x++) {var nC = GetBlurColor(x, y);//return null;newImage.SetPixel(x, y, nC);}}return newImage;}/// <summary>/// 獲取高斯模糊的顏色值/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <returns></returns>private Color GetBlurColor(int x, int y) {double r = 0, g = 0 , b = 0;int index = 0;for (var t = y - this.BlurRadius; t <= y + this.BlurRadius; t++) {for (var l = x - this.BlurRadius; l <= x + this.BlurRadius; l++) {var color = GetDefautColor(l, t);var weighValue = BlurArray[index];r += color.R * weighValue;g += color.G * weighValue;b += color.B * weighValue;index++;}}return Color.FromArgb((byte)r, (byte)g, (byte)b);}private Color GetDefautColor(int x, int y) {if (x < 0 && y < 0)return this.SourceImage.GetPixel(0, 0);else if (x < 0)return this.SourceImage.GetPixel(0, Math.Min(MaxHeight, y));else if (y < 0)return this.SourceImage.GetPixel(Math.Min(MaxWidth, x), 0);elsereturn this.SourceImage.GetPixel(Math.Min(MaxWidth, x), Math.Min(MaxHeight, y));}private void SetBlurArray() {int blur = this.BlurRadius;double sum = 0;for (var y = blur; y >= blur * -1; y--) {for (var x = blur * -1; x <= blur; x++) { var d = GetWeighing(x, y);this.BlurArray.Add(d);sum += d;}}for (var i = 0; i < this.BlurArray.Count; i++)this.BlurArray[i] = this.BlurArray[i] / sum;//sum = 0;//foreach (var item in this.BlurArray)// sum += item;}/// <summary>/// 獲取權重/// </summary>/// <param name="x"></param>/// <param name="y"></param>/// <returns></returns>private double GetWeighing(int x, int y) {double q = (this.BlurRadius * 2 + 1) / 2; return 1 / (2 * Math.PI * Math.Pow(q, 2)) * Math.Exp(-(x * x + y * y) / (2 * q * q));}} }
?這種效率其實很地下,所以網上的解決辦法是將二維高斯改為一維高斯來計算,也就是先橫向模糊,然后再縱向模糊。
另外獲取圖片的RGB顏色值采用的是GetPixel 和SetPixel,這二個函數的效率是很低下的,大家可以到網上找下相關的解決辦法。
?源碼下載
轉載于:https://www.cnblogs.com/zbjuke/p/10304863.html
總結
- 上一篇: win7 64位利用eclipse搭建a
- 下一篇: (vue)在ajax获取数据时使用loa