フッターコンテンツにスキップ
ビデオ

Charlesw TesseractからIronOCRへの移行

このガイドは、.NET 開発者が charlesw/tesseract NuGet パッケージ (Tesseract) から IronOCR への移行手順を説明します。 移行の中心となる問題点は、charlesw ラッパーが課すネイティブバイナリ展開モデルとそのモデルが開発者に書かせるプラットフォーム依存コードです。CI で DllNotFoundException に苦しみ、Linux 上の Leptonica ライブラリパスと格闘し、OCR に関係ない OS 検出ブロックを書いたチームは、スイッチを切り替えた後に何が消えるかを正確に示すこのガイドに出会うでしょう。

Charlesw Tesseractから移行する理由

アーカイブされた charlesw/tesseract パッケージが新しいプロジェクトに問題を引き起こすのは、その API が悪いからではなく、それが要求する展開モデルが現代の .NET インフラストラクチャでは通用しない前提に基づいて設計されているためです。 移住の意思決定を左右する要因は以下のとおりです。

プラットフォームごとのネイティブバイナリ展開。 Tesseract NuGet パッケージは、Windows x64 用の tesseract50.dll、x86 用の別のビルド、Linux x64 用の libtesseract.so などのプラットフォーム固有のネイティブバイナリを出荷しています。これらのバイナリは、P/Invoke 呼び出しが成功するために、実行時に正しい場所に配置される必要があります。 開発者ワークステーションでは、SDKがそれらを自動的にコピーします。 Dockerコンテナ、ARM64ビルドエージェント、または非標準のアプリケーションルートを持つAzure App Serviceでは、それらは動作しません。 新しいデプロイメントターゲットはすべてデバッグセッションとなる。

Leptonicaは隠れた依存関係として存在します。Tesseractの画像読み込みはLeptonicaライブラリによって処理され、LeptonicaはTesseractバイナリとともに独自のネイティブDLLセットとして同梱されています。 Windows では、leptonica-1.82.0.dll が出力ディレクトリに存在している必要があります。 Linuxでは、Leptonica共有ライブラリはバンドルされているか、システムパッケージとしてインストールされている必要があります。 Debian ベースの Docker イメージで libleptonica-dev がないと、Pix.LoadFromFile() の際に役に立たないネイティブ例外が発生し、それを修正するには依存関係を解決するシステムパッケージを知る必要があります。

アプリケーションロジックにおけるプラットフォーム依存コード。 ネイティブバイナリのロードと tessdata パスの解決の組み合わせにより、RuntimeInformation.IsOSPlatform() チェック、コンテナコンテキストのための環境変数検出、およびターゲットにより異なるパス構築ロジックを書くことを開発者に強制します。 そのコードにはOCRのロジックは一切含まれていません。 これは、パッケージのバイナリ管理が不完全であるためにのみ存在する、デプロイメントのための仕組みである。

修復パスのないアーカイブ済みパッケージ。リポジトリは2021年からアーカイブされています。Linuxホスト上のシステムパッケージの更新によってLeptonica ABIが変更された場合、または新しい.NETランタイムによってネイティブバイナリの読み込み動作が変更された場合、更新するバージョンはありません。 選択肢は、ネイティブビルドパイプラインをフォークするか、ライブラリを置き換えるかのどちらかしかない。

Tesseract 4.1.1 エンジンのフリーズ。このパッケージは Tesseract 4.1.1 をラップしています。Tesseract 5 で書き直された LSTM モデルは、劣化文書に対して大幅に高い精度を実現します。 そのアップグレードはcharleswパッケージでは利用できません。ライブラリを切り替える必要があります。

標準パターンのない信頼性処理。 charlesw ラッパーは page.GetMeanConfidence() を 0 から 1 までの浮動小数点数として公開しますが、単語や文字レベルで信頼性しきい値を適用するには、iter.GetConfidence(PageIteratorLevel.Word) を使用したイテレータパターンが必要です。 標準的なフィルタリングAPIは存在しません。 各チームはそれぞれ異なる方法で独自のしきい値ロジックを実装している。

基本的な問題

charleswラッパーは、OCRを実行する前にプラットフォーム固有のネイティブバイナリ構成を必要とします。

// charlesw Tesseract: OS detection required just to find native DLLs
// DllNotFoundException on any platform where binaries do not resolve
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
    Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/app/lib");
}
var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath); // Requires leptonica native DLL
using var page = engine.Process(img);
return page.GetText();
// charlesw Tesseract: OS detection required just to find native DLLs
// DllNotFoundException on any platform where binaries do not resolve
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
    Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/app/lib");
}
var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
using var img = Pix.LoadFromFile(imagePath); // Requires leptonica native DLL
using var page = engine.Process(img);
return page.GetText();
Imports System
Imports System.Runtime.InteropServices
Imports Tesseract

' charlesw Tesseract: OS detection required just to find native DLLs
' DllNotFoundException on any platform where binaries do not resolve
If RuntimeInformation.IsOSPlatform(OSPlatform.Linux) Then
    Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", "/app/lib")
End If

Dim engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
Using img As Pix = Pix.LoadFromFile(imagePath) ' Requires leptonica native DLL
    Using page As Page = engine.Process(img)
        Return page.GetText()
    End Using
End Using
$vbLabelText   $csharpLabel

IronOCRにはネイティブのバイナリ設定がありません。

// IronOCR: no path management, no OS detection, no leptonica dependency
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
// IronOCR: no path management, no OS detection, no leptonica dependency
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read(imagePath).Text;
' IronOCR: no path management, no OS detection, no leptonica dependency
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read(imagePath).Text
$vbLabelText   $csharpLabel

IronOCRとCharlesw Tesseract:機能比較

以下の表は、この移行を評価するチームにとって関連性の高い機能を示しています。

フィーチャー チャールズ・テッセラクト IronOCR
メンテナンス状況 アーカイブ済み(2021年以降更新なし) 積極的なメンテナンス
Tesseractエンジンバージョン 4.1.1(凍結) 5(最新版、最適化済み)
ライセンス アパッチ2.0(無料) 商用 ($999–$2,999 永続)
NuGetのインストール Tesseract IronOcr
ネイティブバイナリ管理 プラットフォームごとのDLLの手動展開 バンドル済み、設定不要
レプトニカ依存症 leptonica-1.82.0.dll / libleptonica-dev が必要 該当なし(社内処理済み)
Tessdata管理 手動でのダウンロードと .csproj コピーエントリ NuGet言語パック
プラットフォーム依存コード 複数ターゲットへの展開に必要 不要
Dockerデプロイメント 明示的な tessdata COPY + Leptonica apt-get が必要 標準 for .NETコンテナ要件のみ
ARM64対応 未確認の投稿アーカイブ バンドル化され、検証済み
画像入力フォーマット TIFF、PNG、BMP、JPG(Leptonica経由) JPG、PNG、BMP、TIFF、GIFなど
複数ページTIFF 手動フレーム反復 input.LoadImageFrames()
ネイティブPDF入力 いいえ(二次図書館が必要) はい
検索可能なPDF出力 なし はい (result.SaveAsSearchablePdf())
組み込みの前処理 None 傾き補正、ノイズ除去、コントラスト補正、二値化、シャープ化、拡大縮小、膨張、収縮、反転
信頼度フィルタリングAPI GetConfidence() を使用した手動イテレータ result.Confidence, word.Confidence
構造化された結果 イテレータパターン (ResultIterator) 直接収集(ページ、段落、行、単語)
バーコード読み取り なし はい(OCR処理中)
地域ベースのOCR なし はい (CropRectangle)
スレッドセーフ 発信者の責任 内蔵
125以上の言語パック tessdataの手動ダウンロード dotnet add package IronOcr.Languages.*
クロスプラットフォーム.NET はい(.NET Standard 2.0) はい(.NET Framework 4.6.2以降、 .NET 5/6/7/8/9)
セキュリティパッチの適用頻度 なし(アーカイブ済み) 定期リリース

