フッターコンテンツにスキップ
他のコンポーネントと比較する

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
$vbLabelText   $csharpLabel

信頼性の高い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ゾーン
ラインレベルの結果 BlockBlockType.LINEによりフィルタリング result.Lines 直接コレクション
座標付き単語レベル BlockBlockType.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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

$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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

これは、生成して放置できるような定型文ではありません。 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
$vbLabelText   $csharpLabel

ポーリングループ、ジョブIDの追跡、S3バケット、結果のページネーションは含まれません。 同じコードで、1枚のJPEG画像も200ページのPDFも処理できます。 処理は完了するか例外をスローします。管理すべき"処理中"といった中間状態はありません。 バッチ処理の場合は、IronOCRはスレッドセーフであり、単一のParallel.ForEachを処理します。

IronTesseractのセットアップガイドでは設定について解説しており、PDF入力ガイドではページ範囲の選択、パスワードで保護されたPDF、およびデータベースやHTTPレスポンスから取得したPDFに対するストリームベースの入力について記載しています。

認証情報管理のオーバーヘッド

AWS TextractでOCR処理を開始するには、1ページも処理する前にIAMの設定を行う必要があります。

AWS Textractのアプローチ

DetectDocumentTextAsyncを呼び出す前に、開発者は:

  1. AWSアカウントを作成するか、既存のアカウントへのアクセス権を取得する
  2. textract:DetectDocumentTexttextract:AnalyzeDocument パーミッションを持ったIAMユーザーまたはロールを作成します
  3. アクセスキーIDとシークレットアクセスキーを生成し、安全に保管する
  4. 認証情報の解決を設定する — 環境変数、AWS 認証情報ファイル、または EC2 インスタンスプロファイル
  5. PDF を処理する場合: S3バケットを作成し、バケット ポリシーを設定し、s3:PutObject およびs3:DeleteObjectパーミッションを追加します
  6. セキュリティ基準を満たすために、認証情報のローテーションポリシーを実施する
  7. 各デプロイメント環境で認証情報を安全に保管する — 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
$vbLabelText   $csharpLabel

クレデンシャルが有効期限が切れたり、回転したり、誤設定されている場合、すべての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")
$vbLabelText   $csharpLabel

ライセンスキーは固定の文字列です。 動作中に有効期限が切れることはなく、ローテーションも不要で、管理すべき権限もありません。 ドキュメントを処理する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 OcrInputCropRectangle ゾーン用
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
$vbLabelText   $csharpLabel

構造化された結果ガイド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
$vbLabelText   $csharpLabel

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}%")
$vbLabelText   $csharpLabel

画像品質補正ガイド画像フィルターチュートリアルは、特定の文書タイプに最適な完全な前処理パイプラインと組み合わせを文書化しています。信頼度スコアの解釈と要素ごとの信頼度アクセスのために、信頼度スコアガイド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
$vbLabelText   $csharpLabel

これは利便性を高めるための包装であり、必須ではありません。 呼び出し元のコードが既にバックグラウンドスレッドで実行されているサーバー側処理の場合、同期呼び出しを直接行うことが推奨されます。

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のあらゆるユースケースを網羅したチュートリアルを提供します。

ご注意AWS Textract と Tesseract は、それぞれの所有者の登録商標です。 このサイトは、Amazon Web Services または Google によって提携、保証、支援されているものではありません。 すべての製品名、ロゴ、およびブランドは各所有者の所有物です。 比較は情報提供のみを目的としており、執筆時点で公開されている情報を反映しています。

よくある質問

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コールを更新します。ほとんどの移行はコードの複雑さを大幅に軽減します。

Kannaopat Udonpant
ソフトウェアエンジニア
ソフトウェアエンジニアになる前に、Kannapatは北海道大学で環境資源の博士号を修了しました。博士号を追求する間に、彼はバイオプロダクションエンジニアリング学科の一部である車両ロボティクスラボラトリーのメンバーになりました。2022年には、C#のスキルを活用してIron Softwareのエンジニアリングチームに参加し、IronPDFに注力しています。Kannapatは、IronPDFの多くのコードを執筆している開発者から直接学んでいるため、この仕事を大切にしています。同僚から学びながら、Iron Softwareでの働く社会的側面も楽しんでいます。コードやドキュメントを書いていない時は、KannapatはPS5でゲームをしたり、『The Last of Us』を再視聴したりしていることが多いです。

アイアンサポートチーム

私たちは週5日、24時間オンラインで対応しています。
チャット
メール
電話してね