汉字识别在将近20年的研究开发过程中,中国大陆先后有十几个
研究单位开展过汉字识别的研发工作,并得到了国家“七五攻
关”计划、863计划、国家自然科学基金的大力支持,目前已有
一些产品面向市场并取得了可喜的销售成绩,如“汉王笔”、
“文通笔”、“汉王 OCR”等。
Tesseract的OCR引擎最先由HP实验室于1985年开始研发,至1995年时已经成为OCR业内最准确的三款识别引擎之一。之后,HP将Tesseract贡
献给开源软件业,让其重焕新生--2005年,Tesseract由美国内华达州信息技术研究所获得,并求诸于Google对Tesseract进行改进、消除
Bug、优化工作。
本文是自己做的一个小程序,通过摄像头采集的数据,然后对图片进行处理,包括灰度二制化,然后用tesseract进行解析正确率可以达到70%以上。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Linq;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Linq;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
/*Trace*/
using System.Diagnostics;
using System.Diagnostics;
namespace SoundVideo
{
public partial class Form1 : Form
{
Camera wc;
string ImgFileName;
string TxtFileName;
string TxtMenuInfo;
int ImgNum = 0;
Image<Gray, Byte> img1;
public Form1()
{
InitializeComponent();
}
{
public partial class Form1 : Form
{
Camera wc;
string ImgFileName;
string TxtFileName;
string TxtMenuInfo;
int ImgNum = 0;
Image<Gray, Byte> img1;
public Form1()
{
InitializeComponent();
}
/************************************************************************/
/* 读写ini文件函数 */
/************************************************************************/
/* 读写ini文件函数 */
/************************************************************************/
private void Form1_Load(object sender, EventArgs e)
{
try
{
//this.btnPlay.Enabled = false;
//this.btnClose.Enabled = true;
//panelPreview.Size = new Size(330,330);
wc = new Camera(pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height);
this.label1.Text = "状态显示";
wc.StartCamera(pictureBox1.Width, pictureBox1.Height);
}
catch
{
MessageBox.Show("打开摄像头有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
{
try
{
//this.btnPlay.Enabled = false;
//this.btnClose.Enabled = true;
//panelPreview.Size = new Size(330,330);
wc = new Camera(pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height);
this.label1.Text = "状态显示";
wc.StartCamera(pictureBox1.Width, pictureBox1.Height);
}
catch
{
MessageBox.Show("打开摄像头有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnPlay_Click(object sender, EventArgs e)
{
try
{
// this.btnPlay.Enabled = false;
//this.btnClose.Enabled = true;
wc = new Camera(pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height);
wc.StartCamera(300, 200);
}
catch
{
MessageBox.Show("打开摄像头有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
{
try
{
// this.btnPlay.Enabled = false;
//this.btnClose.Enabled = true;
wc = new Camera(pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height);
wc.StartCamera(300, 200);
}
catch
{
MessageBox.Show("打开摄像头有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnScroll_Click(object sender, EventArgs e)
{
try
{
wc.capImage(wc.lwndC, "d://test.bmp");
{
try
{
wc.capImage(wc.lwndC, "d://test.bmp");
}
catch
{
MessageBox.Show("抓图有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
img1 = new Image<Gray, Byte>("d://test.bmp");
imageBox1.Image = img1;
}
catch
{
MessageBox.Show("抓图有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
img1 = new Image<Gray, Byte>("d://test.bmp");
imageBox1.Image = img1;
}
private void btnStopCap_Click(object sender, EventArgs e)
{
try
{
wc.stopCapScope(wc.lwndC);
}
catch
{
MessageBox.Show("停止摄像有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
{
try
{
wc.stopCapScope(wc.lwndC);
}
catch
{
MessageBox.Show("停止摄像有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnStartCap_Click(object sender, EventArgs e)
{
try
{
wc.capScope(wc.lwndC, "d://test.avi");
}
catch
{
MessageBox.Show("开始摄像有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
{
try
{
wc.capScope(wc.lwndC, "d://test.avi");
}
catch
{
MessageBox.Show("开始摄像有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnClose_Click(object sender, EventArgs e)
{
try
{
//this.btnPlay.Enabled = true;
//this.btnClose.Enabled = false;
wc.CloseCamera();
}
catch
{
MessageBox.Show("关闭摄像头有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
{
try
{
//this.btnPlay.Enabled = true;
//this.btnClose.Enabled = false;
wc.CloseCamera();
}
catch
{
MessageBox.Show("关闭摄像头有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnAnalys_Click(object sender, EventArgs e)
{
ImgFileName = "d://test.bmp";
if (File.Exists("d://test1.bmp"))
{
ImgFileName = "d://test1.bmp";
}
{
ImgFileName = "d://test1.bmp";
}
TxtFileName = "d://test";
TxtMenuInfo = "d://MenuInfo.txt";
this.txtBoxOutput.Text = " ";
this.label1.Text = "分析中......";
this.label1.Update();
TxtMenuInfo = "d://MenuInfo.txt";
this.txtBoxOutput.Text = " ";
this.label1.Text = "分析中......";
this.label1.Update();
System.Diagnostics.Process OCR = new System.Diagnostics.Process();
OCR.StartInfo.FileName = "tesseract.exe";
OCR.StartInfo.Arguments = ImgFileName + " " + TxtFileName + " -l chi_sim";
OCR.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
OCR.Start();
while (!OCR.HasExited)
{
}
{
}
FileStream OCRResultFile = new FileStream(TxtFileName + ".txt", FileMode.Open, FileAccess.Read);
StreamReader OCRResult_streamReader = new StreamReader(OCRResultFile);
string strLineOCR = OCRResult_streamReader.ReadToEnd();
this.txtBoxOutput.Text = strLineOCR;
StreamReader OCRResult_streamReader = new StreamReader(OCRResultFile);
string strLineOCR = OCRResult_streamReader.ReadToEnd();
this.txtBoxOutput.Text = strLineOCR;
Trace.WriteLine("The OCR result is:");
Trace.WriteLine(strLineOCR);
OCRResult_streamReader.Close();
FileStream menuFile = new FileStream(TxtMenuInfo, FileMode.Open, FileAccess.Read);
Trace.WriteLine(strLineOCR);
OCRResult_streamReader.Close();
FileStream menuFile = new FileStream(TxtMenuInfo, FileMode.Open, FileAccess.Read);
StreamReader menu_streamReader = new StreamReader(menuFile);
string strLineMenu = menu_streamReader.ReadLine();
this.txtBoxMatchMenu.Text = "";
int ppnum = 0;
while (strLineMenu != null)
{
int matchNum = 0;
for (int i = 0; i < strLineMenu.Length; i++)
{
if (strLineOCR.Contains(strLineMenu.Substring(i, 1)))
{
Trace.WriteLine(strLineMenu.Substring(i, 1));
matchNum = matchNum + 1;
}
}
string strLineMenu = menu_streamReader.ReadLine();
this.txtBoxMatchMenu.Text = "";
int ppnum = 0;
while (strLineMenu != null)
{
int matchNum = 0;
for (int i = 0; i < strLineMenu.Length; i++)
{
if (strLineOCR.Contains(strLineMenu.Substring(i, 1)))
{
Trace.WriteLine(strLineMenu.Substring(i, 1));
matchNum = matchNum + 1;
}
}
if (matchNum > strLineMenu.Length * 0.5)
{
this.txtBoxMatchMenu.Text += strLineMenu;
this.txtBoxMatchMenu.Text += "/r/n";
ppnum++;
}
strLineMenu = menu_streamReader.ReadLine();
{
this.txtBoxMatchMenu.Text += strLineMenu;
this.txtBoxMatchMenu.Text += "/r/n";
ppnum++;
}
strLineMenu = menu_streamReader.ReadLine();
}
this.label1.Text = "跑完了......正确率是" + ((double)ppnum / 11) * 100 + "%";
}
private void ImgGrapTimer_Tick(object sender, EventArgs e)
{
this.labelCue.Text = "分析中……";
ImgFileName = "d://ImgAndTxt//Img" + ImgNum.ToString() + ".bmp";
TxtFileName = "d://ImgAndTxt//Txt" + ImgNum.ToString();
TxtMenuInfo = "d://MenuInfo.txt";
/*抓图*/
try
{
wc.capImage(wc.lwndC, ImgFileName);
}
catch
{
MessageBox.Show("抓图有误,请检查", "系统消息", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
/*执行tesseract.exe"*/
System.Diagnostics.Process OCR = new System.Diagnostics.Process();
OCR.StartInfo.FileName = "tesseract.exe";
OCR.StartInfo.Arguments = ImgFileName + " " + TxtFileName + " -l chi_sim";
OCR.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
OCR.Start();
System.Diagnostics.Process OCR = new System.Diagnostics.Process();
OCR.StartInfo.FileName = "tesseract.exe";
OCR.StartInfo.Arguments = ImgFileName + " " + TxtFileName + " -l chi_sim";
OCR.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
OCR.Start();
/*wait直到OCR分析程序跑完*/
while (!OCR.HasExited)
{
}
/*Read OCR Result*/
FileStream OCRResultFile = new FileStream(TxtFileName + ".txt", FileMode.Open, FileAccess.Read);
StreamReader OCRResult_streamReader = new StreamReader(OCRResultFile);
string strLineOCR = OCRResult_streamReader.ReadToEnd();
this.txtBoxOutput.Text = strLineOCR;
Trace.WriteLine("The OCR result is:");
Trace.WriteLine(strLineOCR);
OCRResult_streamReader.Close();
while (!OCR.HasExited)
{
}
/*Read OCR Result*/
FileStream OCRResultFile = new FileStream(TxtFileName + ".txt", FileMode.Open, FileAccess.Read);
StreamReader OCRResult_streamReader = new StreamReader(OCRResultFile);
string strLineOCR = OCRResult_streamReader.ReadToEnd();
this.txtBoxOutput.Text = strLineOCR;
Trace.WriteLine("The OCR result is:");
Trace.WriteLine(strLineOCR);
OCRResult_streamReader.Close();
/*Read Menu Files and Do Match*/
FileStream menuFile = new FileStream(TxtMenuInfo, FileMode.Open, FileAccess.Read);
FileStream menuFile = new FileStream(TxtMenuInfo, FileMode.Open, FileAccess.Read);
StreamReader menu_streamReader = new StreamReader(menuFile);
string strLineMenu = menu_streamReader.ReadLine();
this.txtBoxMatchMenu.Text = "";
while (strLineMenu != null)
{
int matchNum = 0;
for (int i = 0; i < strLineMenu.Length; i++)
{
if (strLineOCR.Contains(strLineMenu.Substring(i, 1)))
{
Trace.WriteLine(strLineMenu.Substring(i, 1));
matchNum = matchNum + 1;
}
}
if (matchNum > strLineMenu.Length * 0.5)
{
this.txtBoxMatchMenu.Text += strLineMenu;
this.txtBoxMatchMenu.Text += "/r/n";
}
strLineMenu = menu_streamReader.ReadLine();
Trace.WriteLine(strLineMenu);
}
string strLineMenu = menu_streamReader.ReadLine();
this.txtBoxMatchMenu.Text = "";
while (strLineMenu != null)
{
int matchNum = 0;
for (int i = 0; i < strLineMenu.Length; i++)
{
if (strLineOCR.Contains(strLineMenu.Substring(i, 1)))
{
Trace.WriteLine(strLineMenu.Substring(i, 1));
matchNum = matchNum + 1;
}
}
if (matchNum > strLineMenu.Length * 0.5)
{
this.txtBoxMatchMenu.Text += strLineMenu;
this.txtBoxMatchMenu.Text += "/r/n";
}
strLineMenu = menu_streamReader.ReadLine();
Trace.WriteLine(strLineMenu);
}
this.labelCue.Text = "跑完了......";
if (ImgNum < 10000)
{
ImgNum = ImgNum + 1;
}
else
{
ImgNum = 0;
}
if (ImgNum < 10000)
{
ImgNum = ImgNum + 1;
}
else
{
ImgNum = 0;
}
}
/*
* 根据图片计算阈值
*/
public double getThreshold()
{
* 根据图片计算阈值
*/
public double getThreshold()
{
img1 = new Image<Gray, Byte>("d://test.bmp");
int height = img1.Height;
Console.WriteLine(height);
int width = img1.Width;
double threshold = 0;
double sum = 0;
int i;
int j;
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
Gray color = img1[i, j];
sum += color.Intensity;
}
}
threshold = sum / (width * height);
return threshold;
}
int height = img1.Height;
Console.WriteLine(height);
int width = img1.Width;
double threshold = 0;
double sum = 0;
int i;
int j;
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
Gray color = img1[i, j];
sum += color.Intensity;
}
}
threshold = sum / (width * height);
return threshold;
}
/*
滑动调整阈值
*/
private void trackBar1_Scroll(object sender, EventArgs e)
{
int num = 0;
int i;
int j;
int height = img1.Height;
int width = img1.Width;
num += trackBar1.Value;
double threshold = getThreshold() * (num / 5);
img1 = new Image<Gray, Byte>("d://test.bmp");
txtBoxMatchMenu.Text = " ";
txtBoxOutput.Text = " ";
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
Gray color = img1[i, j];
if (color.Intensity > threshold)
img1[i, j] = new Gray(255);
else
img1[i, j] = new Gray(0);
if (j > 300)
{
img1[i, j] = new Gray(255);
}
}
}
imageBox1.Image = img1;
img1.Save("d://test1.bmp");
{
for (j = 0; j < width; j++)
{
Gray color = img1[i, j];
if (color.Intensity > threshold)
img1[i, j] = new Gray(255);
else
img1[i, j] = new Gray(0);
if (j > 300)
{
img1[i, j] = new Gray(255);
}
}
}
imageBox1.Image = img1;
img1.Save("d://test1.bmp");
}
}
}
}