クイックスタート:Charlesw TesseractからIronOCRへの移行

ステップ 1: NuGet パッケージを置き換える

charlesw Tesseract パッケージを削除します。

dotnet remove package Tesseract
dotnet remove package Tesseract
SHELL

NuGetからIronOCRをインストールしてください。

dotnet add package IronOcr

ステップ 2: 名前空間の更新

// Before (charlesw Tesseract)
using Tesseract;

// After (IronOCR)
using IronOcr;
// Before (charlesw Tesseract)
using Tesseract;

// After (IronOCR)
using IronOcr;
Imports IronOcr
$vbLabelText   $csharpLabel

ステップ 3: ライセンスの初期化

アプリケーション起動時に、OCR操作が実行される前に、この呼び出しを一度だけ追加してください。

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

IronOCRのライセンスページで無料トライアルライセンスをご利用いただけます。 このトライアルでは、出力から透かしが削除され、APIへのフルアクセスが可能になります。

コード移行の例

ネイティブバイナリパス構成の削除

charlesw/tesseractプロジェクトで最も一般的な初期化パターンは、tessdataパスを構築し、環境ごとにネイティブライブラリのロードを設定するファクトリまたはヘルパークラスを使用することです。 このコードは、ラッパーのデプロイメントモデルのためにのみ存在します。

Charlesw Tesseract アプローチ:

// A realistic factory found in production charlesw/Tesseract projects
public static class OcrEngineFactory
{
    private static string GetTessDataPath()
    {
        // Different path per environment — all wrong until explicitly configured
        if (Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true")
            return "/app/tessdata";                                    // Docker
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            return Path.Combine(AppContext.BaseDirectory, "tessdata"); // Linux bare metal
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            return "/usr/local/share/tessdata";                        // macOS Homebrew install
        return @".\tessdata";                                          // Windows dev machine
    }

    public static TesseractEngine Create(string language = "eng")
    {
        // If leptonica-1.82.0.dll is not in output directory: DllNotFoundException at this line
        // If tessdata folder is missing: TesseractException at engine construction
        return new TesseractEngine(GetTessDataPath(), language, EngineMode.Default);
    }
}

// Call site
using var engine = OcrEngineFactory.Create();
using var img = Pix.LoadFromFile("invoice.jpg");
using var page = engine.Process(img);
Console.WriteLine(page.GetText());
// A realistic factory found in production charlesw/Tesseract projects
public static class OcrEngineFactory
{
    private static string GetTessDataPath()
    {
        // Different path per environment — all wrong until explicitly configured
        if (Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true")
            return "/app/tessdata";                                    // Docker
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            return Path.Combine(AppContext.BaseDirectory, "tessdata"); // Linux bare metal
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            return "/usr/local/share/tessdata";                        // macOS Homebrew install
        return @".\tessdata";                                          // Windows dev machine
    }

    public static TesseractEngine Create(string language = "eng")
    {
        // If leptonica-1.82.0.dll is not in output directory: DllNotFoundException at this line
        // If tessdata folder is missing: TesseractException at engine construction
        return new TesseractEngine(GetTessDataPath(), language, EngineMode.Default);
    }
}

// Call site
using var engine = OcrEngineFactory.Create();
using var img = Pix.LoadFromFile("invoice.jpg");
using var page = engine.Process(img);
Console.WriteLine(page.GetText());
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Tesseract

Public Module OcrEngineFactory
    Private Function GetTessDataPath() As String
        ' Different path per environment — all wrong until explicitly configured
        If Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") = "true" Then
            Return "/app/tessdata"                                    ' Docker
        End If
        If RuntimeInformation.IsOSPlatform(OSPlatform.Linux) Then
            Return Path.Combine(AppContext.BaseDirectory, "tessdata") ' Linux bare metal
        End If
        If RuntimeInformation.IsOSPlatform(OSPlatform.OSX) Then
            Return "/usr/local/share/tessdata"                        ' macOS Homebrew install
        End If
        Return ".\tessdata"                                           ' Windows dev machine
    End Function

    Public Function Create(Optional language As String = "eng") As TesseractEngine
        ' If leptonica-1.82.0.dll is not in output directory: DllNotFoundException at this line
        ' If tessdata folder is missing: TesseractException at engine construction
        Return New TesseractEngine(GetTessDataPath(), language, EngineMode.Default)
    End Function
End Module

' Call site
Using engine As TesseractEngine = OcrEngineFactory.Create()
    Using img As Pix = Pix.LoadFromFile("invoice.jpg")
        Using page As Page = engine.Process(img)
            Console.WriteLine(page.GetText())
        End Using
    End Using
End Using
$vbLabelText   $csharpLabel

IronOCRのアプローチ:

// IronOCR: no factory, no path logic, no OS detection
// Runs identically on Windows, Linux, macOS, and ARM64
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var result = new IronTesseract().Read("invoice.jpg");
Console.WriteLine(result.Text);
// IronOCR: no factory, no path logic, no OS detection
// Runs identically on Windows, Linux, macOS, and ARM64
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var result = new IronTesseract().Read("invoice.jpg");
Console.WriteLine(result.Text);
' IronOCR: no factory, no path logic, no OS detection
' Runs identically on Windows, Linux, macOS, and ARM64
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

Dim result = New IronTesseract().Read("invoice.jpg")
Console.WriteLine(result.Text)
$vbLabelText   $csharpLabel

OcrEngineFactory クラスが削除されます。 プラットフォーム依存のパスロジック、DOTNET_RUNNING_IN_CONTAINER チェック、Leptonica DLL 依存はすべて一緒に消えます。 開発者ワークステーション、CIエージェント、Dockerコンテナ、クラウドVMなど、あらゆる環境で同じ2行のコードが実行されます。 IronTesseractのセットアップガイドには、デフォルト設定の調整が必要な場合の構成オプションが記載されていますが、ほとんどの導入環境では調整は不要です。

レプトニカ画像変換代替

charlesw ラッパーは Leptonica の Pix 型を画像表現として使用します。 OCR 前に画像を操作するコードはすべて Pix を経由して変換する必要があり、Leptonica ネイティブ DLL をロードして動作させる必要があります。 このパターンを OcrInput に置き換えることで、Leptonica 依存を完全に排除できます。

Charlesw Tesseract アプローチ:

// Pix is Leptonica's image type — requires leptonica native DLL
// Converting from System.Drawing.Bitmap requires a temp file round-trip
public string ProcessInMemoryImage(Bitmap bitmap)
{
    // なし direct Bitmap → Pix conversion; must write to temp file
    var tempPath = Path.Combine(Path.GetTempPath(), $"ocr_{Guid.NewGuid()}.png");
    try
    {
        bitmap.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);

        using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
        using var pix = Pix.LoadFromFile(tempPath);   // Leptonica file I/O
        using var page = engine.Process(pix);

        return page.GetText();
    }
    finally
    {
        if (File.Exists(tempPath)) File.Delete(tempPath);
    }
}
// Pix is Leptonica's image type — requires leptonica native DLL
// Converting from System.Drawing.Bitmap requires a temp file round-trip
public string ProcessInMemoryImage(Bitmap bitmap)
{
    // なし direct Bitmap → Pix conversion; must write to temp file
    var tempPath = Path.Combine(Path.GetTempPath(), $"ocr_{Guid.NewGuid()}.png");
    try
    {
        bitmap.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);

        using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
        using var pix = Pix.LoadFromFile(tempPath);   // Leptonica file I/O
        using var page = engine.Process(pix);

        return page.GetText();
    }
    finally
    {
        if (File.Exists(tempPath)) File.Delete(tempPath);
    }
}
Imports System
Imports System.Drawing
Imports System.IO
Imports Tesseract

