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);
}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處理多頁的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,399 Professional,$4,799 Unlimited。 所有功能在每一級別都可用; 區別在於涵蓋的開發者數量和項目數量。
功能比較
| 功能 | GdPicture.NET | IronOCR |
|---|---|---|
| 價格模型 | 基於插件的永久 + 20%/年維護 | 固定永久,年度更新可選 |
| 起步成本(從PDF中進行OCR) | 需要多個插件(聯繫GdPicture了解價格) | $2,399(一個包,所有功能) |
| 資源管理 | 整數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();
}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在多個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
}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對於受密碼保護的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 UsingIronOCR 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);
}
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);
}
英語語言支援捆綁在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);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)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;
}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這沒有錯——資料是可存取的。 但它需要理解和維護一個三維索引到需要詞級資料的每個項目的結果結構中。
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");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基於區域的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;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讀取結果指南和基於區域的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,399Professional涵蓋了相同的工作流程——圖像輸入,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
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消除圖像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;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調整錯誤處理
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
多語言指南涵蓋多種語言文件的配置,其中主語言和輔助語言均指定在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,399永久提供相同的核心OCR成果——圖像文字提取、掃描PDF處理、可搜索的PDF輸出、125+語言、置信度評分、結構化資料存取——通過標準.NET模式不需維護專用的SDK知識。 對於OCR是目標而不是更廣泛文件管理平台組件的團隊來說,這是更合適的契合。
