C#でWindowsにTesseract OCRをインストールする方法
このガイドでは、 .NET開発者がGoogle Cloud VisionをIronOCRに置き換えるための手順を、オンプレミスのOCRエンジンとしてそのまま利用できる方法を説明します。認証情報の削除、Protobuf注釈解析の置き換え、バッチ注釈の簡素化、複数ページ文書の処理という、移行作業の大部分を占める4つの構造的変更について解説します。
Google Cloud Vision OCRから移行する理由
移行の決定は、ほぼ必ず次の2つの認識のいずれかから始まります。コンプライアンス監査によってクラウド上のドキュメント送信がブロックされるか、GCP認証情報、GCSバケット、非同期ポーリング、画像ごとの課金といった管理にかかる運用上のコストが、OCR自体のコストよりも高くなるかのどちらかです。
**サービスアカウントJSONキーのライフサイクル。**開発マシン、CI/CDパイプライン、ステージングサーバー、本番サーバー、Dockerコンテナ、Kubernetesポッドなど、アプリケーションのデプロイごとに、同じサービスアカウントJSONキーファイルが必要です。このファイルにはRSA秘密鍵が含まれています。 ソース管理には決して組み込んではならず、定期的にローテーションされ、ファイルシステムのアクセス許可によって保護され、ローテーションが行われる際にはすべての環境で同時に更新されなければならない。 侵害されたキーは、GCPコンソールで手動で取り消されるまで、APIへのアクセスを許可します。 IronOCRは、この操作インターフェース全体を、アプリケーション起動時に一度だけ設定される単一のライセンスキー文字列に置き換えます。
リクエストごとの課金が大規模に適用される。画像1,000枚あたり1.50ドル、PDFページ1ページあたり0.0015ドルという料金体系は、開発段階ではコストが目に見えないものの、生産段階では大きな負担となる。 月間20万ページを処理する文書処理パイプラインは、GCSストレージ料金やデータ送信料金を除いても、API料金だけで月額300ドルかかる。 その300ドルは毎月、無期限に支払われる。 IronOCRの永久ライセンスは、OCRを従量制の運用費用から、2年目や3年目には運用コストがかからない固定資本項目へと転換します。
GCS の PDF 用非同期パイプライン。Google Cloud Vision は、PDF を API への直接入力として受け付けません。 完全なパイプラインには、2番目のNuGetパッケージ(AsyncBatchAnnotateFilesAsync呼び出し、ポーリングループ、GCSからのJSON出力解析、およびクリーンアップステップが必要です。そのパイプラインは、テキストが抽出される前に50行以上のコードを必要とします。 IronOCRは、外部依存関係なしに、PDFを3行で同期的に読み取ります。
プロトバフシンボル結合。DOCUMENT_TEXT_DETECTION応答は、ページ、ブロック、段落、単語、シンボルのプロトバフ階層の内部にシンボルレベルでテキストを格納します。 段落テキストを読むには、5つのネストされたループを反復し、.SelectMany(w => w.Symbols).Select(s => s.Text)を呼び出す必要があります。 IronOCRは段落テキストをparagraph.Textとして返します - 型付き文字列プロパティです。
**1,800リクエスト毎分デフォルトクォータ。**デフォルトのクォータを超えるバッチワークロードは、超過ごとにパイプラインを60秒間停止させるStatusCode.ResourceExhausted応答を受け取ります。 割り当て量を増やすには、GCPコンソールからのリクエストとGoogleの承認が必要です。 IronOCRは利用可能なCPUコアの速度でローカルに処理を行うため、管理すべきクォータも、承認を得る必要も、レート制限のための再試行ロジックも不要です。
オフライン環境やエアギャップ環境ではサポートされていません。Google Cloud Visionは、Googleのエンドポイントへのインターネット接続が必要です。 エアギャップネットワーク、機密データセンター、および産業用制御システムでは、アーキテクチャの複雑さのレベルに関わらず、これを使用することはできません。 IronOCRは、最初のライセンス認証後、外部ネットワークへの接続を一切行わずに動作します。
基本的な問題
Google Cloud Visionでは、OCRコードの最初の行が実行される前に、ディスク上にJSONキーファイルが存在する必要があります。
// Google Cloud Vision: JSON key file deployed to every server before this line works
// GOOGLE_APPLICATION_CREDENTIALS="/etc/secrets/service-account.json" must be set
// Key contains RSA private key — rotate manually, revoke if compromised
_client = ImageAnnotatorClient.Create();
var image = Image.FromFile("document.jpg");
var response = _client.DetectText(image); // document leaves your infrastructure
string text = response[0].Description;
IronOCRは1つの文字列から始まり、完全にローカルマシン上で動作します。
// IronOCR: one string at startup, no key files, no environment variables
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read("document.jpg").Text; // local, no cloud
IronOCRとGoogle Cloud Vision OCR:機能比較
以下の表は、移行のビジネスケースを作成するチームにとって役立つ機能を直接マッピングしたものです。
| フィーチャー | Google Cloud Vision OCR | IronOCR |
|---|---|---|
| 処理場所 | Google Cloud(リモート) | オンプレミス(ローカル) |
| 認証 | サービスアカウントのJSONキーと環境変数 | ライセンスキー文字列 |
| PDF入力 | GCSへのアップロード + 非同期API | input.LoadPdf() 直接 |
| パスワードで保護されたPDF | サポートされていません | LoadPdf(path, Password: "...") |
| 複数ページTIFF入力 | 制限的 | input.LoadImageFrames() |
| 検索可能なPDF出力 | 不可 | result.SaveAsSearchablePdf() |
| 構造化データへのアクセス | Protobuf: ページ > ブロック > 段落 > 単語 > 記号 | result.Words(型付き.NETオブジェクト) |
| 段落テキストプロパティ | いいえ — シンボル連結が必要です | paragraph.Text 直接プロパティ |
| 信頼度スコア | シンボルごと(ループが必要) | result.Confidence, word.Confidence |
| 画像の自動前処理 | なし(機械学習が処理します) | 傾き補正、ノイズ除去、コントラスト調整、二値化、シャープ化 |
| 地域ベースのOCR | 在来作物なし | CropRectangle 上の OcrInput |
| バーコード読み取り | 別個のAPI機能 | ocr.Configuration.ReadBarCodes = true |
| レート制限 | デフォルト:1,800リクエスト/分 | なし(CPUバウンド) |
| オフライン/エアギャップ | なし | はい |
| 文書ごとの費用 | 画像1,000枚あたり1.50ドル。 PDFページあたり0.0015ドル | なし(永久ライセンス) |
| 対応言語 | 約50 | 125+ |
| FedRAMP認証 | 許可されていません | 該当なし(オンプレミス) |
| HIPAA準拠への道筋 | ビジネスアソシエイト契約が必要です | 第三者によるデータ処理は行いません。 |
| .NET Frameworkのサポート | .NET Standard 2.0以降 | .NET Framework 4.6.2以降および.NET 5/6/7/8/9 |
| 必要なNuGetパッケージ | Google.Cloud.Vision.V1 + Google.Cloud.Storage.V1 | IronOcr のみ |
| 価格設定モデル | リクエストごとの従量課金 | 永続的($999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited) |
クイックスタート:Google Cloud Vision OCR からIronOCRへの移行
ステップ 1: NuGet パッケージを置き換える
Google Cloud パッケージを削除します。
dotnet remove package Google.Cloud.Vision.V1
dotnet remove package Google.Cloud.Storage.V1
NuGetパッケージページからIronOCRをインストールしてください。
ステップ 2: 名前空間の更新
Google Cloud ネームスペースを IronOCR ネームスペースに置き換えてください:
// Before (Google Cloud Vision)
using Google.Cloud.Vision.V1;
using Google.Cloud.Storage.V1;
using Google.Protobuf;
using Grpc.Core;
// After (IronOCR)
using IronOcr;
ステップ 3: ライセンスの初期化
ライセンスの初期化をアプリケーションの起動時に1回だけ追加し、IronTesseractインスタンスが作成される前に実行します:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"本番環境では、環境変数またはシークレットマネージャからキーを読み取ります。
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable not set.");
コード移行の例
サービスアカウント認証情報の構成をなくす
Google Cloud Visionクライアントの初期化は一見1行のように見えますが、実際には広範な前提条件となるインフラストラクチャが必要です。 プロジェクトに参加するすべての開発者、すべてのデプロイ環境、およびすべての CI/CD パイプラインは、コンストラクタが例外をスローせずに完了する前に、完全な認証情報構成が設定されている必要があります。
Google Cloudのビジョンアプローチ:
using Google.Cloud.Vision.V1;
// Prerequisites before this class can be instantiated:
// 1. GCP project created and Vision API enabled in GCP Console
// 2. Service account created with roles/cloudvision.user IAM role
// 3. JSON key file downloaded to every server that runs this code
// 4. GOOGLE_APPLICATION_CREDENTIALS env var pointing to the JSON file
// 5. JSON file excluded from source control via .gitignore
// 6. Key rotation schedule established (recommended: 90 days)
// 7. Separate credentials per environment (dev/staging/prod)
public class DocumentOcrService
{
private readonly ImageAnnotatorClient _client;
private readonly string _projectId;
public DocumentOcrService(string projectId)
{
_projectId = projectId;
// Throws RpcException(StatusCode.PermissionDenied) if any prerequisite is missing
_client = ImageAnnotatorClient.Create();
}
public string ReadDocument(string imagePath)
{
var image = Image.FromFile(imagePath);
var response = _client.DetectText(image);
return response.Count > 0 ? response[0].Description : string.Empty;
}
}
IronOCRのアプローチ:
using IronOcr;
// Prerequisites: set the license key once at app startup
// No JSON files, no environment variables beyond the key, no GCP Console configuration
// No key rotation, no IAM roles, no per-environment credential sets
public class DocumentOcrService
{
private readonly IronTesseract _ocr;
public DocumentOcrService()
{
// IronTesseract is ready immediately — no external validation required
_ocr = new IronTesseract();
}
public string ReadDocument(string imagePath)
{
return _ocr.Read(imagePath).Text;
}
}
運用上の違いは具体的です:Google Cloud Visionは実行時にRpcExceptionの5つのカテゴリを生成します - Unauthenticated - 各カテゴリは異なるインフラ障害モードを表します。 IronOCRの障害モードは、OcrException(処理失敗)です。 設定オプションについてはIronTesseractのセットアップガイドを、ライセンスの詳細についてはIronOCRの製品ページを参照してください。
バッチ注釈リクエストを複数のフィーチャタイプに置き換える
Google Cloud Visionは複数の画像を1つのDOCUMENT_TEXT_DETECTIONの結果を収集する必要がある場合や、多くの画像を送信してラウンドトリップオーバーヘッドを最小化したい場合に使用します。 プロトバフ応答では、各AnnotateImageResponseをインデックスで元のリクエストに戻す必要があります。
Google Cloudのビジョンアプローチ:
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
public class BatchAnnotationService
{
private readonly ImageAnnotatorClient _client;
public BatchAnnotationService()
{
_client = ImageAnnotatorClient.Create();
}
public List<string> BatchAnnotateImages(string[] imagePaths)
{
// Build one request per image with TEXT_DETECTION feature
var requests = imagePaths.Select(path => new AnnotateImageRequest
{
Image = Image.FromFile(path),
Features =
{
new Feature { Type = Feature.Types.Type.TextDetection },
new Feature { Type = Feature.Types.Type.DocumentTextDetection }
}
}).ToList();
// Single round-trip for all images in the batch
var batchResponse = _client.BatchAnnotateImages(requests);
// Match responses back to requests by index
var results = new List<string>();
for (int i = 0; i < batchResponse.Responses.Count; i++)
{
var response = batchResponse.Responses[i];
if (response.Error != null)
{
// Per-item error in batch — must handle individually
results.Add($"Error on {imagePaths[i]}: {response.Error.Message}");
continue;
}
// Prefer DOCUMENT_TEXT_DETECTION full text if available
var fullText = response.FullTextAnnotation?.Text
?? response.TextAnnotations.FirstOrDefault()?.Description
?? string.Empty;
results.Add(fullText);
}
return results;
}
}
IronOCRのアプローチ:
using IronOcr;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
public class BatchAnnotationService
{
public List<string> BatchAnnotateImages(string[] imagePaths)
{
var results = new ConcurrentDictionary<int, string>();
// Parallel processing — no batch size limit, no network round-trips
Parallel.For(0, imagePaths.Length, i =>
{
var ocr = new IronTesseract(); // thread-safe: one instance per thread
results[i] = ocr.Read(imagePaths[i]).Text;
});
// Reconstruct in original order
return Enumerable.Range(0, imagePaths.Length)
.Select(i => results[i])
.ToList();
}
public OcrResult BatchAsDocument(string[] imagePaths)
{
// Load all images into a single OcrInput for combined document output
using var input = new OcrInput();
foreach (var path in imagePaths)
input.LoadImage(path);
return new IronTesseract().Read(input);
}
}
IronOCRは、ネットワークオーバーヘッドを一切発生させることなく、CPUコア間でバッチ処理を並列実行します。 BatchSizeの上限も、応答インデックスの一致も、ネットワークまたは認証情報の失敗に対する項目ごとのエラーハンドリングもありません。 複数の画像を単一の論理ドキュメントに結合するワークロードの場合(例:個々のJPEGとして提出されたスキャンされた複数ページのフォーム)、OcrResultを返します。 マルチスレッドの例では、並列処理のパフォーマンスベンチマークを示しています。
Protobufワードレベル注釈抽出の移行
Google Cloud Visionの単語レベルの境界ボックスと信頼度データを取得するには、ページ、ブロック、段落、単語、シンボルというProtobufの階層全体をたどる必要があります。 単語テキストを抽出するには、各単語からシンボルを連結する必要があります - .Textプロパティがありません。 バウンディングボックスの座標は、個別のX、Y、幅、高さのフィールドではなく、BoundingPolyリストとして保存されます。
Google Cloudのビジョンアプローチ:
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
public record WordAnnotation(string Text, int X, int Y, int Width, int Height, float Confidence);
public class WordLevelExtractor
{
private readonly ImageAnnotatorClient _client;
public WordLevelExtractor()
{
_client = ImageAnnotatorClient.Create();
}
public List<WordAnnotation> ExtractWordAnnotations(string imagePath)
{
var image = Image.FromFile(imagePath);
var annotation = _client.DetectDocumentText(image);
var words = new List<WordAnnotation>();
// Navigate: Pages -> Blocks -> Paragraphs -> Words
foreach (var page in annotation.Pages)
{
foreach (var block in page.Blocks)
{
foreach (var paragraph in block.Paragraphs)
{
foreach (var word in paragraph.Words)
{
// Word.Text does not exist — must concatenate Symbols
var text = string.Concat(word.Symbols.Select(s => s.Text));
// BoundingPoly has Vertices, not X/Y/Width/Height
var vertices = word.BoundingBox.Vertices;
int x = vertices[0].X;
int y = vertices[0].Y;
int width = vertices.Count > 1 ? vertices[1].X - vertices[0].X : 0;
int height = vertices.Count > 2 ? vertices[2].Y - vertices[0].Y : 0;
words.Add(new WordAnnotation(text, x, y, width, height, word.Confidence));
}
}
}
}
return words;
}
}
IronOCRのアプローチ:
using IronOcr;
using System.Collections.Generic;
public record WordAnnotation(string Text, int X, int Y, int Width, int Height, double Confidence);
public class WordLevelExtractor
{
private readonly IronTesseract _ocr;
public WordLevelExtractor()
{
_ocr = new IronTesseract();
}
public List<WordAnnotation> ExtractWordAnnotations(string imagePath)
{
var result = _ocr.Read(imagePath);
// Words are a flat collection — no hierarchy traversal, no symbol concatenation
return result.Words.Select(w => new WordAnnotation(
Text: w.Text, // direct string property
X: w.X,
Y: w.Y,
Width: w.Width,
Height: w.Height,
Confidence: w.Confidence // double, no conversion needed
)).ToList();
}
}
Google Cloud Vision版におけるシンボル連結ループは、設計上の選択ではなく、Protobufスキーマによって要求されるものです。 Word.Textは応答オブジェクトのプロパティではありません。 単語レベルAPIを使用するチームのすべてが同等のループを書きます。IronOCRのConfidenceを一級プロパティとして公開します。 読み取り結果ガイドには、あらゆる粒度レベルで利用可能なプロパティセット全体が記載されています。
複数ページTIFF処理から検索可能なPDF出力へ
Google Cloud Visionは、複数ページのTIFFファイルを連続した一連の画像として扱い、各画像に対して個別のAPI呼び出しが必要となります。 TIFFファイルを受け取り、すべてのフレームに対して構造化された出力を返す単一のAPI呼び出しは存在しません。 Google Cloud Visionの検索結果から検索可能なPDFを生成するには、別途PDF生成ライブラリが必要です。APIはテキストのみを返します。
Google Cloudのビジョンアプローチ:
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
using System.Drawing; // for TIFF frame extraction
using System.Drawing.Imaging;
public class TiffProcessingService
{
private readonly ImageAnnotatorClient _client;
public TiffProcessingService()
{
_client = ImageAnnotatorClient.Create();
}
public List<string> ProcessMultiPageTiff(string tiffPath)
{
var pageTexts = new List<string>();
// Load TIFF and extract frames manually using System.Drawing
using var tiff = System.Drawing.Image.FromFile(tiffPath);
var frameDimension = new FrameDimension(tiff.FrameDimensionsList[0]);
int frameCount = tiff.GetFrameCount(frameDimension);
for (int i = 0; i < frameCount; i++)
{
tiff.SelectActiveFrame(frameDimension, i);
// Save each frame to a temp file — Vision API does not accept TIFF frames directly
var tempPath = Path.Combine(Path.GetTempPath(), $"tiff-frame-{i}.jpg");
tiff.Save(tempPath, ImageFormat.Jpeg);
// One API call per frame — each call = one unit of quota
var visionImage = Google.Cloud.Vision.V1.Image.FromFile(tempPath);
var response = _client.DetectText(visionImage);
pageTexts.Add(response.FirstOrDefault()?.Description ?? string.Empty);
File.Delete(tempPath);
}
// Producing a searchable PDF requires a separate library (e.g., iTextSharp)
// Google Cloud Vision has no PDF output capability
return pageTexts;
}
}
IronOCRのアプローチ:
using IronOcr;
public class TiffProcessingService
{
private readonly IronTesseract _ocr;
public TiffProcessingService()
{
_ocr = new IronTesseract();
}
public string ProcessMultiPageTiff(string tiffPath)
{
using var input = new OcrInput();
// LoadImageFrames handles all TIFF frames in one call — no temp files, no frame loop
input.LoadImageFrames(tiffPath);
var result = _ocr.Read(input);
return result.Text;
}
public void ProcessMultiPageTiffToSearchablePdf(string tiffPath, string outputPdfPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
var result = _ocr.Read(input);
// Google Cloud Vision has no equivalent — this single call produces a searchable PDF
result.SaveAsSearchablePdf(outputPdfPath);
}
public void ProcessLowQualityTiff(string tiffPath, string outputPdfPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
// Preprocessing before OCR improves accuracy on degraded scans
input.Deskew();
input.DeNoise();
input.Contrast();
var result = _ocr.Read(input);
result.SaveAsSearchablePdf(outputPdfPath);
}
}
Google Cloud Vision 版では、フレーム抽出に System.Drawing が必要となり、一時的な JPEG ファイルがディスクに書き込まれ、フレームごとに 1 つの API 呼び出し (フレーム数に比例してクォータを消費)、プレーン テキスト以外の出力を生成するために別途 PDF ライブラリが必要になります。 IronOCRは、SaveAsSearchablePdfを介して検索可能なPDF出力を生成します。 スキャンされたアーカイブTIFFドキュメントの場合、ProcessLowQualityTiffの前処理パイプラインは、一度の通過で最も一般的な品質問題に対処します。 完全なAPIについては、 TIFFおよびGIF入力と検索可能なPDF出力に関するドキュメントを参照してください。
処理速度制限付きバッチ移行(進捗状況追跡機能付き)
本番環境規模では、Google Cloud Visionのデフォルトの1分あたり1,800リクエストというクォータでは、スロットリングを行うか、指数バックオフを用いた再試行ロジックを実装する必要があります。 一晩で5,000件の文書を処理すると、割り当て量を何度も超過することになります。 割り当て量を超過するたびに、パイプラインは強制的に60秒間停止します。 IronOCRには処理速度の制限はありません。パイプラインの制限はCPUコア数と利用可能なスレッド数のみです。
Google Cloudのビジョンアプローチ:
using Google.Cloud.Vision.V1;
using Grpc.Core;
using System.Collections.Generic;
public class ThrottledBatchProcessor
{
private readonly ImageAnnotatorClient _client;
private const int MaxRequestsPerMinute = 1800;
private const int RetryDelayMs = 60_000;
public ThrottledBatchProcessor()
{
_client = ImageAnnotatorClient.Create();
}
public async Task<Dictionary<string, string>> ProcessWithThrottlingAsync(
string[] imagePaths,
IProgress<(int completed, int total)> progress)
{
var results = new Dictionary<string, string>();
int completed = 0;
foreach (var path in imagePaths)
{
bool succeeded = false;
while (!succeeded)
{
try
{
var image = Google.Cloud.Vision.V1.Image.FromFile(path);
var response = _client.DetectText(image);
results[path] = response.FirstOrDefault()?.Description ?? string.Empty;
succeeded = true;
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.ResourceExhausted)
{
// Rate limit exceeded — wait and retry
await Task.Delay(RetryDelayMs);
}
}
progress.Report((++completed, imagePaths.Length));
}
return results;
}
}
IronOCRのアプローチ:
using IronOcr;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class BatchProcessor
{
public Dictionary<string, string> ProcessBatch(
string[] imagePaths,
IProgress<(int completed, int total)> progress)
{
var results = new ConcurrentDictionary<string, string>();
int completed = 0;
// No rate limits — full parallelism, no retry logic needed
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
results[imagePath] = ocr.Read(imagePath).Text;
progress.Report((Interlocked.Increment(ref completed), imagePaths.Length));
});
return new Dictionary<string, string>(results);
}
public void ProcessBatchToSearchablePdfs(
string[] imagePaths,
string outputDirectory)
{
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
var outputPath = Path.Combine(
outputDirectory,
Path.GetFileNameWithoutExtension(imagePath) + "-searchable.pdf");
result.SaveAsSearchablePdf(outputPath);
});
}
}
Google Cloud Vision版はシーケンシャル処理を採用しています。これは、並列リクエストを行うとレート制限のリスクが増大するためです。 各ResourceExhausted例外は、丸々60秒の停止を追加します。 5,000件の文書が処理上限に10回達すると、10分間の待機時間が発生する。 IronOCRのバージョンでは、待機時間なしで利用可能なすべてのコアで並列処理が行われます。 長時間実行バッチの場合、進捗追跡APIは、手動のInterlocked.Increment配線を必要とせずに組み込みの進捗コールバックを提供します。 バッチスキャンでの画像品質問題に対しては、画像品質修正ガイドが、各Read呼び出しの前に追加できる前処理パイプラインをカバーします。
Google Cloud Vision OCR API からIronOCRへのマッピングリファレンス
| Google Cloud Vision | IronOCR | ノート |
|---|---|---|
ImageAnnotatorClient.Create() | new IronTesseract() | クライアントの初期化; 認証ファイル不要 |
Image.FromFile(path) | _ocr.Read(path) または input.LoadImage(path) | IronTesseractでの直接パス読み取りが利用可能 |
_client.DetectText(image) | _ocr.Read(path).Text | TEXT_DETECTION 同等 |
_client.DetectDocumentText(image) | _ocr.Read(path) | DOCUMENT_TEXT_DETECTION 同等; モードは自動です |
response[0].Description | result.Text | 文書全文 |
TextAnnotation | OcrResult | 最上位の結果コンテナ |
annotation.Text | result.Text | 全文文字列 |
annotation.Pages[i] | result.Pages[i] | ページごとのアクセス |
page.Blocks[i].Paragraphs[j] | result.Paragraphs[i] | IronOCRは段落をフラットなコレクションとして表示します |
paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text) | paragraph.Text | 直接文字列プロパティ; 記号の反復なし |
word.BoundingBox.Vertices | word.X, word.Y, word.Width, word.Height | 頂点リストの代わりに離散的な整数プロパティを使用する |
word.Confidence | word.Confidence | 単語ごとの信頼度スコア |
page.Confidence | result.Confidence | 全体的な結果に対する信頼 |
Feature.Types.Type.DocumentTextDetection | 自動翻訳 | IronOCRは処理モードを自動選択します |
BatchAnnotateImagesRequest | Parallel.ForEach + new IronTesseract() スレッドごと | 並列ローカル処理 バッチサイズの上限なし |
_client.BatchAnnotateImages(requests) | new IronTesseract().Read(input) マルチイメージ OcrInputで | 複数画像入力のための単一呼び出し |
AsyncBatchAnnotateFilesAsync() | input.LoadPdf(); _ocr.Read(input) | PDF処理は同期的に行われます。 GCSは不要 |
StorageClient.Create() | 不要 | GCSへの依存なし |
storageClient.UploadObjectAsync() | 不要 | PDFファイルはローカルパスまたはストリームから直接読み込まれます。 |
operation.PollUntilCompletedAsync() | 不要 | 処理は同期的に行われます |
RpcException (StatusCode.ResourceExhausted) | 該当なし | レート制限なし |
RpcException (StatusCode.PermissionDenied) | 該当なし | 実行時認証なし |
GOOGLE_APPLICATION_CREDENTIALS 環境変数 | IronOcr.License.LicenseKey | ファイルパスではなく、文字列の代入です。 |
一般的な移行の問題と解決策
問題1:コンストラクタがGOOGLE_APPLICATION_CREDENTIALSなしで例外をスローする
Google Cloud Vision: 環境変数が設定されていないか無効なファイルを指す場合、StatusCode.PermissionDeniedでスローします。この失敗はスタートアップ時に発生し、最初のAPI呼び出し時ではなく、どれか1つの環境に資格情報が欠けているとアプリケーション全体が初期化に失敗します。
解決策: Google Cloud Visionパッケージを削除した後、すべての環境設定、CI/CDパイプラインシークレット、Kubernetesシークレット、およびDocker ComposeファイルからGOOGLE_APPLICATION_CREDENTIALSのすべての参照を削除します。 単一のIRONOCR_LICENSE環境変数で置き換えます:
// Remove this from every deployment environment:
// GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
// Add this once at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable is required.");
問題2:名前空間削除後にProtobufシンボル連結コードが壊れる
Google Cloud Vision: パラグラフまたは単語のテキストをGoogle.Cloud.Vision.V1名前空間を削除した後にコンパイルエラーを生成します。 これらの呼び出しは、APIレスポンスを受け取ったヘルパークラスやサービスクラス全体に分散されます。
解決策: コードベース内のすべてのw.Symbolsパターンを検索し、IronOCR結果オブジェクトの直接プロパティアクセスで置き換えます。 結果の読み取りハウツーガイドでは、OcrResult.Wordのすべての利用可能なプロパティをカバーしています:
# Find all Protobuf symbol concatenation patterns
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .
grep -rn "w\.Symbols\.Select" --include="*.cs" .
各出現箇所を置換します。
// Before: symbol concatenation required by Protobuf schema
var text = string.Join("", paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text));
// After: direct property on OcrResult.Paragraph
var text = paragraph.Text;
問題3:Storage.V1削除後、PDF処理コードがコンパイルされない
Google Cloud Vision: PollUntilCompletedAsyncを参照しているすべてのコードはコンパイルに失敗します。このコードは複数のサービスクラスにまたがる可能性があり、通常、単一の大きな変更ブロックを表しています。
解決策: GCSパイプライン全体を削除します。50Plus非同期メソッドを、 IronOCRの3行の同等のメソッドに置き換えます。 呼び出し元互換性のために非同期シグネチャを維持していたコードの場合、Task.Runでラップします:
// Delete: StorageClient, GCS upload, AsyncBatchAnnotateFilesAsync,
// PollUntilCompletedAsync, output download, DeleteObjectAsync
// Replace with:
public async Task<string> ProcessPdfAsync(string pdfPath)
{
return await Task.Run(() =>
{
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return new IronTesseract().Read(input).Text;
});
}
新しいコードの場合は、ネイティブ非同期OCRサポートをTask.Runラッパーの代わりに使用します。 PDF入力ガイドでは、ページ範囲の選択方法とパスワードで保護されたPDFの読み込み方法について説明しています。
問題4:レート制限再試行ロジックは不要になりました
Google Cloud Vision: 1,800リクエスト毎分クォータを処理するためにStatusCode.ResourceExhaustedでキャッチし、待って再試行パターンを実装するコードが書かれていました。 この再試行ロジックは、ミドルウェア、パイプラインのステップ、またはバッチ処理ループに組み込まれる場合があります。
**解決策:**クォータエラーに関連するすべての再試行ロジックを削除します。 IronOCRは外部クォータなしでローカル処理を実行します。 エラーハンドラ契約は、RpcExceptionの5つのケースから2つに変わります:
// Remove: all RpcException handlers for ResourceExhausted, PermissionDenied,
// Unavailable, DeadlineExceeded, Unauthenticated
// IronOCR error surface:
try
{
var result = new IronTesseract().Read(imagePath);
if (result.Confidence < 50)
input.DeNoise(); // add preprocessing for low-confidence results
return result.Text;
}
catch (IOException ex)
{
// File not found or locked
throw new InvalidOperationException($"Cannot read: {imagePath}", ex);
}
catch (IronOcr.Exceptions.OcrException ex)
{
// Processing failure — not a transient network error
throw new InvalidOperationException($"OCR failed: {ex.Message}", ex);
}
問題5:複数ページTIFFにはフレーム抽出ループが必要
Google Cloud Vision: 既存のTIFF処理コードは、通常、System.Drawing.Imageを使用してフレームを抽出し、各フレームを一時ディレクトリにJPEGとして保存し、各JPEGを個別のAPI呼び出しとして提出し、その後一時ファイルを削除します。 このパターンはフレームごとに1つのクォータユニットを消費し、クラッシュ時に孤立した一時ファイルを残す可能性があります。
解決策: フレームの抽出ループと一時ファイル管理をinput.LoadImageFrames()で置き換えます。 System.Drawing フレームループ全体が削除されます。
// Remove: System.Drawing frame extraction, temp file writes, per-frame API calls
// Replace with:
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // all frames, no temp files
var result = new IronTesseract().Read(input);
フレーム範囲の選択を含む複数フレーム処理オプションについては、 TIFFおよびGIF入力ガイドを参照してください。
問題6:BoundingPolyの頂点計算の中断
Google Cloud Vision: vertices[2].Y - vertices[0].Y。 移行後、これらの式はIronOCRでは同等のものがありませんVerticesが存在しないためです。
**解決策:**頂点演算を直接整数プロパティに置き換える。 計算は不要です。
// Before: vertex index arithmetic
int x = word.BoundingBox.Vertices[0].X;
int y = word.BoundingBox.Vertices[0].Y;
int width = word.BoundingBox.Vertices[1].X - word.BoundingBox.Vertices[0].X;
int height = word.BoundingBox.Vertices[2].Y - word.BoundingBox.Vertices[0].Y;
// After: direct properties
int x = word.X;
int y = word.Y;
int width = word.Width;
int height = word.Height;
Google Cloud Vision OCR移行チェックリスト
移行前
変更を加える前に、コードベースを監査して、Google Cloud Visionへの依存関係をすべて特定してください。
# Find all Google Cloud Vision namespace imports
grep -rn "using Google.Cloud.Vision" --include="*.cs" .
grep -rn "using Google.Cloud.Storage" --include="*.cs" .
grep -rn "using Grpc.Core" --include="*.cs" .
# Find ImageAnnotatorClient usage
grep -rn "ImageAnnotatorClient" --include="*.cs" .
# Find GCS pipeline code
grep -rn "StorageClient\|UploadObjectAsync\|DeleteObjectAsync" --include="*.cs" .
grep -rn "AsyncBatchAnnotateFilesAsync\|PollUntilCompleted" --include="*.cs" .
# Find Protobuf symbol concatenation
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .
# Find BoundingPoly vertex calculations
grep -rn "BoundingPoly\|BoundingBox\.Vertices" --include="*.cs" .
# Find rate limit retry handlers
grep -rn "ResourceExhausted\|StatusCode\." --include="*.cs" .
# Find environment variable references
grep -rn "GOOGLE_APPLICATION_CREDENTIALS" .
開始前に記入する在庫確認メモ:
- OCR入出力用に作成されたすべてのGCSバケットを一覧表示し、移行後にクリーンアップをスケジュールする サービスアカウントのメールアドレスを記録しておき、移行後にGCPコンソールで無効化できるようにします。
GOOGLE_APPLICATION_CREDENTIALSが設定されているすべての環境を特定する- 設定からGCPプロジェクトIDまたはバケット名を読み取るコードがあれば、移行後に削除してください。
コードの移行
- すべてのプロジェクトから
Google.Cloud.Vision.V1NuGetパッケージを削除する - すべてのプロジェクトから
Google.Cloud.Storage.V1NuGetパッケージを削除する - OCRを実行するすべてのプロジェクトに
IronOcrNuGetパッケージをインストールする - アプリケーション起動時に
IronOcr.License.LicenseKey初期化を追加する - すべての
using IronOcrに置き換える - すべての
using Grpc.Coreインポートを置き換える new IronTesseract()に置き換える- すべてのGCSパイプラインメソッド(
UploadObjectAsync、非同期アノテーション、ポーリング、ダウンロード、削除)を削除する - すべてのPDF処理パス用の
input.LoadPdf()を置き換える(非同期GCSオーケストレーションを削除し) - すべてのプロトバフシンボル結合ループを
OcrResultオブジェクト上で直接置き換える word.Heightに置き換えるUnauthenticated- フレームごとのTIFFループを
input.LoadImageFrames()で置き換える - 順次バッチループをスレッドごとに
Parallel.ForEachに変換する GOOGLE_APPLICATION_CREDENTIALSをすべての環境設定、CI/CDパイプライン、Docker Composeファイル、およびKubernetesシークレットから削除する
移行後
- エラーハンドリングコードに
GoogleApiExceptionのタイプが参照されていないことを確認する - すべてのデプロイメント環境設定から
GOOGLE_APPLICATION_CREDENTIALSが存在しないことを確認する - 本番環境で使用されているものと同じサンプル文書セットでOCRパイプラインを実行し、テキスト出力の品質を比較する。
- GCS非同期パイプラインで以前に処理されたドキュメントでPDF処理をテストし、テキスト出力が同一であることを確認します。
- @
input.LoadPdf(path, Password: "...")でパスワード保護されたPDFをテストする - 以前はサポートされていませんでした input.LoadImageFrames()を使用し、すべてのフレームが処理されていることを確認して、マルチページTIFF処理をテストする バッチプロセッサを代表的なサンプルで実行し、出力品質が以前の結果と一致することを確認します。- あなたのドキュメントコーパスに対して、
result.Confidenceの値が許容範囲内にあることを確認する - 以前は別のPDFライブラリが必要だったドキュメントに対して、
result.SaveAsSearchablePdf()を使用して検索可能なPDF出力を検証する - 外部インターネット接続のない環境でアプリケーションを実行し、OCRが正しく動作することを確認してください。
IronOCRへの移行の主なメリット
認証情報の表面がゼロファイルに縮小されました。 構造移行後、インフラにはJSONキーファイル、GCSバケット設定、IAMロール、サービスアカウント、およびGOOGLE_APPLICATION_CREDENTIALS環境変数がありません。 認証情報全体は、ライセンスキー文字列を含む1つの環境変数によってのみ管理されます。 Google Cloud Visionでは必須の定期操作であったキーローテーションは、もはや適用されない概念となりました。 複数の地域やクラウドプロバイダーで事業を展開するチームにとって、導入構成の複雑さの軽減は即座に実感できる。
外部依存関係なしでPDFおよびTIFFを処理。GCS非同期パイプラインとSystem.Drawing TIFFフレームループは完全に削除されています。 input.LoadImageFrames()は置換です - 両方とも同期的で、両方ともローカルで、結果までの呼び出しから3行です。 Google Cloud Visionでは不可能だったパスワード保護付きPDFも、たった1つの追加パラメータで実現可能になりました。 PDF OCRガイドとTIFF入力ガイドには、入力APIの全内容が記載されています。
CPU速度でのバッチ処理。1分あたり1,800件のリクエスト制限と、必須の60秒間の再試行待機が撤廃されたことで、これまで処理速度に制約されていたバッチジョブが、利用可能なプロセッサコアの速度で実行されるようになりました。 16コアを搭載したマシンは、外部承認を一切必要とせずに、16個の文書を同時に処理できる。 IronTesseractインスタンスを持つものがスロットルされた順次ループの直接的な置き換えです。速度最適化ガイドでは、特定の文書タイプのスループットを調整するエンジン設定オプションをカバーしています。
Protobufを使用しない構造化データ。 すべてのCharactersを公開し、Protobuf名前空間の依存関係はなく、シンボル結合もなく、バウンディングボックスに対する頂点計算もありません。 段落テキストを抽出するために以前20行のネストされたループを必要としたコードはresult.Paragraphs.Select(p => p.Text)に減少します。 ドキュメントのレイアウト分析にワードレベルのポジショニングが必要なユースケースには、word.Heightが直接利用可能です。 OCR結果機能ページには、結果モデルに含まれるすべてのプロパティが記載されています。
検索可能なPDF出力機能が組み込まれています。Google Cloud Visionはテキストのみを返すため、検索可能なPDFを生成するには、別のPDF生成ライブラリが必要となり、 NuGet依存関係の追加、学習すべきAPIの追加、評価すべきライセンスの追加が必要でした。 IronOCRのresult.SaveAsSearchablePdf(outputPath)は、どんなOCR結果からも完全に検索可能なPDFを1行で生成します。ドキュメントのアーカイブワークフローや法的発見のパイプラインでは、これにより依存の一部が完全に排除されます。 検索可能なPDFサンプルは、パターンを最初から最後まで示しています。
規制対象業界におけるデータ主権。IronOCRで処理された文書は、サーバーから外部に送信されることはありません。 HIPAAの対象となる医療記録、ITARで規制される技術データ、CMMCの対象となる防衛請負業者の資料、弁護士と依頼人の間の秘匿特権のある法的文書、およびPCI-DSSの対象となる財務記録については、オンプレミスアーキテクチャでは、サードパーティデータ処理業者というカテゴリがコンプライアンスの範囲から完全に除外されます。 交渉すべきビジネスアソシエイト契約も、締結すべきデータ処理契約も、確認すべきGoogleのデータ保持ポリシーもありません。 IronOCRのドキュメントハブでは、データ所在地の要件が適用されるDocker、Linux、Azure、およびAWS環境におけるデプロイ構成について解説しています。