' Pix is Leptonica's image type — requires leptonica native DLL
' Converting from System.Drawing.Bitmap requires a temp file round-trip
Public Function ProcessInMemoryImage(bitmap As Bitmap) As String
    ' なし direct Bitmap → Pix conversion; must write to temp file
    Dim tempPath As String = Path.Combine(Path.GetTempPath(), $"ocr_{Guid.NewGuid()}.png")
    Try
        bitmap.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png)

        Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
            Using pix As Pix = Pix.LoadFromFile(tempPath) ' Leptonica file I/O
                Using page As Page = engine.Process(pix)
                    Return page.GetText()
                End Using
            End Using
        End Using
    Finally
        If File.Exists(tempPath) Then File.Delete(tempPath)
    End Try
End Function
$vbLabelText   $csharpLabel

IronOCRのアプローチ:

// OcrInput accepts byte arrays and streams — no temp file, no Leptonica
public string ProcessInMemoryImage(byte[] imageBytes)
{
    using var input = new OcrInput();
    input.LoadImage(imageBytes);   // Direct byte array loading

    var result = new IronTesseract().Read(input);
    return result.Text;
}

// Or from a stream — same pattern
public string ProcessFromStream(Stream imageStream)
{
    using var input = new OcrInput();
    input.LoadImage(imageStream);

    var result = new IronTesseract().Read(input);
    return result.Text;
}
// OcrInput accepts byte arrays and streams — no temp file, no Leptonica
public string ProcessInMemoryImage(byte[] imageBytes)
{
    using var input = new OcrInput();
    input.LoadImage(imageBytes);   // Direct byte array loading

    var result = new IronTesseract().Read(input);
    return result.Text;
}

// Or from a stream — same pattern
public string ProcessFromStream(Stream imageStream)
{
    using var input = new OcrInput();
    input.LoadImage(imageStream);

    var result = new IronTesseract().Read(input);
    return result.Text;
}
Imports System.IO

' OcrInput accepts byte arrays and streams — no temp file, no Leptonica
Public Function ProcessInMemoryImage(imageBytes As Byte()) As String
    Using input As New OcrInput()
        input.LoadImage(imageBytes)   ' Direct byte array loading

        Dim result = New IronTesseract().Read(input)
        Return result.Text
    End Using
End Function

' Or from a stream — same pattern
Public Function ProcessFromStream(imageStream As Stream) As String
    Using input As New OcrInput()
        input.LoadImage(imageStream)

        Dim result = New IronTesseract().Read(input)
        Return result.Text
    End Using
End Function
$vbLabelText   $csharpLabel

一時ファイルの往復通信が終了します。 ディスクにファイルを書き込むことなく、変換のために Leptonica DLL を呼び出すことなく、クリーンアップのための finally ブロックもありません。画像入力ガイドストリーム入力ガイド には、URL やメモリマップファイルからの読み込みを含む、サポートされるすべての入力ソースが記載されています。

信頼度閾値フィルタリング

charlesw ラッパーは、信頼性を二つのレベルで公開しています: page.GetMeanConfidence() はページ全体用、iter.GetConfidence(PageIteratorLevel.Word) は個々の単語用です。 出力から信頼度の低い単語を除外するには、イテレータループを手動で管理する必要があります。 IronOCRは結果オブジェクトに信頼度を直接公開するため、しきい値ロジックをLINQ式として扱うことができます。

Charlesw Tesseract アプローチ:

// Word-level confidence filtering requires iterator boilerplate
public List<string> ExtractHighConfidenceWords(string imagePath, float minConfidence = 0.8f)
{
    var highConfidenceWords = new List<string>();

    using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
    using var img = Pix.LoadFromFile(imagePath);
    using var page = engine.Process(img);

    // Page-level confidence only: fine-grained requires the iterator
    Console.WriteLine($"Page confidence: {page.GetMeanConfidence():P1}");

    using var iter = page.GetIterator();
    iter.Begin();
    do
    {
        if (iter.IsAtBeginningOf(PageIteratorLevel.Word))
        {
            var wordText = iter.GetText(PageIteratorLevel.Word)?.Trim();
            var wordConf  = iter.GetConfidence(PageIteratorLevel.Word) / 100f; // Returns 0-100
            if (!string.IsNullOrEmpty(wordText) && wordConf >= minConfidence)
                highConfidenceWords.Add(wordText);
        }
    } while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.Word));

    return highConfidenceWords;
}
// Word-level confidence filtering requires iterator boilerplate
public List<string> ExtractHighConfidenceWords(string imagePath, float minConfidence = 0.8f)
{
    var highConfidenceWords = new List<string>();

    using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
    using var img = Pix.LoadFromFile(imagePath);
    using var page = engine.Process(img);

    // Page-level confidence only: fine-grained requires the iterator
    Console.WriteLine($"Page confidence: {page.GetMeanConfidence():P1}");

    using var iter = page.GetIterator();
    iter.Begin();
    do
    {
        if (iter.IsAtBeginningOf(PageIteratorLevel.Word))
        {
            var wordText = iter.GetText(PageIteratorLevel.Word)?.Trim();
            var wordConf  = iter.GetConfidence(PageIteratorLevel.Word) / 100f; // Returns 0-100
            if (!string.IsNullOrEmpty(wordText) && wordConf >= minConfidence)
                highConfidenceWords.Add(wordText);
        }
    } while (iter.Next(PageIteratorLevel.Para, PageIteratorLevel.Word));

    return highConfidenceWords;
}
Imports System
Imports Tesseract

Public Class WordExtractor
    Public Function ExtractHighConfidenceWords(imagePath As String, Optional minConfidence As Single = 0.8F) As List(Of String)
        Dim highConfidenceWords As New List(Of String)()

        Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
            Using img As Pix = Pix.LoadFromFile(imagePath)
                Using page As Page = engine.Process(img)
                    ' Page-level confidence only: fine-grained requires the iterator
                    Console.WriteLine($"Page confidence: {page.GetMeanConfidence():P1}")

                    Using iter As ResultIterator = page.GetIterator()
                        iter.Begin()
                        Do
                            If iter.IsAtBeginningOf(PageIteratorLevel.Word) Then
                                Dim wordText As String = iter.GetText(PageIteratorLevel.Word)?.Trim()
                                Dim wordConf As Single = iter.GetConfidence(PageIteratorLevel.Word) / 100.0F ' Returns 0-100
                                If Not String.IsNullOrEmpty(wordText) AndAlso wordConf >= minConfidence Then
                                    highConfidenceWords.Add(wordText)
                                End If
                            End If
                        Loop While iter.Next(PageIteratorLevel.Para, PageIteratorLevel.Word)
                    End Using
                End Using
            End Using
        End Using

        Return highConfidenceWords
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCRのアプローチ:

