去噪:用于验证码图片识别的类续(C#代码)

自从发表了用于验证码图片识别的类(C#代码)后,不断有网友下载这个类后,问如何用于一些特定的验证码。总结一下网友们的提问,很多都是不会从复杂背景中提到干净的字符图片来,这主要就是一个去噪问题,即除去图片上的背景、干扰点、干扰线等信息。这当中要用到很多图像学数学算法,首先声明,本人不是学图像学的,以下方法理论说得不对,敬请多批评指正。
    1、如何设前景/背景的分界值
    UnCodebase类中有一个GetPicValidByValue( int dgGrayValue) 函数,可以得到前景的有效区域,常有人问我前景/背景的分界值dgGrayValue是如何确定的(常用的是灰度128)。这个值的获取是有数学算法,叫最大类间方差法,即图像的前后景的平方差为最大时的值就是我们关心的分界值,对付如 这样较复杂的背景非常管用,下面是具体的C#代码。

Code


    2、如何去除干扰点/干扰线
    2.1 干扰点/干扰线的特征分析
    现在网上的大多数的验证码都是加了干扰的,一般分为干扰点和干扰线,如下图。标用1、2、3的分别为点、线、字符。


   去干扰,一般是逐点分析,这三种情况下,每一点及周边8个点的情况都不一样(分别为1点,3点,8点),这是一种干扰信息的粒度比字符的粒度小的典型情况。现在就可以动手编写去杂代码了。
   
    2.2 根据周边有效点数去噪函数

        /// <summary>
        
///  去掉杂点(适合杂点/杂线粗为1)
        
/// </summary>

        
/// <param name="dgGrayValue">背前景灰色界限</param>
        
/// <returns></returns>
        public void ClearNoise(int dgGrayValue, int MaxNearPoints)
        {
            Color piexl;
            
int nearDots = 0
;
            
int
 XSpan, YSpan, tmpX, tmpY;
            
//逐点判断

            for (int i = 0; i < bmpobj.Width; i++)
                
for (int j = 0; j < bmpobj.Height; j++
)
                {
                    piexl 
=
 bmpobj.GetPixel(i, j);
                    
if (piexl.R <
 dgGrayValue)
                    {
                        nearDots 
= 0
;
                        
//判断周围8个点是否全为空

                        if (i == 0 || i == bmpobj.Width - 1 || j == 0 || j == bmpobj.Height - 1)  //边框全去掉
                        {
                            bmpobj.SetPixel(i, j, Color.FromArgb(
255255255
));
                        }
                        
else

                        {
                            
if (bmpobj.GetPixel(i - 1, j - 1).R < dgGrayValue) nearDots++;
                            
if (bmpobj.GetPixel(i, j - 1).R < dgGrayValue) nearDots++
;
                            
if (bmpobj.GetPixel(i + 1, j - 1).R < dgGrayValue) nearDots++
;
                            
if (bmpobj.GetPixel(i - 1, j).R < dgGrayValue) nearDots++
;
                            
if (bmpobj.GetPixel(i + 1, j).R < dgGrayValue) nearDots++
;
                            
if (bmpobj.GetPixel(i - 1, j + 1).R < dgGrayValue) nearDots++
;
                            
if (bmpobj.GetPixel(i, j + 1).R < dgGrayValue) nearDots++
;
                            
if (bmpobj.GetPixel(i + 1, j + 1).R < dgGrayValue) nearDots++
;
                        }

                        
if (nearDots <
 MaxNearPoints)
                            bmpobj.SetPixel(i, j, Color.FromArgb(
255255255));   //去掉单点 && 粗细小3邻边点

                    }
                    
else  //背景

                        bmpobj.SetPixel(i, j, Color.FromArgb(255255255));
                }
        }

    2.3 滤波算法去噪函数
     图像预处理中有多种滤波算法,其原理与方法分别为
     1) 中值滤波
    它通过从图像中的某个采样窗口取出奇数个数据进行排序得到的结果。顾名思义,所谓中值就是窗口中奇数个数据按大小顺序排列后处于中心位置的那个数。中值滤波以窗口的中值作为处理结果。
    实现起来很简单
    1:先对窗口排序
    2:用排序后的中值取代要处理的数据即可
    注意事项:
    1:注意图像边缘数据的处理
    2:对于不同的目的选用不同的窗体,一般有3×3,5×5等等


        /// <summary>
        
/// 3×3中值滤波除杂,yuanbao,2007.10
        
/// </summary>

        
/// <param name="dgGrayValue"></param>
        public void ClearNoise(int dgGrayValue)
        {
            
int
 x, y;
            
byte[] p = new byte[9]; //最小处理窗口3*3

            byte s;
            
//byte[] lpTemp=new BYTE[nByteWidth*nHeight];

            int i, j;

            
//--!!!!!!!!!!!!!!下面开始窗口为3×3中值滤波!!!!!!!!!!!!!!!!

            for (y = 1; y < bmpobj.Height - 1; y++//--第一行和最后一行无法取窗口
            {
                
for (x = 1; x < bmpobj.Width - 1; x++
)
                {
                    
//取9个点的值

                    p[0= bmpobj.GetPixel(x - 1, y - 1).R;
                    p[
1= bmpobj.GetPixel(x, y - 1
).R;
                    p[
2= bmpobj.GetPixel(x + 1, y - 1
).R;
                    p[
3= bmpobj.GetPixel(x - 1
, y).R;
                    p[
4=
 bmpobj.GetPixel(x, y).R;
                    p[
5= bmpobj.GetPixel(x + 1
, y).R;
                    p[
6= bmpobj.GetPixel(x - 1, y + 1
).R;
                    p[
7= bmpobj.GetPixel(x, y + 1
).R;
                    p[
8= bmpobj.GetPixel(x + 1, y + 1
).R;
                    
//计算中值

                    for (j = 0; j < 5; j++)
                    {
                        
for (i = j + 1; i < 9; i++
)
                        {
                            
if (p[j] >
 p[i])
                            {
                                s 
=
 p[j];
                                p[j] 
=
 p[i];
                                p[i] 
=
 s;
                            }
                        }
                    }
              
//      if (bmpobj.GetPixel(x, y).R < dgGrayValue)

                        bmpobj.SetPixel(x, y, Color.FromArgb(p[4], p[4], p[4]));    //给有效值付中值
                }
            }
        }

   经过实际运行证实,中值滤波能有效去除图像中的噪声点,特别是在一片连续变化缓和的区域中(比如人的衣服,皮肤),几乎100%去除灰度突变点(可以认为是噪声点),也因为如此,中值滤波不适合用在一些细节多,如细节点,细节线多的图像中,因为细节点有可能被当成噪声点去除。

 
 

    中值滤波的窗口还可以有多种形状,上面程序选择的是矩形(容易计算),其实窗口还可以是菱形,圆形,十字形等等,不同的窗口形状有不同的滤波效果,对有缓慢且有较长轮廓线的物体适合用矩形或者原型窗口,对于有尖顶角物体的图像适合采用十字形窗口。
    中值滤波可以进行线性组合,不同窗口形状的滤波器可以线性组合
    改进中值滤波方法:
    对一些内容复杂的图像,可以使用复合型中值滤波。如, 中值滤波线性组合、高阶中值滤波组合、加权中值滤波以及迭代中值滤波等。
    中值滤波的线性组合是将几种窗口尺寸大小和形状不同的中值滤波器复合使用,只要各窗口都与中心对称,滤波输出可保持几个方向上的边缘跳变,而且跳变幅度可调节。
    高阶中值滤波组合可以使输入图像中任意方向的细线条保持不变。
    为了在一定的条件下尽可能去除噪声,又有效保持图像细节,可以对中值滤波器参数进行修正, 如加权中值滤波, 也就是对输入窗口进行加权。
    也可以是对中值滤波器的使用方法进行变化, 保证滤波的效果, 还可以和其他滤波器联合使用。
 
    2).均值滤波(模糊算法)
    均值滤波是典型的线性滤波算法,它是指在图像上对待处理的像素给一个模板,该模板包括了其周围的临近像素。将模板中的全体像素的均值来代替原来的像素值的方法。

    3)维纳(Wiener)滤波
    维纳(Wiener)滤波是对退化图像进行恢复处理的另一种常用算法,是一种有约束的恢复处理方法,其采用的维纳滤波器是一种最小均方误差滤波器,其数学形式比较复杂:
    F(u,v)=[(1/H(u,v))*(|H(u,v)|2)/(|H(u,v)|2+s*[Sn(u,v)/Sf(u,v)])]*G(u,v)
& nbsp;   当s为1时,上式就是普通的维纳滤波;如果s为变量,则为参数维纳滤波,如果没有噪声干扰,即Sn (u,v)=0时,上式实际就是前面的逆滤波。从其数学形式可以看出:维纳滤波比逆滤波在对噪声的处理方面要强一些。以上只是理论上的数学形式,在进行实际处理时,往往不知道噪声函数Sn(u,v)和Sf(u,v)的分布情况,因此在实际应用时多用下式进行近似处理:
    F(u,v)=[(1/H(u,v))* (|H(u,v)|2)/(|H(u,v)|2+K)]*G(u,v)
    其中K是一个预先设定的常数。

你可能感兴趣的:(算法,C#,存储,float,n2)