跳至頁尾內容
與其他組件的比較

IronOCR 與 AWS Textract:針對新創公司的 OCR 解決方案

GdPicture.NET在您支付OCR插件的費用之前需要一個核心授權——如果您想讀取PDF或產生可搜索的輸出,您還需要額外的PDF插件。 聯繫GdPicture以獲取當前的定價資訊。 對於需要從圖像和PDF中提取文字的團隊,多個插件的組合成本加上年度維護費用可能會顯著增加。 計費是GdPicture架構的直接後果:它是一個完整的文件成像平台,涵蓋掃描、DICOM、註釋、條碼處理和PDF編輯,而OCR只是眾多插件中的一個。 只有OCR需求的團隊吸收了他們永遠不會完全使用的整個文件成像SDK的成本。

API反映了相同的理念。 GdPicture使用整數圖像ID來跟蹤記憶體中的資源——您載入的每個圖像都會返回一個int,您將方法調用應用於該整數句柄,然後您必須明確釋放它或接受記憶體洩漏。 這種模式早於using語句。 它有效,但每次都將每個清理決策的重擔加諸於開發者。這個比較考察了這兩個緊張關係——基於插件的定價和圖像ID生命周期——以及API複雜性、預處理和PDF處理,並以IronOCR作為對立面。

了解GdPicture.NET

GdPicture.NET是由ORPALIS開發的商業文件成像SDK。 它經過多年的建立,成為一個涵蓋圖像處理、PDF建立和編輯、條碼讀取和生成、TWAIN/WIA掃描器整合、DICOM醫療影像、註釋和審閱工作流程以及具備PDF/A合規的文件歸檔的廣泛平台。 OCR是這個生態系統中的一種能力,通過專用插件提供。

SDK將其功能組織成不同的模塊,每個模塊都有其自己的主要類別:

  • GdPictureImaging——圖像載入、處理、格式轉換和所有整數圖像ID的來源
  • GdPicturePDF——PDF建立、編輯、渲染和頁面級OCR操作(需要單獨的插件授權)
  • GdPictureOCR——文字識別和提取; 使用由GdPictureImaging產生的圖像ID
  • GdPicture1DBarcode / GdPicture2DBarcode——線性和2D條碼讀寫單獨插件授權)
  • GdPictureDocumentImaging——包括去斜、去斑、邊框移除和打孔移除的高級文件清理過濾器(需要單獨的插件)
  • GdPictureAnnotations——文件標註、審閱和編輯

即使是基本的OCR也需要實例化兩個組件——GdPictureOCR來識別文字——並管理其各自生命周期。 從PDF進行的OCR需要第三個:GdPicturePDF。 命名空間本身包含版本號(GdPicture14),這意味著每次SDK主要升級都需要在整個程式碼庫中進行查找並代替。

常見的OCR場景的插件依賴樹如下:

如果您需要 您必須獲得授權
從圖像進行OCR 基礎授權 + OCR插件
從PDF進行OCR 基礎 + OCR插件 + PDF插件
可搜尋的 PDF 輸出 基礎 + OCR插件 + PDF插件
OCR之前的文件清理 基礎 + OCR插件 + 文件成像插件

圖像ID生命周期

GdPicture的定義型架構特徵是整數圖像ID管理。 載入任何圖像都會在GdPicture運行時內部分配記憶體並返回一個int句柄。 您使用該整數在所有後續調用中引用圖像。 當您完成後,您以該整數調用ReleaseGdPictureImage。 如果您沒有,直到進程結束時記憶體才會被釋放。

using GdPicture14;

// Every image load returns an integer handle
int imageId = _imaging.CreateGdPictureImageFromFile(imagePath);

if (imageId == 0)
{
    throw new Exception($"Failed to load image: {_imaging.GetStat()}");
}

try
{
    _ocr.SetImage(imageId);
    _ocr.Language = "eng";

    string resultId = _ocr.RunOCR();

    if (string.IsNullOrEmpty(resultId))
    {
        throw new Exception($"OCR failed: {_ocr.GetStat()}");
    }

    return _ocr.GetOCRResultText(resultId);
}
finally
{
    // CRITICAL: omitting this line causes a memory leak
    _imaging.ReleaseGdPictureImage(imageId);
}
using GdPicture14;

// Every image load returns an integer handle
int imageId = _imaging.CreateGdPictureImageFromFile(imagePath);

if (imageId == 0)
{
    throw new Exception($"Failed to load image: {_imaging.GetStat()}");
}

try
{
    _ocr.SetImage(imageId);
    _ocr.Language = "eng";

    string resultId = _ocr.RunOCR();

    if (string.IsNullOrEmpty(resultId))
    {
        throw new Exception($"OCR failed: {_ocr.GetStat()}");
    }

    return _ocr.GetOCRResultText(resultId);
}
finally
{
    // CRITICAL: omitting this line causes a memory leak
    _imaging.ReleaseGdPictureImage(imageId);
}
Imports GdPicture14

' Every image load returns an integer handle
Dim imageId As Integer = _imaging.CreateGdPictureImageFromFile(imagePath)

If imageId = 0 Then
    Throw New Exception($"Failed to load image: {_imaging.GetStat()}")
End If

Try
    _ocr.SetImage(imageId)
    _ocr.Language = "eng"

    Dim resultId As String = _ocr.RunOCR()

    If String.IsNullOrEmpty(resultId) Then
        Throw New Exception($"OCR failed: {_ocr.GetStat()}")
    End If

    Return _ocr.GetOCRResultText(resultId)
Finally
    ' CRITICAL: omitting this line causes a memory leak
    _imaging.ReleaseGdPictureImage(imageId)
End Try
$vbLabelText   $csharpLabel

處理多頁的PDF時,每個渲染的頁面都會生成單獨的圖像ID。 一份100頁的文件在200 DPI下,如果沒有清理,可以分配1–5 GB的記憶體。 正確的模式要求收集所有ID並在finally塊中釋放——但這種紀律完全是開發者的責任。

理解 IronOCR