// Confidence is a property on each result object — no iterator required
public List<string> ExtractHighConfidenceWords(string imagePath, double minConfidence = 80.0)
{
    var result = new IronTesseract().Read(imagePath);

    Console.WriteLine($"Page confidence: {result.Confidence}%");

    // LINQ directly on the word collection — no iterator state management
    return result.Pages
        .SelectMany(p => p.Lines)
        .SelectMany(l => l.Words)
        .Where(w => w.Confidence >= minConfidence && !string.IsNullOrWhiteSpace(w.Text))
        .Select(w => w.Text)
        .ToList();
}
// Confidence is a property on each result object — no iterator required
public List<string> ExtractHighConfidenceWords(string imagePath, double minConfidence = 80.0)
{
    var result = new IronTesseract().Read(imagePath);

    Console.WriteLine($"Page confidence: {result.Confidence}%");

    // LINQ directly on the word collection — no iterator state management
    return result.Pages
        .SelectMany(p => p.Lines)
        .SelectMany(l => l.Words)
        .Where(w => w.Confidence >= minConfidence && !string.IsNullOrWhiteSpace(w.Text))
        .Select(w => w.Text)
        .ToList();
}
Imports System
Imports System.Collections.Generic
Imports System.Linq

Public Function ExtractHighConfidenceWords(imagePath As String, Optional minConfidence As Double = 80.0) As List(Of String)
    Dim result = New IronTesseract().Read(imagePath)

    Console.WriteLine($"Page confidence: {result.Confidence}%")

    ' LINQ directly on the word collection — no iterator state management
    Return result.Pages _
        .SelectMany(Function(p) p.Lines) _
        .SelectMany(Function(l) l.Words) _
        .Where(Function(w) w.Confidence >= minConfidence AndAlso Not String.IsNullOrWhiteSpace(w.Text)) _
        .Select(Function(w) w.Text) _
        .ToList()
End Function
$vbLabelText   $csharpLabel

イテレータの状態機械はなくなりました。 IronOCRにおける信頼度値は、常に0~100のスケールで表され、100で割る必要はありません。 信頼度スコアガイドでは、単語単位、行単位、ページ単位の信頼度アクセスパターンについて解説しています。 検索結果の閲覧ガイドでは、構造化された検索結果の階層構造全体をどのようにナビゲートするかを示しています。

複数ページTIFFファイルのバッチ処理

複数のフレームを含むTIFFファイルは、文書スキャンワークフローでよく使用されます。 charleswラッパーには、マルチフレームTIFFのサポート機能が組み込まれていません。 処理前に各フレームを手動で抽出する必要があります。 IronOCRは、単一の読み込み呼び出しでマルチフレームTIFFをネイティブに処理します。

Charlesw Tesseract アプローチ:

// charlesw/Tesseract has no multi-frame TIFF support
// Each frame must be extracted via System.Drawing before OCR can run
public string ProcessMultiFrameTiff(string tiffPath)
{
    var fullText = new StringBuilder();

    using var tiffImage = Image.FromFile(tiffPath);
    var frameCount = tiffImage.GetFrameCount(FrameDimension.Page);

    using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);

    for (int i = 0; i < frameCount; i++)
    {
        tiffImage.SelectActiveFrame(FrameDimension.Page, i);

        // Must save each frame as a temp file for Pix to load
        var tempPath = Path.Combine(Path.GetTempPath(), $"tiff_frame_{i}.png");
        try
        {
            tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);

            using var pix  = Pix.LoadFromFile(tempPath);
            using var page = engine.Process(pix);
            fullText.AppendLine(page.GetText());
        }
        finally
        {
            if (File.Exists(tempPath)) File.Delete(tempPath);
        }
    }

    return fullText.ToString();
}
// charlesw/Tesseract has no multi-frame TIFF support
// Each frame must be extracted via System.Drawing before OCR can run
public string ProcessMultiFrameTiff(string tiffPath)
{
    var fullText = new StringBuilder();

    using var tiffImage = Image.FromFile(tiffPath);
    var frameCount = tiffImage.GetFrameCount(FrameDimension.Page);

    using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);

    for (int i = 0; i < frameCount; i++)
    {
        tiffImage.SelectActiveFrame(FrameDimension.Page, i);

        // Must save each frame as a temp file for Pix to load
        var tempPath = Path.Combine(Path.GetTempPath(), $"tiff_frame_{i}.png");
        try
        {
            tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Png);

            using var pix  = Pix.LoadFromFile(tempPath);
            using var page = engine.Process(pix);
            fullText.AppendLine(page.GetText());
        }
        finally
        {
            if (File.Exists(tempPath)) File.Delete(tempPath);
        }
    }

    return fullText.ToString();
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports Tesseract
Imports System.IO
Imports System.Text

Public Function ProcessMultiFrameTiff(tiffPath As String) As String
    Dim fullText As New StringBuilder()

    Using tiffImage As Image = Image.FromFile(tiffPath)
        Dim frameCount As Integer = tiffImage.GetFrameCount(FrameDimension.Page)

        Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
            For i As Integer = 0 To frameCount - 1
                tiffImage.SelectActiveFrame(FrameDimension.Page, i)

                ' Must save each frame as a temp file for Pix to load
                Dim tempPath As String = Path.Combine(Path.GetTempPath(), $"tiff_frame_{i}.png")
                Try
                    tiffImage.Save(tempPath, Imaging.ImageFormat.Png)

                    Using pix As Pix = Pix.LoadFromFile(tempPath)
                        Using page As Page = engine.Process(pix)
                            fullText.AppendLine(page.GetText())
                        End Using
                    End Using
                Finally
                    If File.Exists(tempPath) Then File.Delete(tempPath)
                End Try
            Next
        End Using
    End Using

    Return fullText.ToString()
End Function
$vbLabelText   $csharpLabel

IronOCRのアプローチ:

// LoadImageFrames handles multi-frame TIFFs natively — no frame extraction loop
public string ProcessMultiFrameTiff(string tiffPath)
{
    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath);   // All frames loaded in one call

    var result = new IronTesseract().Read(input);

    // Pages maps directly to TIFF frames
    foreach (var page in result.Pages)
        Console.WriteLine($"Frame {page.PageNumber}: {page.Words.Count()} words");

    return result.Text;
}
// LoadImageFrames handles multi-frame TIFFs natively — no frame extraction loop
public string ProcessMultiFrameTiff(string tiffPath)
{
    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath);   // All frames loaded in one call

    var result = new IronTesseract().Read(input);

    // Pages maps directly to TIFF frames
    foreach (var page in result.Pages)
        Console.WriteLine($"Frame {page.PageNumber}: {page.Words.Count()} words");

    return result.Text;
}
Imports System
Imports IronOcr

