如何在 C# 中除錯 OCR

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronOCR 讓您能夠在源頭偵測 OCR 失敗情況、在單字與字元層級評估辨識品質,並即時監控長時間執行的任務。內建工具(例如診斷檔案記錄、類型化例外層級、每項結果的信心分數,以及 OcrProgress 事件)皆能支援生產管線中的這些工作流程。

本指南將逐步示範各項實作範例:啟用診斷記錄、處理類型化例外、透過信心分數驗證輸出、即時監控工作進度,以及在批次處理管線中隔離錯誤。

快速入門:啟用完整的 OCR 診斷記錄

請在首次呼叫 Read 之前,於 Installation 類別上設定 LogFilePathLogging模式。 只需設定兩項屬性,即可將 Tesseract 的初始化、語言套件載入及處理細節記錄至日誌檔案中。

  1. using NuGet 套件管理員安裝 https://www.nuget.org/packages/IronOcr

    PM > Install-Package IronOcr
  2. 請複製並執行此程式碼片段。

    IronOcr.Installation.LogFilePath = "ocr.log"; IronOcr.Installation.Logging模式 = IronOcr.Installation.LoggingModes.All;
  3. 部署至您的生產環境進行測試

    立即透過免費試用,在您的專案中開始使用 IronOCR

    arrow pointer


如何啟用診斷記錄?

Installation 類別提供了三個記錄控制項。 在呼叫任何 Read 方法之前,請先設定這些參數。

:path=/static-assets/ocr/content-code-examples/how-to/debugging-enable-logging.cs
using IronOcr;

// Write logs to a specific file
Installation.LogFilePath = "logs/ocr_diagnostics.log";

// Enable all logging channels: file + debug output
Installation.LoggingMode = Installation.LoggingModes.All;

// Or pipe logs into your existing ILogger pipeline
Installation.CustomLogger = myLoggerInstance;
Imports IronOcr

' Write logs to a specific file
Installation.LogFilePath = "logs/ocr_diagnostics.log"

' Enable all logging channels: file + debug output
Installation.LoggingMode = Installation.LoggingModes.All

' Or pipe logs into your existing ILogger pipeline
Installation.CustomLogger = myLoggerInstance
$vbLabelText   $csharpLabel

Logging模式 接受來自 Logging模式s 枚舉的旗標值:

表 1:Logging模式s 選項
模式目標輸出使用案例
已停用生產環境搭配外部監控
除錯IDE 除錯輸出視窗在地化開發
檔案LogFilePath伺服器端日誌收集
全部除錯 + 檔案完整診斷擷取

CustomLogger 屬性支援任何 Microsoft.Extensions.Logging.ILogger 實作,讓您能將 OCR 診斷資訊導向 Serilog、NLog 或您管道中的其他結構化記錄接收端。使用 ClearLogFiles 來清除執行間累積的記錄資料。

在啟用記錄功能後,下一步是了解 IronOCR 可能拋出的例外狀況,以及如何處理每種情況。

IronOCR 會拋出哪些例外?

IronOCR 在 IronOcr.Exceptions 命名空間下定義了類型化例外。 透過針對性地處理這些錯誤,而非使用籠統的 catch 區塊,您便能將每種錯誤類型導向正確的修復路徑。

表 2:IronOCR 例外參考
例外Common Cause修正
IronOcrInput例外損壞或不支援的圖片/PDF在載入 OcrInput 之前驗證檔案
IronOcrProduct例外OCR 執行期間發生內部引擎錯誤啟用記錄功能、檢查記錄輸出、更新至最新 NuGet 版本
IronOcrDictionary例外缺少或損壞的 .traineddata 語言檔案重新安裝 NuGet 語言套件或設定 LanguagePackDirectory
IronOcrNative例外原生 C++ 互通失敗安裝 Visual C++ 再發行套件;檢查 AVX 支援
IronOcrLicensing例外缺少或已過期的授權金鑰在呼叫 Read 之前請先設定 LicenseKey
LanguagePack例外未在預期路徑中找到語言套件請檢查 LanguagePackDirectory 或重新安裝 NuGet 語言套件
IronOcrAssemblyVersionMismatch例外部分更新後組件版本不匹配清除 NuGet 快取、還原套件,並確保所有 IronOCR 套件版本一致

