最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#利用PaddleOCRSharp實(shí)現(xiàn)表格文字識(shí)別及可視化對(duì)比

 更新時(shí)間:2026年02月26日 09:00:58   作者:河西石頭  
PaddleOCR 是百度飛槳開(kāi)源的 OCR 工具庫(kù),支持多語(yǔ)言文本識(shí)別,尤其在中文字符識(shí)別上表現(xiàn)優(yōu)異,在 C# 開(kāi)發(fā)中,我們可以通過(guò) PaddleOCRSharp 封裝庫(kù)快速集成 OCR 功能,本文將通過(guò)一個(gè) WinForms 示例,演示如何實(shí)現(xiàn)圖片和 PDF 中的表格文字識(shí)別,需要的朋友可以參考下

引言

PaddleOCR 是百度飛槳開(kāi)源的 OCR 工具庫(kù),支持多語(yǔ)言文本識(shí)別,尤其在中文字符識(shí)別上表現(xiàn)優(yōu)異。在 C# 開(kāi)發(fā)中,我們可以通過(guò) PaddleOCRSharp 封裝庫(kù)快速集成 OCR 功能。本文將通過(guò)一個(gè) WinForms 示例,演示如何實(shí)現(xiàn)圖片和 PDF 中的表格文字識(shí)別,并在窗體中顯示三圖對(duì)比(原圖、檢測(cè)框圖、識(shí)別結(jié)果圖),幫助開(kāi)發(fā)者直觀驗(yàn)證 OCR 效果。

開(kāi)發(fā)環(huán)境

  • Visual Studio 2022(任意版本)
  • .NET Framework 4.8(或 .NET 6/8,本文以 .NET Framework 4.8 為例)
  • NuGet 包版本(詳見(jiàn)下文)

第一部分:環(huán)境準(zhǔn)備和 NuGet 配置

1.1 創(chuàng)建項(xiàng)目

打開(kāi) Visual Studio 2022,創(chuàng)建一個(gè)新的 Windows Forms 應(yīng)用(選擇 .NET Framework 4.8 或更高版本)。

1.2 安裝 NuGet 包

在“管理 NuGet 程序包”中搜索并安裝以下指定版本的包(版本號(hào)已實(shí)際測(cè)試通過(guò)):

包名版本說(shuō)明
PaddleOCRSharp6.1.0PaddleOCR 的 C# 封裝,提供 OCR 識(shí)別引擎
OpenCvSharp4.Windows4.13.0.20260222OpenCV 的 C# 封裝,用于圖像繪制和處理
OpenCvSharp4.Extensions4.13.0.20260222OpenCV 擴(kuò)展方法,便于 Bitmap 與 Mat 互轉(zhuǎn)
OpenCvSharp4.Runtime.win4.13.0.20260222OpenCV 運(yùn)行時(shí)依賴(通常由 Windows 包自動(dòng)引入)
Paddle.Runtime.win_x643.3.0.2Paddle Inference 運(yùn)行時(shí)(PaddleOCRSharp 依賴)
(可選) DevExpress.Win.Design24.2.5用于美化界面,本文使用普通 WinForms 控件,非必須

注意:請(qǐng)確保項(xiàng)目目標(biāo)平臺(tái)為 x64,因?yàn)?Paddle 運(yùn)行時(shí)僅支持 64 位。在項(xiàng)目屬性 -> 生成 -> 目標(biāo)平臺(tái)中選擇 x64。

1.3 引入命名空間

在代碼文件頂部添加以下 using 指令:

using PaddleOCRSharp;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System; // 可能還需要其他基礎(chǔ)命名空間

第二部分:實(shí)現(xiàn)文字識(shí)別并在文本框輸出

2.1 初始化 OCR 引擎

PaddleOCRSharp 提供了 PaddleOCREngine 類,可配置模型路徑和識(shí)別參數(shù)。通常使用默認(rèn)配置即可。

private PaddleOCREngine engine;

// 在窗體構(gòu)造函數(shù)或需要時(shí)初始化
public Form1()
{
    InitializeComponent();
    OCRModelConfig config = null;
    OCRParameter param = new OCRParameter();
    engine = new PaddleOCREngine(config, param);
}

2.2 識(shí)別圖片中的文字

通過(guò) OpenFileDialog 選擇圖片,調(diào)用 DetectText 方法獲取識(shí)別結(jié)果,并將文本顯示在 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));

    // 執(zhí)行識(shí)別
    OCRResult result = engine.DetectText(bitmap);
    if (result != null)
    {
        textBox1.Text = result.Text; // 輸出純文本
    }
}

2.3 識(shí)別 PDF 文檔中的文字