Public Class TiffProcessor
    ' LoadImageFrames handles multi-frame TIFFs natively — no frame extraction loop
    Public Function ProcessMultiFrameTiff(tiffPath As String) As String
        Using input As New OcrInput()
            input.LoadImageFrames(tiffPath) ' All frames loaded in one call

            Dim result = New IronTesseract().Read(input)

            ' Pages maps directly to TIFF frames
            For Each page In result.Pages
                Console.WriteLine($"Frame {page.PageNumber}: {page.Words.Count()} words")
            Next

            Return result.Text
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

一時ファイル抽出ループとフレームごとの破棄処理チェーンは削除されました。 フレームカウント検出が FrameDimension.Page 経由で消えます。 IronOCR は TIFF フレームを OcrResult.Pages にマッピングするため、フレームごとのテキストアクセスは追加のイテレーションロジックを必要としません。 TIFF/GIF入力ガイドでは、フレーム選択や部分的なTIFF処理に関する追加オプションについて説明しています。

検索可能なPDF生成

charleswラッパーはテキスト出力のみを生成します。 スキャンしたドキュメントを検索可能なPDFに変換することは、ドキュメント管理システムの一般的な要件であり、抽出されたテキストを元の画像ページにオーバーレイするために二次PDFライブラリ(IronPDF、PDFSharp、または類似)が必要です。 IronOCRは、二次的なライブラリを使用せずに、1回のメソッド呼び出しで検索可能なPDFを生成します。

Charlesw Tesseract アプローチ:

// charlesw/Tesseract produces text only.
// Creating a searchable PDF requires a second library and significant code.
// The pattern below is representative — actual implementation varies by PDF library.
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
    // Step 1: Extract text from image
    string extractedText;
    using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
    using var img = Pix.LoadFromFile(imagePath);
    using var page = engine.Process(img);
    extractedText = page.GetText();

    // Step 2: Build a PDF with the image as background and text overlay
    // Requires a separate PDF library (not shown — 50-100+ additional lines)
    // The text layer must be positioned to match the original image layout
    // Word-level coordinates from the iterator are needed for accurate alignment
    throw new NotImplementedException(
        "Searchable PDF generation requires a separate PDF library. " +
        "Add PdfSharp, IronPDF, or similar, then implement text layer overlay.");
}
// charlesw/Tesseract produces text only.
// Creating a searchable PDF requires a second library and significant code.
// The pattern below is representative — actual implementation varies by PDF library.
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
    // Step 1: Extract text from image
    string extractedText;
    using var engine = new TesseractEngine(@"./tessdata", "eng", EngineMode.Default);
    using var img = Pix.LoadFromFile(imagePath);
    using var page = engine.Process(img);
    extractedText = page.GetText();

    // Step 2: Build a PDF with the image as background and text overlay
    // Requires a separate PDF library (not shown — 50-100+ additional lines)
    // The text layer must be positioned to match the original image layout
    // Word-level coordinates from the iterator are needed for accurate alignment
    throw new NotImplementedException(
        "Searchable PDF generation requires a separate PDF library. " +
        "Add PdfSharp, IronPDF, or similar, then implement text layer overlay.");
}
Imports Tesseract

Public Sub CreateSearchablePdf(imagePath As String, outputPdfPath As String)
    ' Step 1: Extract text from image
    Dim extractedText As String
    Using engine As New TesseractEngine("./tessdata", "eng", EngineMode.Default)
        Using img As Pix = Pix.LoadFromFile(imagePath)
            Using page As Page = engine.Process(img)
                extractedText = page.GetText()
            End Using
        End Using
    End Using

    ' Step 2: Build a PDF with the image as background and text overlay
    ' Requires a separate PDF library (not shown — 50-100+ additional lines)
    ' The text layer must be positioned to match the original image layout
    ' Word-level coordinates from the iterator are needed for accurate alignment
    Throw New NotImplementedException("Searchable PDF generation requires a separate PDF library. " & _
                                      "Add PdfSharp, IronPDF, or similar, then implement text layer overlay.")
End Sub
$vbLabelText   $csharpLabel

IronOCRのアプローチ:

// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
// なし secondary library, no text overlay code, no coordinate mapping
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
    var result = new IronTesseract().Read(imagePath);
    result.SaveAsSearchablePdf(outputPdfPath);
    Console.WriteLine($"Searchable PDF saved: {outputPdfPath}");
}

// Same API works for multi-page TIFF or existing PDF input
public void MakePdfSearchable(string scannedPdfPath, string outputPdfPath)
{
    var result = new IronTesseract().Read(scannedPdfPath);
    result.SaveAsSearchablePdf(outputPdfPath);
}
// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
// なし secondary library, no text overlay code, no coordinate mapping
public void CreateSearchablePdf(string imagePath, string outputPdfPath)
{
    var result = new IronTesseract().Read(imagePath);
    result.SaveAsSearchablePdf(outputPdfPath);
    Console.WriteLine($"Searchable PDF saved: {outputPdfPath}");
}

// Same API works for multi-page TIFF or existing PDF input
public void MakePdfSearchable(string scannedPdfPath, string outputPdfPath)
{
    var result = new IronTesseract().Read(scannedPdfPath);
    result.SaveAsSearchablePdf(outputPdfPath);
}
' SaveAsSearchablePdf produces a PDF/A-compatible searchable document
' なし secondary library, no text overlay code, no coordinate mapping
Public Sub CreateSearchablePdf(imagePath As String, outputPdfPath As String)
    Dim result = New IronTesseract().Read(imagePath)
    result.SaveAsSearchablePdf(outputPdfPath)
    Console.WriteLine($"Searchable PDF saved: {outputPdfPath}")
End Sub

' Same API works for multi-page TIFF or existing PDF input
Public Sub MakePdfSearchable(scannedPdfPath As String, outputPdfPath As String)
    Dim result = New IronTesseract().Read(scannedPdfPath)
    result.SaveAsSearchablePdf(outputPdfPath)
End Sub
$vbLabelText   $csharpLabel

SaveAsSearchablePdf() は OCR テキストを認識された単語に合わせて目に見えない層として埋め込み、ドキュメントを視覚的外観を変えることなく全文検索可能にします。 検索可能なPDF形式の操作ガイドでは、ページ範囲の選択方法と圧縮オプションについて解説しています。 検索可能なPDFサンプルページで、動作例をご覧いただけます。

チャールズ・テッセラクト API からIronOCRへのマッピング リファレンス

チャールズ・テッセラクト IronOCR相当値
new TesseractEngine(tessDataPath, "eng", EngineMode.Default) new IronTesseract()
Pix.LoadFromFile(imagePath) input.LoadImage(imagePath)
Pix.LoadFromMemory(bytes) input.LoadImage(imageBytes)
engine.Process(pix) ocr.Read(input)
page.GetText() result.Text
page.GetMeanConfidence() result.Confidence (0–100 スケール)
page.GetIterator() result.Pages, result.Words (直接コレクション)
iter.GetText(PageIteratorLevel.Word) word.Text
iter.GetConfidence(PageIteratorLevel.Word) word.Confidence
iter.TryGetBoundingBox(PageIteratorLevel.Word, out var b) word.X, word.Y, word.Width, word.Height
iter.GetText(PageIteratorLevel.Para) paragraph.Text
iter.IsAtBeginningOf(PageIteratorLevel.Block) page.Paragraphs (直接イテレート)
EngineMode.Default 自動(Tesseract 5 LSTM デフォルト)
EngineMode.TesseractOnly ocr.Configuration.PageSegmentationMode
手動 tessdata .traineddata ファイル dotnet add package IronOcr.Languages.French
TessDataPath 定数 + .csproj コピーエントリ 該当なし — バンドル
Leptonica DLL 経由の Pix.LoadFromFile() input.LoadImage() — ネイティブ DLL は不要
プラットフォーム GetTessDataPath() メソッド 該当なし - 削除済み
leptonica-1.82.0.dll / libleptonica-dev 該当なし — Leptonicaへの依存なし
TIFF の一時ファイルフレームの手動抽出 input.LoadImageFrames(tiffPath)
検索可能なPDF出力はありません result.SaveAsSearchablePdf(outputPath)
スレッドごとの new TesseractEngine() 1つの IronTesseract — スレッドセーフ

