简介
光学字符识别(OCR,Optical Character Recognition)是指对文本资料进行扫描,然后对图像文件进行分析处理,获取文字及版面信息的过程。OCR技术非常专业,一般多是印刷、打印行业的从业人员使用,可以快速的将纸质资料转换为电子资料。关于中文OCR,目前国内水平较高的有清华文通、汉王、尚书,其产品各有千秋,价格不菲。国外OCR发展较早,像一些大公司,如IBM、微软、HP等,即使没有推出单独的OCR产品,但是他们的研发团队早已掌握核心技术,将OCR功能植入了自身的软件系统。对于我们程序员来说,一般用不到那么高级的,主要在开发中能够集成基本的OCR功能就可以了。
Tesseract概述
Tesseract的OCR引擎最先由HP实验室于1985年开始研发,至1995年时已经成为OCR业内最准确的三款识别引擎之一。然而,HP不久便决定放弃OCR业务,Tesseract也从此尘封。数年以后,HP意识到,与其将Tesseract束之高阁,不如贡献给开源软件业,让其重焕新生--2005年,Tesseract由美国内华达州信息技术研究所获得,并求诸于Google对Tesseract进行改进、消除Bug、优化工作。Tesseract目前已作为开源项目发布在Google Project(现已托管 github),其项目主页在这里查看,3.0版本已经支持中文OCR,并提供了一个命令行工具。
下面就来看看如何用代码来实现图片转换为文字吧
一:首先需要安装 tesseract-ocr
安装步骤: 在vs中点击工具-》NuGet包管理器-》管理解决方案的NuGet程序包
安装完成后再项目中会添加如下两个文件夹
Tesseract-OCR默认只支持英文,要是需要识别中文需要下载中文包(需要注意版本),这里有一个Tesseract-OCR语言库 地址是:语言库,下载之后将tessdata放在项目根目录即可
现在看一下后台代码的具体实现,我要识别下面四个字
后台代码:
public ActionResult Index()
{
string ocrTtxt = "";
//chi_sim是中文库
const string language = "chi_sim";
//Nuget安装的Tessract版本为3.20,tessdata的版本必须与其匹配,另外路径最后必须以"\"或者"/"结尾
string TessractData = AppDomain.CurrentDomain.BaseDirectory+ @"tessdata\";
TesseractEngine test = new TesseractEngine(TessractData, language);
//创建一个图片对象
Bitmap tmpVal = new Bitmap(AppDomain.CurrentDomain.BaseDirectory + @"Content\name.png");
//灰度化,可以提高识别率
var tmpImage = Helper.Class.ToGray(tmpVal);
//Page tmpPage = test.Process(tmpImage, pageSegMode: test.DefaultPageSegMode);
Page tmpPage = test.Process(tmpImage);
ocrTtxt = tmpPage.GetText();
return View();
}
为了提高ocr的识别率, 我们会想将图片做一些预处理,比如将图片灰度化,去噪点等等,具体代码如下
图片灰度化:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Web;
namespace test.Helper
{
public static class Class
{
/// /// 图像灰度化
/// /// /// public static Bitmap ToGray(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//获取该点的像素的RGB的颜色
Color color = bmp.GetPixel(i, j);
//利用公式计算灰度值
int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
Color newColor = Color.FromArgb(gray, gray, gray);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
//灰度反转:
//把每个像素点的R、G、B三个分量的值0的设为255,255的设为0。
/// /// 图像灰度反转
/// /// /// public static Bitmap GrayReverse(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//获取该点的像素的RGB的颜色
Color color = bmp.GetPixel(i, j);
Color newColor = Color.FromArgb(255 - color.R, 255 - color.G, 255 - color.B);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
//灰度图像二值化:
//在进行了灰度化处理之后,图像中的每个象素只有一个值,那就是象素的灰度值。它的大小决定了象素的亮暗程度。
//为了更加便利的开展下面的图像处理操作,还需要对已经得到的灰度图像做一个二值化处理。
//图像的二值化就是把图像中的象素根据一定的标准分化成两种颜色。在系统中是根据象素的灰度值处理成黑白两种颜色。
//和灰度化相似的,图像的二值化也有很多成熟的算法。它可以采用自适应阀值法,也可以采用给定阀值法。
/// /// 图像二值化1:取图片的平均灰度作为阈值,低于该值的全都为0,高于该值的全都为255
/// /// /// public static Bitmap ConvertTo1Bpp1(Bitmap bmp)
{
int average = 0;
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color color = bmp.GetPixel(i, j);
average += color.B;
}
}
average = (int)average / (bmp.Width * bmp.Height);
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//获取该点的像素的RGB的颜色
Color color = bmp.GetPixel(i, j);
int value = 255 - color.B;
Color newColor = value > average ? Color.FromArgb(0, 0, 0) : Color.FromArgb(255, 255, 255);
bmp.SetPixel(i, j, newColor);
}
}
return bmp;
}
/// /// 图像二值化2
/// /// /// public static Bitmap ConvertTo1Bpp2(Bitmap img)
{
int w = img.Width;
int h = img.Height;
Bitmap bmp = new Bitmap(w, h, PixelFormat.Format1bppIndexed);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
for (int y = 0; y < h; y++)
{
byte[] scan = new byte[(w + 7) / 8];
for (int x = 0; x < w; x++)
{
Color c = img.GetPixel(x, y);
if (c.GetBrightness() >= 0.5) scan[x / 8] |= (byte)(0x80 >> (x % 8));
}
Marshal.Copy(scan, 0, (IntPtr)((int)data.Scan0 + data.Stride * y), scan.Length);
}
bmp.UnlockBits(data);
return bmp;
}
}
public class ValidateCodeUtils
{
public static Bitmap CreateImage(int length, out string validateCode)
{
validateCode = string.Empty;
//颜色列表,用于验证码、噪线、噪点
Color[] color = { Color.Black, Color.Purple, Color.Red, Color.Blue, Color.Brown, Color.Navy };
//字体列表,用于验证码
string[] font = { "Times New Roman", "MS Mincho", "Book Antiqua", "Gungsuh", "PMingLiU", "Impact" };
//验证码的字符集,去掉了一些容易混淆的字符
char[] character = { '2', '3', '4', '5', '6', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
Random rnd = new Random();
//生成验证码字符串
for (int i = 0; i < length; i++)
{
validateCode += character[rnd.Next(character.Length)];
}
Bitmap bmp = new Bitmap(length * 20 + 20, 40);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.White);
画噪线
//for (int i = 0; i < 10; i++)
//{
// int x1 = rnd.Next(20) * rnd.Next(5);
// int y1 = rnd.Next(8) * rnd.Next(5);
// int x2 = rnd.Next(20) * rnd.Next(5);
// int y2 = rnd.Next(8) * rnd.Next(5);
// Color clr = color[rnd.Next(color.Length)];
// g.DrawLine(new Pen(clr), x1, y1, x2, y2);
//}
//画验证码字符串
for (int i = 0; i < validateCode.Length; i++)
{
string fnt = font[rnd.Next(font.Length)];
Font ft = new Font(fnt, 18);
Color clr = color[rnd.Next(color.Length)];
g.DrawString(validateCode[i].ToString(), ft, new SolidBrush(clr), (float)i * 20 + 8, (float)8);
}
画噪点
//for (int i = 0; i < 30; i++)
//{
// int x = rnd.Next(bmp.Width);
// int y = rnd.Next(bmp.Height);
// Color clr = color[rnd.Next(color.Length)];
// bmp.SetPixel(x, y, clr);
//}
try
{
return bmp;
}
finally
{
//显式释放资源
g.Dispose();
}
}
}
}
最后执行代码的下过如下