Winform下对自定义控件进行绘制,需要对一个图片进行灰化,求相关算法。

解决方案 »

  1.   


    高斯模糊的.net实现   
    选择.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; 
      

  2.   


     int Height = this.pictureBox1.Image.Height;
                int Width = this.pictureBox1.Image.Width;
                Bitmap bitmap = new Bitmap(Width, Height);
                Bitmap Mybitmap = (Bitmap)this.pictureBox1.Image;
                Color pixel;
                for (int y = 0; y < Height; y++)
                    {
                        pixel = Mybitmap.GetPixel(x, y);
                        int r, g, b, Result = 0;
                        r = pixel.R;
                        g = pixel.G;
                        b = pixel.B;                    int iType = 1;
                        switch (iType)
                        {
                            case 0://平均值法
                                Result = ((r + g + b) / 3);
                                break;
                            case 1://最大值法
                                Result = r > g ? r : g;
                                Result = Result > b ? Result : b;
                                break;
                            case 2://加权平均值
                                Result = ((int)(0.7 * r) + (int)(0.2 * g) + (int)(0.1 * b));
                                break;
                        }
                        bitmap.SetPixel(x, y, Color.FromArgb(Result, Result, Result));
                    }3种方式自己选一中就行了
      

  3.   

       private void button2_Click(object sender, EventArgs e)
            {
                Graphics myGraphics = this.CreateGraphics();
                Bitmap myBitmap = new Bitmap(this.BackgroundImage);
                int myWidth, myHeight, i, j, iAvg, iPixel;
                Color myColor, myNewColor;
                RectangleF myRect;
                myWidth = myBitmap.Width;
                myHeight = myBitmap.Height;
                myRect = new RectangleF(0, 0, myWidth, myHeight);
                Bitmap bitmap = myBitmap.Clone(myRect, System.Drawing.Imaging.PixelFormat.DontCare);
                i = 0;
                while (i < myWidth - 1)
                {
                    j = 0;
                    while (j < myHeight - 1)
                    {
                        myColor = bitmap.GetPixel(i, j);
                        iAvg = (myColor.R + myColor.G + myColor.B) / 3;
                        iPixel = 0;
                        if (iAvg >= 128)
                            iPixel = 255;
                        else
                            iPixel = 0;
                        myNewColor = Color.FromArgb(255, iPixel, iPixel, iPixel);
                        bitmap.SetPixel(i, j, myNewColor);
                        j = j + 1;
                    }
                    i = i + 1;
                }
                myGraphics.Clear(Color.WhiteSmoke);
                myGraphics.DrawImage(bitmap, new Rectangle(0, 0, myWidth, myHeight));
            }
    积木效果
    //
      

  4.   

    一句代码:System.Windows.Forms.ControlPaint.DrawImageDisabled()
      

  5.   

    其实就将彩色图片灰度化,将RGB三色转换为单色。所谓的128叫阈值,不一定非得是128,特殊场合也可以动态选取。