PDF 識(shí)別使用 DetectTextPDF 方法,需要傳入 PDF 字節(jié)數(shù)組和分辨率(通常 150 或 200)。該方法支持分頁(yè)回調(diào),便于顯示進(jìn)度。

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);
    
    // 設(shè)置回調(diào)顯示處理進(jìn)度
    Action<int> progress = page => Console.WriteLine($"正在處理第 {page} 頁(yè)");
    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 對(duì)象除了包含整體文本外,還包含了每個(gè)文本塊的詳細(xì)信息(如位置坐標(biāo)、置信度等),這些信息將在第三部分用于繪制檢測(cè)框。

第三部分:實(shí)現(xiàn)三圖對(duì)比顯示

為了直觀驗(yàn)證 OCR 效果,我們希望在識(shí)別后彈出一個(gè)新窗體,展示三幅并排的圖像:

  • 原圖:原始輸入圖像。
  • 檢測(cè)框圖:在原圖上繪制淺藍(lán)色檢測(cè)框(BGR = 255,255,0),不顯示文字。
  • 識(shí)別結(jié)果圖:純白色背景,繪制淺藍(lán)色檢測(cè)框,并用黑色文字居中顯示識(shí)別結(jié)果(解決中文顯示問(wèn)題)。

由于 OpenCvSharp 的 PutText 不支持中文,我們需要借助 System.Drawing 繪制中文,再將結(jié)果轉(zhuǎn)回 OpenCV 的 Mat 進(jìn)行拼接。

3.1 創(chuàng)建對(duì)比窗體 Form2

在項(xiàng)目中添加一個(gè)新窗體 Form2,放置一個(gè) PictureBox 控件(命名為 pictureBox1),并將 SizeMode 設(shè)置為 AutoSize,同時(shí)啟用窗體的 AutoScroll 屬性以支持滾動(dòng)查看大圖。

3.2 編寫(xiě)繪圖方法

核心函數(shù) DrawThreeImages 接收原始圖像和 OCR 結(jié)果,返回拼接后的 Bitmap。

private Bitmap DrawThreeImages(Bitmap original, OCRResult ocrResult)
{
    // 1. 將原圖轉(zhuǎn)為 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); // 淺藍(lán)色

    // 獲取文本塊列表(根據(jù)實(shí)際屬性名調(diào)整,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 轉(zhuǎn)為 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;

                // 計(jì)算文本框的邊界矩形
                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;

                // 根據(jù)框高度動(dòng)態(tài)設(shè)置字體大?。s0.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 轉(zhuǎn)回 Mat
        textMat = BitmapConverter.ToMat(textBmp);
        textBmp.Dispose();
    }

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

    // 5. 轉(zhuǎn)換為 Bitmap
    Bitmap resultBitmap = BitmapConverter.ToBitmap(resultMat);

    // 6. 釋放資源
    originalMat.Dispose();
    boxesMat.Dispose();
    textMat.Dispose();
    resultMat.Dispose();

    return resultBitmap;
}

3.3 在識(shí)別后顯示對(duì)比窗體

修改圖片識(shí)別按鈕的點(diǎn)擊事件,識(shí)別完成后調(diào)用上述方法,并顯示 Form2。