請使用以下 try-catch 區塊分別處理每種例外類型,並套用例外篩選器進行條件式記錄。

輸入

IronOCR Solutions 向 Acme Corporation 開立的單頁供應商發票,已透過 LoadPdf 載入至 OcrInput。 內容包含四項明細、稅金及總計金額——文字種類足夠豐富,足以讓每個例外處理程序進行實際演練。

invoice_scan.PDF:用於依序演示各類型例外處理程序的供應商發票(編號 #INV-2024-7829)。

:path=/static-assets/ocr/content-code-examples/how-to/debugging-exception-handling.cs
using IronOcr;
using IronOcr.Exceptions;

var ocr = new IronTesseract();

try
{
    using var input = new OcrInput();
    input.LoadPdf("invoice_scan.pdf");

    OcrResult result = ocr.Read(input);
    Console.WriteLine($"Text: {result.Text}");
    Console.WriteLine($"Confidence: {result.Confidence:P1}");
}
catch (IronOcrInputException ex)
{
    // File could not be loaded — corrupt, locked, or unsupported format
    Console.Error.WriteLine($"Input error: {ex.Message}");
}
catch (IronOcrDictionaryException ex)
{
    // Language pack missing — common in containerized deployments
    Console.Error.WriteLine($"Language pack error: {ex.Message}");
}
catch (IronOcrNativeException ex) when (ex.Message.Contains("AVX"))
{
    // CPU does not support AVX instructions
    Console.Error.WriteLine($"Hardware incompatibility: {ex.Message}");
}
catch (IronOcrLicensingException)
{
    Console.Error.WriteLine("License key is missing or invalid.");
}
catch (IronOcrProductException ex)
{
    // Catch-all for other IronOCR engine errors
    Console.Error.WriteLine($"OCR engine error: {ex.Message}");
    Console.Error.WriteLine($"Stack trace: {ex.StackTrace}");
}
Imports IronOcr
Imports IronOcr.Exceptions

Dim ocr As New IronTesseract()

Try
    Using input As New OcrInput()
        input.LoadPdf("invoice_scan.pdf")

        Dim result As OcrResult = ocr.Read(input)
        Console.WriteLine($"Text: {result.Text}")
        Console.WriteLine($"Confidence: {result.Confidence:P1}")
    End Using
Catch ex As IronOcrInputException
    ' File could not be loaded — corrupt, locked, or unsupported format
    Console.Error.WriteLine($"Input error: {ex.Message}")
Catch ex As IronOcrDictionaryException
    ' Language pack missing — common in containerized deployments
    Console.Error.WriteLine($"Language pack error: {ex.Message}")
Catch ex As IronOcrNativeException When ex.Message.Contains("AVX")
    ' CPU does not support AVX instructions
    Console.Error.WriteLine($"Hardware incompatibility: {ex.Message}")
Catch ex As IronOcrLicensingException
    Console.Error.WriteLine("License key is missing or invalid.")
Catch ex As IronOcrProductException
    ' Catch-all for other IronOCR engine errors
    Console.Error.WriteLine($"OCR engine error: {ex.Message}")
    Console.Error.WriteLine($"Stack trace: {ex.StackTrace}")
End Try
$vbLabelText   $csharpLabel

輸出

成功輸出

發票載入順暢,引擎會同時回傳字元數與信心分數。

顯示成功透過 OCR 讀取 invoice_scan.pdf 的終端機輸出,包含字元數與信心分數

失敗的輸出

載入缺失的 PDF 檔案時觸發例外狀況的終端機輸出

請將 catch 區塊依從最具體到最通用的順序排列。 when 子句在 IronOcrNative例外 篩選器上,用於篩選與 AVX 相關的錯誤,同時不會擷取無關的原生錯誤。 每個處理程序都會記錄例外訊息; 該 catch-all 區塊亦會擷取堆疊追蹤資訊,以供事後分析之用。

捕捉正確的例外狀況能告訴您出了問題,但無法反映引擎在成功運作時的表現如何。 為此,請使用信心分數。

如何利用信心分數驗證 OCR 輸出結果?

每個 OcrResult 都會公開一個 Confidence 屬性,其值介於 0 到 1 之間,代表引擎針對所有識別出的字元所計算出的平均統計確定度。 您可以在結果層級的每個層級(文件頁面段落單字字元)存取此內容。

請採用閾值門控模式,以防止低品質的結果向下傳遞。

輸入

一張熱感收據,包含明細項目、折扣、總額及BARCODE,透過 LoadImage 載入。 其狹窄的寬度、等寬字體以及淡色的PRINT字體,使其成為測試單字信心閾值的實用壓力測試。

FoodMart 的熱感收據範例,顯示明細購買項目、總額及已使用的獎勵點數,作為 OCR 輸入內容

receipt.png:用於展示閾值門控信心驗證及收據影像逐字準確度深入分析的熱感應收據掃描圖

:path=/static-assets/ocr/content-code-examples/how-to/debugging-confidence-scoring.cs
using IronOcr;

var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("receipt.png");

OcrResult result = ocr.Read(input);
double confidence = result.Confidence;

Console.WriteLine($"Overall confidence: {confidence:P1}");

// Threshold-gated decision
if (confidence >= 0.90)
{
    Console.WriteLine("ACCEPT — high confidence, processing result.");
    ProcessResult(result.Text);
}
else if (confidence >= 0.70)
{
    Console.WriteLine("FLAG — moderate confidence, queuing for review.");
    QueueForReview(result.Text, confidence);
}
else
{
    Console.WriteLine("REJECT — low confidence, logging for investigation.");
    LogRejection("receipt.png", confidence);
}

// Drill into per-page and per-word confidence for diagnostics
foreach (var page in result.Pages)
{
    Console.WriteLine($"  Page {page.PageNumber}: {page.Confidence:P1}");

    var lowConfidenceWords = page.Words
        .Where(w => w.Confidence < 0.70)
        .ToList();

    foreach (var word in lowConfidenceWords)
    {
        Console.WriteLine($"    Low-confidence word: \"{word.Text}\" ({word.Confidence:P1})");
    }
}
Imports IronOcr

Dim ocr As New IronTesseract()
Using input As New OcrInput()
    input.LoadImage("receipt.png")

    Dim result As OcrResult = ocr.Read(input)
    Dim confidence As Double = result.Confidence

    Console.WriteLine($"Overall confidence: {confidence:P1}")

    ' Threshold-gated decision
    If confidence >= 0.9 Then
        Console.WriteLine("ACCEPT — high confidence, processing result.")
        ProcessResult(result.Text)
    ElseIf confidence >= 0.7 Then
        Console.WriteLine("FLAG — moderate confidence, queuing for review.")
        QueueForReview(result.Text, confidence)
    Else
        Console.WriteLine("REJECT — low confidence, logging for investigation.")
        LogRejection("receipt.png", confidence)
    End If

    ' Drill into per-page and per-word confidence for diagnostics
    For Each page In result.Pages
        Console.WriteLine($"  Page {page.PageNumber}: {page.Confidence:P1}")

        Dim lowConfidenceWords = page.Words _
            .Where(Function(w) w.Confidence < 0.7) _
            .ToList()

        For Each word In lowConfidenceWords
            Console.WriteLine($"    Low-confidence word: ""{word.Text}"" ({word.Confidence:P1})")
        Next
    Next
End Using
$vbLabelText   $csharpLabel

輸出

顯示信心分數、接受/標記/拒絕決策,以及收據影像中每WORD低信心詳細分析的終端機輸出

此模式對於 OCR 銜接至資料輸入、發票處理或合規工作流程的處理鏈至關重要。 按WORD細查功能可精確識別源圖像中哪些區域導致了畫質劣化; 您隨後可套用影像品質濾鏡進行方向校正,並重新處理。 若要深入了解信心分數,請參閱信心等級操作指南

對於長期運行的任務,僅憑信心是不夠的。 您還需要了解引擎是否仍在運作,而這正是 OcrProgress 事件派生的原因。

如何即時監控 OCR 的進度?

對於多頁文件,每當一頁處理完畢後,OcrProgress 上的 IronTesseract 事件便會觸發。 OcrProgressEventArgs 物件會公開進度百分比、已耗時、總頁數及已完成頁數。 此範例以這份三頁的季度報告作為輸入:一份結構化的商業文件,內容涵蓋執行摘要、營收明細及營運指標。

輸入

透過 LoadPdf 載入的 2024 年第一季三頁財務報告。 第一頁涵蓋包含 KPI 指標的執行摘要,第二頁包含按產品線和地區劃分的營收表格,第三頁則涵蓋營運處理量 — 每種頁面類型都會產生獨特的每頁處理時間,您可在進度回調中觀察到這些數據。

quarterly_report.pdf: Three-page Q1 2024 financial report (executive summary, revenue breakdown, operational metrics) used to demonstrate real-time `OcrProgress` callbacks per page.

:path=/static-assets/ocr/content-code-examples/how-to/debugging-progress-monitoring.cs
using IronOcr;

var ocr = new IronTesseract();

ocr.OcrProgress += (sender, e) =>
{
    Console.WriteLine(
        $"[OCR] {e.ProgressPercent}% complete | " +
        $"Page {e.PagesComplete}/{e.TotalPages} | " +
        $"Elapsed: {e.Duration.TotalSeconds:F1}s"
    );
};

using var input = new OcrInput();
input.LoadPdf("quarterly_report.pdf");

OcrResult result = ocr.Read(input);
Console.WriteLine($"Finished in {result.Pages.Count()} pages, confidence: {result.Confidence:P1}");
Imports IronOcr

Dim ocr = New IronTesseract()

AddHandler ocr.OcrProgress, Sub(sender, e)
    Console.WriteLine(
        $"[OCR] {e.ProgressPercent}% complete | " &
        $"Page {e.PagesComplete}/{e.TotalPages} | " &
        $"Elapsed: {e.Duration.TotalSeconds:F1}s"
    )
End Sub

Using input As New OcrInput()
    input.LoadPdf("quarterly_report.pdf")

    Dim result As OcrResult = ocr.Read(input)
    Console.WriteLine($"Finished in {result.Pages.Count()} pages, confidence: {result.Confidence:P1}")
End Using
$vbLabelText   $csharpLabel

輸出

顯示三頁 PDF 文件中每頁 OcrProgress 事件回調、完成百分比及耗時之終端機輸出

將此事件整合至您的記錄基礎架構中,以追蹤 OCR 工作執行時間並偵測停滯狀況。 若經過的時間超過閾值,而進度百分比卻未增加,管道可將該工作標記為待查。 這對於批次 PDF 處理特別有用,因為單一格式錯誤的頁面就可能導致整個工作停滯。

進度監控會顯示執行狀態,但若未能隔離檔案層級的錯誤,仍可能導致整個批次作業提前終止。

如何處理批次 OCR 處理流程中的錯誤?

在生產環境中,單一檔案的失敗不應導致整個批次中斷。 請針對每個檔案分別標示錯誤,並附帶上下文記錄失敗情況,最後生成一份摘要報告。 此範例處理一個包含掃描文件的資料夾,內含發票、採購訂單、服務合約,以及一個刻意損毀的檔案,用以觸發錯誤處理流程。 以下為代表性範例:

輸入

傳遞給 Directory.GetFiles 的 PDF 文件夾——包含一張發票、一份採購訂單、一份服務合約,以及一個刻意損毀的檔案。以下兩個代表性範例展示了該處理流程在單次執行中處理的文件多樣性。

:path=/static-assets/ocr/content-code-examples/how-to/debugging-batch-pipeline.cs
using IronOcr;
using IronOcr.Exceptions;

var ocr = new IronTesseract();
Installation.LogFilePath = "batch_debug.log";
Installation.LoggingMode = Installation.LoggingModes.File;

string[] files = Directory.GetFiles("scans/", "*.pdf");
int succeeded = 0, failed = 0;
double totalConfidence = 0;
var failures = new List<(string File, string Error)>();

foreach (string file in files)
{
    try
    {
        using var input = new OcrInput();
        input.LoadPdf(file);

        OcrResult result = ocr.Read(input);
        totalConfidence += result.Confidence;
        succeeded++;

        Console.WriteLine($"OK: {Path.GetFileName(file)} — {result.Confidence:P1}");
    }
    catch (IronOcrInputException ex)
    {
        failed++;
        failures.Add((file, $"Input error: {ex.Message}"));
        Console.Error.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.Message}");
    }
    catch (IronOcrProductException ex)
    {
        failed++;
        failures.Add((file, $"Engine error: {ex.Message}"));
        Console.Error.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.Message}");
    }
    catch (Exception ex)
    {
        failed++;
        failures.Add((file, $"Unexpected: {ex.Message}"));
        Console.Error.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.GetType().Name}: {ex.Message}");
    }
}