IronOCR是為.NET構建的商業OCR庫,作為單個NuGet包構建。 其設計目標是無需配置的準確性:安裝包、設置授權金鑰、調用Read。 該程式庫包裹了一個優化的Tesseract 5引擎,具有自動預處理、原生PDF處理和結構化結果存取,所有這些均通過標準.NET模式暴露。

關鍵特徵:

  • 單個NuGet包——dotnet add package IronOcr安裝所有內容,包括英語語言支援; 無外部資源資料夾,無本地二進製管理
  • 標準.NET資源管理——IDisposable; 一個using語句處理所有清理,無論是否發生例外
  • 自動預處理——Deskew, DeNoise, Contrast, Binarize和EnhanceResolution在OcrInput上的一行方法調用; 引擎還會在沒有明確指令的情況下應用自動修正
  • 原生PDF輸入——掃描的PDF和原生PDF均可直接輸入IronTesseract.Read,無需單獨的渲染步驟
  • 設計為執行緒安全——單個IronTesseract實例處理併發請求; Parallel.ForEach 工作時無需額外同步
  • 125+語言——作為獨立的NuGet包分發(IronOcr.Languages.French等),無需管理tessdata資料夾
  • 結構化結果存取——.Barcodes作為具有坐標資料的型別化集合

定價是永久的:$999 Lite,$1,499 Plus,$2,999 Professional,$5,999 Unlimited。 所有功能在每一級別都可用; 區別在於涵蓋的開發者數量和項目數量。

功能比較

