Dynamsoft OCRからIronOCRへの移行
このガイドでは、Dynamsoft Label Recognizer からIronOCRへ移行する.NET開発者向けの完全な移行パスを提供します。 本書では、 NuGetパッケージの置換、名前空間の更新、ライセンスの初期化、および一般的な機能比較とは異なるシナリオにおける実践的なコード移行の例を取り上げています。これには、テンプレート構成の削除、ランタイム設定 JSON の削除、リージョン定義の移行、および結果解析の簡素化が含まれます。
Dynamsoft OCRから移行する理由
Dynamsoft Label Recognizerは、特定の用途に特化した専用ツールです。その高い精度は、限定的な導入環境では有効ですが、アプリケーションの範囲が当初のMRZやVINのユースケースを超えて拡大すると、問題が生じます。
ランタイム設定JSONはメンテナンスサーフェスです。 すべてのDynamsoft認識ワークフローはAppendSettingsFromStringから始まり、パラメータ配列、文字モデル、地域参照を宣言するJSONドキュメントをロードします。 これらのJSONテンプレートは、バイナリにコンパイルされるのではなく、個別のデプロイメント成果物です。 これらは、DynamsoftがSDKのバージョン間でテンプレートスキーマを変更する際に、バージョン管理、デプロイメントパイプライン管理、および手動更新を必要とする。 IronOCRはゼロ構成ファイルを必要としません: .Read()を呼び出すと、エンジンが適切な設定を自動的に選択します。
年間サブスクリプション料金体系。Dynamsoftラベル認識ソフトウェアのライセンス料金は、デバイス1台あたり年間599ドル以上です。 永久的な選択肢は存在しない。 5台のデバイスで構成される処理クラスターの年間費用は2,995ドル以上で、その予算はMRZと構造化ラベル認識のみを対象としている。 バーコード用のDynamsoft Barcode Reader、またはエッジ補正用のDynamsoft Document Normalizerを追加すると、年間費用は製品数に応じて増加します。 IronOCRのLiteライセンスは一回限りの料金で$999、一般的なOCR、構造化ラベル、バーコード、ネイティブPDF、検索可能なPDF出力、および125以上の言語を1つのパッケージでカバーします。
地域定義にはJSONテンプレートが必要です。 Dynamsoftでの認識地域の定義は、JSONブロックLabelRecognizerParameterArrayで参照し、イメージ処理が始まる前にドキュメント全体をロードすることを意味します。 IronOCRはOcrInput.LoadImageに直接渡す単一のコンストラクタを使用します。 地域を変更するには、数値を1つ編集するだけで済み、JSONドキュメントを再解析する必要はありません。
結果の解析は完全にあなたの責任です。 LineResult配列を返します。 必要な構造(フィールドオフセット、日付変換、チェックデジット検証、名前区切り文字の処理など)はすべて、生の出力の上にカスタム解析コードを追加する必要があります。 IronOCRは.Charactersを型付きのコレクションとしてバウンディングボックス座標、信頼スコア、およびフォントメタデータがすでに入力された状態で返します。
ネイティブなPDFサポートがないため、隠れた依存関係が生じます。Dynamsoft Label RecognizerにはPDF入力機能がありません。 処理パイプラインに送られてくるPDFファイルはすべて、最初のDynamsoft呼び出しの前に、各ページをビットマップにレンダリングするための外部ライブラリ、ページ反復ループ、および結果集約ステップを必要とします。 IronOCRはPDFをネイティブに読み取ります: new IronTesseract().Read("document.pdf")は、二次依存、レンダリングループ、または一時画像フォルダーなしで、すべてのページを処理します。
マルチプロダクトの初期化ブロックはスコープの拡大と共に成長します。 構造化ラベル、バーコード、ドキュメントの正規化を処理するDynamsoftアプリケーションは、3つの静的InitLicense呼び出しをスタートアップ時に持ち、3つのディスポーザルチェーン、3つの独立したSDKバージョン依存を持ちます。 SDKをアップグレードするということは、すべての製品間で連携を取る必要があることを意味します。 IronOCRは、アプリケーションがどの機能を使用するかに関わらず、初期化行が1つとパッケージバージョンが1つだけ存在する。
基本的な問題
Dynamsoftでは、認識を開始する前に、実行時にJSON設定ファイルが読み込まれる必要があります。
// Dynamsoft: JSON template required before any image processing
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
string settings = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Label"",
""ReferenceRegionNameArray"": [""VinRegion""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VinRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [5, 40],
""SecondPoint"": [95, 40],
""ThirdPoint"": [95, 60],
""FourthPoint"": [5, 60]
}
}]
}";
recognizer.AppendSettingsFromString(settings); // fails silently if JSON is malformed
var results = recognizer.RecognizeFile(imagePath);
// Dynamsoft: JSON template required before any image processing
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
string settings = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Label"",
""ReferenceRegionNameArray"": [""VinRegion""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VinRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [5, 40],
""SecondPoint"": [95, 40],
""ThirdPoint"": [95, 60],
""FourthPoint"": [5, 60]
}
}]
}";
recognizer.AppendSettingsFromString(settings); // fails silently if JSON is malformed
var results = recognizer.RecognizeFile(imagePath);
' Dynamsoft: JSON template required before any image processing
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
Dim settings As String = "{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Label"",
""ReferenceRegionNameArray"": [""VinRegion""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VinRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [5, 40],
""SecondPoint"": [95, 40],
""ThirdPoint"": [95, 60],
""FourthPoint"": [5, 60]
}
}]
}"
recognizer.AppendSettingsFromString(settings) ' fails silently if JSON is malformed
Dim results = recognizer.RecognizeFile(imagePath)
// IronOCR: no JSON, no template files — region is a constructor argument
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var region = new CropRectangle(x: 50, y: 400, width: 900, height: 200);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
// IronOCR: no JSON, no template files — region is a constructor argument
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var region = new CropRectangle(x: 50, y: 400, width: 900, height: 200);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
Imports IronOcr
' IronOCR: no JSON, no template files — region is a constructor argument
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim region As New CropRectangle(x:=50, y:=400, width:=900, height:=200)
Using input As New OcrInput()
input.LoadImage(imagePath, region)
Dim result = New IronTesseract().Read(input)
Console.WriteLine(result.Text)
End Using
IronOCRとDynamsoft OCR:機能比較
以下の表は、2つのライブラリ間の機能的な差を包括的に示したものです。
| フィーチャー | Dynamsoft ラベル認識ツール | IronOCR |
|---|---|---|
| 一般文書OCR | サポートされていません | フルサポート |
| MRZ認識 | 特殊出力(生テキスト出力) | 構造化フィールドを組み込んでいます |
| VIN認識 | 専門的な(テンプレートが必要) | 領域ターゲティング機能を備えた標準OCR |
| 工業用ラベルの読み取り | 専門的な(テンプレートが必要) | はい、CropRectangle経由 |
| ランタイム設定の構成 | 必須 (JSON 経由 AppendSettingsFromString) |
不要 |
| テンプレートのデプロイ成果物 | 必須(JSONファイル) | None |
| ネイティブPDF入力 | サポートされていません | はい |
| パスワードで保護されたPDF | サポートされていません | はい |
| 複数ページTIFF入力 | 手作業によるページの反復 | ネイティブ (LoadImageFrames) |
| 検索可能なPDF出力 | サポートされていません | はい (SaveAsSearchablePdf) |
| バーコード読み取り | 別製品(Dynamsoft バーコードリーダー) | 組み込み (ReadBarCodes = true) |
| 自動前処理 | 制限的 | はい(傾き補正、ノイズ除去、コントラスト補正、二値化、シャープ化、膨張補正、収縮補正) |
| 構造化された出力(単語、行、段落) | 生のLineResultテキスト文字列 |
座標と信頼度を含めて完全に入力済み |
| 言語サポート | 限定(ラテン語:MRZ) | 125以上の言語に対応し、 NuGetパッケージとして提供されています。 |
| 多言語同時通訳 | サポートされていません | はい (OcrLanguage.French + OcrLanguage.German) |
| 信頼度スコア | 行ごと | 単語ごと、行ごと、ページごと |
| hOCRエクスポート | サポートされていません | はい |
| ライセンスモデル | 年間購読料(端末1台あたり年間599ドル以上) | 永続的 ($999 一回限り、Lite層) |
| 複数の製品が必要です | はい(完全カバーには3歳以上) | いいえ(1個口) |
| .NET Frameworkのサポート | .NET Framework 4.x以降 | .NET Framework 4.6.2以降、 .NET 5/6/7/8/9 |
| クロスプラットフォーム展開 | はい | はい(Windows、Linux、macOS、Docker、Azure、AWS) |
| NuGetパッケージ | Dynamsoft.LabelRecognizer |
IronOcr |
クイックスタート:Dynamsoft OCRからIronOCRへの移行
ステップ 1: NuGet パッケージを置き換える
Dynamsoftパッケージを削除してください。
dotnet remove package Dynamsoft.LabelRecognizer
dotnet remove package Dynamsoft.LabelRecognizer
NuGetギャラリーからIronOCRをインストールしてください。
dotnet add package IronOcr
ステップ 2: 名前空間の更新
// Before (Dynamsoft)
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// After (IronOCR)
using IronOcr;
// Before (Dynamsoft)
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// After (IronOCR)
using IronOcr;
Imports IronOcr
ステップ 3: ライセンスの初期化
各Dynamsoftの静的InitLicense呼び出しをアプリケーションのスタートアップ時の単一のIronOCRライセンス割り当てに置き換えます:
// Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY");
// After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY");
// After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
' Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY")
' After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
コード移行の例
テンプレートベースの認識からゼロコンフィグエンジンへ
DynamsoftのJSONテンプレートシステムは、画像処理が行われる前に、キャラクターモデル、領域仕様、認識パラメータに関する詳細な指示をSDKに提供します。 ほとんどの実際のOCRワークロードでは、この構成は認識のメリットを生むことなくセットアップの複雑さを増すだけです。なぜなら、基盤となるTesseractエンジンがレイアウト検出を自動的に処理するからです。
Dynamsoftのアプローチ:
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// JSON template required before recognition
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
string invoiceTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""Invoice_Header"",
""ReferenceRegionNameArray"": [""HeaderRegion""],
""CharacterModelName"": ""NumberLetter""
}],
""ReferenceRegionArray"": [{
""Name"": ""HeaderRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [0, 0],
""SecondPoint"": [100, 0],
""ThirdPoint"": [100, 20],
""FourthPoint"": [0, 20]
}
}]
}";
recognizer.AppendSettingsFromString(invoiceTemplate);
var results = recognizer.RecognizeFile("invoice.jpg");
var headerText = new StringBuilder();
foreach (var result in results)
foreach (var line in result.LineResults)
headerText.AppendLine(line.Text);
Console.WriteLine(headerText.ToString());
recognizer.Dispose();
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;
// JSON template required before recognition
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
string invoiceTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""Invoice_Header"",
""ReferenceRegionNameArray"": [""HeaderRegion""],
""CharacterModelName"": ""NumberLetter""
}],
""ReferenceRegionArray"": [{
""Name"": ""HeaderRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [0, 0],
""SecondPoint"": [100, 0],
""ThirdPoint"": [100, 20],
""FourthPoint"": [0, 20]
}
}]
}";
recognizer.AppendSettingsFromString(invoiceTemplate);
var results = recognizer.RecognizeFile("invoice.jpg");
var headerText = new StringBuilder();
foreach (var result in results)
foreach (var line in result.LineResults)
headerText.AppendLine(line.Text);
Console.WriteLine(headerText.ToString());
recognizer.Dispose();
Imports Dynamsoft.LabelRecognizer
Imports Dynamsoft.Core
Imports System.Text
' JSON template required before recognition
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
Dim invoiceTemplate As String = "{
""LabelRecognizerParameterArray"": [{
""Name"": ""Invoice_Header"",
""ReferenceRegionNameArray"": [""HeaderRegion""],
""CharacterModelName"": ""NumberLetter""
}],
""ReferenceRegionArray"": [{
""Name"": ""HeaderRegion"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [0, 0],
""SecondPoint"": [100, 0],
""ThirdPoint"": [100, 20],
""FourthPoint"": [0, 20]
}
}]
}"
recognizer.AppendSettingsFromString(invoiceTemplate)
Dim results = recognizer.RecognizeFile("invoice.jpg")
Dim headerText As New StringBuilder()
For Each result In results
For Each line In result.LineResults
headerText.AppendLine(line.Text)
Next
Next
Console.WriteLine(headerText.ToString())
recognizer.Dispose()
IronOCRのアプローチ:
using IronOcr;
// No template file — region specified inline, engine auto-configures
var region = new CropRectangle(x: 0, y: 0, width: 1200, height: 200);
using var input = new OcrInput();
input.LoadImage("invoice.jpg", region);
input.Deskew();
var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
Console.WriteLine($"Confidence: {result.Confidence}%");
using IronOcr;
// No template file — region specified inline, engine auto-configures
var region = new CropRectangle(x: 0, y: 0, width: 1200, height: 200);
using var input = new OcrInput();
input.LoadImage("invoice.jpg", region);
input.Deskew();
var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
Console.WriteLine($"Confidence: {result.Confidence}%");
Imports IronOcr
' No template file — region specified inline, engine auto-configures
Dim region As New CropRectangle(x:=0, y:=0, width:=1200, height:=200)
Using input As New OcrInput()
input.LoadImage("invoice.jpg", region)
input.Deskew()
Dim result = New IronTesseract().Read(input)
Console.WriteLine(result.Text)
Console.WriteLine($"Confidence: {result.Confidence}%")
End Using
Dynamsoftの手法では、画像処理を行う前に、JSONテンプレートの作成、検証、および展開を行う必要があります。 AppendSettingsFromString内のタイプミスはランタイムで空の結果を返します — コンパイル時検証はありません。 IronOCRのCropRectangleはプレーンなコンストラクタです: コンパイル時タイプチェック、外部ファイルなし、デプロイメントアーティファクトなし。 すべてのターゲティングパターンについては、地域ベースのOCRガイドを参照してください。
地域移行を伴うVINコードスキャン
車両識別番号の抽出は、Dynamsoft Label Recognizerの得意分野です。 そのVINテンプレートモデルは、特定の17文字の英数字形式に最適化されています。 IronOCRへの移行により、テンプレートモデルは前処理パイプラインと領域ターゲティングに置き換えられ、文字モデルの設定を必要とせずに同じVINプレート条件に対応できるようになります。
Dynamsoftのアプローチ:
using Dynamsoft.LabelRecognizer;
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
// VIN requires a specific character model and region configuration
string vinTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Scan"",
""ReferenceRegionNameArray"": [""VIN_Zone""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VIN_Zone"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [10, 35],
""SecondPoint"": [90, 35],
""ThirdPoint"": [90, 65],
""FourthPoint"": [10, 65]
}
}]
}";
recognizer.AppendSettingsFromString(vinTemplate);
var results = recognizer.RecognizeFile("vehicle-vin.jpg");
string rawVin = results
.SelectMany(r => r.LineResults)
.Select(l => l.Text)
.FirstOrDefault() ?? string.Empty;
Console.WriteLine($"Raw VIN text: {rawVin}"); // still requires validation
recognizer.Dispose();
using Dynamsoft.LabelRecognizer;
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
// VIN requires a specific character model and region configuration
string vinTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Scan"",
""ReferenceRegionNameArray"": [""VIN_Zone""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VIN_Zone"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [10, 35],
""SecondPoint"": [90, 35],
""ThirdPoint"": [90, 65],
""FourthPoint"": [10, 65]
}
}]
}";
recognizer.AppendSettingsFromString(vinTemplate);
var results = recognizer.RecognizeFile("vehicle-vin.jpg");
string rawVin = results
.SelectMany(r => r.LineResults)
.Select(l => l.Text)
.FirstOrDefault() ?? string.Empty;
Console.WriteLine($"Raw VIN text: {rawVin}"); // still requires validation
recognizer.Dispose();
Imports Dynamsoft.LabelRecognizer
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
' VIN requires a specific character model and region configuration
Dim vinTemplate As String = "{
""LabelRecognizerParameterArray"": [{
""Name"": ""VIN_Scan"",
""ReferenceRegionNameArray"": [""VIN_Zone""],
""CharacterModelName"": ""VIN""
}],
""ReferenceRegionArray"": [{
""Name"": ""VIN_Zone"",
""Localization"": {
""SourceType"": ""LST_MANUAL_SPECIFICATION"",
""FirstPoint"": [10, 35],
""SecondPoint"": [90, 35],
""ThirdPoint"": [90, 65],
""FourthPoint"": [10, 65]
}
}]
}"
recognizer.AppendSettingsFromString(vinTemplate)
Dim results = recognizer.RecognizeFile("vehicle-vin.jpg")
Dim rawVin As String = results _
.SelectMany(Function(r) r.LineResults) _
.Select(Function(l) l.Text) _
.FirstOrDefault() OrElse String.Empty
Console.WriteLine($"Raw VIN text: {rawVin}") ' still requires validation
recognizer.Dispose()
IronOCRのアプローチ:
using IronOcr;
using System.Text.RegularExpressions;
// Target the VIN plate region directly — no template file
var vinRegion = new CropRectangle(x: 100, y: 350, width: 800, height: 300);
using var input = new OcrInput();
input.LoadImage("vehicle-vin.jpg", vinRegion);
input.Contrast(); // recover faded stamped digits
input.Sharpen(); // clarify character boundaries on embossed plates
var result = new IronTesseract().Read(input);
// VIN: 17 chars, no I/O/Q
var vinMatch = Regex.Match(result.Text, @"\b[A-HJ-NPR-Z0-9]{17}\b");
string vin = vinMatch.Success ? vinMatch.Value : result.Text.Trim();
Console.WriteLine($"VIN: {vin}");
Console.WriteLine($"Confidence: {result.Confidence}%");
using IronOcr;
using System.Text.RegularExpressions;
// Target the VIN plate region directly — no template file
var vinRegion = new CropRectangle(x: 100, y: 350, width: 800, height: 300);
using var input = new OcrInput();
input.LoadImage("vehicle-vin.jpg", vinRegion);
input.Contrast(); // recover faded stamped digits
input.Sharpen(); // clarify character boundaries on embossed plates
var result = new IronTesseract().Read(input);
// VIN: 17 chars, no I/O/Q
var vinMatch = Regex.Match(result.Text, @"\b[A-HJ-NPR-Z0-9]{17}\b");
string vin = vinMatch.Success ? vinMatch.Value : result.Text.Trim();
Console.WriteLine($"VIN: {vin}");
Console.WriteLine($"Confidence: {result.Confidence}%");
Imports IronOcr
Imports System.Text.RegularExpressions
' Target the VIN plate region directly — no template file
Dim vinRegion As New CropRectangle(x:=100, y:=350, width:=800, height:=300)
Using input As New OcrInput()
input.LoadImage("vehicle-vin.jpg", vinRegion)
input.Contrast() ' recover faded stamped digits
input.Sharpen() ' clarify character boundaries on embossed plates
Dim result = New IronTesseract().Read(input)
' VIN: 17 chars, no I/O/Q
Dim vinMatch = Regex.Match(result.Text, "\b[A-HJ-NPR-Z0-9]{17}\b")
Dim vin As String = If(vinMatch.Success, vinMatch.Value, result.Text.Trim())
Console.WriteLine($"VIN: {vin}")
Console.WriteLine($"Confidence: {result.Confidence}%")
End Using
SecondPoint仕様と同じピクセル参照フレームを使用します — Dynamsoftのパーセンテージ値をイメージ寸法で掛け算することで変換します。 プリプロセッシングパイプライン(Contrast, Sharpen)は、DynamsoftがそのVINテンプレートに焼き付ける文字モデル最適化を置き換えます。 画像品質補正ガイドでは、エンボス加工された表面や低コントラストの表面に適したフィルターの選択方法について解説しています。
複数ページTIFFファイルのバッチ処理
Dynamsoft Label Recognizerは、単一の画像を処理します。 文書管理システム、医療画像アーカイブ、ファックスパイプラインなどでよく見られる複数ページのTIFF文書は、外部での反復処理が必要となる。つまり、各フレームを読み込み、個別に認識器に通し、結果を集約する必要がある。 IronOCRはマルチフレームTIFFをLoadImageFramesを介してネイティブに処理します。
Dynamsoftのアプローチ:
using Dynamsoft.LabelRecognizer;
// Requires an external TIFF library to extract frames
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(genericTemplate);
// External library needed to iterate TIFF frames
var tiffImage = System.Drawing.Image.FromFile("scanned-batch.tiff");
int frameCount = tiffImage.GetFrameCount(
System.Drawing.Imaging.FrameDimension.Page);
var allText = new StringBuilder();
for (int i = 0; i < frameCount; i++)
{
tiffImage.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
string tempPath = $"frame_{i}.jpg";
tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Jpeg);
var results = recognizer.RecognizeFile(tempPath);
foreach (var r in results)
foreach (var line in r.LineResults)
allText.AppendLine(line.Text);
System.IO.File.Delete(tempPath); // clean up temp files
}
Console.WriteLine(allText.ToString());
recognizer.Dispose();
using Dynamsoft.LabelRecognizer;
// Requires an external TIFF library to extract frames
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(genericTemplate);
// External library needed to iterate TIFF frames
var tiffImage = System.Drawing.Image.FromFile("scanned-batch.tiff");
int frameCount = tiffImage.GetFrameCount(
System.Drawing.Imaging.FrameDimension.Page);
var allText = new StringBuilder();
for (int i = 0; i < frameCount; i++)
{
tiffImage.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
string tempPath = $"frame_{i}.jpg";
tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Jpeg);
var results = recognizer.RecognizeFile(tempPath);
foreach (var r in results)
foreach (var line in r.LineResults)
allText.AppendLine(line.Text);
System.IO.File.Delete(tempPath); // clean up temp files
}
Console.WriteLine(allText.ToString());
recognizer.Dispose();
Imports Dynamsoft.LabelRecognizer
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Text
' Requires an external TIFF library to extract frames
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
recognizer.AppendSettingsFromString(genericTemplate)
' External library needed to iterate TIFF frames
Dim tiffImage As Image = Image.FromFile("scanned-batch.tiff")
Dim frameCount As Integer = tiffImage.GetFrameCount(FrameDimension.Page)
Dim allText As New StringBuilder()
For i As Integer = 0 To frameCount - 1
tiffImage.SelectActiveFrame(FrameDimension.Page, i)
Dim tempPath As String = $"frame_{i}.jpg"
tiffImage.Save(tempPath, Imaging.ImageFormat.Jpeg)
Dim results = recognizer.RecognizeFile(tempPath)
For Each r In results
For Each line In r.LineResults
allText.AppendLine(line.Text)
Next
Next
File.Delete(tempPath) ' clean up temp files
Next
Console.WriteLine(allText.ToString())
recognizer.Dispose()
IronOCRのアプローチ:
using IronOcr;
// No frame iteration, no temp files, no external TIFF library
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff"); // loads all frames natively
input.Deskew();
input.DeNoise();
var ocr = new IronTesseract();
var result = ocr.Read(input);
// Results organized per page
foreach (var page in result.Pages)
{
Console.WriteLine($"Frame {page.PageNumber}: {page.Lines.Count} lines");
Console.WriteLine(page.Text);
}
// Save entire batch as a single searchable PDF
result.SaveAsSearchablePdf("batch-searchable.pdf");
using IronOcr;
// No frame iteration, no temp files, no external TIFF library
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff"); // loads all frames natively
input.Deskew();
input.DeNoise();
var ocr = new IronTesseract();
var result = ocr.Read(input);
// Results organized per page
foreach (var page in result.Pages)
{
Console.WriteLine($"Frame {page.PageNumber}: {page.Lines.Count} lines");
Console.WriteLine(page.Text);
}
// Save entire batch as a single searchable PDF
result.SaveAsSearchablePdf("batch-searchable.pdf");
Imports IronOcr
' No frame iteration, no temp files, no external TIFF library
Using input As New OcrInput()
input.LoadImageFrames("scanned-batch.tiff") ' loads all frames natively
input.Deskew()
input.DeNoise()
Dim ocr As New IronTesseract()
Dim result = ocr.Read(input)
' Results organized per page
For Each page In result.Pages
Console.WriteLine($"Frame {page.PageNumber}: {page.Lines.Count} lines")
Console.WriteLine(page.Text)
Next
' Save entire batch as a single searchable PDF
result.SaveAsSearchablePdf("batch-searchable.pdf")
End Using
Dynamsoftアプローチは、フレーム抽出にSystem.Drawingを必要とし、フレームごとにディスク上に一時ファイルを作成し、各パスの後に手動クリーンアップが必要です。 IronOCRのLoadImageFramesは、すべてのフレームを1回の呼び出しで読み取ります — 一時ファイルなし、フレームインデックストラッキングなし。 OCR後、SaveAsSearchablePdfは単一のメソッド呼び出しで検索可能なドキュメントとしてバッチ全体をアーカイブします。 マルチフレームTIFFガイドと検索可能なPDF出力ガイドでは、これらの両方の機能について詳しく解説しています。
構造化された単語レベルの結果解析
Dynamsoft DLRResult配列を返します。 各Locationコレクションを含みます。 単語レベルの位置を抽出するには、行テキストを空白で分割し、行の境界ボックスを比例的に分割する必要がありますが、この近似法はプロポーショナルフォントでは機能しません。 IronOCRは単語レベルのバウンディングボックスを各OcrResult.Wordオブジェクト上に型付きプロパティとして表面化します。
Dynamsoftのアプローチ:
using Dynamsoft.LabelRecognizer;
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(settingsJson);
var results = recognizer.RecognizeFile("form-scan.jpg");
foreach (var dlrResult in results)
{
foreach (var lineResult in dlrResult.LineResults)
{
// Line-level data only — word boundaries are not provided
Console.WriteLine($"Text: {lineResult.Text}");
Console.WriteLine($"Confidence: {lineResult.Confidence}");
// Location is a quadrilateral — four corner points
var loc = lineResult.Location;
Console.WriteLine($"Top-left: ({loc.Points[0].X}, {loc.Points[0].Y})");
// To get word positions: split text and divide bounding box manually
var words = lineResult.Text.Split(' ');
int approxWidth = (loc.Points[1].X - loc.Points[0].X) / words.Length;
for (int i = 0; i < words.Length; i++)
{
int wordX = loc.Points[0].X + (i * approxWidth);
Console.WriteLine($" Word '{words[i]}' approx at x={wordX}");
}
}
}
recognizer.Dispose();
using Dynamsoft.LabelRecognizer;
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(settingsJson);
var results = recognizer.RecognizeFile("form-scan.jpg");
foreach (var dlrResult in results)
{
foreach (var lineResult in dlrResult.LineResults)
{
// Line-level data only — word boundaries are not provided
Console.WriteLine($"Text: {lineResult.Text}");
Console.WriteLine($"Confidence: {lineResult.Confidence}");
// Location is a quadrilateral — four corner points
var loc = lineResult.Location;
Console.WriteLine($"Top-left: ({loc.Points[0].X}, {loc.Points[0].Y})");
// To get word positions: split text and divide bounding box manually
var words = lineResult.Text.Split(' ');
int approxWidth = (loc.Points[1].X - loc.Points[0].X) / words.Length;
for (int i = 0; i < words.Length; i++)
{
int wordX = loc.Points[0].X + (i * approxWidth);
Console.WriteLine($" Word '{words[i]}' approx at x={wordX}");
}
}
}
recognizer.Dispose();
Imports Dynamsoft.LabelRecognizer
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer As New LabelRecognizer()
recognizer.AppendSettingsFromString(settingsJson)
Dim results = recognizer.RecognizeFile("form-scan.jpg")
For Each dlrResult In results
For Each lineResult In dlrResult.LineResults
' Line-level data only — word boundaries are not provided
Console.WriteLine($"Text: {lineResult.Text}")
Console.WriteLine($"Confidence: {lineResult.Confidence}")
' Location is a quadrilateral — four corner points
Dim loc = lineResult.Location
Console.WriteLine($"Top-left: ({loc.Points(0).X}, {loc.Points(0).Y})")
' To get word positions: split text and divide bounding box manually
Dim words = lineResult.Text.Split(" "c)
Dim approxWidth As Integer = (loc.Points(1).X - loc.Points(0).X) \ words.Length
For i As Integer = 0 To words.Length - 1
Dim wordX As Integer = loc.Points(0).X + (i * approxWidth)
Console.WriteLine($" Word '{words(i)}' approx at x={wordX}")
Next
Next
Next
recognizer.Dispose()
IronOCRのアプローチ:
using IronOcr;
var result = new IronTesseract().Read("form-scan.jpg");
// Word-level positions are first-class properties — no manual division
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}");
foreach (var line in paragraph.Lines)
{
foreach (var word in line.Words)
{
Console.WriteLine(
$" Word: '{word.Text}' " +
$"at ({word.X},{word.Y}) " +
$"size {word.Width}x{word.Height} " +
$"confidence {word.Confidence}%");
}
}
}
}
using IronOcr;
var result = new IronTesseract().Read("form-scan.jpg");
// Word-level positions are first-class properties — no manual division
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}");
foreach (var line in paragraph.Lines)
{
foreach (var word in line.Words)
{
Console.WriteLine(
$" Word: '{word.Text}' " +
$"at ({word.X},{word.Y}) " +
$"size {word.Width}x{word.Height} " +
$"confidence {word.Confidence}%");
}
}
}
}
Imports IronOcr
Dim result = New IronTesseract().Read("form-scan.jpg")
' Word-level positions are first-class properties — no manual division
For Each page In result.Pages
For Each paragraph In page.Paragraphs
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}")
For Each line In paragraph.Lines
For Each word In line.Words
Console.WriteLine(
$" Word: '{word.Text}' " &
$"at ({word.X},{word.Y}) " &
$"size {word.Width}x{word.Height} " &
$"confidence {word.Confidence}%")
Next
Next
Next
Next
IronOCRは真の階層構造を提供します。ページには段落が含まれ、段落には行が含まれ、行には単語が含まれ、単語には文字が含まれます。 各レベルは、.Confidenceを型付き整数およびダブルプロパティとして公開します — 四辺形の座標演算は必要ありません。 構造化結果ガイドには、アクセス可能なすべてのプロパティが記載されており、信頼度スコアリングガイドには、自動文書レビューパイプラインにおける信頼度の閾値設定について説明されています。
大量ラベルスキャン向け非同期並列処理
Dynamsoftラベル認識器はスレッドセーフですが、そのRecognizeFile呼び出しは同期的です。 それをAppendSettingsFromStringを通じて構成状態を共有するため、複数のスレッドでテンプレートをロードするには慎重な初期化シーケンスが必要です。 IronOCRのIronTesseractインスタンスは独立しています: タスクごとに1つ作成し、Readを呼び出すと、スレッドモデルが単純になります。
Dynamsoftのアプローチ:
using Dynamsoft.LabelRecognizer;
using System.Threading.Tasks;
// InitLicense must be called once before parallel work begins
LabelRecognizer.InitLicense(licenseKey);
// Each thread needs its own recognizer instance with its own template load
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
await Task.WhenAll(imagePaths.Select(async path =>
{
// Cannot share recognizer instances safely across tasks
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(templateJson); // reload JSON per instance
await Task.Run(() =>
{
var dlrResults = recognizer.RecognizeFile(path);
var text = string.Join("\n",
dlrResults.SelectMany(r => r.LineResults).Select(l => l.Text));
results.Add(text);
});
recognizer.Dispose();
}));
Console.WriteLine($"Processed {results.Count} images");
using Dynamsoft.LabelRecognizer;
using System.Threading.Tasks;
// InitLicense must be called once before parallel work begins
LabelRecognizer.InitLicense(licenseKey);
// Each thread needs its own recognizer instance with its own template load
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
await Task.WhenAll(imagePaths.Select(async path =>
{
// Cannot share recognizer instances safely across tasks
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(templateJson); // reload JSON per instance
await Task.Run(() =>
{
var dlrResults = recognizer.RecognizeFile(path);
var text = string.Join("\n",
dlrResults.SelectMany(r => r.LineResults).Select(l => l.Text));
results.Add(text);
});
recognizer.Dispose();
}));
Console.WriteLine($"Processed {results.Count} images");
Imports Dynamsoft.LabelRecognizer
Imports System.Threading.Tasks
Imports System.Collections.Concurrent
' InitLicense must be called once before parallel work begins
LabelRecognizer.InitLicense(licenseKey)
' Each thread needs its own recognizer instance with its own template load
Dim results As New ConcurrentBag(Of String)()
Await Task.WhenAll(imagePaths.Select(Async Function(path)
' Cannot share recognizer instances safely across tasks
Dim recognizer As New LabelRecognizer()
recognizer.AppendSettingsFromString(templateJson) ' reload JSON per instance
Await Task.Run(Sub()
Dim dlrResults = recognizer.RecognizeFile(path)
Dim text = String.Join(vbLf, dlrResults.SelectMany(Function(r) r.LineResults).Select(Function(l) l.Text))
results.Add(text)
End Sub)
recognizer.Dispose()
End Function))
Console.WriteLine($"Processed {results.Count} images")
IronOCRのアプローチ:
using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;
var extractedTexts = new ConcurrentDictionary<string, string>();
// Each IronTesseract instance is independent — no shared state
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
extractedTexts[imagePath] = result.Text;
});
foreach (var (path, text) in extractedTexts)
Console.WriteLine($"{System.IO.Path.GetFileName(path)}: {text.Length} characters");
using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;
var extractedTexts = new ConcurrentDictionary<string, string>();
// Each IronTesseract instance is independent — no shared state
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
extractedTexts[imagePath] = result.Text;
});
foreach (var (path, text) in extractedTexts)
Console.WriteLine($"{System.IO.Path.GetFileName(path)}: {text.Length} characters");
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Threading.Tasks
Dim extractedTexts As New ConcurrentDictionary(Of String, String)()
' Each IronTesseract instance is independent — no shared state
Parallel.ForEach(imagePaths, Sub(imagePath)
Dim ocr As New IronTesseract()
Dim result = ocr.Read(imagePath)
extractedTexts(imagePath) = result.Text
End Sub)
For Each kvp In extractedTexts
Dim path = kvp.Key
Dim text = kvp.Value
Console.WriteLine($"{System.IO.Path.GetFileName(path)}: {text.Length} characters")
Next
IronOCRは、並列処理を開始する前に初期化シーケンスを必要としません。 アプリケーションのスタートアップ時に1つのIronOcr.License.LicenseKey割り当てで全てのインスタンスをアクティブにします。 スレッドごとにテンプレートを再読み込みしたり、インスタンスごとにJSON検証を行ったりすることはありません。 非ブロッキングサーバーサイドシナリオのために、非同期OCRガイドには、ASP.NET CoreおよびAzure Functionsのawaitベースのパターンが含まれています。
スキャンしたラベルアーカイブからの検索可能なPDF出力
Dynamsoftには、いかなる種類のPDF出力機能もありません。 Dynamsoftで処理されたスキャン済みラベルアーカイブは、画像のみのファイルとして残るため、検索できず、文書管理システムによるインデックス作成もできず、PDF/Aアーカイブ規格にも準拠していません。 IronOCRは検索可能なPDF出力をOcrResultオブジェクトの単一のメソッド呼び出しとして追加します。
Dynamsoftのアプローチ:
using Dynamsoft.LabelRecognizer;
// Process scanned label — extract text into a string
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(labelTemplate);
var results = recognizer.RecognizeFile("scanned-labels.jpg");
var extractedText = new StringBuilder();
foreach (var r in results)
foreach (var line in r.LineResults)
extractedText.AppendLine(line.Text);
// Cannot create a searchable PDF — save text to a sidecar .txt file instead
System.IO.File.WriteAllText("scanned-labels.txt", extractedText.ToString());
// The original image remains unsearchable
Console.WriteLine("No PDF output available in Dynamsoft Label Recognizer.");
recognizer.Dispose();
using Dynamsoft.LabelRecognizer;
// Process scanned label — extract text into a string
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(labelTemplate);
var results = recognizer.RecognizeFile("scanned-labels.jpg");
var extractedText = new StringBuilder();
foreach (var r in results)
foreach (var line in r.LineResults)
extractedText.AppendLine(line.Text);
// Cannot create a searchable PDF — save text to a sidecar .txt file instead
System.IO.File.WriteAllText("scanned-labels.txt", extractedText.ToString());
// The original image remains unsearchable
Console.WriteLine("No PDF output available in Dynamsoft Label Recognizer.");
recognizer.Dispose();
Imports Dynamsoft.LabelRecognizer
Imports System.IO
Imports System.Text
' Process scanned label — extract text into a string
LabelRecognizer.InitLicense(licenseKey)
Dim recognizer = New LabelRecognizer()
recognizer.AppendSettingsFromString(labelTemplate)
Dim results = recognizer.RecognizeFile("scanned-labels.jpg")
Dim extractedText = New StringBuilder()
For Each r In results
For Each line In r.LineResults
extractedText.AppendLine(line.Text)
Next
Next
' Cannot create a searchable PDF — save text to a sidecar .txt file instead
File.WriteAllText("scanned-labels.txt", extractedText.ToString())
' The original image remains unsearchable
Console.WriteLine("No PDF output available in Dynamsoft Label Recognizer.")
recognizer.Dispose()
IronOCRのアプローチ:
using IronOcr;
// Read, preprocess, and produce a searchable PDF archive in one pipeline
using var input = new OcrInput();
input.LoadImage("scanned-labels.jpg");
input.Deskew();
input.Contrast();
var ocr = new IronTesseract();
var result = ocr.Read(input);
// Searchable PDF: original image layer preserved, invisible text layer added
result.SaveAsSearchablePdf("scanned-labels-searchable.pdf");
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%");
Console.WriteLine($"Extracted text preview: {result.Text.Substring(0, 100)}");
using IronOcr;
// Read, preprocess, and produce a searchable PDF archive in one pipeline
using var input = new OcrInput();
input.LoadImage("scanned-labels.jpg");
input.Deskew();
input.Contrast();
var ocr = new IronTesseract();
var result = ocr.Read(input);
// Searchable PDF: original image layer preserved, invisible text layer added
result.SaveAsSearchablePdf("scanned-labels-searchable.pdf");
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%");
Console.WriteLine($"Extracted text preview: {result.Text.Substring(0, 100)}");
Imports IronOcr
' Read, preprocess, and produce a searchable PDF archive in one pipeline
Using input As New OcrInput()
input.LoadImage("scanned-labels.jpg")
input.Deskew()
input.Contrast()
Dim ocr As New IronTesseract()
Dim result = ocr.Read(input)
' Searchable PDF: original image layer preserved, invisible text layer added
result.SaveAsSearchablePdf("scanned-labels-searchable.pdf")
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%")
Console.WriteLine($"Extracted text preview: {result.Text.Substring(0, 100)}")
End Using
検索可能なPDF出力では、元のスキャン画像がフル解像度で保持され、その上に目に見えないOCRテキストレイヤーが追加されます。これにより、文書管理システム、検索インデックス、PDFビューアでラベルの内容を検索できるようになります。 検索可能なPDF形式のハウツーガイドとスキャン文書処理ガイドでは、複数ページのアーカイブとバッチ変換ワークフローについて解説しています。
Dynamsoft OCR API からIronOCRへのマッピングリファレンス
| Dynamsoft ラベル認識ツール | IronOCR相当値 |
|---|---|
LabelRecognizer.InitLicense(key) |
IronOcr.License.LicenseKey = key |
new LabelRecognizer() |
new IronTesseract() |
recognizer.AppendSettingsFromString(json) |
不要 — 自動設定 |
recognizer.RecognizeFile(path) |
ocr.Read(path) |
recognizer.RecognizeByFile(path, templateName) |
ocr.Read(path) |
recognizer.RecognizeBuffer(buffer, width, height, ...) |
ocr.Read(input) |
DLRResult[](結果の配列) |
OcrResult(単一の結果オブジェクト) |
DLRResult.LineResults |
OcrResult.Lines |
DLRLineResult.Text |
OcrResult.Line.Text |
DLRLineResult.Confidence |
OcrResult.Line.Words[i].Confidence |
DLRLineResult.Location.Points[i] |
OcrResult.Line.X, .Y, .Width, .Height |
ReferenceRegionArray(JSON) |
new CropRectangle(x, y, w, h) |
LabelRecognizerParameterArray(JSON) |
不要 |
テンプレートのCharacterModelName |
不要 |
recognizer.Dispose() |
using var ocr = new IronTesseract() |
| PDF入力はサポートされていません | input.LoadPdf(path) |
| 検索可能なPDF出力はありません | result.SaveAsSearchablePdf(path) |
| 複数ページのTIFF入力は受け付けていません | input.LoadImageFrames(path) |
| バーコード読み取り(別製品) | ocr.Configuration.ReadBarCodes = true |
複数のInitLicense呼び出し(製品ごと) |
単一のIronOcr.License.LicenseKey割り当て |
一般的な移行の問題と解決策
問題1:移行後にAppendSettingsFromStringが空の結果を返す
Dynamsoft: DLRResult配列を返します。 例外は発生しません。 Dynamsoftから移行するチームの中には、このような静かなエラーを防ぐために、結果解析コード全体に防御的なnullチェックを追加する場合があります。
解決策: AppendSettingsFromStringを完全に削除します。 IronOCRはテンプレートの設定を必要としません。 特定の地域をターゲットにする必要がある場合、ReferenceRegionArray JSONをCropRectangleに置き換えます:
// Remove all AppendSettingsFromString calls
// Replace region JSON with a CropRectangle constructor
var region = new CropRectangle(x: 0, y: 400, width: 1200, height: 300);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
// Remove all AppendSettingsFromString calls
// Replace region JSON with a CropRectangle constructor
var region = new CropRectangle(x: 0, y: 400, width: 1200, height: 300);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
Imports System
' Remove all AppendSettingsFromString calls
' Replace region JSON with a CropRectangle constructor
Dim region As New CropRectangle(x:=0, y:=400, width:=1200, height:=300)
Using input As New OcrInput()
input.LoadImage(imagePath, region)
Dim result = New IronTesseract().Read(input)
End Using
IronTesseractのセットアップガイドには、 JSON文字列ではなくプロパティとして設定できるすべてのエンジン構成オプションが記載されています。
問題2:アプリケーション起動時のInitLicense呼び出しが複数回発生する
Dynamsoft: ラベル認識器、バーコードリーダー、ドキュメントノーマライザを使用するアプリケーションは、それぞれスタートアップ時に3つの個別のInitLicenseメソッドを呼び出し、それぞれが自身のライセンスキーを必要とします。 チームは3つの環境変数を保存し、3つのキーを独立してローテーションし、3つの別々の初期化エラーをデバッグします。
解決策: すべてのDynamsoft InitLicense呼び出しを削除します。 IronOCRの1行に置き換えてください。
// Remove:
// LabelRecognizer.InitLicense(mrzKey);
// BarcodeReader.InitLicense(barcodeKey);
// DocumentNormalizer.InitLicense(docKey);
// Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// Remove:
// LabelRecognizer.InitLicense(mrzKey);
// BarcodeReader.InitLicense(barcodeKey);
// DocumentNormalizer.InitLicense(docKey);
// Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' Remove:
' LabelRecognizer.InitLicense(mrzKey)
' BarcodeReader.InitLicense(barcodeKey)
' DocumentNormalizer.InitLicense(docKey)
' Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
環境変数を1つ設定するだけで、OCR、バーコード、PDF処理、125以上の言語など、 IronOCRのすべての機能が有効になり、機能ごとに初期化する必要はありません。
問題3:LineResultテキスト集約で文字化けした出力が生成される
Dynamsoft: DLRResultを返します。 すべての結果を\nセパレーターで連結するアプリケーションは、ページ上の異なるラベルゾーンから行を混在させた出力を生成します — なぜなら、DLRResultオブジェクトの順序は、読み指示順序ではなく地域検出順序だからです。
解決策: IronOCRの結果階層は、出力を読み上げ順に整理します。 自然なドキュメント順序でテキストにアクセスするには、Pages → Paragraphs → Lines構造を使用します:
var result = new IronTesseract().Read(imagePath);
// Reading-order text — no manual aggregation
Console.WriteLine(result.Text);
// Or access paragraph-level groupings
foreach (var paragraph in result.Pages[0].Paragraphs)
Console.WriteLine(paragraph.Text);
var result = new IronTesseract().Read(imagePath);
// Reading-order text — no manual aggregation
Console.WriteLine(result.Text);
// Or access paragraph-level groupings
foreach (var paragraph in result.Pages[0].Paragraphs)
Console.WriteLine(paragraph.Text);
Imports IronOcr
Dim result = New IronTesseract().Read(imagePath)
' Reading-order text — no manual aggregation
Console.WriteLine(result.Text)
' Or access paragraph-level groupings
For Each paragraph In result.Pages(0).Paragraphs
Console.WriteLine(paragraph.Text)
Next
問題4:デプロイメントサーバー上にテンプレートJSONファイルが見つからない
Dynamsoft:テンプレートJSONファイルは、個別のデプロイメント成果物です。 新しいサーバーでテンプレートファイルが欠落しているか、間違ったパスになっている場合、AppendSettingsFromStringは失敗します — 時には静かに、時にはランタイム例外で — デプロイメントはアプリケーションコードに触れることなく認識を壊します。
解決策: IronOCRにはテンプレートファイルがありません。 NuGetパッケージを置き換えて名前空間を更新した後、デプロイメントアーティファクトのリストは、アプリケーションのバイナリと1つの環境変数のみに縮小されます。 必要に応じて、起動時の検証チェックを追加してください。
// Validate license at startup — no template files to check
if (!IronOcr.License.IsValidLicense)
throw new InvalidOperationException("IronOCR license key is invalid or missing.");
var ocr = new IronTesseract();
// Ready to process — no file dependencies
// Validate license at startup — no template files to check
if (!IronOcr.License.IsValidLicense)
throw new InvalidOperationException("IronOCR license key is invalid or missing.");
var ocr = new IronTesseract();
// Ready to process — no file dependencies
Imports IronOcr
' Validate license at startup — no template files to check
If Not IronOcr.License.IsValidLicense Then
Throw New InvalidOperationException("IronOCR license key is invalid or missing.")
End If
Dim ocr As New IronTesseract()
' Ready to process — no file dependencies
第5号:複数製品にわたる廃棄チェーン管理
Dynamsoft: 各Dynamsoft製品インスタンス(IDisposableを実装します。 複数の製品を集約するサービスクラスは、多段のDispose呼び出しがないと、ネイティブリソースリークが発生し、負荷時にメモリの成長として現れます。
解決策: IronOCRのIDisposableを実装していますが、ディスポーザルモデルはより簡単です — 1クラス、1パターン。 DIコンテナにシングルトンとして単一usingブロックを短命インスタンスのために使用します:
// Short-lived pattern
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = new IronTesseract().Read(input);
// Long-lived singleton (register in Program.cs)
builder.Services.AddSingleton<IronTesseract>();
// Short-lived pattern
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = new IronTesseract().Read(input);
// Long-lived singleton (register in Program.cs)
builder.Services.AddSingleton<IronTesseract>();
Imports IronOcr
' Short-lived pattern
Using input As New OcrInput()
input.LoadImage(imagePath)
Dim result = (New IronTesseract()).Read(input)
End Using
' Long-lived singleton (register in Program.vb)
builder.Services.AddSingleton(Of IronTesseract)()
進捗状況追跡ガイドでは、長時間実行されるバッチジョブのライフサイクル管理について説明し、非同期OCRガイドでは、 ASP.NET Coreにおけるシングルトンパターンについて説明しています。
問題6:カスタムラベル形式では文字モデルが利用できません
Dynamsoft: テンプレート内のCharacterModelNameフィールドは、Dynamsoft SDKインストールディレクトリに存在する必要があるモデルファイルを参照します。 カスタムキャラクターモデルを使用するには、Dynamsoftのポータルから追加のモデルファイルをダウンロードし、適切なSDKパスに配置する必要があります。 モデルが欠落しているため、認識が失敗し、不可解な実行時エラーが発生します。
解決策: IronOCRは文字モデルファイルを使用しません。 カスタムフォントや特殊フォントの場合は、カスタム言語トレーニングを使用してください。
// No character model files needed
// For specialized fonts, use a custom language pack
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English; // or load a custom trained pack
using var input = new OcrInput();
input.LoadImage(specializedFontImage);
input.Binarize(); // helps with specialized font clarity
var result = ocr.Read(input);
// No character model files needed
// For specialized fonts, use a custom language pack
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English; // or load a custom trained pack
using var input = new OcrInput();
input.LoadImage(specializedFontImage);
input.Binarize(); // helps with specialized font clarity
var result = ocr.Read(input);
Imports IronTesseract
' No character model files needed
' For specialized fonts, use a custom language pack
Dim ocr As New IronTesseract()
ocr.Language = OcrLanguage.English ' or load a custom trained pack
Using input As New OcrInput()
input.LoadImage(specializedFontImage)
input.Binarize() ' helps with specialized font clarity
Dim result = ocr.Read(input)
End Using
カスタムフォントのトレーニングガイドでは、ファイルパスの設定なしで、独自のラベルフォント用のカスタム言語パックをトレーニングする方法について説明します。
Dynamsoft OCR移行チェックリスト
移行前
コードベースを監査して、Dynamsoftへの参照をすべて特定する。
# Find all Dynamsoft using statements
grep -r "using Dynamsoft" --include="*.cs" .
# Find InitLicense calls (one per product)
grep -r "InitLicense" --include="*.cs" .
# Find AppendSettingsFromString calls (template loads)
grep -r "AppendSettingsFromString" --include="*.cs" .
# Find template JSON strings (inline or file references)
grep -r "LabelRecognizerParameterArray\|ReferenceRegionArray\|CharacterModelName" --include="*.cs" .
# Find RecognizeFile and RecognizeByFile calls
grep -r "RecognizeFile\|RecognizeByFile\|RecognizeBuffer" --include="*.cs" .
# Find LineResult result parsing patterns
grep -r "LineResults\|DLRResult\|DLRLineResult" --include="*.cs" .
# Identify any JSON template files in the project
find . -name "*.json" | xargs grep -l "LabelRecognizerParameterArray" 2>/dev/null
# Find all Dynamsoft using statements
grep -r "using Dynamsoft" --include="*.cs" .
# Find InitLicense calls (one per product)
grep -r "InitLicense" --include="*.cs" .
# Find AppendSettingsFromString calls (template loads)
grep -r "AppendSettingsFromString" --include="*.cs" .
# Find template JSON strings (inline or file references)
grep -r "LabelRecognizerParameterArray\|ReferenceRegionArray\|CharacterModelName" --include="*.cs" .
# Find RecognizeFile and RecognizeByFile calls
grep -r "RecognizeFile\|RecognizeByFile\|RecognizeBuffer" --include="*.cs" .
# Find LineResult result parsing patterns
grep -r "LineResults\|DLRResult\|DLRLineResult" --include="*.cs" .
# Identify any JSON template files in the project
find . -name "*.json" | xargs grep -l "LabelRecognizerParameterArray" 2>/dev/null
在庫調査結果:
InitLicense呼び出しサイトをカウントします(使用中のDynamsoft製品ごとに1つ)- 各認識テンプレートごとに
AppendSettingsFromString呼び出しサイトをカウントします - 移行後に削除されるすべての JSON テンプレートファイルを一覧表示します
- 任意の
CropRectangleに変換します) - 別製品でカバーされている機能(バーコード、文書正規化など)に注意してください。
コードの移行
Dynamsoft.LabelRecognizerNuGetパッケージと他のDynamsoftパッケージを削除しますIronOcrNuGetパッケージ(dotnet add package IronOcr)をインストールします- すべての
using IronOcr;に置き換えます - アプリケーションのスタートアップ時に単一の
LabelRecognizer.InitLicense(key)呼び出しをすべて置き換えます AppendSettingsFromString(json)呼び出しをすべて削除します — 同等のものは必要ありませんReferenceRegionArrayJSON座標をnew CropRectangle(x, y, width, height)コンストラクタに置き換えますnew IronTesseract()に置き換えますocr.Read(path)に置き換えます.Words階層に置き換えます- 手動の
result.Textまたは構造化ページ列挙に置き換えます BarcodeReader.InitLicense+ocr.Configuration.ReadBarCodes = trueに置き換えます- マルチプロダクト
using var ocr = new IronTesseract()に置き換えます - プロジェクトおよびデプロイメント成果物からJSONテンプレートファイルを削除します。
- TIFFファイル上のフレーム反復ループを
input.LoadImageFrames(path)に置き換えます - スキャンされた出力をアーカイブする必要がある場所に
result.SaveAsSearchablePdf(outputPath)を追加します
移行後
- アプリケーションのスタートアップ時に
trueを返すことを確認します - すべての認識結果が以前に動作していた入力に対して空でない
result.Textを返すことを確認します - 代表的なサンプルの
result.Confidenceをチェックする — 80%以上の値は良好な認識品質を示します - 以前のDynamsoft地域結果と
CropRectangle出力を比較して、地域ターゲット精度をテストします - 以前はDynamsoftバーコードリーダーが必要だった入力で
ocr.Configuration.ReadBarCodes = trueを実行して、バーコード読み取りを検証します - マルチページTIFF処理がフレームごとに1
OcrResult.Pageを生成することを確認します - 検索可能なPDF出力がPDFビューアでテキスト検索可能であることを確認します。
Parallel.ForEachを使って並列処理テストを実行し、スレッドの競合がないことを確認します- すべてのデプロイ対象 (Linux、Docker、Azure) をテストし、JSON テンプレート ファイルなしで単一パッケージのデプロイが機能することを確認します。
- Dynamsoft ライセンスキーの環境変数がデプロイメント構成に残っていないことを確認します。
IronOCRへの移行の主なメリット
1つのパッケージでマルチプロダクトの調整コストを排除。 すべての機能 — 一般的なOCR、MRZ抽出、バーコード読み取り、ネイティブPDF入力、検索可能なPDF出力、前処理、および125以上の言語 — は1つのIronOcr NuGetパッケージとして提供されます。 バージョンアップグレードは1つの.csprojファイルの1つのパッケージエントリに影響し、ライセンスキーローテーションは1つの環境変数です。 デプロイメント成果物のインベントリは、アプリケーションバイナリのみに縮小され、JSONテンプレートファイルやキャラクターモデルディレクトリは含まれません。
設定ファイルへの依存は一切ありません。Dynamsoftテンプレートシステムでは、実行時にJSONファイルが存在し、正しくパスが設定されている必要があります。IronOCRは、 NuGetパッケージ自体以外に実行時ファイルへの依存はありません。 Dockerイメージは決定論的になる。つまり、CI(継続的インテグレーション)を通過したものが、本番環境で実行されるものと全く同じになる。 Dockerデプロイメントガイドには、Linux用に1apt-get install行のみ必要とする完全なDockerfileが示されています。
構造化された出力が統合コードを削減します。 Dynamsoftは生のLineResultテキスト文字列を返します。 構造化データ抽出(フィールド位置、単語境界、トークンごとの信頼度など)には、コードが所有しテストする後処理が必要です。 IronOCRの結果階層では、ページ、段落、行、単語、文字が、座標と信頼度スコアを持つ入力済みコレクションとして、各レベルで表示されます。 Dynamsoftから移行するチームは、通常、結果処理コードの30~50%を削除します。なぜなら、IronOCRは、これまで手作業で構築していた構造をそのまま提供するからです。 OCR結果機能ページには、完全な出力モデルが記載されています。
永久ライセンスは年間予算の不確実性を解消します。Dynamsoft Label Recognizerには永久ライセンスオプションはありません。 ラベル認識だけでも、処理クラスターを5年間稼働させるには年間2,995ドル以上の費用がかかり、これにバーコードや文書正規化製品を追加する費用は含まれません。 IronOCRの$999 Liteライセンスは、一度購入すればすべての機能を無制限に利用可能です。 政府機関、Enterprise、および長期にわたる運用環境においては、コアとなる文書処理コンポーネントから年間更新の依存関係を取り除くことで、調達の複雑さを軽減し、プロジェクト途中でサブスクリプションが失効するリスクを排除できます。 IronOCRのライセンスページには、すべてのティアとそれぞれのカバー範囲が記載されています。
プラットフォーム固有の設定なしでクロスプラットフォームに対応。IronOCRは、NuGetのランタイム識別子グラフを介して、Windows x64、Linux x64、macOS x64、およびmacOS ARM用の適切なランタイムバイナリを解決します。 条件付きusing IronOcr;コードがモディフィケーションなしで、Windows、Linux、AWS Lambda、Azure App Serviceでコンパイルおよび実行されます。
対応言語はアプリケーションのニーズに合わせて拡張可能です。Dynamsoft Label Recognizerは、ラテン文字のMRZフォーマット向けに設計されています。 ラテン文字以外の文字体系(アラビア語、中国語、日本語、韓国語、ヘブライ語など)は、設計範囲外となる。 IronOCRは125以上の言語を個別のNuGetパッケージとしてサポートしています: dotnet add package IronOcr.Languages.Arabicは、認識パイプラインでのコード変更なしでアラビア語サポートを追加します。言語インデックスには利用可能なすべての言語パックが一覧されています。 国際的な身分証明書、多言語の配送ラベル、国境を越えた請求書などを処理するアプリケーションにとって、この幅広い機能により、1つのライブラリで、成長するアプリケーションが遭遇するあらゆる種類の文書を網羅できます。
よくある質問
なぜDynamsoft OCR SDKからIronOCRに移行する必要があるのですか?
一般的な推進要因には、COM相互接続の複雑さの解消、ファイルベースのライセンス管理の置き換え、ページ単位の課金の回避、Docker/コンテナデプロイの有効化、標準的な.NETツールと統合するNuGetネイティブワークフローの採用などがあります。
Dynamsoft OCR SDKからIronOCRに移行する際の主なコード変更は何ですか?
Dynamsoft OCRの初期化シーケンスをIronTesseractのインスタンス化に置き換え、COMのライフサイクル管理(明示的なCreate/Load/Closeパターン)を削除し、結果のプロパティ名を更新します。その結果、定型的な行が大幅に減少します。
IronOCRをインストールして移行を開始するにはどうすればいいですか?
パッケージマネージャーコンソールで'Install-Package IronOcr'を実行するか、CLIで'dotnet add package IronOcr'を実行してください。言語パックは別のパッケージです:例えばフランス語の場合は'dotnet add package IronOcr.Languages.French'となります。
IronOCRはDynamsoft OCR SDKの標準的なビジネス文書のOCR精度に匹敵しますか?
IronOCRは、請求書、契約書、領収書、入力フォームなどの標準的なビジネスコンテンツで高い精度を達成しています。画像前処理フィルター(傾き補正、ノイズ除去、コントラスト強調)により、劣化した入力の認識をさらに向上させます。
IronOCR はDynamsoft OCR SDKが別途インストールする言語データをどのように扱うのですか?
IronOCRの言語データはNuGetパッケージとして配布されます。'dotnet add package IronOcr.Languages.German'でドイツ語のサポートがインストールされます。手動でのファイル配置やディレクトリパスは必要ありません。
Dynamsoft OCR SDKからIronOCRへの移行は、デプロイメント・インフラの変更が必要ですか?
IronOCRはDynamsoft OCR SDKよりもインフラストラクチャの変更が少なくて済みます。SDKのバイナリパス、ライセンスファイルの配置、ライセンスサーバーの設定は必要ありません。NuGetパッケージには完全なOCRエンジンが含まれており、ライセンスキーはアプリケーションコードに設定された文字列です。
移行後のIronOCRライセンスの設定方法は?
アプリケーションの起動コードでIronOcr.License.LicenseKey = "YOUR-KEY "を割り当てます。DockerまたはKubernetesでは、キーを環境変数として保存し、スタートアップで読み込む。License.IsValidLicenseを使用して、トラフィックを受け入れる前にバリデーションを行う。
IronOCR はDynamsoft OCRと同じようにPDFを処理できますか?
IronOCRはネイティブPDFもスキャンしたPDFも読み取ります。IronTesseractをインスタンス化し、ocr.Read(input)を呼び出し、入力はPDFパスまたはOcrPdfInputであり、OcrResultページを反復します。別のPDFレンダリングパイプラインは必要ありません。
IronOCRはどのように大量処理のスレッディングを処理するのですか?
IronTesseractはスレッド毎にインスタンス化しても安全です。Parallel.ForEachまたはタスクプールでスレッドごとにインスタンスを1つスピンアップし、OCRを同時に実行し、完了したら各インスタンスを破棄します。グローバルステートやロックは必要ありません。
IronOCRはテキスト抽出後、どのような出力形式をサポートしていますか?
IronOCRはテキスト、単語座標、信頼度スコア、ページ構造を含む構造化された結果を返します。エクスポートオプションには、プレーンテキスト、検索可能なPDF、下流処理用の構造化結果オブジェクトが含まれます。
IronOCRの価格はDynamsoft OCR SDKよりもワークロードのスケーリングが予測できますか?
IronOCRは、定額制の永久ライセンスを採用しており、ページ単位やボリューム単位の料金はかかりません。10,000ページでも1,000万ページでも、ライセンスコストは一定です。ボリュームライセンスとチームライセンスのオプションはIronOCRの価格ページをご覧ください。
Dynamsoft OCR SDKからIronOCRに移行した後、既存のテストはどうなりますか?
抽出されたテキストコンテンツをアサートするテストは、移行後もパスし続ける必要があります。APIコールパターンやCOMオブジェクトのライフサイクルを検証するテストは、IronOCRのシンプルな初期化と結果モデルを反映するように更新する必要があります。