// Summary report
Console.WriteLine($"\n--- Batch Summary ---");
Console.WriteLine($"Total: {files.Length} | Passed: {succeeded} | Failed: {failed}");
if (succeeded > 0)
    Console.WriteLine($"Average confidence: {totalConfidence / succeeded:P1}");

foreach (var (f, err) in failures)
    Console.WriteLine($"  {Path.GetFileName(f)}: {err}");
Imports IronOcr
Imports IronOcr.Exceptions
Imports System.IO

Dim ocr As New IronTesseract()
Installation.LogFilePath = "batch_debug.log"
Installation.LoggingMode = Installation.LoggingModes.File

Dim files As String() = Directory.GetFiles("scans/", "*.pdf")
Dim succeeded As Integer = 0
Dim failed As Integer = 0
Dim totalConfidence As Double = 0
Dim failures As New List(Of (File As String, Error As String))()

For Each file As String In files
    Try
        Using input As New OcrInput()
            input.LoadPdf(file)

            Dim result As OcrResult = ocr.Read(input)
            totalConfidence += result.Confidence
            succeeded += 1

            Console.WriteLine($"OK: {Path.GetFileName(file)} — {result.Confidence:P1}")
        End Using
    Catch ex As IronOcrInputException
        failed += 1
        failures.Add((file, $"Input error: {ex.Message}"))
        Console.Error.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.Message}")
    Catch ex As IronOcrProductException
        failed += 1
        failures.Add((file, $"Engine error: {ex.Message}"))
        Console.Error.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.Message}")
    Catch ex As Exception
        failed += 1
        failures.Add((file, $"Unexpected: {ex.Message}"))
        Console.Error.WriteLine($"FAIL: {Path.GetFileName(file)} — {ex.GetType().Name}: {ex.Message}")
    End Try