一般的な移行の問題と解決策

問題1:LeptonicaまたはTesseractバイナリでDllNotFoundExceptionが発生する

charlesw Tesseract: System.DllNotFoundException: Unable to load DLL 'leptonica-1.82.0': The specified module could not be found. Leptonica ネイティブ DLL が期待される場所にないときにこの例外が発生します。 これは、新しい Docker コンテナ、CI エージェント、または NuGet パッケージの runtimes/ フォルダーが正しくコピーされなかった任意の環境で一般的です。

解決策: Tesseract パッケージを削除します。 IronOcr をインストールします。 IronOCRはすべてのネイティブバイナリを内部的にバンドルしており、システムLeptonicaへのP/Invokeは行いません。 外部のLeptonica依存関係が存在しないため、例外は発生しません。

dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
dotnet remove package Tesseract
:InstallCmd dotnet add package IronOcr
SHELL

apt-get install libleptonica-dev は不要です。 ネイティブ DLL 用の <CopyToOutputDirectory> エントリはありません。

問題2:デプロイ後のTessdataパスエラー

charlesw Tesseract: Tesseract.TesseractException: Failed to initialise tesseract engine. これは TessDataPath が実行時に解決されないときに発生します。エラーなしでコンパイルされ、実行時にのみ失敗し、失敗パスは展開環境に依存します。

解決策: IronOCRにはtessdataパスの概念は存在しません。 定数を削除し、.csprojCopyToOutputDirectory XML を削除し、それを構築するファクトリメソッドを削除します。 言語データはNuGetパッケージとして配布されます。

# Replace this manual tessdata file management:
#   tessdata/eng.traineddata  (15 MB, manually downloaded)
#   tessdata/fra.traineddata  (15 MB, manually downloaded)
#   .csproj <CopyToOutputDirectory> entry

# With NuGet packages:
dotnet add package IronOcr.Languages.French
# Replace this manual tessdata file management:
#   tessdata/eng.traineddata  (15 MB, manually downloaded)
#   tessdata/fra.traineddata  (15 MB, manually downloaded)
#   .csproj <CopyToOutputDirectory> entry

# With NuGet packages:
dotnet add package IronOcr.Languages.French
SHELL

多言語ガイドでは、言語パッケージを追加した後に多言語認識を設定する方法を説明しています。

問題3:ベースイメージの更新時にコンテナのビルドが失敗する

charlesw Tesseract: Dockerfile は Leptonica ネイティブ依存を満たすために apt-get install -y libleptonica-dev を含みます。 ベースイメージがDebian BullseyeからBookwormに移行した場合、またはLeptonicaパッケージ名がディストリビューション間で変更された場合、ビルドはaptエラーで失敗します。 この問題を解決するには、新しいディストリビューションでどのパッケージ名を使用すべきかを知る必要があります。

解決策: Leptonica apt-get 行を完全に削除します。 Linux 上の IronOCR は、すでに System.Drawing を使用する .NET アプリケーションが必要とする標準的な libgdiplus パッケージのみ必要です:

# Before: Leptonica explicit install — breaks on base image updates
RUN apt-get update && apt-get install -y libleptonica-dev

# After: standard .NET Linux requirement only
RUN apt-get update && apt-get install -y libgdiplus

Dockerデプロイメントガイドには、一般的なベースイメージ用のテスト済みDockerfileテンプレートが掲載されています。 Charlesw固有のインフラストラクチャコードは必要ありません。

問題4:イテレータパターンが空ページまたは空白ページで途切れる

charlesw Tesseract: ResultIteratornull を特定のページセグメントから返し、ループ全体で明示的な null チェックを必要とします。null チェックを見落とすと、空白ページや認識可能なテキストがない画像で NullReferenceException を引き起こします。

解決策: IronOCRの結果コレクションは決してnullになりません。 空のページからは空のコレクションが返されます。 null参照ではなく、テキストコンテンツをチェックする。

// Before: null checks required at every iterator level
var wordText = iter.GetText(PageIteratorLevel.Word);
if (wordText != null && wordText.Trim().Length > 0)
    results.Add(wordText.Trim());

// After: collection is safe to enumerate; check content as needed
foreach (var word in result.Pages.SelectMany(p => p.Lines).SelectMany(l => l.Words))
{
    if (!string.IsNullOrWhiteSpace(word.Text))
        results.Add(word.Text);
}
// Before: null checks required at every iterator level
var wordText = iter.GetText(PageIteratorLevel.Word);
if (wordText != null && wordText.Trim().Length > 0)
    results.Add(wordText.Trim());

// After: collection is safe to enumerate; check content as needed
foreach (var word in result.Pages.SelectMany(p => p.Lines).SelectMany(l => l.Words))
{
    if (!string.IsNullOrWhiteSpace(word.Text))
        results.Add(word.Text);
}
' Before: null checks required at every iterator level
Dim wordText = iter.GetText(PageIteratorLevel.Word)
If wordText IsNot Nothing AndAlso wordText.Trim().Length > 0 Then
    results.Add(wordText.Trim())
End If

' After: collection is safe to enumerate; check content as needed
For Each word In result.Pages.SelectMany(Function(p) p.Lines).SelectMany(Function(l) l.Words)
    If Not String.IsNullOrWhiteSpace(word.Text) Then
        results.Add(word.Text)
    End If
Next
$vbLabelText   $csharpLabel

問題5:負荷がかかった状態でのねじの安全違反

charlesw Tesseract: TesseractEngine はスレッドセーフではありません。 ASP.NETアプリケーションで、複数の同時リクエスト間で1つのインスタンスを共有すると、アクセス違反や結果の破損が発生します。 標準的な解決策は、スレッドごとに1つのエンジンを作成することですが、これはAPIからは明らかではなく、問題が発生した場合のエラーメッセージは難解なネイティブ例外です。

解決策: IronTesseract はスレッドセーフです。 1つのインスタンスが同時リクエストを処理できるか、または最大スループットのためには Parallel.ForEach 内で各スレッドごとに1つ作成するのが良いです。どちらのパターンも変更なしで機能します。

// Thread-safe parallel processing — IronTesseract handles concurrent access
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
Parallel.ForEach(imageFiles, imagePath =>
{
    var ocr    = new IronTesseract();
    var result = ocr.Read(imagePath);
    results.Add(result.Text);
});
// Thread-safe parallel processing — IronTesseract handles concurrent access
var results = new System.Collections.Concurrent.ConcurrentBag<string>();
Parallel.ForEach(imageFiles, imagePath =>
{
    var ocr    = new IronTesseract();
    var result = ocr.Read(imagePath);
    results.Add(result.Text);
});
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

