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

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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

自从发表了用于验证码图片识别的类(C#代码)后,不断有网友下载这个类后,问如何用于一些特定的验证码。总结一下网友们的提问,很多都是不会从复杂背景中提到干净的字符图片来,这主要就是一个去噪问题,即除去图片上的背景、干扰点、干扰线等信息。这当中要用到很多图像学数学算法,首先声明,本人不是学图像学的,以下方法理论说得不对,敬请多批评指正。

1、如何设前景/背景的分界值

UnCodebase类中有一个GetPicValidByValue( int dgGrayValue) 函数,可以得到前景的有效区域,常有人问我前景/背景的分界值dgGrayValue是如何确定的(常用的是灰度128)。这个值的获取是有数学算法,叫最大类间方差法,即图像的前后景的平方差为最大时的值就是我

们关心的分界值,对付如这样较复杂的背景非常管用,下面是具体的C#代码。

///

///得到灰度图像前景背景的临界值最大类间方差法,yuanbao,2007.08

///

///前景背景的临界值

public int GetDgGrayValue()

{

int[] pixelNum = new int[256]; //图象直方图,共256个点

int n, n1, n2;

int total; //total为总和,累计值

double m1, m2, sum, csum, fm ax, sb; //sb为类间方差,fmax存储最大方差值

int k, t, q;

int threshValue = 1; // 阈值

int step = 1;

//生成直方图

for (int i =0; i < bmpobj.Width ; i++)

{

for (int j = 0; j < bmpobj.Height; j++)

{

//返回各个点的颜色,以RGB表示

pixelNum[bmpobj.GetPixel(i,j).R]++; //相应的直方图加1

}

}

//直方图平滑化

for (k = 0; k <= 255; k++)

{

total = 0;

for (t = -2; t <= 2; t++) //与附近2个灰度做平滑化,t值应取较小的值

{

q = k + t;

if (q < 0) //越界处理

q = 0;

if (q > 255)

q = 255;

total = total + pixelNum[q]; //total为总和,累计值

}

pixelNum[k] = (int)((float)total / 5.0 + 0.5); //平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值

}

//求阈值

sum = csum = 0.0;

n = 0;

//计算总的图象的点数和质量矩,为后面的计算做准备

for (k = 0; k <= 255; k++)

{

sum += (double)k * (double)pixelNum[k]; //x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和

n += pixelNum[k]; //n为图象总的点数,归一化后就是累积概率

}

fm ax = -1.0; //类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行

n1 = 0;

for (k = 0; k < 256; k++) //对每个灰度(从0到255)计算一次分

割后的类间方差sb

{

n1 += pixelNum[k]; //n1为在当前阈值遍前景图象的点数if (n1 == 0) { continue; } //没有分出前景后景

n2 = n - n1; //n2为背景图象的点数

if (n2 == 0) { break; } //n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环

csum += (double)k * pixelNum[k]; //前景的“灰度的值*其点数”的总和 m1 = csum / n1; //m1为前景的平均灰度

m2 = (sum - csum) / n2; //m2为背景的平均灰度

sb = (double)n1 * (double)n2 * (m1 - m2) * (m1 - m2); //sb为类间方差

if (sb > fm ax) //如果算出的类间方差大于前一次算出的类间方差 {

fm ax = sb; //fm ax始终为最大类间方差(otsu)

threshValue = k; //取最大类间方差时对应的灰度的k就是最佳阈值

}

}

return threshValue;

}

2、如何去除干扰点/干扰线

2.1 干扰点/干扰线的特征分析

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

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

2.2 根据周边有效点数去噪函数

///

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

///

///背前景灰色界限

///

public void ClearNoise(int dgGrayValue, int MaxNearPoints)

{

Color piexl;

int nearDots = 0;

int XSpan, YSpan, tm pX, t m pY;

//逐点判断

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.Hei

相关文档
最新文档