欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c#实现高斯模糊

程序员文章站 2022-04-28 13:29:02
说说高斯模糊 高斯模糊的理论我这里就不太多费话了,百度下太多,都是抄来抄去。 主要用到二个函数“高斯函数” 一维形式为: 二维形式为: X,Y对应的一维二维坐标,σ表示模糊半径(半径* 2 + 1) / 2) 根据这二个公式获取对应的权重。 先看二维 假设我们现在图片中的像素点位置为(0,0) 假设 ......

说说高斯模糊

高斯模糊的理论我这里就不太多费话了,百度下太多,都是抄来抄去。

主要用到二个函数“高斯函数”

一维形式为:

c#实现高斯模糊

二维形式为:

c#实现高斯模糊

x,y对应的一维二维坐标,σ表示模糊半径(半径* 2 + 1) / 2)

根据这二个公式获取对应的权重。

 

先看二维

假设我们现在图片中的像素点位置为(0,0)

假设我们设置的模糊半径为1,那么对应的坐标为如下图

c#实现高斯模糊

它是以(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 为我们设置的模糊半径

c#实现高斯模糊

上图是我们计算的结果,这9个值的结果的总和为:0.779483679709388,该值不能大于1。这个时候我们要将上面的9个值 除以0.779483679709388,使他们的和为1.

 除以0.779483679709388之后为:

c#实现高斯模糊

假设这9个点上的rgb颜色值中的r值乘以上图矩阵中的值,如下图

c#实现高斯模糊

 

计算之后的颜色值

 c#实现高斯模糊

求和为: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);
            else
                return 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));
        }
    }
}