C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# PaddleOCRSharp表格文字识别及对比

C#利用PaddleOCRSharp实现表格文字识别及可视化对比

作者:河西石头

PaddleOCR 是百度飞桨开源的 OCR 工具库,支持多语言文本识别,尤其在中文字符识别上表现优异,在 C# 开发中,我们可以通过 PaddleOCRSharp 封装库快速集成 OCR 功能,本文将通过一个 WinForms 示例,演示如何实现图片和 PDF 中的表格文字识别,需要的朋友可以参考下

引言

PaddleOCR 是百度飞桨开源的 OCR 工具库,支持多语言文本识别,尤其在中文字符识别上表现优异。在 C# 开发中,我们可以通过 PaddleOCRSharp 封装库快速集成 OCR 功能。本文将通过一个 WinForms 示例,演示如何实现图片和 PDF 中的表格文字识别,并在窗体中显示三图对比(原图、检测框图、识别结果图),帮助开发者直观验证 OCR 效果。

开发环境

第一部分:环境准备和 NuGet 配置

1.1 创建项目

打开 Visual Studio 2022,创建一个新的 Windows Forms 应用(选择 .NET Framework 4.8 或更高版本)。

1.2 安装 NuGet 包

在“管理 NuGet 程序包”中搜索并安装以下指定版本的包(版本号已实际测试通过):

包名版本说明
PaddleOCRSharp6.1.0PaddleOCR 的 C# 封装,提供 OCR 识别引擎
OpenCvSharp4.Windows4.13.0.20260222OpenCV 的 C# 封装,用于图像绘制和处理
OpenCvSharp4.Extensions4.13.0.20260222OpenCV 扩展方法,便于 Bitmap 与 Mat 互转
OpenCvSharp4.Runtime.win4.13.0.20260222OpenCV 运行时依赖(通常由 Windows 包自动引入)
Paddle.Runtime.win_x643.3.0.2Paddle Inference 运行时(PaddleOCRSharp 依赖)
(可选) DevExpress.Win.Design24.2.5用于美化界面,本文使用普通 WinForms 控件,非必须

注意:请确保项目目标平台为 x64,因为 Paddle 运行时仅支持 64 位。在项目属性 -> 生成 -> 目标平台中选择 x64。

1.3 引入命名空间

在代码文件顶部添加以下 using 指令:

using PaddleOCRSharp;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System; // 可能还需要其他基础命名空间

第二部分:实现文字识别并在文本框输出

2.1 初始化 OCR 引擎

PaddleOCRSharp 提供了 PaddleOCREngine 类,可配置模型路径和识别参数。通常使用默认配置即可。

private PaddleOCREngine engine;

// 在窗体构造函数或需要时初始化
public Form1()
{
    InitializeComponent();
    OCRModelConfig config = null;
    OCRParameter param = new OCRParameter();
    engine = new PaddleOCREngine(config, param);
}

2.2 识别图片中的文字

通过 OpenFileDialog 选择图片,调用 DetectText 方法获取识别结果,并将文本显示在 TextBox 中。

private void btnImageOCR_Click(object sender, EventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.Filter = "图像文件|*.bmp;*.jpg;*.jpeg;*.png;*.tiff";
    if (ofd.ShowDialog() != DialogResult.OK) return;

    byte[] imageBytes = File.ReadAllBytes(ofd.FileName);
    Bitmap bitmap = new Bitmap(new MemoryStream(imageBytes));

    // 执行识别
    OCRResult result = engine.DetectText(bitmap);
    if (result != null)
    {
        textBox1.Text = result.Text; // 输出纯文本
    }
}

2.3 识别 PDF 文档中的文字

PDF 识别使用 DetectTextPDF 方法,需要传入 PDF 字节数组和分辨率(通常 150 或 200)。该方法支持分页回调,便于显示进度。

private void btnPDFOCR_Click(object sender, EventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.Filter = "PDF文件|*.pdf";
    if (ofd.ShowDialog() != DialogResult.OK) return;

    byte[] pdfBytes = File.ReadAllBytes(ofd.FileName);
    
    // 设置回调显示处理进度
    Action<int> progress = page => Console.WriteLine($"正在处理第 {page} 页");
    var result = engine.DetectTextPDF(pdfBytes, 150, progress);

    StringBuilder sb = new StringBuilder();
    foreach (var page in result.Pages)
    {
        sb.AppendLine(page.Text);
    }
    textBox1.Text = sb.ToString();
}

注意:OCRResult 对象除了包含整体文本外,还包含了每个文本块的详细信息(如位置坐标、置信度等),这些信息将在第三部分用于绘制检测框。

第三部分:实现三图对比显示

为了直观验证 OCR 效果,我们希望在识别后弹出一个新窗体,展示三幅并排的图像:

由于 OpenCvSharp 的 PutText 不支持中文,我们需要借助 System.Drawing 绘制中文,再将结果转回 OpenCV 的 Mat 进行拼接。

3.1 创建对比窗体 Form2

在项目中添加一个新窗体 Form2,放置一个 PictureBox 控件(命名为 pictureBox1),并将 SizeMode 设置为 AutoSize,同时启用窗体的 AutoScroll 属性以支持滚动查看大图。

3.2 编写绘图方法