private void btnImageOCR_Click(object sender, EventArgs e)
{
    // ... 前面的識(shí)別代碼 ...
    if (ocrResult != null)
    {
        textBox1.Text = ocrResult.Text;

        // 生成三圖對(duì)比
        Bitmap merged = DrawThreeImages(bitmap, ocrResult);

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

3.4 效果預(yù)覽

運(yùn)行程序,選擇一張包含表格的圖片,識(shí)別后彈出 Form2,可以看到:

  • 左側(cè)原圖;
  • 中間原圖疊加淺藍(lán)色檢測(cè)框;
  • 右側(cè)純白背景,檢測(cè)框內(nèi)居中顯示黑色文字(中文正確顯示)。

總結(jié)

通過(guò) PaddleOCRSharpOpenCvSharp,我們能夠在 C# 中輕松集成 PaddleOCR 的高效文字識(shí)別能力。本文不僅實(shí)現(xiàn)了基礎(chǔ)的文本提取,還通過(guò)三圖對(duì)比功能直觀展示了檢測(cè)和識(shí)別效果,尤其解決了中文顯示問(wèn)題。這種可視化方式對(duì)于調(diào)試 OCR 參數(shù)、驗(yàn)證識(shí)別準(zhǔn)確率非常有幫助。

未來(lái)可根據(jù)需求擴(kuò)展:如識(shí)別表格結(jié)構(gòu)、輸出結(jié)構(gòu)化數(shù)據(jù)等。希望本文能為你的 C# OCR 開(kāi)發(fā)提供參考。

注意事項(xiàng)

  • 務(wù)必使用 x64 平臺(tái)編譯。
  • 若中文顯示仍有問(wèn)題,檢查系統(tǒng)是否安裝 Microsoft YaHei 字體,或更換為其他中文字體(如“SimSun”)。

以上就是C#利用PaddleOCRSharp實(shí)現(xiàn)表格文字識(shí)別及可視化對(duì)比的詳細(xì)內(nèi)容,更多關(guān)于C# PaddleOCRSharp表格文字識(shí)別及對(duì)比的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例

    C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例

    這篇文章主要為大家詳細(xì)介紹了C#基于Socket的TCP通信實(shí)現(xiàn)聊天室案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#中操作Office文檔的完整教程

    C#中操作Office文檔的完整教程

    這篇文章介紹了如何在C#中使用Microsoft Office Interop組件來(lái)操作Word、Excel和PowerPoint文檔,包括創(chuàng)建、讀取、修改、插入表格、添加圖表、轉(zhuǎn)換為PDF等操作,同時(shí),還提供了注意事項(xiàng)、常見(jiàn)問(wèn)題解決方法和部署注意事項(xiàng),需要的朋友可以參考下
    2025-10-10
  • C#中將DataTable轉(zhuǎn)化成List<T>的方法解析

    C#中將DataTable轉(zhuǎn)化成List<T>的方法解析

    大家應(yīng)該都知道在.net項(xiàng)目中使用到DataTable和List<T>集合的地方較多,有的時(shí)候需要將DataTable轉(zhuǎn)化成List<T>,那么改如何轉(zhuǎn)化呢?下面通過(guò)這篇文章來(lái)一起學(xué)習(xí)下吧,本文中給出了詳細(xì)的示例代碼,相信對(duì)大家的理解和學(xué)習(xí)具有一定的參考借鑒價(jià)值。
    2016-12-12
  • C#中l(wèi)ock用法詳解

    C#中l(wèi)ock用法詳解

    這篇文章主要介紹了C#中l(wèi)ock用法,以實(shí)例形式詳細(xì)分析了lock語(yǔ)句的用法及用途,需要的朋友可以參考下
    2014-11-11
  • C#使用log4net記錄日志的方法步驟

    C#使用log4net記錄日志的方法步驟

    本文主要介紹了C#使用log4net記錄日志的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C#使用集合實(shí)現(xiàn)二叉查找樹(shù)

    C#使用集合實(shí)現(xiàn)二叉查找樹(shù)

    這篇文章介紹了C#使用集合實(shí)現(xiàn)二叉查找樹(shù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • C#中File類的文件操作方法詳解

    C#中File類的文件操作方法詳解

    這篇文章主要介紹了C#中File類的文件操作方法,以實(shí)例的形式詳細(xì)分析了File類對(duì)文件的創(chuàng)建、打開(kāi)、復(fù)制、刪除等各種常用的操作,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-11-11
  • C#實(shí)現(xiàn)在購(gòu)物車(chē)系統(tǒng)中生成不重復(fù)訂單號(hào)的方法

    C#實(shí)現(xiàn)在購(gòu)物車(chē)系統(tǒng)中生成不重復(fù)訂單號(hào)的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)在購(gòu)物車(chē)系統(tǒng)中生成不重復(fù)訂單號(hào)的方法,涉及C#中時(shí)間與字符串操作的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下
    2015-05-05
  • WPF多線程更新UI的兩種實(shí)用方案

    WPF多線程更新UI的兩種實(shí)用方案

    在WPF開(kāi)發(fā)中,使用多線程處理耗時(shí)任務(wù)是常見(jiàn)做法,但若嘗試在后臺(tái)線程直接修改UI元素,系統(tǒng)會(huì)拋出異常,本文將詳細(xì)介紹WPF 多線程更新UI的兩種實(shí)用方案,需要的朋友可以參考下
    2025-09-09
  • 基于WPF實(shí)現(xiàn)驗(yàn)證碼控件

    基于WPF實(shí)現(xiàn)驗(yàn)證碼控件

    這篇文章主要介紹了如何利用WPF實(shí)現(xiàn)一個(gè)簡(jiǎn)單的驗(yàn)證碼控件,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,需要的可以參考一下
    2022-08-08

最新評(píng)論

集贤县| 威宁| 苍梧县| 商洛市| 宣武区| 淮阳县| 青海省| 达拉特旗| 阜南县| 进贤县| 井研县| 时尚| 龙口市| 大余县| 如东县| 东山县| 缙云县| 侯马市| 石柱| 南川市| 康马县| 山丹县| 固原市| 温宿县| 治县。| 汝阳县| 汉寿县| 枣阳市| 周口市| 文水县| 常州市| 拉萨市| 张家界市| 北宁市| 石阡县| 化州市| 环江| 铜陵市| 拉萨市| 临城县| 莆田市|