Next

' Summary report
Console.WriteLine(vbCrLf & "--- Batch Summary ---")
Console.WriteLine($"Total: {files.Length} | Passed: {succeeded} | Failed: {failed}")
If succeeded > 0 Then
    Console.WriteLine($"Average confidence: {totalConfidence / succeeded:P1}")
End If

For Each failure In failures
    Console.WriteLine($"  {Path.GetFileName(failure.File)}: {failure.Error}")
Next
$vbLabelText   $csharpLabel

輸出

顯示批次處理結果的終端機輸出,內容包含各檔案的字元數、信心分數、一份因 PDF 檔案損壞而產生的錯誤,以及摘要行

外層的 catch 區塊負責處理各種不可預見的錯誤,包括共用儲存空間的網路超時、權限問題,或是處理大型 TIFF 檔案時的記憶體不足狀況。 每次處理失敗時,系統會將檔案路徑與錯誤訊息記錄至摘要中,同時迴圈會繼續處理剩餘的檔案。 位於 batch_debug.log 的日誌檔案,會記錄任何觸發內部診斷的檔案之引擎層級詳細資訊。

為了在服務或網頁應用程式中實現非阻塞執行,IronOCR 支援 ReadAsync,其採用相同的 try-catch 結構。

若處理流程執行時未出現錯誤,但擷取的文字仍不正確,根本原因幾乎總是源於影像品質,而非程式碼。 以下是處理方式。