核心函数 DrawThreeImages 接收原始图像和 OCR 结果,返回拼接后的 Bitmap。

private Bitmap DrawThreeImages(Bitmap original, OCRResult ocrResult)
{
    // 1. 将原图转为 Mat,确保为 3 通道彩色
    Mat originalMat = BitmapConverter.ToMat(original);
    if (originalMat.Channels() == 1)
        Cv2.CvtColor(originalMat, originalMat, ColorConversionCodes.GRAY2BGR);
    else if (originalMat.Channels() == 4)
        Cv2.CvtColor(originalMat, originalMat, ColorConversionCodes.BGRA2BGR);

    // 2. 第二张图:原图克隆,仅绘制框
    Mat boxesMat = originalMat.Clone();

    // 3. 第三张图:纯白色背景
    Mat textMat = new Mat(originalMat.Size(), originalMat.Type(), Scalar.White);

    // 定义颜色(BGR顺序)
    Scalar lightBlue = new Scalar(255, 255, 0); // 浅蓝色

    // 获取文本块列表(根据实际属性名调整,PaddleOCRSharp 中为 TextBlocks)
    var blocks = ocrResult.TextBlocks;
    if (blocks != null)
    {
        // 3.1 先用 OpenCV 绘制框到 boxesMat 和 textMat
        foreach (var block in blocks)
        {
            var points = block.BoxPoints; // 通常为 List<PointF> 或 PointF[]
            if (points == null || points.Count < 4) continue;

            Point[] pts = new Point[4];
            for (int i = 0; i < 4; i++)
                pts[i] = new Point((int)points[i].X, (int)points[i].Y);

            Cv2.Polylines(boxesMat, new[] { pts }, true, lightBlue, 2);
            Cv2.Polylines(textMat, new[] { pts }, true, lightBlue, 2);
        }

        // 3.2 将 textMat 转为 Bitmap,用 System.Drawing 绘制中文文字
        Bitmap textBmp = BitmapConverter.ToBitmap(textMat);
        textMat.Dispose();

        using (Graphics g = Graphics.FromImage(textBmp))
        {
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

            foreach (var block in blocks)
            {
                var points = block.BoxPoints;
                if (points == null || points.Count < 4) continue;
                string text = block.Text;
                if (string.IsNullOrEmpty(text)) continue;

                // 计算文本框的边界矩形
                float minX = points.Min(p => p.X);
                float maxX = points.Max(p => p.X);
                float minY = points.Min(p => p.Y);
                float maxY = points.Max(p => p.Y);
                float width = maxX - minX;
                float height = maxY - minY;
                if (width <= 0 || height <= 0) continue;

                // 根据框高度动态设置字体大小(约0.4倍)
                float fontSize = height * 0.4f;
                fontSize = Math.Max(8, Math.Min(48, fontSize));

                using (Font font = new Font("Microsoft YaHei", fontSize, FontStyle.Regular, GraphicsUnit.Pixel))
                using (Brush brush = new SolidBrush(Color.Black))
                using (StringFormat sf = new StringFormat())
                {
                    sf.Alignment = StringAlignment.Center;
                    sf.LineAlignment = StringAlignment.Center;

                    float centerX = (minX + maxX) / 2;
                    float centerY = (minY + maxY) / 2;

                    g.DrawString(text, font, brush, centerX, centerY, sf);
                }
            }
        }

        // 将绘制好的 Bitmap 转回 Mat
        textMat = BitmapConverter.ToMat(textBmp);
        textBmp.Dispose();
    }

    // 4. 水平拼接三张图
    Mat[] mats = { originalMat, boxesMat, textMat };
    Mat resultMat = new Mat();
    Cv2.HConcat(mats, resultMat);

    // 5. 转换为 Bitmap
    Bitmap resultBitmap = BitmapConverter.ToBitmap(resultMat);

    // 6. 释放资源
    originalMat.Dispose();
    boxesMat.Dispose();
    textMat.Dispose();
    resultMat.Dispose();

    return resultBitmap;
}

3.3 在识别后显示对比窗体

修改图片识别按钮的点击事件,识别完成后调用上述方法,并显示 Form2。

private void btnImageOCR_Click(object sender, EventArgs e)
{
    // ... 前面的识别代码 ...
    if (ocrResult != null)
    {
        textBox1.Text = ocrResult.Text;

        // 生成三图对比
        Bitmap merged = DrawThreeImages(bitmap, ocrResult);

        // 显示新窗体
        Form2 form2 = new Form2();
        form2.pictureBox1.Image = merged;
        form2.Show();
    }
}

3.4 效果预览

运行程序,选择一张包含表格的图片,识别后弹出 Form2,可以看到:

总结

通过 PaddleOCRSharpOpenCvSharp,我们能够在 C# 中轻松集成 PaddleOCR 的高效文字识别能力。本文不仅实现了基础的文本提取,还通过三图对比功能直观展示了检测和识别效果,尤其解决了中文显示问题。这种可视化方式对于调试 OCR 参数、验证识别准确率非常有帮助。

未来可根据需求扩展:如识别表格结构、输出结构化数据等。希望本文能为你的 C# OCR 开发提供参考。

注意事项

以上就是C#利用PaddleOCRSharp实现表格文字识别及可视化对比的详细内容,更多关于C# PaddleOCRSharp表格文字识别及对比的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文