zoukankan      html  css  js  c++  java
  • 高斯模糊的.net实现 (摘自网络)

    摘自:http://dormforce.net/Blog/hiworld/archive/2005/05/19/4720.aspx
    //我看这段代码的体会

    //本文有两个错误 ,一是下面的代码
    for(int x = -fi; x <=fi; x++)
        
    for(int y = -fi; y <= fi; y++{
         
    int sqrtFi = fi * fi;
         
    double ex = Math.Pow(Math.E, (-(x * x + y * y)/(2 * sqrtFi)));
         
    double result = ex / (2 * Math.PI * sqrtFi);
         GAUSS[x 
    + fi, y + fi] = result;
        }

    //(-(x * x + y * y)/(2 * sqrtFi))都是整形,结果会使ex值大部分是1,应该(-(x * x + y * y)/(2 * sqrtFi))结果大多数是0,
    //修改方法:int sqrtFi = fi * fi;为double  sqrtFi = fi * fi;

    第二次,高斯模板没有归一化,造成图片模糊后,亮度变黑.



    选择.net来做图像处理唯一的好处就是避免了烦琐的编程细节,可以全部精力投入在算法上.
    在图像结构分析之前,我使用了高斯模糊来去粗取精, 将细节部分的去掉,将边缘强化.
    高斯模糊的算法很简单了, 使用高斯函数和图像做卷积, 不过复杂度真是不错, 宽度=2的高斯模糊要做 24*n(n是图像像素)次浮点运算
    不过如果把重复计算的除外,就只有4*n次了, 而且宽度约大, 重复计算的越多. 我最早实现的不加任何优化的算法真是奇满无比,在被
    acdsee的高斯模糊速度bs后,我开始优化,最后终于在速度上比较能够接受(还是要被acdsee鄙视)不过,这个慢速度,vm也多少要负点责任吧...(我又不能使用pointer,所有的数值在使用时都是copy的,这个就比用c实现慢多了...)
     private double[,] GAUSS; //高斯函数的值, 每次都计算高斯函数太夸张了吧...事先计算好,放这里备用
     private const int FI = 2; //高斯函数宽度
    //初试化高斯函数
    private void IniGauss(int fi) {
       GAUSS = new double[fi * 2 + 1, fi * 2 + 1];
     
       for(int x = -fi; x <=fi; x++)
        for(int y = -fi; y <= fi; y++) {
         int sqrtFi = fi * fi;
         double ex = Math.Pow(Math.E, (-(x * x + y * y)/(2 * sqrtFi)));
         double result = ex / (2 * Math.PI * sqrtFi);
         GAUSS[x + fi, y + fi] = result;
        }
      }
     
    //事先计算好每个像素在卷积中要用到的值,避免重复运算, WeightedColor是自定义struct, 只有3个字段,
    //分别是double R; double G; double B;
    private WeightedColor[,,] GetWeightedColor(Bitmap source, int fi) {
       WeightedColor[,,] retVal = new WeightedColor[fi + 1 + fi, source.Width, source.Height];
       double r = 0, g = 0, b = 0;
       
       for(int i = 0; i < source.Width; i++)
        for(int j = 0; j <source.Height; j++) {
         //Calculate weighted color
         Color c = source.GetPixel(i, j);
     
         for(int k = 0; k < fi + 1 + fi; k++) {
          //From center to edge
          double weight;
          if( k < fi + 1)
           weight = GAUSS[fi, fi + k];
          else
           //对角
           weight = GAUSS[k, k];
          r = c.R * weight;
          g = c.G * weight;
          b = c.B * weight;
          r = r > 255 ? 255 : r;
          g = g > 255 ? 255 : g;
          b = b > 255 ? 255 : b;
          retVal[k, i, j] = WeightedColor.FromRGB(r, g, b);
         }
        }
     
    //计算一个点的卷积值
    private Color GetFilteredColor(Bitmap source, int x, int y, int fi, WeightedColor[,,] colorMap) {
       int w = source.Width, h = source.Height;
       double r = 0, g = 0, b = 0;
     
       for(int u = x - fi; u <= x + fi; u++)
        for(int v = y - fi; v <= y + fi; v++) {
         if(u >= 0 && u < w && v >= 0 && v < h) {
          //wx, wy is the distance between x and u, y and v
          int wx = Math.Abs(u - x), wy = Math.Abs(v - y);
          //Use which version of colorMap
          int wVersion;
          if(wx == wy && wx != 0)//对角
           wVersion = fi + wx;
          else
           wVersion = wx > wy ? wx : wy;
          WeightedColor tmpC = colorMap[wVersion, u, v];
          r += tmpC.R;
          g += tmpC.G;
          b += tmpC.B;
         }
        }
       r = r > 255 ? 255 : r;
       g = g > 255 ? 255 : g;
       b = b > 255 ? 255 : b;
       return Color.FromArgb((int)r, (int)g, (int)b);
      }
       return retVal;
      }
     
    //使用这个函数对图像进行过滤
     private Bitmap GaussianFilt(Bitmap source, int fi) {
       Bitmap retVal = new Bitmap(source.Width, source.Height);
       WeightedColor[,,] colorMap = GetWeightedColor(source, fi);
       for(int i = 0; i < source.Width; i++)
        for(int j = 0; j <source.Height; j++) {
         Color fColor = GetFilteredColor(source, i, j, fi, colorMap);
         retVal.SetPixel(i, j, fColor);
        }
       return retVal;
      }
     
    //使用范例
    Bitmap fbmp = GaussianFilt(bmp, FI);
    pictureBox1.Image = fbmp;
     
  • 相关阅读:
    Dao层
    I/O流
    导入第三方jar包
    怎么使用log4j
    JDBC访问数据库的步骤
    抽象和封装
    JDBC中PreparedStatement接口提供的execute、executeQuery和executeUpdate之间的区别及用法
    ResultSet next方法
    实体类(entity)的作用
    接口的作用
  • 原文地址:https://www.cnblogs.com/wzyexf/p/700358.html
Copyright © 2011-2022 走看看