如何調試 OCR 準確度?

若信心分數持續偏低,問題出在原始圖像而非 OCR 引擎。IronOCR 提供預處理工具來解決此問題:

  • 套用影像品質濾鏡(例如銳化、去噪、膨脹與蝕蝕)以提升文字清晰度
  • 使用方向校正功能,自動校正並旋轉掃描文件
  • 處理前請先調整低解析度圖片的 DPI 設定
  • 運用電腦視覺技術,在複雜版面中偵測並區隔文字區域
  • IronOCR Utility 讓您可直觀地測試濾鏡組合,並匯出最佳的 C# 設定

針對部署相關問題,IronOCR 提供針對 Azure FunctionsDocker 與 Linux 以及一般環境設定的專用疑難排解指南。

接下來該去哪裡?

既然您已了解如何在執行階段除錯 IronOCR,請進一步探索:

若用於正式生產環境,請記得取得授權以移除浮水印並使用完整功能。

常見問題

在 C# 中除錯 OCR 時常見哪些問題?

常見問題包括 OCR 結果不正確、信心分數過低以及發生意外的例外狀況。IronOCR 提供日誌記錄和信心評分等工具,協助識別並解決這些問題。

IronOCR 如何協助處理 C# 中的錯誤?

IronOCR 提供類型化的例外狀況與詳細的錯誤訊息,有助於在 C# 應用程式執行 OCR 操作時,有效理解並處理錯誤。

