IronOCRとNanonets OCRの比較
AWS Textractのページ単位の料金モデルは、低量では安価に見えますが、スケールアップするとコストが無限に蓄積されます。 アプリケーションが処理するすべてのドキュメントはネットワークを離れ、Amazonのデータセンターに移動し、Amazonのインフラストラクチャによって処理され、その請求額は無限に蓄積されます。 .NETでOCRオプションを評価するチームにとって、問題はTextractが正確な結果を生成するかどうか(実際、正確な結果を生成します)だけではなく、ページごとのコストモデル、必須のクラウド送信、および複数ページ文書用の非同期ポーリングアーキテクチャが、アプリケーションの実際のニーズに合致するかどうかです。
AWS Textractを理解する
AWS TextractはAmazonのマネージドドキュメント解析サービスで、AWS SDK for .NETを通じてAWSSDK.Textract NuGetパッケージでアクセスできます。 これはクラウドAPIとして機能します。アプリケーションはドキュメントデータをAmazonのインフラストラクチャに送信し、構造化された結果を受け取ります。 このサービスを利用するには、AWSアカウント、Textractのアクセス許可を持つIAM認証情報、およびOCR操作ごとにインターネット接続が必要です。
Textractは、それぞれ価格が異なる複数の分析モードを提供しています。
- DetectDocumentText: 基本的なテキスト抽出(現在のページ単位の料金はAWS Textractの料金を参照してください)
- AnalyzeDocument (Tables): 基本的なテキストよりも高いページ単位の料金での構造化テーブル抽出
- AnalyzeDocument (Forms): 基本的なテーブル抽出よりも高いページ単位の料金でのキーと値のフォーム抽出
- AnalyzeExpense:請求書と領収書の解析(1ページあたり0.01ドル)
- AnalyzeID:本人確認書類の抽出(1ページあたり0.025ドル)
- StartDocumentTextDetection / StartDocumentAnalysis:複数ページの PDF には非同期 API が必要で、S3 ステージング バケット、ジョブ ポーリング、および結果のページネーションが必須となります。
結果モデルはBlockオブジェクトのフラットなリストを使用し、テーブルやフォーム、その他の構造化出力を再構築するためにリレーションシップIDをたどる必要があります。 シンプルなテーブル抽出にはBlockType.WORDブロックを取得する必要があります。 この関係グラフモデルは複雑な文書構造を処理できますが、軽量ではありません。
S3-Asyncパイプライン
単一イメージの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 = $"uploads/{Guid.NewGuid()}.pdf"
Using 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 = 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 = 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サポート: S3ステージングや非同期ジョブなしで、ファイルパスまたはストリームを介してPDFを直接読み取ります - スレッドセーフ: 単一の
IronTesseractインスタンスがスレッドを跨いで同時リクエストを問題なく処理します - 永続ライセンス: $999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited — 一回の支払いで、ページごとの料金や使用メーターはありません
- 125以上の言語パック:個別のNuGetパッケージとしてインストールされ、ローカルでロードされるため、ネットワーク呼び出しは不要です。
機能比較
| フィーチャー | AWS テクストラクト | IronOCR |
|---|---|---|
| 処理場所 | Amazonクラウド(必須) | ローカル/店内 |
| 複数ページPDF | S3と非同期ジョブが必要です | 直接同期呼び出し |
| コストモデル | ページ単位(現在の価格についてはAWSにお問い合わせください) | 永久ライセンス、ページごとの料金は不要 |
| インターネット接続が必要です | いつも | 一度もない |
| 認証情報の設定 | IAMユーザー/ロール + オプションのS3 | 単一ライセンスキー文字列 |
| エアギャップ展開 | 不可 | 完全サポート |
| 暗号化されたPDFのサポート | サポートされていません | 組み込み(パスワードパラメータ) |
詳細な機能比較
| フィーチャー | AWS テクストラクト | 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 |
| 処理モデル | ||
| 同期(画像) | はい(1ページのみ) | はい(すべての文書タイプ) |
| 非同期 | 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ラムダ | ネイティブ | サポート対象 |
| アジュール | はい | はい |
| 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機能(基本的なテキスト検出、テーブル抽出、フォーム抽出)には異なる料金があります。 テーブルとフォームフィールドを含むドキュメントは、基本的なテキスト検出よりも高い料金が発生し、無制限にコストが増加し、予払いする方法がありません。
高ページボリュームでは、3年間の総コストが大幅であり、メーターは動き続けます。
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人の開発者、無制限のプロジェクト、無制限のページ量をカバーします。 1年経過後は、処理されるページ数に対する継続的な費用は無料となります。 大量のページを処理するチームにとって、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 Highの認証を取得しています。 これらのフレームワークは基本的なアーキテクチャを変更するものではありません。すべての操作において、ドキュメントはお客様のインフラストラクチャから送信されます。 ITAR(国際武器取引規制)の対象となる技術データについては、これは単なるコンプライアンス上のニュアンスではなく、禁止事項です。 CUI(機密情報)を含むCMMCレベル3のワークロードにおいて、クラウド経由での送信には特定の認可が必要ですが、ほとんどの防衛関連請負業者はこれを保有していません。 エアギャップ環境(研究ネットワーク、産業用制御環境、機密施設など)においては、Textractは利用できません。
AWS Textractは6つの地域にて利用可能です: 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)上で動作します。処理はAmazonのマネージドサービスではなく、お客様自身のAWSアカウントの範囲内で行われます。
非同期ポーリングと同期処理
Textractの同期型(単一画像)APIと非同期型(複数ページの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制限は1秒あたり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バケット、結果のページネーションは含まれません。 同じコードで、1枚のJPEG画像も200ページのPDFも処理できます。 処理は完了するか例外をスローします。管理すべき"処理中"といった中間状態はありません。 バッチ処理の場合は、IronOCRはスレッドセーフであり、単一のParallel.ForEachを処理します。
IronTesseractのセットアップガイドでは設定について解説しており、PDF入力ガイドではページ範囲の選択、パスワードで保護されたPDF、およびデータベースやHTTPレスポンスから取得したPDFに対するストリームベースの入力について記載しています。
認証情報管理のオーバーヘッド
AWS TextractでOCR処理を開始するには、1ページも処理する前にIAMの設定を行う必要があります。
AWS Textractのアプローチ
DetectDocumentTextAsyncを呼び出す前に、開発者は:
- AWSアカウントを作成するか、既存のアカウントへのアクセス権を取得する
textract:DetectDocumentTextとtextract:AnalyzeDocumentパーミッションを持ったIAMユーザーまたはロールを作成します- アクセスキーIDとシークレットアクセスキーを生成し、安全に保管する
- 認証情報の解決を設定する — 環境変数、AWS 認証情報ファイル、または EC2 インスタンスプロファイル
- PDF を処理する場合: S3バケットを作成し、バケット ポリシーを設定し、
s3:PutObjectおよびs3:DeleteObjectパーミッションを追加します - セキュリティ基準を満たすために、認証情報のローテーションポリシーを実施する
- 各デプロイメント環境で認証情報を安全に保管する — Dockerシークレット、Kubernetesシークレット、AWS Secrets Manager、または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パッケージが削除されます(AWSSDK.Textract, AWSSDK.S3, 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 |
OcrInput と CropRectangle ゾーン用 |
StartDocumentTextDetectionRequest |
OcrInput — 同期的、開始不要 |
GetDocumentTextDetectionRequest |
必須ではありません — 即時結果 |
Document.Bytes |
input.LoadImage(bytes) または input.LoadImage(stream) |
S3Object(ドキュメントステージング) |
ファイルパスの文字列またはストリーム |
Block (BlockType.LINE) |
result.Lines |
Block (BlockType.WORD) |
result.Words |
Block (BlockType.TABLE) |
単語位置グループ化result.Wordsによる |
Block (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を少量のデータから導入したチームは、ある特定の局面に直面することがよくあります。四半期ごとの予算レビューでOCR処理のAWS請求書が提示され、誰かが"このコストは固定なのか"と尋ねるのです。 そうではありません。 高ページボリュームでは、年間Textractコストはかなりのものになる可能性があります — 現在の料金についてはAWS Textractの料金ページを参照してください。 $2,999でのIronOCR Professionalライセンスは高めのページボリュームで迅速に元が取れます。
コンプライアンス要件がクラウド処理を阻害する場合
文書デジタル化ワークフローを導入する医療機関は、プロジェクトの途中で、HIPAA PHI(保護対象健康情報)がBAA(業務委託契約)および追加の法的審査なしにクラウドサービスを経由できないこと、あるいはセキュリティチームがクラウド経由の送信を全面的に禁止していることに気づくことがよくあります。 技術図面、仕様書、または機密情報(CUI)を扱う防衛関連企業は、ITARおよびCMMCの制約により、AWS Textractの利用が除外されます。 機密通信を扱う法律事務所も、同様の懸念を抱えています。 これらは単なる理論上のコンプライアンス上の例外事例ではなく、調達審査、セキュリティ監査、契約交渉において頻繁に問題となるものです。 IronOCRはローカルで処理を行うため、ドキュメントデータに関するコンプライアンス上の懸念は、Amazonのインフラストラクチャが対象範囲内かどうかではなく、自社のインフラストラクチャが対象範囲内かどうかという点に集約されます。
非同期PDFの複雑さがその価値を上回る場合
アップロード、ジョブの開始、ポーリング、結果のページネーション、クリーンアップという5段階のS3非同期パイプラインは、技術的に実装が難しいものではありません。 維持管理、試験、運用が困難である。 どの段階も失敗の危険性をはらんでいる。 S3へのアップロード失敗時には、再試行ロジックが必要となる。 Textractジョブの失敗時には、一時的なエラーと永続的なエラーを区別する必要がある。 ポーリングのタイムアウトには、キャンセル処理とは別にタイムアウト処理が必要です。 結果のページネーションには、複数のAPI呼び出しにわたる状態の蓄積が必要です。 S3のクリーンアップが失敗した場合、孤立したオブジェクトがコストを増大させるため、アラートを発する必要があります。 このパイプラインを本番環境に導入したチームは、構築に費やした時間よりも、その維持管理に費やすエンジニアリング時間の方がはるかに多いのが一般的です。 IronOCRの同等品 — input.LoadPdf(path) 次にocr.Read(input) — 五つの段階とそれに対応する失敗モードをすべて排除します。
展開環境にインターネットアクセスがない場合
隔離されたネットワークセグメントで実行されるDockerコンテナ、インターネットへのアウトバウンド接続がないオンプレミス サーバー、エアギャップされた研究環境、厳格なネットワーク制御が適用される産業システムには、すべて共通する特徴が 1 つあります。それは、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、レイアウト対応のドキュメント処理を構築するための座標アクセスをカバーしています。
S3段階PDF処理を直接LoadPdfに置き換える
検出ジョブを開始する前にS3にアップロードするTextractのコードは、PDFを直接読み込むコードに置き換えることができます。 ステージングバケットなし、アップロードタイミングなし、クリーンアップロジックなし。
// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
// IronOCR equivalent:
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)
// IronOCR equivalent:
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 PdfProcessor
' Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
' IronOCR equivalent:
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コードはSDKが非同期しかないため、必然的にasync Task<t>されています。 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を設定し、ドキュメント内のバーコードが1回でテキストとともに抽出されます — 別途バーコードスキャンステップは不要 -長時間処理の進捗状況追跡:外部サービスをポーリングすることなく、複数ページ処理の進捗状況イベントを購読します。 -スキャン文書処理:両面スキャンや異なる向きのページなど、一般的なオフィススキャナー出力向けに最適化されたパイプライン - 多言語同時抽出: 読み込み時に言語パックを組み合わせます —
OcrLanguage.French + OcrLanguage.German— APIティアの変更はありません -パスポートおよびIDの読み取り: 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パッケージは同じ現代 for .NETターゲットをサポートしていますが、デプロイメントモデルは完全なAWS SDK依存性ツリー、IAMクレデンシャルインフラストラクチャ、およびこの記事を通して文書化されたアーキテクチャの制約を含みます。 IronOCRは、Tesseract 5エンジンのアップデートや.NETランタイムの進歩(リリースされた.NET 10との互換性を含む)に対応した定期的なリリースを行い、活発な開発を続けています。
結論
AWS TextractとIronOCRは、 .NETアプリケーション内のドキュメントからテキストを抽出するという同じ問題を解決するが、根本的に互換性のないアーキテクチャ上の前提に基づいている。 Textractは、ドキュメントがネットワーク外に送信される可能性があること、クラウドサービスのコストがデータ量に比例して増加すること、および複数ページのPDFファイルの場合、S3ステージングを使用した5段階の非同期パイプラインが妥当であることを前提としています。 IronOCRは、文書が処理された場所に留まること、ライセンス費用が処理量とは切り離されていること、そしてPDF処理には画像処理と同じ3行のコードが必要であることを前提としている。
コスト計算は明らかな分岐点です。低量であれば、Textractのページ単位の料金は管理可能です。 ボリュームが増えると、年間コストが大きく累積します。 テーブル抽出を伴う高ページボリュームでは、複数年のTextractコストが$5,999でのIronOCRのUnlimitedライセンスをはるかに超える可能性があります。 最初の数学が当てはまります:1ページ当たりのモデルは急速に加算され、その動きは止まりません。
データ主権は、2つ目の構造的制約である。 医療、法律、金融、政府機関などの業務においては、文書の処理場所に関する問題は好みの問題ではなく、コンプライアンス上の要件である。 IronOCRは、設定ではなく設計上、ローカルで処理を実行します。 有効化できる"ローカルモード"はありません。 ローカル処理のみが唯一のモードです。 つまり、コンプライアンスに関する答えは単純明快です。文書は他に保管場所がないため、社内インフラ内に留まります。
本格的な規模でOCRを評価するチーム、またはドキュメントデータが社内インフラストラクチャから外部に持ち出せない環境で運用するチーム向けに、IronOCRのドキュメントは、完全なAPIリファレンス、Docker、AWS、Azure、Linux向けのデプロイガイド、および基本的な画像読み取りから検索可能なPDF生成、多言語抽出まで、OCRのあらゆるユースケースを網羅したチュートリアルを提供します。
よくある質問
Amazon Textractとは何ですか?
Amazon Textractは、開発者や企業が画像や文書からテキストを抽出するために使用するOCRソリューションです。.NETアプリケーション開発のためにIronOCRと一緒に評価されたいくつかのOCRオプションの一つです。
IronOCRは.NET開発者向けAmazon Textractと比較してどうですか?
IronOCRはNuGetネイティブ for .NET OCRライブラリで、.Coreエンジンとして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経由でインストールします:パッケージマネージャーコンソールで'Install-Package IronOcr'、またはCLIで'dotnet add package IronOcr'。追加の言語パックも同様にインストールされます。ネイティブSDKインストーラーは必要ありません。
IronOCRはAmazon Textractとは異なり、Dockerやコンテナ化されたデプロイメントに適していますか?
IronOCRはNuGetパッケージによってDockerコンテナで動作します。ライセンスキーは環境変数で設定します。OCRエンジン自体にはライセンスファイル、SDKパス、ボリュームマウントは必要ありません。
Amazon Textractと比較して、購入前にIronOCRを試すことはできますか?
IronOCRのトライアルモードでは、ドキュメントを処理し、出力に透かしをオーバーレイしたOCR結果を返します。ライセンスを購入する前に、ご自身の文書で精度を確認することができます。
IronOCRはテキスト抽出とバーコード読み取りをサポートしていますか?
IronOCRはテキスト抽出とOCRに重点を置いています。バーコード読み取りについては、Iron SoftwareはIronBarcodeをコンパニオンライブラリとして提供しています。どちらも個別に、あるいはIron Suiteのバンドルとして提供されています。
Amazon TextractからIronOCRへの移行は簡単ですか?
Amazon TextractからIronOCRへの移行は通常、初期化シーケンスをIronTesseractのインスタンス生成に置き換え、COMライフサイクル管理を削除し、APIコールを更新します。ほとんどの移行はコードの複雑さを大幅に軽減します。

