一、前言
通过查看网络资料以及书籍资料,发现大多数OCR识别功能都是基于Python语言开发的,对于习惯使用C# 开发语言的程序猿们,岂不是一件很苦恼的事!当然想学习Python,掌握多一项技能也并不是坏事!为了方便使用,想使用C# 的往下看(或需要使用当作工作辅助也行,资源下载在最后有链接)。
二、开发要求
1、图形处理库Clipper、Emgu.CV
2、高性能推理引擎 Microsoft.ML.OnnxRuntime
3、借用PaddleOCR模型
4、现有功能,选择照片识别、截图识别,选择PDF文件识别
三、部分代码
cs
using Emgu.CV;
using OcrDemo.Helpers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OcrDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string fileFilter = "所有文件 (*.*)|*.*|bmp|*.bmp|jpg|*.jpg|jpeg|*.jpeg|png|*.png";
private Bitmap bmp;
private string outPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "output");
private Stopwatch stopwatch = new Stopwatch();
private string filePath = "";
private int threadNum = 4;
private OcrLite ocrEngin;
private void Form1_Load(object sender, EventArgs e)
{
try
{
if (!Directory.Exists(outPath))
{
Directory.CreateDirectory(outPath);
}
splitContainer1.SplitterDistance = (int)(splitContainer1.Width * 0.5);
splitContainer2.SplitterDistance = (int)(splitContainer2.Width * 0.5);
string appPath = AppDomain.CurrentDomain.BaseDirectory;
string appDir = Directory.GetParent(appPath).FullName;
}
catch (Exception ex)
{
SetMessge(ex.Message);
}
}
private void SetMessge(string info, int infoType = 0)
{
//info = DataHelper.DateFormat(DateTime.Now) + "" + info + "\n";
info = info + "\n";
if (this.InvokeRequired)
{
// 如果需要跨线程调用,则使用 Invoke 方法
this.Invoke(new Action(() =>
{
rTB_Message.AppendText(info);
// 滚动文本框以使光标所在位置可见
//rTB_ResultInfo.ScrollToCaret();
// 选中插入点
rTB_Message.Focus();
}));
}
else
{
// 如果在 UI 线程中,则直接更新控件
rTB_Message.AppendText(info);
// 滚动文本框以使光标所在位置可见
//rTB_ResultInfo.ScrollToCaret();
// 选中插入点
rTB_Message.Focus();
}
}
private void tool_bt_select_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = fileFilter;
if (ofd.ShowDialog() == DialogResult.OK)
{
Application.DoEvents();
filePath = ofd.FileName;
var imagebyte = File.ReadAllBytes(filePath);
bmp = new Bitmap(new MemoryStream(imagebyte));
pictureBox1.Image = bmp;
rTB_Message.Clear();
if (bmp == null) return;
stopwatch.Restart();
OcrResult ocrResult = ocrEngin.Detect(filePath, padding, imgResize, boxScoreThresh, boxThresh, unClipRatio, doAngle, mostAngle);
stopwatch.Stop();
SetMessge(ocrResult.StrRes);
SetMessge("------------------------------");
//SetMessge(ocrResult.ToString());
SetMessge($"--------------耗时: {stopwatch.ElapsedMilliseconds} 毫秒----------------");
pictureBox2.Image = ocrResult.BoxImg.ToBitmap();
}
}
private void tool_bt_screenshot_Click(object sender, EventArgs e)
{
this.Hide();
System.Threading.Thread.Sleep(200);
Application.DoEvents();
ScreenCapturer.ScreenCapturerTool screenCapturer = new ScreenCapturer.ScreenCapturerTool();
if (screenCapturer.ShowDialog() == DialogResult.OK)
{
bmp = (Bitmap)screenCapturer.Image;
string newFiles = outPath+"\\" + DataHelper.GetTimestamp() + ".jpg";
bmp.Save(newFiles, ImageFormat.Jpeg);
pictureBox1.Image = bmp;
try
{
stopwatch.Restart();
OcrResult ocrResult = ocrEngin.Detect(newFiles, padding, imgResize, boxScoreThresh, boxThresh, unClipRatio, doAngle, mostAngle);
stopwatch.Stop();
SetMessge(ocrResult.StrRes);
SetMessge($"--------------耗时: {stopwatch.ElapsedMilliseconds} 毫秒----------------");
//SetMessge(ocrResult.ToString());
pictureBox2.Image = ocrResult.BoxImg.ToBitmap();
}
catch (Exception ex)
{
SetMessge(ex.Message);
}
}
this.Show();
}
private void tool_bt_PDF_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "所有文件 (*.*)|*.*|PDF|*.pdf";
if (ofd.ShowDialog() == DialogResult.OK)
{
string pdfPath = ofd.FileName;
// 1. 解析PDF获取页面图像
using (var document = PdfDocument.Load(pdfPath))
{
string firstFiles = "";
stopwatch.Restart();
for (int pageIndex = 0; pageIndex < document.PageCount; pageIndex++)
{
// 渲染PDF页面为图像
using (var image = document.Render(pageIndex, 400, 800, false))
{
string newFiles = outPath + "\\" + DataHelper.GetTimestamp() + ".jpg";
if (pageIndex == 0)
{
firstFiles = newFiles;
}
image.Save(newFiles, ImageFormat.Jpeg);
OcrResult ocrResult = ocrEngin.Detect(newFiles, padding, imgResize, boxScoreThresh, boxThresh, unClipRatio, doAngle, mostAngle);
stopwatch.Stop();
SetMessge(ocrResult.StrRes);
}
}
if (firstFiles.Length > 0)
{
var imagebyte = File.ReadAllBytes(firstFiles);
pictureBox1.Image = new Bitmap(new MemoryStream(imagebyte));
}
//SetMessge(ocrResult.ToString());
SetMessge($"--------------耗时: {stopwatch.ElapsedMilliseconds} 毫秒----------------");
}
}
}
}
}
四、效果展示
C#之OCR识别
(图一为屏幕截图识别,图二为动车票信息识别)


五、资源下载
链接:https://download.csdn.net/download/weixin_42148410/90827048