如何调试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. 使用 NuGet 包管理器安装 https://www.nuget.org/packages/IronOcr

    PM > Install-Package IronOcr
  2. 复制并运行这段代码。

    IronOcr.Installation.LogFilePath = "ocr.log"; IronOcr.Installation.Logging模式 = IronOcr.Installation.Logging模式s.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;
$vbLabelText   $csharpLabel

Logging模式 接受来自Logging模式s枚举的标志值:

表 1:日志模式选项
模式输出目标用例
None禁用带有外部监控的生产
DebugIDE调试输出窗口本地开发
FileLogFilePath服务器端日志收集
All调试 + 文件完整的诊断捕获

CustomLogger 属性支持任何 Microsoft.Extensions.Logging.ILogger 实现,允许您将 OCR 诊断信息定向到 Serilog、NLog 或管道中的其他结构化日志接收器。使用ClearLogFiles可清除运行之间累积的日志数据。

日志记录就绪后,下一步是了解IronOCR可能抛出哪些异常以及如何处理每一种异常。

IronOCR会抛出哪些异常?

IronOCR在IronOcr.例外情况s命名空间下定义了类型化异常。 与其进行一刀切式拦截,不如专门针对这些故障类型进行拦截,这样可以将每种故障类型路由到正确的修复路径。

表 2: IronOCR异常参考
例外情况常见原因修复
IronOcrInput例外情况损坏或不支持的图像/PDF在加载到OcrInput之前验证文件
IronOcrProduct例外情况OCR执行期间的内部引擎错误启用日志,检查日志输出,更新到最新的NuGet版本
IronOcrDictionary例外情况缺少或损坏的.traineddata语言文件重新安装语言包NuGet或设置LanguagePackDirectory
IronOcrNative例外情况原生C++互操作失败安装Visual C++ Redistributable;检查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}");
}
$vbLabelText   $csharpLabel

输出

成功输出

发票加载正常,引擎返回字符数和置信度评分。

终端输出显示成功读取 invoice_scan.pdf 的 OCR 字符集,包括字符数和置信度。

输出失败

终端输出显示加载缺失的 PDF 文件时抛出异常

按从最具体到最一般的顺序排列捕获块。 when 子句在 IronOcrNative例外情况 过滤器中用于检测与 AVX 相关的故障,而不会捕获不相关的本机错误。 每个处理程序都会记录异常消息; 兜底块还会捕获堆栈跟踪信息,以便进行事后分析。

捕获正确的异常可以告诉你哪里出了问题,但并不能告诉你引擎在成功运行时表现如何。 为此,可以使用置信度评分。

如何使用置信度分数验证 OCR 输出?

每个OcrResult都公开一个 Confidence 属性,该属性的值介于 0 和 1 之间,表示引擎对所有已识别字符的统计确定性平均值。 您可以在结果层次结构的每个级别访问此功能:文档页面段落单词字符

使用阈值门控模式防止低质量结果向下游传播。

输入

通过 LoadImage 加载的热敏收据,包含明细项目、折扣、总计和条形码。 它的窄宽度、等宽字体和淡淡的印刷字体使其成为逐字置信度阈值的实用压力测试。

这是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})");
    }
}
$vbLabelText   $csharpLabel

输出

终端输出显示收据图像的置信度评分、接受/标记/拒绝决定,以及逐字低置信度细分信息。

这种模式在OCR反馈到数据输入、发票处理或合规工作流的管道中至关重要。 逐字分析可以准确地确定源图像的哪些区域导致了图像质量下降; 然后您可以应用图像质量滤镜方向校正并重新处理。 对于置信评分的更深入了解,请参阅置信度级别指导

对于需要长期从事的工作来说,光有自信是不够的。 你还需要知道引擎是否仍在运行,而这正是 OcrProgress 事件的作用所在。

如何实时监控OCR识别进度?

对于多页文档,OcrProgress 事件在 IronTesseract 上会在每个页面完成后触发。 OcrProgressEventArgs 对象公开进度百分比、已用时间、总页数和已完成页数。 该示例使用这份三页的季度报告作为输入:一份结构化的商业文档,包括执行摘要、收入明细和运营指标。

输入

通过 LoadPdf 加载的 2024 年第一季度三页财务报告。 第一页涵盖了执行摘要和 KPI 指标,第二页包含按产品线和地区划分的收入表,第三页涵盖了运营处理量——每种页面类型都会产生不同的每页时间,您可以在进度回调中观察到。

quarterly_report.pdf:2024 年第一季度三页财务报告(执行摘要、收入明细、运营指标),用于演示每页的实时`OcrProgress`回调。

: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}");
$vbLabelText   $csharpLabel

输出

终端输出显示了三页 PDF 文件中每页的 OcrProgress 事件回调次数、完成百分比和耗时。

将此事件连接到您的日志记录基础架构,以跟踪 OCR 作业持续时间并检测停滞情况。 如果经过的时间超过阈值而进度百分比没有增加,则管道可以标记该作业以进行调查。 这对于批量PDF处理特别有用,因为单个格式错误的页面可能会阻止整个作业。

进度监控显示执行状态,但如果不进行隔离,文件级故障仍然可能导致整个批处理提前停止。

如何处理批量 OCR 流程中的错误?

在生产环境中,单个文件故障不应该导致整个批次停止运行。 按文件隔离错误,记录故障及其上下文,并在最后生成总结报告。 该示例处理一个包含发票、采购订单和服务合同的扫描文档文件夹,Plus一个故意损坏的文件以触发错误路径。 下面展示的是一个具有代表性的例子:

输入

传递给 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}");
$vbLabelText   $csharpLabel

输出

终端输出显示批处理管道的结果,包括每个文件的字符数、置信度分数、一个来自损坏 PDF 的错误以及摘要行。

外部 catch 块处理意外错误,包括共享存储上的网络超时、权限问题或大型 TIFF 文件内存不足的情况。 每个故障记录文件路径和错误消息以供总结,而循环继续处理剩余的文件。 位于 batch_debug.log 的日志文件捕获任何触发内部诊断的文件的引擎级详细信息。

对于服务或 Web 应用程序中的非阻塞执行, IronOCR支持ReadAsync ,它使用相同的 try-catch 结构。

如果管道运行没有错误,但提取的文本仍然错误,那么根本原因几乎总是图像质量而不是代码。 以下是解决之道。

如何调试OCR准确率?

如果置信度得分持续偏低,则问题出在源图像上,而不是 OCR 引擎。IronOCR 提供了IronOCR工具来解决这个问题:

针对部署特定问题, IronOCR维护了Azure FunctionsDocker 和 Linux的专门故障排除指南以及一般环境设置指南。

接下来我该去哪里?

既然您已经了解如何在运行时调试IronOCR ,请探索以下内容:

如需用于生产,请务必获取许可证以去除水印并使用全部功能。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

准备开始了吗?
Nuget 下载 5,556,263 | 版本: 2026.3 刚刚发布
Still Scrolling Icon

还在滚动吗?

想快速获得证据? PM > Install-Package IronOcr
运行示例 观看您的图像变成可搜索文本。