c# 验证码的识别主要分为预处理、分割、识别三个步骤

首先我从网站上下载验证码

处理结果如下:

1.图片预处理,即二值化图片

*就是将图像上的像素点的灰度值设置为0或255。

原理如下:

代码如下:

#region 二值化图片
/// <summary>
/// 二值化图片
/// 就是将图像上的像素点的灰度值设置为0或255
/// </summary>
/// <returns>处理后的验证码</returns>
public Bitmap BinaryZaTion()
{
for (int x = 0; x < img.Width; x++)
{
for (int y = 0; y < img.Height; y++)
{
__c = img.GetPixel(x, y);
//灰度值
int __tc = (__c.R + __c.G + __c.B) / 3;
//大于阙值 黑色
if (__tc > t)
{
img.SetPixel(x, y, Color.FromArgb(__c.A, b, b, b));
//黑色点个数自加
__blackNum++;
}
//大于阙值 白色
else
{
img.SetPixel(x, y, Color.FromArgb(__c.A, w, w, w));
}
}
}
return img;
}
#endregion

二值化过后需要判断图片的黑白比列,若果黑色比白色多,需要对图片反色处理。

代码如下:

 #region 是否需要反色
/// <summary>
/// 是否需要反色
/// </summary>
/// <returns>是否需要反色</returns>
public bool IsNeedInverseColor()
{
if ((__blackNum * 1.0 / (img.Width * img.Height)) > 0.5)
{
return true;
}
else
{
return false;
}
}
#endregion #region 反色
/// <summary>
/// 反色
/// </summary>
/// <returns>处理后的验证码</returns>
public Bitmap InverseColor()
{
for (int x = 0; x < img.Width; x++)
{
for (int y = 0; y < img.Height; y++)
{
__c = img.GetPixel(x, y);
img.SetPixel(x, y, Color.FromArgb(__c.A, w - __c.R, w - __c.G, w - __c.B));
}
}
return img;
}
#endregion

处理结果如下:

2.图片分割

我的做法是先每一竖行判断是否是纯白色行,不是的话记录当前x坐标,然后没以横行判断是否纯白色行,这样就能的到每一个数字的区域,然后将区域画出来。

代码如下:

 #region 分割图片
/// <summary>
/// 分割图片
/// </summary>
/// <returns>处理后的验证码</returns>
public Bitmap CutImg()
{
//Y轴分割
CutY();
//区域个数
__count = 0;
if (XList.Count > 1)
{
//x起始值
int __start = XList[0];
//x结束值
int __end = XList[XList.Count - 1];
//x索引
int __idx = 0;
while (__start != __end)
{
//区域宽度
int __w = __start;
//区域个数自加
__count++;
while (XList.Contains(__w) && __idx < XList.Count)
{
//区域宽度自加
__w++;
//x索引自加
__idx++;
}
//区域X轴坐标
int x = __start;
//区域Y轴坐标
int y = 0;
//区域宽度
int width = __w - __start;
//区域高度
int height = img.Height;
/*
* X轴分割当前区域
*/
CutX(img.Clone(new Rectangle(x, y, width, height), img.PixelFormat));
if (YList.Count > 1 && YList.Count != img.Height)
{
int y1 = YList[0];
int y2 = YList[YList.Count - 1];
if (y1 != 1)
{
y = y1 - 1;
}
height = y2 - y1 + 1;
}
//GDI+绘图对象
Graphics g = Graphics.FromImage(img);
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingMode = CompositingMode.SourceOver;
g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
//画出验证码区域
g.DrawRectangle(new Pen(Brushes.Green), new Rectangle(x, y, width, height));
g.Dispose();
//起始值指向下一组
if (__idx < XList.Count)
{
__start = XList[__idx];
}
else
{
__start = __end;
} }
}
return img;
}
#endregion #region Y轴字符分割图片
/// <summary>
/// 得到Y轴分割点
/// 判断每一竖行是否有黑色
/// 有则添加
/// </summary>
/// <param name="img">要验证的图片</param>
private void CutY()
{
XList.Clear();
for (int x = 0; x < img.Width; x++)
{
isWhilteLine = false;
for (int y = 0; y < img.Height; y++)
{
__c = img.GetPixel(x, y);
if (__c.R == w)
{
isWhilteLine = true;
}
else
{
isWhilteLine = false;
break;
}
}
if (!isWhilteLine)
{
XList.Add(x);
}
}
}
#endregion #region X轴字符分割图片
/// <summary>
/// 得到X轴分割点
/// 判断每一横行是否有黑色
/// 有则添加
/// </summary>
/// <param name="tempImg">临时区域</param>
private void CutX(Bitmap tempImg)
{
YList.Clear();
for (int x = 0; x < tempImg.Height; x++)
{
isWhilteLine = false;
for (int y = 0; y < tempImg.Width; y++)
{
__c = tempImg.GetPixel(y, x);
if (__c.R == w)
{
isWhilteLine = true;
}
else
{
isWhilteLine = false;
break;
}
}
if (!isWhilteLine)
{
YList.Add(x);
}
}
tempImg.Dispose();
}
#endregion

效果如下:

3.识别

识别呢就是提取出图片的特征

我的做法是将图片数字区域逐一分成4*4的区域,计算出各个区域的黑色点所占的百分比,然后将计算出来的结果和以前计算的特征进行比较,求出欧氏距离 d = sqrt( (x1-x2)^2+(y1-y2)^2 )最小的一个作为结果。

部分代码如下:

#region 黑色像素比列
/// <summary>
/// 计算黑色像素比列
/// </summary>
/// <param name="tempimg"></param>
/// <returns></returns>
private double PixlPercent(Bitmap tempimg)
{
int temp = 0;
int w_h = tempimg.Width * tempimg.Height;
for (int x = 0; x < tempimg.Width; x++)
{
for (int y = 0; y < tempimg.Height; y++)
{
__c = tempimg.GetPixel(x, y);
if (__c.R == b)
{
temp++;
}
}
}
tempimg.Dispose();
double result = temp * 1.0 / w_h;
result = result.ToString().Length > 3 ? Convert.ToDouble(result.ToString().Substring(0, 3)) : result;
return result;
}
#endregion

效果如下:

本代码只做研究学习之用。

新手上路,有任何建议、意见联系 pigkeli@qq.com 。

[置顶] c#验证码识别、图片二值化、分割、分类、识别的更多相关文章

  1. python图片二值化提高识别率

    import cv2from PIL import Imagefrom pytesseract import pytesseractfrom PIL import ImageEnhanceimport ...

  2. C#图片灰度处理(位深度24→位深度8)、C#图片二值化处理(位深度8→位深度1)

    C#图片灰度处理(位深度24→位深度8) #region 灰度处理 /// <summary> /// 将源图像灰度化,并转化为8位灰度图像. /// </summary> / ...

  3. 机器学习进阶-项目实战-信用卡数字识别 1.cv2.findContour(找出轮廓) 2.cv2.boudingRect(轮廓外接矩阵位置) 3.cv2.threshold(图片二值化操作) 4.cv2.MORPH_TOPHAT(礼帽运算突出线条) 5.cv2.MORPH_CLOSE(闭运算图片内部膨胀) 6. cv2.resize(改变图像大小) 7.cv2.putText(在图片上放上文本)

    7. cv2.putText(img, text, loc, text_font, font_scale, color, linestick) # 参数说明:img表示输入图片,text表示需要填写的 ...

  4. 验证码图片二值化问题 BitmapData 怎么解决

    对不起,这算是一篇求助啦,先上图,防止不清楚,放大了一点,下面是图片,上面是没有二值化的,下面是二值化之后的,我其实不懂什么是二值化啦,就是一定范围变黑,变白 问题: 为什么我的结果上面还是有很多彩色 ...

  5. c#实现图片二值化例子(黑白效果)

    C#将图片2值化示例代码,原图及二值化后的图片如下: 原图: 二值化后的图像: 实现代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2 ...

  6. OpenCV - 图片二值化,计算白色像素点的个数

    直接上代码吧: import cv2 import numpy as np from PIL import Image area = def getWhitePixel(img): global ar ...

  7. python的N个小功能(图片预处理:打开图片,滤波器,增强,灰度图转换,去噪,二值化,切割,保存)

    ############################################################################################# ###### ...

  8. 基于Java对图片进行二值化处理

    一直以来对Java的图形处理能力表无力,但好像又不是那么一回事,之前用PHP做过一些应用,涉及到验证码的识别,其中有个图片二值化的步骤,今天换成Java来实现下 在java的扩展包javax.imag ...

  9. 二值化方法:Kittler:Minimum Error Thresholding

    Kittler二值化方法,是一种经典的基于直方图的二值化方法.由J. Kittler在1986年发表的论文“Minimum Error Thresholding”提出.论文是对贝叶斯最小错误阈值的准则 ...

随机推荐

  1. Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-2.xml, reason: Connectio (andriod sdk manager) http://dl-ssl.google.com/android上不去解决方案

    Fetching https://dl-ssl.google.com/android/repository/addons_list-2.xml  Fetched Add-ons List succes ...

  2. python 字典有序无序及查找效率,hash表

    刚学python的时候认为字典是无序,通过多次插入,如di = {}, 多次di['testkey']='testvalue' 这样测试来证明无序的.后来接触到了字典查找效率这个东西,查了一下,原来字 ...

  3. Python 模块(八) socketserver 以及 线程、进程

    目录 异常处理 socketserver 线程.进程 一.异常处理 try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执 ...

  4. linux操作系统死机处理办法

    这个方法可以在各种情况下安全地重启计算机.大家在键盘上找,可以找到一个叫做“Sys Rq”的键,在台机的键盘上通常与 Prt Sc 共键,在笔记本可能在其他位置,如 Delete.以台机为例,要使用这 ...

  5. Identity-修改Error错误提示为中文

    第一步:重写IdentityErrorDescriber public class CustomIdentityErrorDescriber : IdentityErrorDescriber     ...

  6. Mybatis 的Log4j日志输出问题 - 以及有关日志的所有问题

    使用Mybatis的时候,有些时候能输出(主要是指sql,参数,结果)日志.有些时候就不能. 无法输出日志的时候,无论怎么配置log4j,不管是properties的还是xml的,都不起作用. 有些时 ...

  7. Nginx 开启 debug 日志的办法

    译序:一般来讲,Nginx 的错误日志级别是 error,作为 Nginx 用户来讲,你设置成 info 就足够用了.         但有时有些难以挖掘的 bug,需要看到更详细的 debug 级别 ...

  8. Java学习之国际化程序

    国际化程序就是把程序的语言根据用户使用的语言显示,各个国家的用户都可以看懂 实现方法就是把输出文字都写在配置文件里,然后根据用户系统语言选择不同的语言输出 package com.gh; import ...

  9. SQL Server 2008 还原数据库

    1.得到数据库备份文件,怎么得到的,[能够看这里]~ 2.把备份文件加个.bak 的后缀,比如: 3.打开SQL , 你能够新建一个空数据库 , 或者利用原有的数据库 , 点击右键>>任务 ...

  10. stm32之中断系统

    概述: 提供中断控制器,用于总体管理异常,称之为“嵌套向量中断控制器:Nested Vectored Interrupt Controller (NVIC) VIC:中断管理器: NVIC:内嵌中断管 ...