' Thread-safe parallel processing — IronTesseract handles concurrent access
Dim results As New ConcurrentBag(Of String)()
Parallel.ForEach(imageFiles, Sub(imagePath)
    Dim ocr As New IronTesseract()
    Dim result = ocr.Read(imagePath)
    results.Add(result.Text)
End Sub)
$vbLabelText   $csharpLabel

非同期OCRガイドでは、スレッドブロッキングが許容されないASP.NET Coreコントローラー向けの非同期パターンについて説明します。

問題6:実行時にARM64バイナリが見つからない

Charlesw Tesseract: AWS Graviton (Linux ARM64) または Apple Silicon CI エージェントでは、アーカイブされたパッケージに ARM64 ネイティブバイナリが含まれていない場合があります。 失敗はエンジン作成時の DllNotFoundException または BadImageFormatException であり、パッケージがサポートする経路を持たないプラットフォーム上での実行時エラーです。

解決策: IronOCRは、LinuxとmacOSの両方に対応した検証済みのARM64バイナリを提供しています。 コード変更なしでARM64環境にデプロイできます。 Linux導入ガイドmacOS導入ガイドには、サポートされているランタイム識別子が記載されています。

チャールズ・テッセラクト 移行チェックリスト

移行前

コードベースを監査して、変更されるすべてのパターンを特定する。

# Find all references to Tesseract namespace (engine creation, Pix usage, iterator usage)
grep -rn "using Tesseract" --include="*.cs" .

# Find TesseractEngine instantiation points
grep -rn "TesseractEngine" --include="*.cs" .

# Find Pix usage (Leptonica image type)
grep -rn "Pix\." --include="*.cs" .

# Find tessdata path constants and methods
grep -rn "tessdata\|TessDataPath\|traineddata" --include="*.cs" .

# Find platform-conditional deployment code
grep -rn "IsOSPlatform\|DOTNET_RUNNING_IN_CONTAINER\|LD_LIBRARY_PATH" --include="*.cs" .

# Find iterator pattern usage
grep -rn "GetIterator\|ResultIterator\|PageIteratorLevel" --include="*.cs" .

# Find confidence calls
grep -rn "GetMeanConfidence\|GetConfidence" --include="*.cs" .

# Find .csproj tessdata copy entries
grep -rn "tessdata" --include="*.csproj" .
# Find all references to Tesseract namespace (engine creation, Pix usage, iterator usage)
grep -rn "using Tesseract" --include="*.cs" .

# Find TesseractEngine instantiation points
grep -rn "TesseractEngine" --include="*.cs" .

# Find Pix usage (Leptonica image type)
grep -rn "Pix\." --include="*.cs" .

# Find tessdata path constants and methods
grep -rn "tessdata\|TessDataPath\|traineddata" --include="*.cs" .

# Find platform-conditional deployment code
grep -rn "IsOSPlatform\|DOTNET_RUNNING_IN_CONTAINER\|LD_LIBRARY_PATH" --include="*.cs" .

# Find iterator pattern usage
grep -rn "GetIterator\|ResultIterator\|PageIteratorLevel" --include="*.cs" .

# Find confidence calls
grep -rn "GetMeanConfidence\|GetConfidence" --include="*.cs" .

# Find .csproj tessdata copy entries
grep -rn "tessdata" --include="*.csproj" .
SHELL

プロジェクトが対象とするデプロイ環境(Docker、Linux、ARM64、Azure、AWS)に注意してください。これらは、charlesw/tesseractが最も多くの設定を必要とする環境であり、 IronOCRはそれらの設定を不要にします。

コードの移行

  1. charlesw ラッパーをアンインストールするために dotnet remove package Tesseract を実行します
  2. IronOCR をインストールするために dotnet add package IronOcr を実行します
  3. アプリケーション起動時に IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; を追加します
  4. すべての using Tesseract; 文を using IronOcr; に置き換えます
  5. tessdata パス定数と、環境ごとにパスを構築するメソッドを削除します。
  6. tessdata パス選択のために書かれたすべての RuntimeInformation.IsOSPlatform() ブロックを削除します
  7. tessdata ファイルの <CopyToOutputDirectory> エントリをすべての .csproj ファイルから削除します
  8. ソース管理や展開アーティファクトストアから tessdata .traineddata ファイルを削除します
  9. 以前に .traineddata ファイルとして展開された各言語のために dotnet add package IronOcr.Languages.* を追加します
  10. TesseractEngine + Pix.LoadFromFile() + engine.Process() チェーンを new IronTesseract().Read() に置き換えます
  11. すべての Pix.LoadFromFile() および Pix.LoadFromMemory() 呼び出しを input.LoadImage() に置き換えます
  12. すべての page.GetText() 呼び出しを result.Text に置き換えます
  13. イテレータに基づいた単語/行抽出を result.Pages の直接コレクションアクセスに置き換えます
  14. iter.GetConfidence() しきい値ロジックを result.Words または result.Lines 上の LINQ に置き換えます
  15. Dockerfile およびデプロイメントスクリプトから libleptonica-dev / leptonica-1.82.0.dll を削除します

移行後

コードの更新が完了したら、以下の点を確認してください。

  • OCRはWindows上でネイティブDLLエラーなしで正常に動作します
  • OCR は、libgdiplus を超えてapt-get の変更なしに Docker Linux コンテナで成功裏に実行されます
  • OCRは、ARM64プラットフォームが展開マトリックスに含まれている場合、そのプラットフォーム上でテキスト出力を生成します。
  • 複数ページのTIFFファイルは、最初のフレームだけでなく、すべてのフレームのテキストを返します。
  • 信頼度フィルタリングは、以前のイテレータ実装と同じ、信頼度の高い単語の論理セットを返します。
  • 言語固有のドキュメント(フランス語、ドイツ語など)は、言語NuGetパッケージのインストール後に正しく認識されます。
  • 並列OCR処理は例外や出力の破損なく完了する
  • 以前の実装ではテキストのみが返されていたところ、検索可能なPDF出力が生成されます。
  • CI/CDパイプラインは、tessdataのダウンロード手順やLeptonicaのインストールコマンドなしでビルドされます。
  • 前回の実装の検証に使用したのと同じ画像コーパスに対してスモークテストを実施する。

IronOCRへの移行の主なメリット

自己完結型デプロイメントモデル。移行後、OCRの依存関係は単一のNuGetパッケージ参照によって完全に記述されます。 ソース管理には tessdata ファイルがなく、CopyToOutputDirectory エントリがなく、ネイティブ DLL 配布手順もなく、Leptonica システムパッケージもありません。 以前は複数ステップのアーティファクト管理が必要だった CI/CD パイプラインが dotnet publish に簡略化されます。 charleswラッパーをサポートするために蓄積されていたデプロイメント関連のコードは、完全に削除されました。

条件ロジックなしでプラットフォーム間の互換性を実現。同じアプリケーションバイナリが、Windows x64、Linux x64、Linux ARM64、macOS x64、およびmacOS ARM64で変更なしに動作します。 AWS Graviton、Apple Silicon CI、Raspberry Piなど、ARM64デプロイメントターゲットを追加するチームは、新しいプラットフォーム検出コードを記述する必要はありません。 Linux導入ガイドAWS導入ガイドは、テスト済みの構成を裏付けています。