功能 GdPicture.NET IronOCR
價格模型 基於插件的永久 + 20%/年維護 固定永久,年度更新可選
起步成本(從PDF中進行OCR) 需要多個插件(聯繫GdPicture了解價格) $2,999(一個包,所有功能)
資源管理 整數ID的手動跟蹤和釋放 IDisposable / using 語句
命名空間穩定性 命名空間中的版號(GdPicture14 與版本無關(IronOcr
PDF OCR 需要單獨的PDF插件 內建,無需額外授權
安裝 多個NuGet包 + 外部資源資料夾 單個NuGet,無外部檔案
跨平台 Windows, Linux, macOS Windows, Linux, macOS, Docker, AWS, Azure

詳細功能比較

功能 GdPicture.NET IronOCR
設置和安裝
NuGet安裝 需要多個包 dotnet add package IronOcr
外部資源資料夾 必需(tessdata風格的語言檔案) 不需要(捆綁)
授權激活 LicenseManager.RegisterKEY() IronOcr.License.LicenseKey = "..."
組件初始化 PDF OCR工作流程的3–4個類 new IronTesseract()
命名空間的重大升級 必須更新每個源文件 不需要更改
OCR能力
圖像OCR
PDF OCR 是(需要PDF插件) 是(內建)
受密碼保護的 PDF
多頁PDF 手動頁面迴圈 + ID清理 自動
可搜尋的 PDF 輸出 OcrPage + SaveToFile result.SaveAsSearchablePdf()
hOCR匯出 不是
預處理
糾偏 通過GdPictureDocumentImaging插件 input.Deskew()
噪音去除 通過GdPictureDocumentImaging插件 input.DeNoise()
對比增強 通過GdPictureImaging input.Contrast()
二值化 通過GdPictureImaging input.Binarize()
DPI增強 通過GdPictureImaging input.EnhanceResolution(300)
自動修正(無需程式碼) 不是 是(內建於Read中)
資源管理
記憶體管理模型 整數ID的手動跟蹤 IDisposable / GC
記憶體洩漏風險 高(遺失ReleaseGdPictureImage) 無(使用語句)
執行緒安全性 手動實例管理 設計上的執行緒安全
結果和資料
純文字 GetOCRResultText(resultId) result.Text
信心分數 GetOCRResultConfidence(resultId) result.Confidence
字級資料 巢狀的塊/行/詞迭代 result.Words 集合
坐標存取 通過塊/行/詞索引調用 直接.X, .Y, .Width, .Height
OCR期間的條碼讀取 通過單獨的條碼插件 ocr.Configuration.ReadBarCodes = true
語言
語言數量 基於Tesseract,類似的覆蓋範圍 125+ 透過NuGet包
語言分發 資源文件資料夾 NuGet包
一次傳遞多語言 是(AddSecondaryLanguage
部署
Docker 支持 支援(有文件記載)
Linux 支持 支持
AWS Lambda 可能 有文件指南
Azure應用服務 可能 有文件指南

圖像 ID 生命週期與可處理的 OcrInput

GdPicture和IronOCR之間最重要的架構差異不是功能差距——而是每個程式庫對其處理的圖像的内存的處理方式。

GdPicture方法

GdPicture中的每個圖像在運行時管理的池中存在為一個整數句柄。 通過載入圖像獲取句柄,將該整數傳遞給OCR和其他操作,然後在完成時釋放它。 遵循時這種模式是明確且正確的。 問題在於很容易出錯,後果是不受限的記憶體增長。

隨機存取記憶體在PDF OCR工作流程中最清楚地顯示出風險。 每次對pdf.RenderPageToGdPictureImage()的調用都會在記憶體中分配一個新的光柵圖像,並返回一個新的整數ID。 100頁的文件會建立100個單獨的分配。 如果漏掉了一次ReleaseGdPictureImage調用,進程就會積累洩漏的記憶體:

using GdPicture14;

public string ExtractTextFromPdf(string pdfPath)
{
    var text = new StringBuilder();

    using var pdf = new GdPicturePDF();

    GdPictureStatus status = pdf.LoadFromFile(pdfPath, false);
    if (status != GdPictureStatus.OK)
        throw new Exception($"Failed to load PDF: {status}");

    int pageCount = pdf.GetPageCount();

    for (int i = 1; i <= pageCount; i++)
    {
        pdf.SelectPage(i);

        // Each page render = new memory allocation + new integer ID
        int imageId = pdf.RenderPageToGdPictureImage(200, false);

        if (imageId == 0) continue;

        try
        {
            _ocr.SetImage(imageId);
            _ocr.Language = "eng";
            string resultId = _ocr.RunOCR();

            if (!string.IsNullOrEmpty(resultId))
                text.AppendLine(_ocr.GetOCRResultText(resultId));
        }
        finally
        {
            // Without this: ~10–50MB leaked per page
            _imaging.ReleaseGdPictureImage(imageId);
        }
    }

    return text.ToString();
}
using GdPicture14;

public string ExtractTextFromPdf(string pdfPath)
{
    var text = new StringBuilder();

    using var pdf = new GdPicturePDF();

    GdPictureStatus status = pdf.LoadFromFile(pdfPath, false);
    if (status != GdPictureStatus.OK)
        throw new Exception($"Failed to load PDF: {status}");

    int pageCount = pdf.GetPageCount();

    for (int i = 1; i <= pageCount; i++)
    {
        pdf.SelectPage(i);

        // Each page render = new memory allocation + new integer ID
        int imageId = pdf.RenderPageToGdPictureImage(200, false);

        if (imageId == 0) continue;

        try
        {
            _ocr.SetImage(imageId);
            _ocr.Language = "eng";
            string resultId = _ocr.RunOCR();

            if (!string.IsNullOrEmpty(resultId))
                text.AppendLine(_ocr.GetOCRResultText(resultId));
        }
        finally
        {
            // Without this: ~10–50MB leaked per page
            _imaging.ReleaseGdPictureImage(imageId);
        }
    }

    return text.ToString();
}
Imports GdPicture14
Imports System.Text

Public Function ExtractTextFromPdf(ByVal pdfPath As String) As String
    Dim text As New StringBuilder()

    Using pdf As New GdPicturePDF()
        Dim status As GdPictureStatus = pdf.LoadFromFile(pdfPath, False)
        If status <> GdPictureStatus.OK Then
            Throw New Exception($"Failed to load PDF: {status}")
        End If

        Dim pageCount As Integer = pdf.GetPageCount()

        For i As Integer = 1 To pageCount
            pdf.SelectPage(i)

            ' Each page render = new memory allocation + new integer ID
            Dim imageId As Integer = pdf.RenderPageToGdPictureImage(200, False)

            If imageId = 0 Then Continue For

            Try
                _ocr.SetImage(imageId)
                _ocr.Language = "eng"
                Dim resultId As String = _ocr.RunOCR()

                If Not String.IsNullOrEmpty(resultId) Then
                    text.AppendLine(_ocr.GetOCRResultText(resultId))
                End If
            Finally
                ' Without this: ~10–50MB leaked per page
                _imaging.ReleaseGdPictureImage(imageId)
            End Try
        Next
    End Using

    Return text.ToString()
End Function
$vbLabelText   $csharpLabel

在多個PDF中的批處理會加劇這種情況。 每個finally中釋放它們的註釋。 這是基礎設施工作,而不是OCR工作。

IronOCR方法

IDisposable。 一個using語句保證無論方法是正常返回還是拋出,都會進行清理。 無需跟蹤的整數ID,無需初始化的單獨成像組件,PDF頁面無需外部DPI渲染步驟。

using IronOcr;

public string ExtractTextFromPdf(string pdfPath)
{
    // LoadPdf handles page rendering internally
    using var input = new OcrInput();
    input.LoadPdf(pdfPath);

    var result = new IronTesseract().Read(input);

    foreach (var page in result.Pages)
        Console.WriteLine($"Page {page.PageNumber}: {page.Text}");

    return result.Text;
    // using block exits — all internal resources released automatically
}
using IronOcr;

public string ExtractTextFromPdf(string pdfPath)
{
    // LoadPdf handles page rendering internally
    using var input = new OcrInput();
    input.LoadPdf(pdfPath);

    var result = new IronTesseract().Read(input);

    foreach (var page in result.Pages)
        Console.WriteLine($"Page {page.PageNumber}: {page.Text}");

    return result.Text;
    // using block exits — all internal resources released automatically
}
Imports IronOcr

Public Function ExtractTextFromPdf(pdfPath As String) As String
    ' LoadPdf handles page rendering internally
    Using input As New OcrInput()
        input.LoadPdf(pdfPath)

        Dim result = New IronTesseract().Read(input)

        For Each page In result.Pages
            Console.WriteLine($"Page {page.PageNumber}: {page.Text}")
        Next

        Return result.Text
        ' using block exits — all internal resources released automatically
    End Using
End Function
$vbLabelText   $csharpLabel

對於受密碼保護的PDF,參數是一個命名參數,而不需要額外狀態檢查的單獨重載:

using var input = new OcrInput();
input.LoadPdf("encrypted.pdf", Password: "secret");

var result = new IronTesseract().Read(input);
result.SaveAsSearchablePdf("searchable-output.pdf");
using var input = new OcrInput();
input.LoadPdf("encrypted.pdf", Password: "secret");

var result = new IronTesseract().Read(input);
result.SaveAsSearchablePdf("searchable-output.pdf");
Imports IronOcr

Using input As New OcrInput()
    input.LoadPdf("encrypted.pdf", Password:="secret")

    Dim result = New IronTesseract().Read(input)
    result.SaveAsSearchablePdf("searchable-output.pdf")
End Using
$vbLabelText   $csharpLabel

IronOCR PDF輸入指南涵蓋了包括頁面範圍選擇在內的其他選項。 對於已經熟悉OcrInput無需建立新的心理模型。

插件捆绑成本

對於一個從圖像和PDF中提取文字並生成可搜索輸出的伺服器應用,GdPicture授權堆疊需要多個插件。 聯繫GdPicture以獲取Professional核心授權、OCR插件和PDF插件的當前定價。 年度維護費用(通常佔總授權成本的一個比例)隨著時間的推移累積。

IronOCR Professional在單個包中涵蓋相同的工作流程:

IronOCR Professional:              $professionalLicense(一次性)
可選年度更新:           $plusLicense/年

3年的總費用(永久,不更新):$professionalLicense

多年的成本差異可能會根據更新偏好進行顯著變化。 這種差距的存在是因為GdPicture的插件模型是針對整個文件成像平台而定價的,而不是針對OCR專注的工作負載。 在最常見的OCR輸入格式中,使其可用的PDF插件是必需的。

評估GdPicture的團隊為OCR支付了在OCR專注的待辦歌單中很少出現的功能:TWAIN/WIA掃描器整合、DICOM醫療影像、註釋和編輯工作流程,以及超出文字提取的高級PDF編輯。 參見IronOCR許可頁面,所有功能在每層均可用的定價模型——無插件,無附加項,無逐功能授權決策。

API複雜性和預處理

GdPicture通過GdPictureDocumentImaging插件(去斜、去斑、邊框移除)公開預處理。 在進行OCR之前應用去斜需要文件成像插件授權,對於處理可變質量掃描文件的工作流程創造了堆疊中的第三個成本。

GdPicture方法

低質量掃描PDF的完整工作流程——載入、預處理、OCR每頁、釋放——跨越了三個組件類,並需要在每個步驟中進行仔細的狀態檢查:

using GdPicture14;

public void CreateSearchablePdf(string inputPdf, string outputPdf)
{
    using var pdf = new GdPicturePDF();

    GdPictureStatus status = pdf.LoadFromFile(inputPdf, false);
    if (status != GdPictureStatus.OK)
        throw new Exception($"Load failed: {status}");

    int pageCount = pdf.GetPageCount();

    for (int i = 1; i <= pageCount; i++)
    {
        pdf.SelectPage(i);

        // OcrPage adds text layer to each page
        // Requires: OCR plugin + PDF plugin + resource folder path
        GdPictureStatus ocrStatus = pdf.OcrPage(
            "eng",
            @"C:\GdPicture\Resources\OCR",  // 外部資源資料夾 required
            "",
            200
        );

        if (ocrStatus != GdPictureStatus.OK)
            Console.WriteLine($"Warning: Page {i} OCR failed: {ocrStatus}");
    }

    pdf.SaveToFile(outputPdf, true);
}
using GdPicture14;

public void CreateSearchablePdf(string inputPdf, string outputPdf)
{
    using var pdf = new GdPicturePDF();

    GdPictureStatus status = pdf.LoadFromFile(inputPdf, false);
    if (status != GdPictureStatus.OK)
        throw new Exception($"Load failed: {status}");

    int pageCount = pdf.GetPageCount();

    for (int i = 1; i <= pageCount; i++)
    {
        pdf.SelectPage(i);

        // OcrPage adds text layer to each page
        // Requires: OCR plugin + PDF plugin + resource folder path
        GdPictureStatus ocrStatus = pdf.OcrPage(
            "eng",
            @"C:\GdPicture\Resources\OCR",  // 外部資源資料夾 required
            "",
            200
        );

        if (ocrStatus != GdPictureStatus.OK)
            Console.WriteLine($"Warning: Page {i} OCR failed: {ocrStatus}");
    }

    pdf.SaveToFile(outputPdf, true);
}
Imports GdPicture14

Public Sub CreateSearchablePdf(inputPdf As String, outputPdf As String)
    Using pdf As New GdPicturePDF()

        Dim status As GdPictureStatus = pdf.LoadFromFile(inputPdf, False)
        If status <> GdPictureStatus.OK Then
            Throw New Exception($"Load failed: {status}")
        End If

        Dim pageCount As Integer = pdf.GetPageCount()

        For i As Integer = 1 To pageCount
            pdf.SelectPage(i)

            ' OcrPage adds text layer to each page
            ' Requires: OCR plugin + PDF plugin + resource folder path
            Dim ocrStatus As GdPictureStatus = pdf.OcrPage(
                "eng",
                "C:\GdPicture\Resources\OCR",  ' 外部資源資料夾 required
                "",
                200
            )

            If ocrStatus <> GdPictureStatus.OK Then
                Console.WriteLine($"Warning: Page {i} OCR failed: {ocrStatus}")
            End If
        Next

        pdf.SaveToFile(outputPdf, True)
    End Using
End Sub
$vbLabelText   $csharpLabel

ResourceFolder路徑並非可選。 它必須在運行時解析為包含C:\GdPicture\Resources\OCR時或者將應用部署到Linux或者Docker映像不包括該目錄結構時在生產中失敗。 除錯這些失敗通常意味著追踪通用GdPictureStatus錯誤程式碼,這些錯誤程式碼對根本原因說不了多少。

IronOCR方法

IronOCR中的等效工作流程——包括預處理去斜和去噪——是五行:

using IronOcr;

public void CreateSearchablePdf(string inputPdf, string outputPdf)
{
    var ocr = new IronTesseract();

    using var input = new OcrInput();
    input.LoadPdf(inputPdf);
    input.Deskew();   //不是separate plugin required
    input.DeNoise();

    var result = ocr.Read(input);
    result.SaveAsSearchablePdf(outputPdf);
}
using IronOcr;

public void CreateSearchablePdf(string inputPdf, string outputPdf)
{
    var ocr = new IronTesseract();

    using var input = new OcrInput();
    input.LoadPdf(inputPdf);
    input.Deskew();   //不是separate plugin required
    input.DeNoise();

    var result = ocr.Read(input);
    result.SaveAsSearchablePdf(outputPdf);
}
Imports IronOcr

Public Sub CreateSearchablePdf(inputPdf As String, outputPdf As String)
    Dim ocr As New IronTesseract()

    Using input As New OcrInput()
        input.LoadPdf(inputPdf)
        input.Deskew() '不是separate plugin required
        input.DeNoise()

        Dim result = ocr.Read(input)
        result.SaveAsSearchablePdf(outputPdf)
    End Using
End Sub
$vbLabelText   $csharpLabel

英語語言支援捆綁在NuGet包中。 其他語言作為NuGet包安裝(.traineddata文件在文件系統路徑中。 影像質量校正指南影像方向校正指南涵蓋了在OcrInput上可用的完整集預處理選項。

對於置信感知處理——例如,在將結果寫入資料庫之前過濾低於閾值的結果——結果物件直接暴露置信度:

var result = new IronTesseract().Read("scanned.jpg");
Console.WriteLine($"Confidence: {result.Confidence}%");

// Per-word confidence for fine-grained filtering
var highConfidenceWords = result.Words
    .Where(w => w.Confidence > 85)
    .Select(w => w.Text);
var result = new IronTesseract().Read("scanned.jpg");
Console.WriteLine($"Confidence: {result.Confidence}%");

// Per-word confidence for fine-grained filtering
var highConfidenceWords = result.Words
    .Where(w => w.Confidence > 85)
    .Select(w => w.Text);
Imports System
Imports System.Linq

Dim result = (New IronTesseract()).Read("scanned.jpg")
Console.WriteLine($"Confidence: {result.Confidence}%")

' Per-word confidence for fine-grained filtering
Dim highConfidenceWords = result.Words _
    .Where(Function(w) w.Confidence > 85) _
    .Select(Function(w) w.Text)
$vbLabelText   $csharpLabel

GdPicture需要三個巢狀迴圈——塊、行、詞——才能達到相同的資料,每個層次都以基於索引的方法調用(GetOCRResultBlockLineWordConfidence(resultId, b, l, w))。 置信度分數如何做展示了結構化存取模型的常用範例。

結構化資料和結果存取

提取每個詞的坐標和置信度值是文件理解工作流程的常見需求——發票欄位提取、表單處理和佈局分析都需要它。

GdPicture方法

GdPicture從GdPictureOCR實例上的方法調用來查詢該ID。 達到每個詞的置信度需要遍歷三個巢狀層次:

using GdPicture14;

public List<(string word, float confidence)> GetWordConfidences(int imageId)
{
    var words = new List<(string, float)>();

    _ocr.SetImage(imageId);
    _ocr.Language = "eng";
    string resultId = _ocr.RunOCR();

    int blockCount = _ocr.GetOCRResultBlockCount(resultId);

    for (int b = 0; b < blockCount; b++)
    {
        int lineCount = _ocr.GetOCRResultBlockLineCount(resultId, b);

        for (int l = 0; l < lineCount; l++)
        {
            int wordCount = _ocr.GetOCRResultBlockLineWordCount(resultId, b, l);

            for (int w = 0; w < wordCount; w++)
            {
                string word = _ocr.GetOCRResultBlockLineWordText(resultId, b, l, w);
                float conf = _ocr.GetOCRResultBlockLineWordConfidence(resultId, b, l, w);
                words.Add((word, conf));
            }
        }
    }

    return words;
}
using GdPicture14;

public List<(string word, float confidence)> GetWordConfidences(int imageId)
{
    var words = new List<(string, float)>();

    _ocr.SetImage(imageId);
    _ocr.Language = "eng";
    string resultId = _ocr.RunOCR();

    int blockCount = _ocr.GetOCRResultBlockCount(resultId);

    for (int b = 0; b < blockCount; b++)
    {
        int lineCount = _ocr.GetOCRResultBlockLineCount(resultId, b);

        for (int l = 0; l < lineCount; l++)
        {
            int wordCount = _ocr.GetOCRResultBlockLineWordCount(resultId, b, l);

            for (int w = 0; w < wordCount; w++)
            {
                string word = _ocr.GetOCRResultBlockLineWordText(resultId, b, l, w);
                float conf = _ocr.GetOCRResultBlockLineWordConfidence(resultId, b, l, w);
                words.Add((word, conf));
            }
        }
    }

    return words;
}
Imports GdPicture14

Public Function GetWordConfidences(imageId As Integer) As List(Of (word As String, confidence As Single))
    Dim words As New List(Of (String, Single))()

    _ocr.SetImage(imageId)
    _ocr.Language = "eng"
    Dim resultId As String = _ocr.RunOCR()

    Dim blockCount As Integer = _ocr.GetOCRResultBlockCount(resultId)

    For b As Integer = 0 To blockCount - 1
        Dim lineCount As Integer = _ocr.GetOCRResultBlockLineCount(resultId, b)

        For l As Integer = 0 To lineCount - 1
            Dim wordCount As Integer = _ocr.GetOCRResultBlockLineWordCount(resultId, b, l)

            For w As Integer = 0 To wordCount - 1
                Dim word As String = _ocr.GetOCRResultBlockLineWordText(resultId, b, l, w)
                Dim conf As Single = _ocr.GetOCRResultBlockLineWordConfidence(resultId, b, l, w)
                words.Add((word, conf))
            Next
        Next
    Next

    Return words
End Function
$vbLabelText   $csharpLabel

這沒有錯——資料是可存取的。 但它需要理解和維護一個三維索引到需要詞級資料的每個項目的結果結構中。

IronOCR方法

.Words。 LINQ直接在其上工作:

using IronOcr;

var result = new IronTesseract().Read("invoice.jpg");

// All words with position and confidence
foreach (var word in result.Words)
{
    Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) — {word.Confidence:P0}");
}

// Lines, paragraphs, and pages follow the same pattern
foreach (var line in result.Lines)
    Console.WriteLine(line.Text);

foreach (var page in result.Pages)
    Console.WriteLine($"Page {page.PageNumber}: {page.Text.Length} characters");
using IronOcr;

var result = new IronTesseract().Read("invoice.jpg");

// All words with position and confidence
foreach (var word in result.Words)
{
    Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) — {word.Confidence:P0}");
}

// Lines, paragraphs, and pages follow the same pattern
foreach (var line in result.Lines)
    Console.WriteLine(line.Text);

foreach (var page in result.Pages)
    Console.WriteLine($"Page {page.PageNumber}: {page.Text.Length} characters");
Imports IronOcr

Dim result = New IronTesseract().Read("invoice.jpg")

' All words with position and confidence
For Each word In result.Words
    Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) — {word.Confidence:P0}")
Next

' Lines, paragraphs, and pages follow the same pattern
For Each line In result.Lines
    Console.WriteLine(line.Text)
Next

For Each page In result.Pages
    Console.WriteLine($"Page {page.PageNumber}: {page.Text.Length} characters")
Next
$vbLabelText   $csharpLabel

基於區域的OCR——從文件的一個定義的矩形提取文字——同樣直接:

var region = new CropRectangle(0, 0, 600, 100); // header area

using var input = new OcrInput();
input.LoadImage("invoice.jpg", region);

var headerText = new IronTesseract().Read(input).Text;
var region = new CropRectangle(0, 0, 600, 100); // header area

using var input = new OcrInput();
input.LoadImage("invoice.jpg", region);

var headerText = new IronTesseract().Read(input).Text;
Imports IronOcr

Dim region As New CropRectangle(0, 0, 600, 100) ' header area

Using input As New OcrInput()
    input.LoadImage("invoice.jpg", region)

    Dim headerText As String = New IronTesseract().Read(input).Text
End Using
$vbLabelText   $csharpLabel

讀取結果指南基於區域的OCR指南顯示了這些模式如何擴展到多頁文件和結構化欄位提取的工作流程。

API 地圖參考

GdPicture.NET IronOCR 等效
LicenseManager.RegisterKEY("key") IronOcr.License.LicenseKey = "key"
new GdPictureImaging() 不需要——由內部處理
new GdPictureOCR() new IronTesseract()
new GdPicturePDF() 不需要——由OcrInput.LoadPdf()處理
ocr.ResourceFolder = path 不需要——資源捆綁在NuGet中
imaging.CreateGdPictureImageFromFile(path) input.LoadImage(path)OcrInput
imaging.ReleaseGdPictureImage(imageId) using var input = new OcrInput() ——自動的
ocr.SetImage(imageId) 不需要——OcrInput 握住圖像
ocr.Language = "eng" ocr.Language = OcrLanguage.English
ocr.RunOCR()resultId ocr.Read(input)OcrResult
ocr.GetOCRResultText(resultId) result.Text
ocr.GetOCRResultConfidence(resultId) result.Confidence
ocr.GetOCRResultBlockLineWordText(resultId, b, l, w) result.Words[i].Text
ocr.GetOCRResultBlockLineWordConfidence(resultId, b, l, w) result.Words[i].Confidence
pdf.LoadFromFile(path, false)GdPictureStatus input.LoadPdf(path) ——在失敗時拋出
pdf.LoadFromFile(path, password) input.LoadPdf(path, Password: password)
pdf.RenderPageToGdPictureImage(200, false) 不需要——IronOCR內部渲染
pdf.SelectPage(i) 不需要——預設情況下處理所有頁面
pdf.GetPageCount() 不需要——或result.Pages.Count
pdf.OcrPage("eng", resourcePath, "", 200) result.SaveAsSearchablePdf(outputPath)
pdf.SaveToFile(outputPath, true) result.SaveAsSearchablePdf(outputPath)
imaging.GetStat() / ocr.GetStat() 標準.NET異常
GdPictureStatus.OK 每次調用後檢查 不需要——例外正常傳播
using GdPicture14; using IronOcr;

當團隊考慮從GdPicture.NET遷移到IronOCR

OCR是唯一的要求

實施文件引入流水線的團隊——處理掃描發票、醫療表單處理、合同文字提取——經常評估GdPicture,因為它出現在企業軟體目錄中,與LEADTOOLS和Kofax一起。 一旦插件依賴表變得清晰,情況就會改變。 如果需要PDF輸入,則PDF插件不可選。 如果需要預處理,則文件成像插件不可選。 需要從具有去斜校正的掃描PDF中進行OCR的團隊需要三個插件授權,其Professional入門成本相當可觀。當需求是文字提取,且GdPicture功能列表中沒有其他需要的功能時,這種定價代表了純粹的開銷。 IronOCR在$2,999Professional涵蓋了相同的工作流程——圖像輸入,PDF輸入,預處理,可搜索的PDF輸出——從一個包中,無需做出插件決策。

生產中的記憶體洩漏事件

在高吞吐量的文件處理服務中,整數ID的生命週期很容易出現生產事故。 在負載下處理上傳PDF的網路API端點最終會發生圖像釋放調用未達到的程式碼路徑——錯誤分支中的早期返回,清理塊之前未處理的異常,或者只是新人開發者對模式不熟,加了一個幫助方法,將整數圖像句柄作為參數,忘記釋放它。 記憶體增長,服務變慢,根本原因在堆轉儲中並不明顯。除錯過這些事件的團隊通常需要一個運行時處理清理的模型。IronOCR中的標準處置模式就是這種模型——結構化清理由編譯器強制,而不是由開發人員在每個調用點進行紀律。

版本升級摩擦

GdPicture將主要版本號嵌入其命名空間中。 從版本14升至版本15需要更新每個參考GdPicture類的源文件中的命名空間指令。 在一個有OCR、PDF處理和圖像處理分佈在幾十個服務和實用程式類的應用中,這是一項非平凡的遷移任務——它不提供任何功能好處。 每個現代的.NET程式庫從Microsoft.EntityFrameworkCore到Newtonsoft.Json都使用與版本無關的命名空間,通過NuGet包版本號管理版本。 IronOCR遵循該慣例:相同的命名空間導入適用於從版本1到目前的版本。

微服務和容器部署

GdPicture OCR要求在運行時在特定路徑上存在包含語言資料文件的外部資源資料夾。在容器化部署中,這意味著要麼將這些文件烘焙到Docker映像中,要麼掛載一個卷,要麼配置一個啟動腳本來下載它們。 典型的結果是Docker映像比必要的大幾百兆字節,這一部署清單項目被遺漏,並且在乾淨的容器重啟時,由於卷未掛載而導致生產故障。 IronOCR將英語支援捆綁在包中; 附加語言作為NuGet包安裝,並且是構建輸出的一部分。 容器從還原步驟中獲得它所需的東西,無需配置路徑。 Docker部署指南Linux部署指南涵蓋了每個目標環境的具體配置。

沒有文件成像專業知識的開發團隊

GdPicture占地面積大是必要的——它涵蓋了完整的文件成像平台。 對於加入團隊來維護OCR微服務的開發者而言,理解成像組件、OCR組件、PDF組件、整數ID生命周期、狀態返回程式碼處理和資源資料夾配置是初始的一個高投資。 IronOCR的OCR表面面積是三個類別:引擎、輸入容器和結果物件。 這是90%用例的整個心理模型。 讓一個新開發者上手意味著指引他們IronTesseract設置而不是閱讀多模塊的SDK指南。

常見的遷移考量

替換組件初始化

GdPicture需要四步初始化順序:通過GdPictureOCR,並設置資源資料夾路徑。 IronOCR將這一步驟減少為一個屬性分配,該屬性屬於Startup.cs

// Remove
LicenseManager lm = new LicenseManager();
lm.RegisterKEY("GDPICTURE-LICENSE-KEY");
_imaging = new GdPictureImaging();
_ocr = new GdPictureOCR();
_ocr.ResourceFolder = @"C:\GdPicture\Resources\OCR";

// Replace with
IronOcr.License.LicenseKey = "IRONOCR-LICENSE-KEY";
// IronTesseract instances are instantiated per-use or as a singleton
// Remove
LicenseManager lm = new LicenseManager();
lm.RegisterKEY("GDPICTURE-LICENSE-KEY");
_imaging = new GdPictureImaging();
_ocr = new GdPictureOCR();
_ocr.ResourceFolder = @"C:\GdPicture\Resources\OCR";

// Replace with
IronOcr.License.LicenseKey = "IRONOCR-LICENSE-KEY";
// IronTesseract instances are instantiated per-use or as a singleton
' Remove
Dim lm As New LicenseManager()
lm.RegisterKEY("GDPICTURE-LICENSE-KEY")
_imaging = New GdPictureImaging()
_ocr = New GdPictureOCR()
_ocr.ResourceFolder = "C:\GdPicture\Resources\OCR"

' Replace with
IronOcr.License.LicenseKey = "IRONOCR-LICENSE-KEY"
' IronTesseract instances are instantiated per-use or as a singleton
$vbLabelText   $csharpLabel

消除圖像ID跟蹤

每次ReleaseGdPictureImage調用在現有的程式碼庫中。 這些清理調用在IronOCR中完全移除——OcrInput處理處置。 遷移是機械性的:找到每一個using var input = new OcrInput()內,並用IronOCR等效方法調用替換GdPicture方法調用。

// Remove
int imageId = _imaging.CreateGdPictureImageFromFile(path);
if (imageId == 0) throw new Exception(_imaging.GetStat().ToString());
_ocr.SetImage(imageId);
_ocr.Language = "eng";
string resultId = _ocr.RunOCR();
if (string.IsNullOrEmpty(resultId)) throw new Exception(_ocr.GetStat().ToString());
string text = _ocr.GetOCRResultText(resultId);
_imaging.ReleaseGdPictureImage(imageId);

// Replace with
using var input = new OcrInput();
input.LoadImage(path);
var result = new IronTesseract().Read(input);
string text = result.Text;
// Remove
int imageId = _imaging.CreateGdPictureImageFromFile(path);
if (imageId == 0) throw new Exception(_imaging.GetStat().ToString());
_ocr.SetImage(imageId);
_ocr.Language = "eng";
string resultId = _ocr.RunOCR();
if (string.IsNullOrEmpty(resultId)) throw new Exception(_ocr.GetStat().ToString());
string text = _ocr.GetOCRResultText(resultId);
_imaging.ReleaseGdPictureImage(imageId);

// Replace with
using var input = new OcrInput();
input.LoadImage(path);
var result = new IronTesseract().Read(input);
string text = result.Text;
Imports System

' Remove
Dim imageId As Integer = _imaging.CreateGdPictureImageFromFile(path)
If imageId = 0 Then Throw New Exception(_imaging.GetStat().ToString())
_ocr.SetImage(imageId)
_ocr.Language = "eng"
Dim resultId As String = _ocr.RunOCR()
If String.IsNullOrEmpty(resultId) Then Throw New Exception(_ocr.GetStat().ToString())
Dim text As String = _ocr.GetOCRResultText(resultId)
_imaging.ReleaseGdPictureImage(imageId)

' Replace with
Using input As New OcrInput()
    input.LoadImage(path)
    Dim result = New IronTesseract().Read(input)
    Dim text As String = result.Text
End Using
$vbLabelText   $csharpLabel

調整錯誤處理

GdPicture使用GdPictureStatus返回程式碼,在每次重要操作後檢查。 IronOCR拋出標準.NET異常。 遷移用FileNotFoundException從圖像中讀取文字教學包含了常見場景的錯誤處理模式。

語言包部署

GdPicture語言文件是文件系統資料夾中的.traineddata文件。 IronOCR語言包是NuGet包。 遷移從部署清單中移除資源文件夾,並為每種所需的語言新增NuGet包引用:

# Remove filesystem dependency for each language
# Add NuGet package instead
dotnet add package IronOcr.Languages.French
dotnet add package IronOcr.Languages.German
dotnet add package IronOcr.Languages.ChineseSimplified
# Remove filesystem dependency for each language
# Add NuGet package instead
dotnet add package IronOcr.Languages.French
dotnet add package IronOcr.Languages.German
dotnet add package IronOcr.Languages.ChineseSimplified
SHELL

多語言指南涵蓋多種語言文件的配置,其中主語言和輔助語言均指定在IronTesseract實例上。

其他IronOCR功能

在本比較中涵蓋的領域之外,IronOCR包括純OCR上下文中不具備直接GdPicture對應的功能:

  • 異步OCR——ReadAsync 用於 ASP.NET Core 請求處理程式和後台服務中的非阻塞操作
  • 頁面旋轉檢測——無需手動預處理即可自動檢測和校正旋轉頁面
  • 進度跟蹤——面向UI進度條的長時間運行批處理作業的回調型進度事件
  • 流輸入——input.LoadImage(stream) 直接接受 System.IO.Stream 避免在流水線架構中寫入臨時文件
  • 專業化文件閱讀——通過統一的IronTesseract 接口專門處理護照、車牌、MICR支票和手寫文字

.NET 相容性和未來準備

IronOCR支持.NET 8、.NET 9、.NET Standard 2.0和.NET Framework 4.6.2及更高版本。 單個NuGet包在Windows x64、Windows x86、Linux x64和macOS上完全相同地部署。 GdPicture.NET也支持跨平台目標,但其插件架構意味著Linux和容器部署必須針對每個插件的本地依賴單獨進行考量。 IronOCR的命名空間在所有主要版本更改中一直保持IronOcr,這意味著升級路徑無需在整個程式碼庫中進行查找替換操作。 隨著.NET 10在2026年底到來,IronOCR跨越連續.NET版本的相容性不損API更改的記錄為長期維護週期的應用提供了一個穩定的基礎。

結論

GdPicture.NET對於需要集中化的文件成像平台的團隊來說是一個合法的選擇——掃描器整合、PDF編輯、註釋、DICOM支援和OCR在一個SDK中,來自一個供應商。 此用例確實存在。 當這些能力中的大多數實際上在範疇內時,插件模型是有意義的。

當需求是OCR而答案是GdPicture時,錯配就出現了。 PDF插件不可分為OCR從PDF用例。 文件成像插件與預處理不可分離。 整數ID的生命週期不是可選的——它是整個SDK的基礎資源管理模型。 需要從掃描的PDF中提取文字的團隊吸收了所有這些複雜性及其所有成本,並且沒有額外的能力為他們的工作量證明其合理性。

多年來的定價差距對於單一開發者的專業工作流程來說可能是相當大的。 程式碼複雜性差距是可以衡量的:基本OCR加上清理需超過25行,而單行就可以做到。 運行差距——外部資源資料夾、版本特定的命名空間、多組件初始化——作為部署摩擦和新手入門時間顯現,而不是作為行數,但它是真實的。

IronOCR在$2,999永久提供相同的核心OCR成果——圖像文字提取、掃描PDF處理、可搜索的PDF輸出、125+語言、置信度評分、結構化資料存取——通過標準.NET模式不需維護專用的SDK知識。 對於OCR是目標而不是更廣泛文件管理平台組件的團隊來說,這是更合適的契合。

請注意GdPicture.NET、Kofax OmniPage、LEADTOOLS和Tesseract是其各自所有者的註冊商標。 本網站與Apryse、Google、Kofax、LEAD Technologies、Nutrient或ORPALIS沒有任何聯繫,未獲得其認可或支援。 所有產品名稱、標誌和品牌均為其各自所有者的財產。 比較僅供資訊用途,並反映撰寫時獲得的公開資訊。

常見問題

什麼是GdPicture.NET OCR?

GdPicture.NET OCR是一種供開發者和企業用於從圖像和文件中提取文字的OCR解決方案。它是與IronOCR一起評估的幾個OCR選擇之一,用於.NET應用程式開發。

IronOCR與GdPicture.NET OCR對於.NET開發者有何不同?

IronOCR是一個NuGet原生的.NET OCR程式庫,使用IronTesseract作為其核心引擎。與GdPicture.NET OCR相比,它提供了更簡單的部署(沒有SDK安裝程式)、統一價格及乾淨的C# API,沒有COM互操作或雲端依賴。

IronOCR比GdPicture.NET OCR更容易設置嗎?

IronOCR 通過一個單一的 NuGet 套件安裝。無需 SDK 安裝程式、複製授權文件、註冊 COM 元件或管理單獨的運行時二進位檔案。整個 OCR 引擎都打包在套件中。

GdPicture.NET OCR和IronOCR之間的準確性有何不同?

IronOCR 在標準商業文件、發票、收據和掃描表單上達到了高識別準確度。對於極度退化的文件或罕見文字,準確度會根據來源品質變化。IronOCR 包含影像預處理篩選器,以改善低品質輸入的識別。

IronOCR 支援 PDF 文字提取嗎?

是的。IronOCR 能從原生 PDF 和掃描的 PDF 圖像中一次性提取文字。它還支持多頁 TIFF 檔案、影像和流。對於掃描的 PDF,OCR 會逐頁應用並生成每頁的結果物件。

GdPicture.NET OCR的授權與IronOCR的授權有何不同?

IronOCR 採用固定費率的永久授權,無須為每頁或每次掃描支付費用。處理大量文件的組織無論數量多少都支付相同的授權費用。詳細資訊和批量定價在 IronOCR 授權頁面上。

IronOCR 支援哪些語言?

IronOCR 透過單獨的 NuGet 語言包支持 127 種語言。新增一種語言只需一個 'dotnet add package IronOcr.Languages.{Language}' 命令。無需手動放置文件或配置路徑。

如何在.NET專案中安裝IronOCR?

通過 NuGet 安裝:在套件管理員控制台或 CLI 中分別使用 'Install-Package IronOcr' 或 'dotnet add package IronOcr'。其他語言包也是這樣安裝的。無需本地 SDK 安裝程式。

IronOCR適合用於Docker及容器化部署,這是GdPicture.NET無法實現的嗎?

是的。IronOCR 通過其 NuGet 載於 Docker 容器中運行。授權金鑰通過環境變數設置。無需授權文件、SDK 路徑或量掛載來執行 OCR 引擎。

與GdPicture.NET相比,我能在購買之前試用IronOCR嗎?

是的。IronOCR 試用模式中處理文件並在輸出上附上浮水印結果。您可以在購買授權前驗證自己文件的準確性。

IronOCR 支援條碼閱讀與文字提取嗎?

IronOCR 專注於文字提取和 OCR。對於條碼閱讀,Iron Software 提供了額外的 IronBarcode 程式庫。兩者均可個別使用或作為 Iron Suite 套件的一部分。

從GdPicture.NET OCR遷移到IronOCR容易嗎?

從GdPicture.NET OCR到IronOCR的遷移通常涉及將初始化序列替換為IronTesseract實例化,移除COM生命週期管理,以及更新API調用。大多數遷移大幅降低了程式碼的複雜性。

Kannaopat Udonpant
軟體工程師
在成為軟體工程師之前,Kannapat在日本北海道大學完成了環境資源博士學位。在攻讀學位期間,Kannapat還成為車輛機器人實驗室的一員,該實驗室隸屬於生產工程系。在2022年,他憑藉C#技能加入了Iron Software的工程團隊,專注於IronPDF。Kannapat珍視他的工作,因為他能直接向撰寫大部分IronPDF程式碼的開發者學習。除了同儕學習,Kannapat還喜歡在Iron Software工作的社交方面。不寫程式碼或文件時,Kannapat通常在他的PS5上玩遊戲或重看The Last of Us。

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話