IronOCR 和 Nanonets OCR 之間的比較
AWS Textract的每頁定價模型在低量時可能看起來較便宜,但在大規模下成本會無限倍增。 您應用程式處理的每一份文件都會離開您的網路、進入Amazon資料中心、由Amazon基礎架構處理,帳單則會無限累積。 對於評估.NET OCR選項的團隊來說,問題不僅僅是Textract是否能產生準確的結果──它確實能──還有每頁成本模型、 必須的雲端傳輸,以及多頁文件的非同步輪詢架構是否符合您應用程式的實際需求。
了解AWS Textract
AWS Textract是Amazon的文件分析管理服務,可透過AWSSDK.Textract NuGet套件在.NET上使用AWS SDK存取。 它以雲端API形式運行:您的應用程式將文件資料傳送至Amazon的基礎架構並接收結構化結果。 該服務需要AWS帳戶、具有Textract許可權的IAM憑證,以及每次OCR操作的網際網路連線。
Textract提供幾種不同的分析模式,每種模式的定價各不相同:
- DetectDocumentText: 基本文字擷取(查看AWS Textract 定價了解當前每頁費用)
- AnalyzeDocument(表格): 結構化表格擷取,費用高於基本文字
- AnalyzeDocument(表單): 鍵值對表單擷取,費用高於表格擷取
- AnalyzeExpense: 發票和收據解析,每頁費用0.01美元
- AnalyzeID: 身份文件擷取,每頁費用0.025美元
- StartDocumentTextDetection / StartDocumentAnalysis: 任一多頁PDF必需的異步API,需使用S3中繼桶、工作輪詢及結果分頁
結果模型使用平面列表的Block物件,其中包含必須預先遍歷以重建表格、表單或任何結構化輸出的關聯ID。 簡單的表格擷取需要遍歷BlockType.WORD塊。 這種關聯圖模型處理複雜的文件結構,但並不輕量。
S3-非同步管道
單圖像OCR透過DetectDocumentTextAsync可在請求中直接傳遞文件位元組。多頁PDF則無法。 任何PDF都需要完整的異步管道:
// AWS Textract: 多頁PDF requires S3 + async job
public async Task<string> ProcessPdfAsync(string pdfPath)
{
// Step 1: Upload to S3 — credentials for two services required
var key = $"uploads/{Guid.NewGuid()}.pdf";
using (var fileStream = File.OpenRead(pdfPath))
{
await _s3Client.PutObjectAsync(new PutObjectRequest
{
BucketName = _bucketName,
Key = key,
InputStream = fileStream
});
}
try
{
// Step 2: Start async Textract job
var startResponse = await _textractClient.StartDocumentTextDetectionAsync(
new StartDocumentTextDetectionRequest
{
DocumentLocation = new DocumentLocation
{
S3Object = new S3Object { Bucket = _bucketName, Name = key }
}
});
var jobId = startResponse.JobId;
// Step 3: Poll every 5 seconds until complete
GetDocumentTextDetectionResponse getResponse;
do
{
await Task.Delay(5000);
getResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId });
} while (getResponse.JobStatus == JobStatus.IN_PROGRESS);
if (getResponse.JobStatus != JobStatus.SUCCEEDED)
throw new Exception($"Textract job failed: {getResponse.StatusMessage}");
// Step 4: Paginate through result blocks
var allText = new StringBuilder();
string nextToken = null;
do
{
var pageResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest
{
JobId = jobId,
NextToken = nextToken
});
foreach (var block in pageResponse.Blocks.Where(b => b.BlockType == BlockType.LINE))
allText.AppendLine(block.Text);
nextToken = pageResponse.NextToken;
} while (nextToken != null);
return allText.ToString();
}
finally
{
// Step 5: 總是需要 clean up S3
await _s3Client.DeleteObjectAsync(_bucketName, key);
}
}
// AWS Textract: 多頁PDF requires S3 + async job
public async Task<string> ProcessPdfAsync(string pdfPath)
{
// Step 1: Upload to S3 — credentials for two services required
var key = $"uploads/{Guid.NewGuid()}.pdf";
using (var fileStream = File.OpenRead(pdfPath))
{
await _s3Client.PutObjectAsync(new PutObjectRequest
{
BucketName = _bucketName,
Key = key,
InputStream = fileStream
});
}
try
{
// Step 2: Start async Textract job
var startResponse = await _textractClient.StartDocumentTextDetectionAsync(
new StartDocumentTextDetectionRequest
{
DocumentLocation = new DocumentLocation
{
S3Object = new S3Object { Bucket = _bucketName, Name = key }
}
});
var jobId = startResponse.JobId;
// Step 3: Poll every 5 seconds until complete
GetDocumentTextDetectionResponse getResponse;
do
{
await Task.Delay(5000);
getResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId });
} while (getResponse.JobStatus == JobStatus.IN_PROGRESS);
if (getResponse.JobStatus != JobStatus.SUCCEEDED)
throw new Exception($"Textract job failed: {getResponse.StatusMessage}");
// Step 4: Paginate through result blocks
var allText = new StringBuilder();
string nextToken = null;
do
{
var pageResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest
{
JobId = jobId,
NextToken = nextToken
});
foreach (var block in pageResponse.Blocks.Where(b => b.BlockType == BlockType.LINE))
allText.AppendLine(block.Text);
nextToken = pageResponse.NextToken;
} while (nextToken != null);
return allText.ToString();
}
finally
{
// Step 5: 總是需要 clean up S3
await _s3Client.DeleteObjectAsync(_bucketName, key);
}
}
Imports System
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Imports Amazon.S3
Imports Amazon.Textract
Imports Amazon.Textract.Model
Public Class PdfProcessor
Private _s3Client As IAmazonS3
Private _textractClient As IAmazonTextract
Private _bucketName As String
Public Async Function ProcessPdfAsync(pdfPath As String) As Task(Of String)
' Step 1: Upload to S3 — credentials for two services required
Dim key As String = $"uploads/{Guid.NewGuid()}.pdf"
Using fileStream As FileStream = File.OpenRead(pdfPath)
Await _s3Client.PutObjectAsync(New PutObjectRequest With {
.BucketName = _bucketName,
.Key = key,
.InputStream = fileStream
})
End Using
Try
' Step 2: Start async Textract job
Dim startResponse = Await _textractClient.StartDocumentTextDetectionAsync(
New StartDocumentTextDetectionRequest With {
.DocumentLocation = New DocumentLocation With {
.S3Object = New S3Object With {.Bucket = _bucketName, .Name = key}
}
})
Dim jobId As String = startResponse.JobId
' Step 3: Poll every 5 seconds until complete
Dim getResponse As GetDocumentTextDetectionResponse
Do
Await Task.Delay(5000)
getResponse = Await _textractClient.GetDocumentTextDetectionAsync(
New GetDocumentTextDetectionRequest With {.JobId = jobId})
Loop While getResponse.JobStatus = JobStatus.IN_PROGRESS
If getResponse.JobStatus <> JobStatus.SUCCEEDED Then
Throw New Exception($"Textract job failed: {getResponse.StatusMessage}")
End If
' Step 4: Paginate through result blocks
Dim allText As New StringBuilder()
Dim nextToken As String = Nothing
Do
Dim pageResponse = Await _textractClient.GetDocumentTextDetectionAsync(
New GetDocumentTextDetectionRequest With {
.JobId = jobId,
.NextToken = nextToken
})
For Each block In pageResponse.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
allText.AppendLine(block.Text)
Next
nextToken = pageResponse.NextToken
Loop While nextToken IsNot Nothing
Return allText.ToString()
Finally
' Step 5: 總是需要 clean up S3
Await _s3Client.DeleteObjectAsync(_bucketName, key)
End Try
End Function
End Class
這是可靠PDF處理的最小可行實作 — 五個不同階段、兩個AWS服務客戶端,以及finally塊中的清理邏輯。 完整的生產版本,含有適當的錯誤處理、限速重試邏輯和超時管理,運行150-300行。
理解 IronOCR
IronOCR是商業化的.NET OCR程式庫,完全在您的基礎架構上運行。 它封裝了一個優化的Tesseract 5引擎,具有自動圖像預處理、本地PDF支持,以及同步API,不需要外部服務調用或中繼步驟即可直接產生結果。
IronOCR架構的主要特點:
- 僅進行本地處理: 沒有文件資料離開運行您應用程式的機器
- 單一NuGet套件:
dotnet add package IronOcr安裝所有內容,包括本機二進制文件 - 自動預處理: 傾斜校正、降噪、對比度增強、二值化和解析度縮放會在劣質輸入上自動發生
- 本地PDF支持: 通過檔案路徑或流直接讀取PDF,無需S3中繼或異步工作
- 執行緒安全: 單個
IronTesseract實例處理多執行緒請求而不發生競爭 - 永久授權: $999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited — 一次付費,無每頁收費,無使用量計量
- 125+語言包: 作為單獨的NuGet套件安裝,本地載入,無需網路調用
功能比較
| 功能 | AWS Textract | IronOCR |
|---|---|---|
| 處理位置 | Amazon雲(強制性) | 本地 / 內部部署 |
| 多頁PDF | 需要S3 + 異步工作 | 直接同步調用 |
| 成本模型 | 每頁(聯繫AWS了解當前定價) | 永久授權,沒有每頁費用 |
| 需要網際網路 | 總是需要 | 絕不需要 |
| 憑證設置 | IAM使用者/角色 + 可選S3 | 單一授權密鑰字串 |
| 氣隙部署 | 無法實現 | 全面支持 |
| 加密PDF支持 | 不支持 | 內建(密碼參數) |
詳細功能比較
| 功能 | AWS Textract | IronOCR |
|---|---|---|
| 文字擷取 | ||
| 基本OCR(圖像) | 是 — DetectDocumentTextAsync |
是 — ocr.Read(path) |
| 多頁PDF | 需要S3 + 異步輪詢 | 直接 input.LoadPdf(path) |
| 受密碼保護的 PDF | 不支持 | input.LoadPdf(path, Password: "x") |
| 流輸入 | 是(請求中的位元組陣列) | 是 — input.LoadImage(stream) |
| 結構擷取 | ||
| 表格提取 | AnalyzeDocument + 區塊圖遍歷 |
基於單詞位置的重建 |
| 表單欄位擷取 | AnalyzeDocument + 鍵-值-集合區塊 |
區域基於CropRectangle區域 |
| 行級結果 | Block 按照 BlockType.LINE 過濾 |
result.Lines 直接集合 |
| 單詞級與座標 | Block 按照 BlockType.WORD 過濾 |
result.Words 帶有 .X, .Y, .Width |
| 置信分數 | 每區塊信心 | 每單詞和整體 result.Confidence |
| 處理模型 | ||
| 同步(圖像) | 是(僅限單頁) | 是(所有文件型別) |
| 異步 | PDF必需 | 可選 — Task.Run() 包裝器 |
| 批量處理 | 需要管理速率限制(預設5 TPS) | 無約束的 Parallel.ForEach |
| 預處理 | ||
| 自動矯正 | 未提供 | input.Deskew() |
| 噪音去除 | 內部(不可配置) | input.DeNoise() |
| 對比增強 | 內部(不可配置) | input.Contrast() |
| 解析度增強 | 內部(不可配置) | input.EnhanceResolution(300) |
| 二值化 | 內部 | input.Binarize() |
| 輸出格式 | ||
| 純文字 | 是 | 是 |
| 可搜尋的PDF | 不是 | result.SaveAsSearchablePdf(path) |
| hOCR | 不是 | result.SaveAsHocrFile(path) |
| 結構化JSON | 通過區塊序列化 | result.Words / result.Lines |
| 部署 | ||
| 內部部署 | 不是 | 是 |
| 氣隙 | 不是 | 是 |
| Docker | 是(注入的AWS憑證) | 是(無需憑證) |
| AWS Lambda | 本地 | 支持 |
| Azure | 是 | 是 |
| Linux | 是(由AWS管理) | 是 — get-started/linux/ |
| 合規性 | ||
| HIPAA | 需要與AWS簽訂BAA | 無外部處理器 |
| GDPR | 資料會穿越到AWS地... | 資料留在邊界內 |
| ITAR | 未經特殊授權禁止 | 完全在內部部署 |
| 氣隙 / CMMC-3級 | 無法實現 | 支持 |
大規模的成本
每頁定價模型是AWS Textract 的基本結構限制。 看似每頁微小的費用在真實文件工作流程中會大幅累積。
AWS Textract 方法
// Every call to this method costs money — per page, permanently
public async Task<string> DetectTextAsync(string imagePath)
{
var imageBytes = File.ReadAllBytes(imagePath); // Image leaves your network
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
var response = await _client.DetectDocumentTextAsync(request); // per-page charge
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
// Every call to this method costs money — per page, permanently
public async Task<string> DetectTextAsync(string imagePath)
{
var imageBytes = File.ReadAllBytes(imagePath); // Image leaves your network
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
var response = await _client.DetectDocumentTextAsync(request); // per-page charge
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
Imports System.IO
Imports System.Threading.Tasks
' Every call to this method costs money — per page, permanently
Public Async Function DetectTextAsync(imagePath As String) As Task(Of String)
Dim imageBytes = File.ReadAllBytes(imagePath) ' Image leaves your network
Dim request = New DetectDocumentTextRequest With {
.Document = New Document With {
.Bytes = New MemoryStream(imageBytes)
}
}
Dim response = Await _client.DetectDocumentTextAsync(request) ' per-page charge
Return String.Join(vbLf, response.Blocks _
.Where(Function(b) b.BlockType = BlockType.LINE) _
.Select(Function(b) b.Text))
End Function
請參閱AWS Textract 定價頁面的當前每頁費率。 不同API功能(基本文字檢測、表格擷取、表單擷取)有不同的費用。 包含表格和表單欄位的文件所需的費用高於基本文字檢測,並隨著聲量增長無上限且無法提前付款。
在高頁量時,三年總成本可能是相當龐大的,計費不會停止。
IronOCR方法
// One license.不是per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
// One license.不是per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
Imports IronOcr
' One license.不是per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read("document.jpg").Text
$2,999 Professional授權涵蓋10位開發者、無限專案和無限頁量。 一年後,已處理頁面的持續成本為零。 對於大量頁數的處理團隊來說,IronOCR授權相較於持續的每頁雲端費用而言很快就回本了。
IronOCR 授權頁面涵蓋層級詳情、用於用途基於計費場景的SaaS訂閱選項,以及OEM再分發條款。
資料主權與合規性
AWS Textract 的架構使得一項保證無法實現:您的文件會留在您的基礎架構中。 每次OCR操作會將文件內容傳送到Amazon的伺服器。
AWS Textract 方法
// This code sends PHI, legal documents, financial records — whatever is in
// the file — to Amazon Web Services infrastructure
public async Task<string> ProcessSensitiveDocumentAsync(string documentPath)
{
var imageBytes = File.ReadAllBytes(documentPath);
// Data crosses your security perimeter here
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
// Amazon processes it; you receive text back
var response = await _client.DetectDocumentTextAsync(request);
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
// This code sends PHI, legal documents, financial records — whatever is in
// the file — to Amazon Web Services infrastructure
public async Task<string> ProcessSensitiveDocumentAsync(string documentPath)
{
var imageBytes = File.ReadAllBytes(documentPath);
// Data crosses your security perimeter here
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
// Amazon processes it; you receive text back
var response = await _client.DetectDocumentTextAsync(request);
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
Imports System.IO
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.Textract.Model
Public Class DocumentProcessor
Private _client As AmazonTextractClient
Public Sub New(client As AmazonTextractClient)
_client = client
End Sub
' This code sends PHI, legal documents, financial records — whatever is in
' the file — to Amazon Web Services infrastructure
Public Async Function ProcessSensitiveDocumentAsync(documentPath As String) As Task(Of String)
Dim imageBytes = File.ReadAllBytes(documentPath)
' Data crosses your security perimeter here
Dim request As New DetectDocumentTextRequest With {
.Document = New Document With {
.Bytes = New MemoryStream(imageBytes)
}
}
' Amazon processes it; you receive text back
Dim response = Await _client.DetectDocumentTextAsync(request)
Return String.Join(vbLf, response.Blocks _
.Where(Function(b) b.BlockType = BlockType.LINE) _
.Select(Function(b) b.Text))
End Function
End Class
AWS提供符合範圍實體的HIPAA商業合作夥伴協議,且GovCloud 區域提供FedRAMP高級授權。 這些框架不會改變基本架構:每次操作文件都會離開您的基礎架構。 對於受ITAR控制的技術資料,這不是合規微妙之處——這是禁止的。 對於需要特定授權的CMMC-3級工作負載,雲端傳輸需要特定的授權,大多數承包商無法擁有。 對於氣隙系統——研究網路、工業控制環境、機密設施——Textract僅無效。
AWS Textract在六個區域提供:us-east-1, us-west-2, eu-west-1, eu-west-2, ap-southeast-1, 和 ap-southeast-2。 具有地區居民需求的組織在這些區域外無法合規。
IronOCR方法
// IronOCR: document bytes never leave this process
public string ProcessSensitiveDocument(string documentPath)
{
// Processes entirely on local hardware — no network call
var ocr = new IronTesseract();
return ocr.Read(documentPath).Text;
}
// IronOCR: document bytes never leave this process
public string ProcessSensitiveDocument(string documentPath)
{
// Processes entirely on local hardware — no network call
var ocr = new IronTesseract();
return ocr.Read(documentPath).Text;
}
' IronOCR: document bytes never leave this process
Public Function ProcessSensitiveDocument(documentPath As String) As String
' Processes entirely on local hardware — no network call
Dim ocr As New IronTesseract()
Return ocr.Read(documentPath).Text
End Function
因為IronOCR是本地執行的,它自然而然地適合於處理PHI的醫療工作流程、處理特權通信的法律文件系統、處理付款卡影像的金融應用,以及處理CUI的國防合同商管道。 沒有外部處理器可供審核,無需協商BAA,無需滿足資料居民約束。 合規範圍為您組織自己的基礎架構。
對於需要本地處理但部署在AWS基礎架構的團隊,IronOCR 無需依賴于Textract在AWS EC2和Lambda上運行,因為處理在你自己的AWS帳戶邊界內進行,而不是在Amazon提供的托管服務中。
非同步輪詢與同步處理
在Textract同步(單一圖像)和異步(多頁PDF)API之間的架構分裂並不是小的API細節。 它塑造了服務如何構建,錯誤如何處理,以及程式碼維護人員需要閱讀與理解多少程式碼。
AWS Textract 方法
// Full production-grade async processor for Textract PDF handling
public class TextractAsyncProcessor
{
private readonly AmazonTextractClient _textractClient;
private readonly AmazonS3Client _s3Client;
private readonly string _bucketName;
private readonly TimeSpan _pollInterval = TimeSpan.FromSeconds(5);
private readonly TimeSpan _maxWaitTime = TimeSpan.FromMinutes(10);
public async Task<DocumentResult> ProcessDocumentAsync(
string localFilePath,
CancellationToken cancellationToken = default)
{
var s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}";
try
{
// Phase 1: Upload to S3
await UploadToS3Async(localFilePath, s3Key, cancellationToken);
// Phase 2: Start Textract job
var jobId = await StartTextractJobAsync(s3Key, cancellationToken);
// Phase 3: Poll until complete (up to 10 minutes)
var pollResult = await PollForCompletionAsync(jobId, cancellationToken);
if (!pollResult.Success)
throw new Exception($"Textract job failed: {pollResult.ErrorMessage}");
// Phase 4: Retrieve paginated results
return await GetAllResultsAsync(jobId, cancellationToken);
}
finally
{
// Phase 5: S3 cleanup — must succeed or storage costs accumulate
await DeleteFromS3Async(s3Key, cancellationToken);
}
}
private async Task<(bool Success, string ErrorMessage)> PollForCompletionAsync(
string jobId, CancellationToken cancellationToken)
{
var startTime = DateTime.UtcNow;
int pollCount = 0;
while (DateTime.UtcNow - startTime < _maxWaitTime)
{
cancellationToken.ThrowIfCancellationRequested();
var response = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId }, cancellationToken);
pollCount++;
switch (response.JobStatus)
{
case JobStatus.SUCCEEDED: return (true, null);
case JobStatus.FAILED: return (false, response.StatusMessage ?? "Unknown error");
case JobStatus.IN_PROGRESS:
await Task.Delay(_pollInterval, cancellationToken);
break;
default:
throw new Exception($"Unknown job status: {response.JobStatus}");
}
}
return (false, "Job timed out");
}
}
// Full production-grade async processor for Textract PDF handling
public class TextractAsyncProcessor
{
private readonly AmazonTextractClient _textractClient;
private readonly AmazonS3Client _s3Client;
private readonly string _bucketName;
private readonly TimeSpan _pollInterval = TimeSpan.FromSeconds(5);
private readonly TimeSpan _maxWaitTime = TimeSpan.FromMinutes(10);
public async Task<DocumentResult> ProcessDocumentAsync(
string localFilePath,
CancellationToken cancellationToken = default)
{
var s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}";
try
{
// Phase 1: Upload to S3
await UploadToS3Async(localFilePath, s3Key, cancellationToken);
// Phase 2: Start Textract job
var jobId = await StartTextractJobAsync(s3Key, cancellationToken);
// Phase 3: Poll until complete (up to 10 minutes)
var pollResult = await PollForCompletionAsync(jobId, cancellationToken);
if (!pollResult.Success)
throw new Exception($"Textract job failed: {pollResult.ErrorMessage}");
// Phase 4: Retrieve paginated results
return await GetAllResultsAsync(jobId, cancellationToken);
}
finally
{
// Phase 5: S3 cleanup — must succeed or storage costs accumulate
await DeleteFromS3Async(s3Key, cancellationToken);
}
}
private async Task<(bool Success, string ErrorMessage)> PollForCompletionAsync(
string jobId, CancellationToken cancellationToken)
{
var startTime = DateTime.UtcNow;
int pollCount = 0;
while (DateTime.UtcNow - startTime < _maxWaitTime)
{
cancellationToken.ThrowIfCancellationRequested();
var response = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId }, cancellationToken);
pollCount++;
switch (response.JobStatus)
{
case JobStatus.SUCCEEDED: return (true, null);
case JobStatus.FAILED: return (false, response.StatusMessage ?? "Unknown error");
case JobStatus.IN_PROGRESS:
await Task.Delay(_pollInterval, cancellationToken);
break;
default:
throw new Exception($"Unknown job status: {response.JobStatus}");
}
}
return (false, "Job timed out");
}
}
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.S3
Imports Amazon.Textract.Model
' Full production-grade async processor for Textract PDF handling
Public Class TextractAsyncProcessor
Private ReadOnly _textractClient As AmazonTextractClient
Private ReadOnly _s3Client As AmazonS3Client
Private ReadOnly _bucketName As String
Private ReadOnly _pollInterval As TimeSpan = TimeSpan.FromSeconds(5)
Private ReadOnly _maxWaitTime As TimeSpan = TimeSpan.FromMinutes(10)
Public Async Function ProcessDocumentAsync(localFilePath As String, Optional cancellationToken As CancellationToken = Nothing) As Task(Of DocumentResult)
Dim s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}"
Try
' Phase 1: Upload to S3
Await UploadToS3Async(localFilePath, s3Key, cancellationToken)
' Phase 2: Start Textract job
Dim jobId = Await StartTextractJobAsync(s3Key, cancellationToken)
' Phase 3: Poll until complete (up to 10 minutes)
Dim pollResult = Await PollForCompletionAsync(jobId, cancellationToken)
If Not pollResult.Success Then
Throw New Exception($"Textract job failed: {pollResult.ErrorMessage}")
End If
' Phase 4: Retrieve paginated results
Return Await GetAllResultsAsync(jobId, cancellationToken)
Finally
' Phase 5: S3 cleanup — must succeed or storage costs accumulate
Await DeleteFromS3Async(s3Key, cancellationToken)
End Try
End Function
Private Async Function PollForCompletionAsync(jobId As String, cancellationToken As CancellationToken) As Task(Of (Success As Boolean, ErrorMessage As String))
Dim startTime = DateTime.UtcNow
Dim pollCount As Integer = 0
While DateTime.UtcNow - startTime < _maxWaitTime
cancellationToken.ThrowIfCancellationRequested()
Dim response = Await _textractClient.GetDocumentTextDetectionAsync(New GetDocumentTextDetectionRequest With {.JobId = jobId}, cancellationToken)
pollCount += 1
Select Case response.JobStatus
Case JobStatus.SUCCEEDED
Return (True, Nothing)
Case JobStatus.FAILED
Return (False, If(response.StatusMessage, "Unknown error"))
Case JobStatus.IN_PROGRESS
Await Task.Delay(_pollInterval, cancellationToken)
Case Else
Throw New Exception($"Unknown job status: {response.JobStatus}")
End Select
End While
Return (False, "Job timed out")
End Function
End Class
這不是可以生成並忘記的樣板。 當Textract工作在中途失敗時,S3清理還是必須執行。 當工作在10分鐘後超時時,呼叫者還是需要一個乾淨的錯誤。 當在輪詢期間網路中斷時,重試策略不應創造重複工作。 每種失敗模式都需要明確處理——上面顯示的結構是最基本的負責任的實作。
批量處理新增了另一層:Textract的預設StartDocumentTextDetection TPS限制為5個請求每秒。 處理100個文件要求ProvisionedThroughputExceededException的重試邏輯。
IronOCR方法
// IronOCR: same synchronous API regardless of document type or size
public string ProcessDocument(string filePath)
{
using var input = new OcrInput();
if (Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
input.LoadPdf(filePath);
else
input.LoadImage(filePath);
return new IronTesseract().Read(input).Text;
}
// IronOCR: same synchronous API regardless of document type or size
public string ProcessDocument(string filePath)
{
using var input = new OcrInput();
if (Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
input.LoadPdf(filePath);
else
input.LoadImage(filePath);
return new IronTesseract().Read(input).Text;
}
Imports System.IO
' IronOCR: same synchronous API regardless of document type or size
Public Function ProcessDocument(filePath As String) As String
Using input As New OcrInput()
If Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase) Then
input.LoadPdf(filePath)
Else
input.LoadImage(filePath)
End If
Return New IronTesseract().Read(input).Text
End Using
End Function
沒有輪詢迴圈,無需跟蹤工作ID,沒有S3桶,無需結果分頁。 同一程式碼處理單個JPEG和200頁PDF。 處理要麼完成要麼拋出——無需管理中間的"進行中"狀態。 對於批量處理,IronOCR是執行緒安全的,單個Parallel.ForEach。
IronTesseract設定指南介紹了配置,以及PDF輸入指南記錄了頁面範圍選擇、帶密碼保護的PDF和從資料庫或HTTP回應檢索的PDF流式輸入。
憑證管理開銷
開始使用AWS Textract進行OCR操作前需要在未處理單一頁面前配置IAM。
AWS Textract 方法
在調用DetectDocumentTextAsync之前,開發人員必須:
- 建立AWS帳戶或獲得現有帳戶的存取權限
- 建立具備
textract:AnalyzeDocument許可的IAM使用者或角色 - 生成和安全儲存存取密鑰ID和私密存取密鑰
- 配置憑證解析——環境變數、AWS憑證文件或EC2實例配置文件
- 如處理PDF:建立S3桶、配置桶策略、新增
s3:DeleteObject許可 - 實施符合安全標準的憑證輪換策略
- 在每個部署環境中安全存存憑證——如Docker秘密、Kubernetes秘密、AWS秘密管理器或CI/CD流水線變數
// Every environment needs these configured before this constructor succeeds
public TextractOcrService()
{
// Reads credentials from environment, ~/.aws/credentials, or IAM role
_client = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
}
// Every environment needs these configured before this constructor succeeds
public TextractOcrService()
{
// Reads credentials from environment, ~/.aws/credentials, or IAM role
_client = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
}
' Every environment needs these configured before this constructor succeeds
Public Sub New()
' Reads credentials from environment, ~/.aws/credentials, or IAM role
_client = New AmazonTextractClient(Amazon.RegionEndpoint.USEast1)
End Sub
當憑證過期、輪換或配置錯誤時,每次OCR調用都會失敗並攜帶ErrorCode == "AccessDeniedException"。 在生產系統中,這意味著需要為憑證失敗實作特定的catch塊並監控IAM策略漂移。
IronOCR方法
// One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
' Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
授權密鑰是一個靜態字串。 它不會在操作中途過期、無需輪換且不攜帶任何需管理的權限。 處理文件的Docker容器不需要注入的AWS憑證、綁定到執行背景的IAM角色,或AWS STS的網路存取以刷新令牌。
從Textract轉向IronOCR時的完全憑證開銷減少情況:三個NuGet套件被刪除(AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_DEFAULT_REGION環境變數被移除,以及IAM角色和S3桶配置被除役。 圖像輸入指南和流輸入指南介紹了滿足Textract的位元組陣列和S3物件文件模型的完整輸入方法範圍。
API 地圖參考
| AWS Textract API | IronOCR 等效 |
|---|---|
AmazonTextractClient |
IronTesseract |
AmazonS3Client |
不需要 |
DetectDocumentTextRequest |
OcrInput |
DetectDocumentTextResponse |
OcrResult |
AnalyzeDocumentRequest |
CropRectangle設定區域 |
StartDocumentTextDetectionRequest |
OcrInput — 同步,無需啟動 |
GetDocumentTextDetectionRequest |
不需要——結果立即給出 |
Document.Bytes |
input.LoadImage(stream) |
S3Object(文件中纄載) |
文件路徑字串或流 |
BlockType.LINE) |
result.Lines |
BlockType.WORD) |
result.Words |
BlockType.TABLE) |
單詞位置分組透過result.Words |
BlockType.KEY_VALUE_SET) |
CropRectangle區域擷取 |
Block.Confidence |
word.Confidence / result.Confidence |
JobStatus.SUCCEEDED |
不適用—同步返回 |
JobStatus.IN_PROGRESS |
不適用—無異步狀態 |
response.NextToken(分頁) |
不適用—結果不分頁 |
ProvisionedThroughputExceededException |
不適用—無TPS限制 |
client.DetectDocumentTextAsync(request) |
ocr.Read(path) |
client.AnalyzeDocumentAsync(request) |
ocr.Read(input) |
client.StartDocumentTextDetectionAsync(request) |
ocr.Read(input) |
client.GetDocumentTextDetectionAsync(request) |
不適用 |
當團隊考慮從AWS Textract轉到IronOCR
當月度帳單成為預算專案
起初使用Textract的團隊在低量下,通常會遭遇具體的時刻:AWS的OCR處理賬單出現在季度預算評審上,然後有人問這個費用是否是固定的。 並不是。 在高頁量下,年Textract成本可能相當龐大──查看AWS Textract 定價頁面了解當前費率。IronOCRProfessional許可以$2,999一次性支付自己很快就在中等到高頁量下物有所值。
當合規要求阻礙雲端處理時
健康組織實施文件數位化工作流的過程中經常會在中專案發現HIPAA PHI不能因缺少BAA和額外法律審查而流綞雲諸服務,或者其安全團隊完全禁止雲伺服器傳輸。 處理技術圖紙、規格或任何CUI的國防承包商面臨ITAR和CMMC限制,將Textract排除在考量之外。 處理機密通信的法律公司有類似的擔憂。 這些不是理論上的合規邊緣案例——它們經常在採購評審、安全審計中出現,並且也會在合同談判中出現。 IronOCR是本地處理的,因此關於文件資料合規問題能被簡化爲確定您的自有基礎架構是否在範圍內,而不是Amazon的基礎架構是否在範圍內。
當異步PDF複雜性超過其價值時
五階段S3-異步管道──上傳、開始工作、輪詢、分頁結果和清理──在技術上不難實現。 它難以維護、測試和運行。 每個階段都是失敗點。 S3上傳失敗需要重試邏輯。 Textract工作失敗需要區分瞬態與永久錯誤。 輪詢超時需要與取消分開的超時處理。 結果分頁需要跨多個API調用累積狀態。 S3清理失敗需要警告以因為孤立物件會增加成本。 已將該管道交付生產的團隊通常花在維護它的持續工程時間比構建它的時間還多。IronOCR的等效品──ocr.Read(input)──消除了所有五個階段及其相關的失敗模式。
當部屬環境缺乏網路連接時
運行於隔離網路段的Docker容器、無向外網路的內部部署伺服器、氣隙研究環境和工業系統,全都與一個特色共通:AWS Textract無法使用。 IronOCR以作標準NuGet包的形式安裝,安裝后運行不再進行任何網路調用。 在這些環境中運行.NET應用程式的團隊沒有Textract選項,需要的是本地處理的程式庫。 Docker 部署指南和 Linux 部署指南覆蓋了容器化環境的具體配置。
當速率限制節流中斷批量工作流程時
預設的StartDocumentTextDetection TPS限制為每秒5個請求。 DetectDocumentText同步調用也受到速率限制。 處理數百或數千個文件的批量作業必須實施ProvisionedThroughputExceededException的增量備退返策略和速率補充計時器。 AWS支持TPS限速升級請求,但需要佐證文件與審核,而無保證。 IronOCR能依據本地CPU的能力以最快的速度執行──32核伺服器可同時處理32個文件不需節流配置或服務層討論。
常見的遷移考量
用直接集合替換塊圖
Textract代理所有的結果以平面BlockType加以區分和被關聯ID排列陣列連接。 IronOCR提供直接型別集合。
// Textract: filter flat block list by type
var lines = response.Blocks.Where(b => b.BlockType == BlockType.LINE);
var words = response.Blocks.Where(b => b.BlockType == BlockType.WORD);
// IronOCR: direct access to typed collections
var result = ocr.Read(imagePath);
var lines = result.Lines; // IEnumerable<OcrResult.OcrResultLine>
var words = result.Words; // IEnumerable<OcrResult.OcrResultWord>
foreach (var word in result.Words)
Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%");
// Textract: filter flat block list by type
var lines = response.Blocks.Where(b => b.BlockType == BlockType.LINE);
var words = response.Blocks.Where(b => b.BlockType == BlockType.WORD);
// IronOCR: direct access to typed collections
var result = ocr.Read(imagePath);
var lines = result.Lines; // IEnumerable<OcrResult.OcrResultLine>
var words = result.Words; // IEnumerable<OcrResult.OcrResultWord>
foreach (var word in result.Words)
Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%");
' Textract: filter flat block list by type
Dim lines = response.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
Dim words = response.Blocks.Where(Function(b) b.BlockType = BlockType.WORD)
' IronOCR: direct access to typed collections
Dim result = ocr.Read(imagePath)
Dim lines = result.Lines ' IEnumerable(Of OcrResult.OcrResultLine)
Dim words = result.Words ' IEnumerable(Of OcrResult.OcrResultWord)
For Each word In result.Words
Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%")
Next
結構化結果指南涵蓋result.Pages, result.Paragraphs, result.Lines, result.Words以及用於構建布局感知文件處理的坐標存取。
用直接LoadPdf替換S3-階段PDF處理
任何在檔案擷取開始前上傳至S3的Textract程式碼都可以被直接的PDF載入所代替。 無中繼桶、上傳定時及清理邏輯。
// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
//IronOCRequivalent:
public string ProcessPdf(string pdfPath)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return ocr.Read(input).Text;
}
// Specific page ranges (no Textract equivalent without async job per range)
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return ocr.Read(input).Text;
}
// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
//IronOCRequivalent:
public string ProcessPdf(string pdfPath)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return ocr.Read(input).Text;
}
// Specific page ranges (no Textract equivalent without async job per range)
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return ocr.Read(input).Text;
}
Imports IronOcr
Public Class OcrProcessor
' Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
' IronOCRequivalent:
Public Function ProcessPdf(pdfPath As String) As String
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadPdf(pdfPath)
Return ocr.Read(input).Text
End Using
End Function
' Specific page ranges (no Textract equivalent without async job per range)
Public Function ProcessPdfPages(pdfPath As String, startPage As Integer, endPage As Integer) As String
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadPdfPages(pdfPath, startPage, endPage)
Return ocr.Read(input).Text
End Using
End Function
End Class
增加預處理以替換在Textract中產生低定量信心的文件
Textract的預處理是內部且無法配置的。 當掃描的文件產生不良結果時,唯一的選擇是重試或接受低信度輸出。 IronOCR直接揭露了預處理管道。
// For documents that returned low-confidence results from Textract
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew(); // Fix rotation from scanner misalignment
input.DeNoise(); // Remove scanner noise artifacts
input.Contrast(); // Boost faint text
input.EnhanceResolution(300); // Scale to optimal OCR resolution
var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
// For documents that returned low-confidence results from Textract
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew(); // Fix rotation from scanner misalignment
input.DeNoise(); // Remove scanner noise artifacts
input.Contrast(); // Boost faint text
input.EnhanceResolution(300); // Scale to optimal OCR resolution
var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
Imports IronOcr
Dim input As New OcrInput()
input.LoadImage("low-quality-scan.jpg")
input.Deskew() ' Fix rotation from scanner misalignment
input.DeNoise() ' Remove scanner noise artifacts
input.Contrast() ' Boost faint text
input.EnhanceResolution(300) ' Scale to optimal OCR resolution
Dim result = New IronTesseract().Read(input)
Console.WriteLine($"Confidence: {result.Confidence}%")
圖像質量矯正指南和圖像濾鏡教學完整記錄了預處理管道及適合於特定文件型別的最佳組合。為了信心分數參考和單元件信心存取, 信心分數指南涵蓋result.Confidence屬性和逐字信心值。
處理非同步到同步模板轉變時
現有Textract程式碼必要時使用async Task<t>因為SDK僅支援異步。 IronOCR操作是同步的。 對於已經具有異步調用鏈的應用程式程式碼中,將IronOCR調用包裹到Task.Run中以維持異步邊界。
// Preserves async call site for minimal refactoring
public async Task<string> ExtractTextAsync(string path)
{
return await Task.Run(() => new IronTesseract().Read(path).Text);
}
// Preserves async call site for minimal refactoring
public async Task<string> ExtractTextAsync(string path)
{
return await Task.Run(() => new IronTesseract().Read(path).Text);
}
Imports System.Threading.Tasks
' Preserves async call site for minimal refactoring
Public Async Function ExtractTextAsync(path As String) As Task(Of String)
Return Await Task.Run(Function() New IronTesseract().Read(path).Text)
End Function
這是一個方便的包裝器,非必須必要。 對於呼叫程式碼已在後台執行緒上的伺服器端處理,則更直接偏向同步呼叫。
其他IronOCR功能
除了上述比較外,IronOCR提供了AWS Textract所無法比擬的功能:
- OCR期間的條碼讀取: 設
ocr.Configuration.ReadBarCodes = true,以便文件中的條碼與文字一道在一次掃內被擷取出來——無需單獨的條碼掃瞄步驟 - 長期工作進度跟踪: 在多頁處理期間訂閱進度事件,無需polling外部服務
- 掃描文件處理: 針對包括雙面掃描和混合方向頁面在內的典型辦公商掃描器輸出的優化管道
- 多語言的同步擷取: 在讀取時合併語言包——
OcrLanguage.French + OcrLanguage.German——無需API層改變 - 護照和ID讀取: 對身份文件的可機讀區域,提供針對條目提取結構化欄位,不需要手動區域定義的專門管道
.NET 相容性和未來準備
IronOCR針對.NET 8和.NET 9,並持續與.NET Standard 2.0專案和.NET Framework 4.6.2至4.8保持相容。本程式庫透過單個NuGet包提供Windows x64、Windows x86、Linux x64和macOS的本地二進位檔──無需運行時標識符切換或平台特定包參考。 AWS Textract的AWSSDK.Textract包支持相同的現代.NET 目標,但偵測模型需攜帶完整AWS SDK依賴樹、IAM憑證基礎架構以及本文件篇所記錄的架構限制。 IronOCR保持活躍開發,跟蹤Tesseract 5引擎更新和.NET運行時進展包括針對即將發佈的.NET 10的相容性。
結論
AWS Textract和IronOCR解決了相同的問題——從.NET應用中提取文件中的文字——但其基本架構假設不相容。 Textract假設文件可以離開您的網路,假定雲端服務成本隨群量線性擴展,並假定多頁PDF需要一個含有S3中繼的五階段異步管道。 IronOCR假設文件仍留在處理它們的地方,許可成本應與群量脫鉤,並呈現出與程式處理相似的程式碼一樣是能面對PDF處理的三段程式碼。
費用算術是最清晰的區分線。在低量下,Textract的逐頁費用是可管理的。 隨著規模增長,年成本顯著倍增。 當以表格擷取的高頁量時,多年Textract成本可能遠遠超過即便的IronOCR的Unlimited許可組在$5,999。 開頭的數學不變:逐頁模式增加得非常快,而且從未停止。
資料主權是第二個結構限制。 對於醫療、法律、金融和政府工作負載,在哪處理文件這一問題不是偏好——而是一個合規要求。 IronOCR的處理是內建本端的,而不是通過配置。 無需啟用"本地模式"; 本地處理是唯一的模式。 這讓合規問題變得簡單:您的文件留在您的基礎架構中因為沒有其他地方去。
對於在真正規模上評估OCR 或在文件資料無法離開內部租件上的團隊,IronOCR 的文件提供完整的API引用、適用於Docker、AWS、Azure和Linux的部署指南,以及涵蓋從基本影像閱讀到可搜尋的PDF生成功能和多語言擷取的全部OCR用例教學。
常見問題
什麼是 Amazon Textract?
Amazon Textract 是開發人員和企業用來從圖片和文件中提取文字的 OCR 解決方案。它是與 IronOCR 一起評估的多個 OCR 選項之一,用於 .NET 應用程式開發。
IronOCR 與 Amazon Textract 對 .NET 開發人員來說如何比較?
IronOCR 是一個 NuGet 原生的 .NET OCR 程式庫,使用 IronTesseract 作為其核心引擎。與 Amazon Textract 相比,它提供更簡單的部署(無 SDK 安裝程式)、統一價格以及無 COM 互操作或雲端依賴的乾淨 C# API。
IronOCR 的設置是否比 Amazon Textract 更簡單?
IronOCR 通過一個單一的 NuGet 套件安裝。無需 SDK 安裝程式、複製授權文件、註冊 COM 元件或管理單獨的運行時二進位檔案。整個 OCR 引擎都打包在套件中。
Amazon Textract 和 IronOCR 之間的準確性有何不同?
IronOCR 在標準商業文件、發票、收據和掃描表單上達到了高識別準確度。對於極度退化的文件或罕見文字,準確度會根據來源品質變化。IronOCR 包含影像預處理篩選器,以改善低品質輸入的識別。
IronOCR 支援 PDF 文字提取嗎?
是的。IronOCR 能從原生 PDF 和掃描的 PDF 圖像中一次性提取文字。它還支持多頁 TIFF 檔案、影像和流。對於掃描的 PDF,OCR 會逐頁應用並生成每頁的結果物件。
Amazon Textract 與 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 和容器化部署,而不像 Amazon Textract 一樣?
是的。IronOCR 通過其 NuGet 載於 Docker 容器中運行。授權金鑰通過環境變數設置。無需授權文件、SDK 路徑或量掛載來執行 OCR 引擎。
與 Amazon Textract 相比,我可以在購買前試用 IronOCR 嗎?
是的。IronOCR 試用模式中處理文件並在輸出上附上浮水印結果。您可以在購買授權前驗證自己文件的準確性。
IronOCR 支援條碼閱讀與文字提取嗎?
IronOCR 專注於文字提取和 OCR。對於條碼閱讀,Iron Software 提供了額外的 IronBarcode 程式庫。兩者均可個別使用或作為 Iron Suite 套件的一部分。
從 Amazon Textract 遷移到 IronOCR 是否簡單?
從 Amazon Textract 遷移到 IronOCR 通常包括用 IronTesseract 實例化替換初始化序列、移除 COM 生命週期管理和更新 API 呼叫。大多數遷移能顯著降低程式碼複雜性。

