Tesseract-OCR 中文识别(附上源码)

源码:Demo下载

简介

        光学字符识别(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();
            }
        }
    }
}

最后执行代码的下过如下

猜你喜欢

转载自blog.csdn.net/IT_rookie_newbie/article/details/82377599