IronOCR 提供了哪些用於除錯的記錄功能?

IronOCR 內建日誌記錄功能,可透過記錄 OCR 操作的詳細資訊,協助追蹤 OCR 流程並識別潛在問題。

信心評分如何改善 OCR 結果?

IronOCR 的信心分數功能有助於判斷辨識文字的準確性,讓開發人員能專注於信心分數較低的區域,並改善 OCR 結果。

我能否使用 IronOCR 追蹤 OCR 任務的進度?

是的,IronOCR 提供進度追蹤功能,讓開發人員能夠監控 OCR 任務的狀態與執行時間,從而協助進行更完善的資源管理與效能優化。

針對 OCR 錯誤處理,建議採用哪些 try-catch 模式?

IronOCR 建議採用已通過生產環境驗證的 try-catch 模式來優雅地處理例外狀況,確保 OCR 應用程式具備穩健性與可維護性。

IronOCR 的內建工具如何提升 OCR 除錯效能?

IronOCR 的工具,例如記錄、類型化例外狀況及信心評分,為問題的識別與解決提供全面支援,從而提升除錯流程的效率。

在 OCR 應用程式中,錯誤記錄為何如此重要?

錯誤記錄至關重要,因為它能提供 OCR 處理過程中發生何種問題的洞察,讓開發人員能夠快速診斷並修復應用程式中的問題。

在 IronOCR 的除錯過程中,類型化例外扮演什麼角色?

IronOCR 中的類型化例外狀況會提供具體的錯誤資訊,讓開發人員在除錯時更容易理解問題的本質,並採取適當的解決方案。

開發人員如何從 IronOCR 的除錯功能中受益?

開發人員可利用 IronOCR 的除錯功能,有效率地排除問題、提升應用程式穩定性,並改善 OCR 結果的整體品質。

Curtis Chau
技術撰稿人

Curtis Chau 擁有卡爾頓大學(Carleton University)的電腦科學學士學位,專精於前端開發,並精通 Node.js、TypeScript、JavaScript 及 React。他熱衷於打造直觀且美觀的用戶介面,喜歡運用現代框架,並創建結構完善、視覺上吸引人的手冊。

除了開發工作之外,Curtis 對物聯網(IoT)抱有濃厚興趣,致力於探索整合硬體與軟體的創新方法。閒暇時,他喜歡玩遊戲和開發 Discord 機器人,將對科技的熱愛與創意相結合。

準備開始了嗎?
Nuget 下載 5,896,332 | 版本: 2026.5 just released
Still Scrolling Icon

還在往下捲動嗎?

想要快速確認成果嗎? PM > Install-Package IronOcr
執行範例 觀看您的圖片轉為可搜尋文字。