Tesseract 5の精度向上:内蔵プリプロセス機能搭載。Tesseract 4.1.1からTesseract 5へのアップグレードにより、劣化文書の認識精度が向上しました。 IronOCRは、エンジンのアップグレードに加えて自動前処理機能を追加し、エンジンが各画像を処理する前に、傾き補正、ノイズ除去、コントラスト正規化、および二値化を適用します。 以前は許容できる精度基準を満たすためにカスタムの前処理パイプラインが必要だった文書も、追加のコードなしでその基準を満たすことができるようになった。 画像品質補正ガイドでは、デフォルト設定以上の調整が必要な場合の具体的な前処理オプションについて説明しています。

直接結果ナビゲーションはイテレータのボイラープレートを置き換えます。 charlesw イテレータパターン — GetIterator(), Begin(), Next(), IsAtBeginningOf(), null チェックなど — はシンプルなコレクションによって置き換えられます。 単語、行、段落、ページは、結果オブジェクトのプロパティです。 信頼度に基づくフィルタリングは、LINQ 式です。 以前は、単語レベルのデータを抽出するコードには、15~30行のイテレータ管理が必要だった。 IronOCRでいうと、2~3行に相当します。 OCR結果機能ページでは、構造化された出力モデル全体を要約しています。

二次ライブラリなしの検索可能な PDF 出力。 result.SaveAsSearchablePdf() は認識された単語に合わせたテキストレイヤーを持つ PDF を生成し、二次的な PDF ライブラリを必要としません。 検索可能なPDFを取り込む文書管理システムでは、別途PDF生成ステップは不要になりました。抽出されたテキストを提供する結果オブジェクトが検索可能なファイルも書き込むため、文書処理パイプラインは単一のライブラリ依存関係で済みます。

アクティブなメンテナンスとセキュリティパッチ適用範囲。IronOCRは、Tesseract 5モデルの改善、 .NETランタイム互換性の検証、および基盤となるC++エンジンのセキュリティパッチ適用範囲を追跡する定期的なアップデートを受け取ります。この依存関係は、アーカイブされたパッケージのようなリスクプロファイルを持たなくなったため、コンプライアンスレビューでセキュリティパッチパスの欠落に関する問題が指摘されることはありません。 .NET 10が2026年までに一般提供開始されるにつれて、 IronOCRのドキュメントハブは、回避策やフォークを必要とせずに、現在の互換性を反映したものとなるでしょう。

ご注意PDFSharp や Tesseract はそれぞれの所有者の登録商標です。 このサイトはGoogleやempira Software GmbHによって承認されておらず、支援されていません。 すべての製品名、ロゴ、およびブランドは各所有者の所有物です。 比較は情報提供のみを目的としており、執筆時点で公開されている情報を反映しています。

よくある質問

なぜcharlesw/tesseract(.NET Tesseractラッパー)からIronOCRへ移行する必要があるのですか?

一般的な推進要因には、COM相互接続の複雑さの解消、ファイルベースのライセンス管理の置き換え、ページ単位の課金の回避、Docker/コンテナデプロイの有効化、標準的な.NETツールと統合するNuGetネイティブワークフローの採用などがあります。

charlesw/tesseract(.NETテッセラクト・ラッパー)からIronOCRへ移行する際の主なコード変更は何ですか?

charlesw/tesseractの初期化シーケンスをIronTesseractのインスタンス化に置き換え、COMのライフサイクル管理(明示的なCreate/Load/Closeパターン)を削除し、結果のプロパティ名を更新します。その結果、定型的な行が大幅に減少します。

IronOCRをインストールして移行を開始するにはどうすればいいですか?

パッケージマネージャーコンソールで'Install-Package IronOcr'を実行するか、CLIで'dotnet add package IronOcr'を実行してください。言語パックは別のパッケージです:例えばフランス語の場合は'dotnet add package IronOcr.Languages.French'となります。

IronOCRは標準的なビジネス文書のcharlesw/tesseract (.NET Tesseract wrapper)のOCR精度に匹敵しますか?

IronOCRは、請求書、契約書、領収書、入力フォームなどの標準的なビジネスコンテンツで高い精度を達成しています。画像前処理フィルター(傾き補正、ノイズ除去、コントラスト強調)により、劣化した入力の認識をさらに向上させます。

IronOCRはcharlesw/tesseract(.NET Tesseractラッパー)が別途インストールする言語データをどのように扱うのですか?

IronOCRの言語データはNuGetパッケージとして配布されます。'dotnet add package IronOcr.Languages.German'でドイツ語のサポートがインストールされます。手動でのファイル配置やディレクトリパスは必要ありません。

charlesw/tesseract(.NETのTesseractラッパー)からIronOCRへの移行はデプロイインフラの変更が必要ですか?

IronOCRはcharlesw/tesseract(.NET Tesseractラッパー)よりもインフラストラクチャの変更を必要としません。SDKのバイナリパス、ライセンスファイルの配置、ライセンスサーバーの設定は必要ありません。NuGetパッケージには完全なOCRエンジンが含まれており、ライセンスキーはアプリケーションコードに設定された文字列です。

移行後のIronOCRライセンスの設定方法は?

アプリケーションの起動コードでIronOcr.License.LicenseKey = "YOUR-KEY "を割り当てます。DockerまたはKubernetesでは、キーを環境変数として保存し、スタートアップで読み込む。License.IsValidLicenseを使用して、トラフィックを受け入れる前にバリデーションを行う。

IronOCRはcharlesw/tesseractと同じようにPDFを処理できますか?

IronOCRはネイティブPDFもスキャンしたPDFも読み取ります。IronTesseractをインスタンス化し、ocr.Read(input)を呼び出し、入力はPDFパスまたはOcrPdfInputであり、OcrResultページを反復します。別のPDFレンダリングパイプラインは必要ありません。

IronOCRはどのように大量処理のスレッディングを処理するのですか?

IronTesseractはスレッド毎にインスタンス化しても安全です。Parallel.ForEachまたはタスクプールでスレッドごとにインスタンスを1つスピンアップし、OCRを同時に実行し、完了したら各インスタンスを破棄します。グローバルステートやロックは必要ありません。

IronOCRはテキスト抽出後、どのような出力形式をサポートしていますか?

IronOCRはテキスト、単語座標、信頼度スコア、ページ構造を含む構造化された結果を返します。エクスポートオプションには、プレーンテキスト、検索可能なPDF、下流処理用の構造化結果オブジェクトが含まれます。

IronOCRの価格はcharlesw/tesseract(.NET Tesseractラッパー)よりもワークロードのスケーリングが予測可能ですか?

IronOCRは、定額制の永久ライセンスを採用しており、ページ単位やボリューム単位の料金はかかりません。10,000ページでも1,000万ページでも、ライセンスコストは一定です。ボリュームライセンスとチームライセンスのオプションはIronOCRの価格ページをご覧ください。

charlesw/tesseract (.NET Tesseractラッパー)からIronOCRに移行した後、既存のテストはどうなりますか?

抽出されたテキストコンテンツをアサートするテストは、移行後もパスし続ける必要があります。APIコールパターンやCOMオブジェクトのライフサイクルを検証するテストは、IronOCRのシンプルな初期化と結果モデルを反映するように更新する必要があります。

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

アイアンサポートチーム

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