在 IronOCR 中处理大 PDF 文件

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

在大型多页 PDF 上运行 OCR 会激增内存并导致进程崩溃。 通常的罪魁祸首是一次将所有页面加载到内存中。

System.OutOfMemoryException

OcrInput.LoadPdf("large.pdf") 一次性读取所有页面。 IronOCR 的成像系统随后同时渲染每个页面,而且因为 DPI 默认为 OutOfMemoryException 或资源死锁。

解决方案

解决方法是逐个页面处理 PDF 并保持渲染 DPI 尽可能低以容许的文本质量。

1. 获取页面数

using IronPdf.PdfDocument (或任何 PDF 库)打开文档以读取页面数。

using var pdf = IronPdf.PdfDocument.FromFile(pdfPath);
var pageCount = pdf.PageCount;
using var pdf = IronPdf.PdfDocument.FromFile(pdfPath);
var pageCount = pdf.PageCount;
Imports IronPdf

Using pdf = IronPdf.PdfDocument.FromFile(pdfPath)
    Dim pageCount = pdf.PageCount
End Using
$vbLabelText   $csharpLabel

2. 一次加载一个页面

循环浏览页面,使用 OcrInput.LoadPdfPage("file.pdf", pageIndex, dpi) 单独加载每一页。 在视觉质量得到保持的情况下,将 DPI 降到 80 以下以节省内存。

3. 读取和连接

将每个单页输入传递给 IronTesseract.Read() 并将结果追加到 StringBuilder

var ocr = new IronTesseract();
var pdfPath = "large.pdf";
using var pdf = IronPdf.PdfDocument.FromFile(pdfPath);
var pageCount = pdf.PageCount;
var textBuilder = new StringBuilder();
for (int i = 0; i < pageCount; i++)
{
    using var input = new OcrInput();
    input.LoadPdfPage(pdfPath, i, 80);
    var result = ocr.Read(input);
    textBuilder.Append(result.Text);
    textBuilder.Append(' '); // Add space between pages
}
Console.WriteLine(textBuilder.ToString().Trim());
var ocr = new IronTesseract();
var pdfPath = "large.pdf";
using var pdf = IronPdf.PdfDocument.FromFile(pdfPath);
var pageCount = pdf.PageCount;
var textBuilder = new StringBuilder();
for (int i = 0; i < pageCount; i++)
{
    using var input = new OcrInput();
    input.LoadPdfPage(pdfPath, i, 80);
    var result = ocr.Read(input);
    textBuilder.Append(result.Text);
    textBuilder.Append(' '); // Add space between pages
}
Console.WriteLine(textBuilder.ToString().Trim());
Imports IronOcr
Imports IronPdf
Imports System.Text

Dim ocr As New IronTesseract()
Dim pdfPath As String = "large.pdf"
Using pdf = PdfDocument.FromFile(pdfPath)
    Dim pageCount As Integer = pdf.PageCount
    Dim textBuilder As New StringBuilder()
    For i As Integer = 0 To pageCount - 1
        Using input As New OcrInput()
            input.LoadPdfPage(pdfPath, i, 80)
            Dim result = ocr.Read(input)
            textBuilder.Append(result.Text)
            textBuilder.Append(" ") ' Add space between pages
        End Using
    Next
    Console.WriteLine(textBuilder.ToString().Trim())
End Using
$vbLabelText   $csharpLabel

using 在每个 OcrInput 上释放页面的图像数据,这样内存可以在循环中保持平稳,而不是随着页面数而增加。

选项:先压缩 PDF

对于非常复杂或图像密集的文件,逐页循环可能仍然困难。 在执行 OCR 之前使用 IronPDF 的 Compress API 压缩 PDF 以减少 IronOCR 需要处理的图像数据。 这在扫描或图像密集的文档上最有效。

直接压缩到流中,然后将该流加载到 OcrInput

var pdf = PdfDocument.FromFile(pdfPath);
var stream = pdf.CompressPdfToStream(CompressStructTree: true);
var ocrTesseract = new IronTesseract();
using var ocrInput = new OcrInput();
ocrInput.LoadPdfPage(stream, 1);
var pdf = PdfDocument.FromFile(pdfPath);
var stream = pdf.CompressPdfToStream(CompressStructTree: true);
var ocrTesseract = new IronTesseract();
using var ocrInput = new OcrInput();
ocrInput.LoadPdfPage(stream, 1);
Imports IronTesseract

Dim pdf = PdfDocument.FromFile(pdfPath)
Dim stream = pdf.CompressPdfToStream(CompressStructTree:=True)
Dim ocrTesseract = New IronTesseract()
Using ocrInput As New OcrInput()
    ocrInput.LoadPdfPage(stream, 1)
End Using
$vbLabelText   $csharpLabel

当 PDF 内含嵌入图像时,在压缩时降低 JpegQuality 以进一步缩减数据:

var pdf = PdfDocument.FromFile(@"D:\hugePdf.pdf");
var stream = pdf.CompressPdfToStream(JpegQuality: 75, CompressStructTree: true);
var pdf = PdfDocument.FromFile(@"D:\hugePdf.pdf");
var stream = pdf.CompressPdfToStream(JpegQuality: 75, CompressStructTree: true);
Imports System

Dim pdf = PdfDocument.FromFile("D:\hugePdf.pdf")
Dim stream = pdf.CompressPdfToStream(JpegQuality:=75, CompressStructTree:=True)
$vbLabelText   $csharpLabel

警告在循环中重用相同的 MemoryStream? 在每次读取之前将其位置重置为 0。 流在读取后即消耗,所以下一次读取如果位置未复位将会失败。

调试提示

  • 降低 DPI:80 的值设为 100 范围内,当文本仍清晰可读时大幅减少内存使用。
  • 避免在大文件上LoadPdf()只有在文档真正小的时候才一次性读取整个文档。
  • 提早释放:OcrInput 封装在 using 语句中,以便在页面之间释放内存。
  • 小心并行化:只有在机器有额外内存和 CPU 时才同时处理页面; 这在大型 PDF 上适得其反。
Curtis Chau
技术作家

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

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

准备开始了吗?
Nuget 下载 6,136,090 | 版本: 2026.7 刚刚发布
Still Scrolling Icon

还在滚动吗?

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