Ir para o conteúdo do rodapé
VíDEOS

Migrando do Charlesw Tesseract para o IronOCR

Este guia orienta os desenvolvedores .NET na migração do pacote NuGet charlesw/tesseract (Tesseract) para o IronOCR. A migração se concentra em um problema específico: o modelo de implantação de binário nativo que o wrapper charlesw impõe e o código condicional de plataforma que esse modelo força os desenvolvedores a escrever. As equipes que lutaram com DllNotFoundException no CI, lutaram com caminhos de biblioteca Leptonica no Linux ou escreveram blocos de detecção de SO que não têm nada a ver com OCR encontrarão neste guia exatamente o que desaparece após a troca.

Por que migrar do Charlesw Tesseract?

O pacote arquivado charlesw/tesseract causa problemas em novos projetos não porque a API seja ruim, mas porque o modelo de implantação que ele requer foi projetado em torno de suposições que não se sustentam na infraestrutura moderna do .NET. Eis o que motiva as decisões de migração:

Implantação de Binário Nativo por Plataforma. O pacote NuGet Tesseract distribui binários nativos específicos da plataforma: tesseract50.dll para Windows x64, uma construção separada para x86, libtesseract.so para Linux x64. Esses binários devem estar na localização correta no momento da execução para que as chamadas P/Invoke sejam bem-sucedidas. Em uma estação de trabalho de desenvolvedor, o SDK os copia automaticamente. Em um contêiner Docker, um agente de compilação ARM64 ou um Serviço de Aplicativo do Azure com uma raiz de aplicativo não padrão, isso não ocorre. Cada novo destino de implantação se torna uma sessão de depuração.

Leptonica como uma dependência oculta. O carregamento de imagens do Tesseract é gerenciado pela biblioteca Leptonica, que é distribuída como um conjunto próprio de DLLs nativas junto com os binários do Tesseract. Não Windows, leptonica-1.82.0.dll deve estar presente no diretório de saída. Não Linux, a biblioteca compartilhada Leptonica deve ser incluída ou instalada como um pacote do sistema. Imagens Docker baseadas em Debian sem libleptonica-dev falham em Pix.LoadFromFile() com uma exceção nativa não explicativa, e corrigi-la requer saber qual pacote de sistema resolve a dependência.

Código Condicional de Plataforma na Lógica da Aplicação. A combinação de carregamento de binário nativo e resolução de caminho tessdata força os desenvolvedores a escrever verificações RuntimeInformation.IsOSPlatform(), detecção de variáveis de ambiente para contextos de contêiner e lógica de construção de caminho que varia conforme o alvo. Nenhum desse código é lógica de OCR. Trata-se de uma infraestrutura de implantação que existe unicamente porque o gerenciamento binário do pacote está incompleto.

Pacote arquivado sem caminho de correção. O repositório está arquivado desde 2021. Quando uma atualização de pacote do sistema em um host Linux altera a ABI do Leptonica, ou quando um novo runtime do .NET altera o comportamento de carregamento de binários nativos, não há versão para a qual atualizar. As únicas opções são criar um fork do pipeline de compilação nativo ou substituir a biblioteca.

Congelamento do mecanismo do Tesseract 4.1.1. Este pacote encapsula o Tesseract 4.1.1. O modelo LSTM reescrito do Tesseract 5 oferece uma precisão significativamente maior em documentos degradados. Essa atualização não está disponível através do pacote charlesw — ela requer a troca de bibliotecas.

Gestão de Confiança Sem um Padrão Padrão. O wrapper charlesw expõe page.GetMeanConfidence() como um float entre 0 e 1, mas aplicar limiares de confiança no nível de palavra ou caractere requer o padrão de iterador com iter.GetConfidence(PageIteratorLevel.Word). Não existe uma API de filtragem padrão; Cada equipe implementa sua própria lógica de limite de forma diferente.

O problema fundamental

O wrapper charlesw requer configuração binária nativa específica da plataforma antes que o OCR possa ser executado:

// 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

O IronOCR não possui configuração binária nativa:

// 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 vs Charlesw Tesseract: Comparação de Recursos

A tabela a seguir descreve as funcionalidades relevantes para as equipes que avaliam essa migração:

Recurso Charlesw Tesseract IronOCR
Estado de manutenção Arquivado (sem atualizações desde 2021) Mantido ativamente
versão do motor Tesseract 4.1.1 (congelado) 5 (atual, otimizado)
Licença Apache 2.0 (gratuito) Comercial ($999–$2.999 perpétuo)
Instalação do NuGet Tesseract IronOcr
Gerenciamento binário nativo Implantação manual de DLL por plataforma Pacote com configuração zero
Dependência de Leptonica Requer leptonica-1.82.0.dll / libleptonica-dev Não aplicável (tratado internamente)
Gestão de dados Tess Download manual e entrada de cópia .csproj Pacotes de idiomas NuGet
Código condicional à plataforma Necessário para implantação em múltiplos alvos. Não é necessário
Implantação do Docker Requer COPY tessdata explícito + Leptonica apt-get Requisitos padrão do contêiner .NET apenas
Suporte a ARM64 Postagem não confirmada Agrupado e validado
formatos de entrada de imagem TIFF, PNG, BMP, JPG (via Leptonica) JPG, PNG, BMP, TIFF, GIF e muito mais
TIFF de várias páginas Iteração manual de quadros input.LoadImageFrames()
Entrada nativa de PDF Não (requer biblioteca secundária) Sim
Saída em PDF pesquisável Não Sim (result.SaveAsSearchablePdf())
Pré-processamento integrado None Corrigir distorção, reduzir ruído, aumentar contraste, binarizar, aumentar nitidez, redimensionar, dilatar, erodir, inverter
API de filtragem de confiança Iterador manual com GetConfidence() result.Confidence, word.Confidence
Resultados estruturados Padrão iterador (ResultIterator) Coleções diretas (Páginas, Parágrafos, Linhas, Palavras)
Leitura de código de barras Não Sim (durante a passagem pelo OCR)
OCR baseado em região Não Sim (CropRectangle)
Segurança da rosca Responsabilidade do chamador Embutido
Mais de 125 pacotes de idiomas Downloads manuais de tessdata dotnet add package IronOcr.Languages.*
.NET multiplataforma Sim (.NET Standard 2.0) Sim (.NET Framework 4.6.2+, .NET 5/6/7/8/9)
cadência de aplicação de patches de segurança Nenhum (arquivado) Lançamentos regulares

Guia Rápido: Migração doCharlesw Tesseractpara o IronOCR

Passo 1: Substitua o pacote NuGet

Remova o pacote Tesseract charlesw:

dotnet remove package Tesseract
dotnet remove package Tesseract
SHELL

Instale o IronOCR a partir do NuGet :

dotnet add package IronOcr

Etapa 2: Atualizar Namespaces

// Before (charlesw Tesseract)
using Tesseract;

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

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

Etapa 3: Inicializar a licença

Adicione esta chamada uma única vez na inicialização do aplicativo, antes da execução de qualquer operação de OCR:

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

Uma licença de avaliação gratuita está disponível na página de licenciamento do IronOCR . A versão de avaliação remove a marca d'água da saída e permite acesso total à API.

Exemplos de migração de código

Removendo a configuração do caminho binário nativo

O padrão de inicialização mais comum em projetos charlesw/tesseract é uma classe de fábrica ou auxiliar que constrói o caminho do tessdata e configura o carregamento de bibliotecas nativas por ambiente. Este código existe exclusivamente devido ao modelo de implantação do wrapper.

Abordagem do Tesseract de Charlesw:

// 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

Abordagem 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

Toda a classe OcrEngineFactory é deletada. A lógica de caminho condicional de plataforma, a verificação DOTNET_RUNNING_IN_CONTAINER, e a dependência de DLL Leptonica desaparecem com ele. Em todos os ambientes — estação de trabalho do desenvolvedor, agente de CI, contêiner Docker, VM na nuvem — são executadas as mesmas duas linhas. O guia de configuração do IronTesseract aborda opções de configuração para quando os valores padrão precisam ser ajustados, mas para a maioria das implantações nenhuma alteração é necessária.

Substituição de conversão de imagem Leptonica

O wrapper charlesw usa o tipo Pix da Leptonica como sua representação de imagem. Qualquer código que manipula imagens antes do OCR deve converter através de Pix, o que requer que a DLL nativa da Leptonica seja carregada e operacional. Substituir esse padrão por OcrInput elimina completamente a dependência da Leptonica.

Abordagem do Tesseract de Charlesw:

// 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)
{
    // Não 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)
{
    // Não 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

Public Class ImageProcessor
    ' 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
        ' Não 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
End Class
$vbLabelText   $csharpLabel

Abordagem 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

O processo de transferência de arquivos temporários desaparece. Nenhum arquivo é escrito em disco, nenhuma DLL Leptonica é invocada para a conversão e não há bloco finally para limpar. O guia de entrada de imagem e o guia de entrada de fluxo documentam todas as fontes de entrada suportadas, incluindo carregamento de URLs e arquivos mapeados na memória.

Filtragem por Limiar de Confiança

O wrapper charlesw expõe a confiança em dois níveis: page.GetMeanConfidence() para a página inteira, e iter.GetConfidence(PageIteratorLevel.Word) para palavras individuais. Filtrar palavras de baixa confiança da saída requer o gerenciamento manual de um loop iterador. O IronOCR expõe a confiança diretamente nos objetos de resultado, tornando a lógica de limite uma expressão LINQ.

Abordagem do Tesseract de Charlesw:

// 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

Abordagem 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

A máquina de estados do iterador desapareceu. Os valores de confiança no IronOCR estão em uma escala de 0 a 100, sem necessidade de divisão por 100. O guia de pontuação de confiança abrange padrões de acesso à confiança por palavra, por linha e por página. O guia de resultados de leitura mostra como navegar por toda a hierarquia estruturada de resultados.

Processamento em lote de TIFF de várias páginas

Arquivos TIFF com múltiplos quadros são comuns em fluxos de trabalho de digitalização de documentos. O wrapper charlesw não possui suporte integrado para TIFF com múltiplos quadros; Cada fotograma deve ser extraído manualmente antes do processamento. O IronOCR processa arquivos TIFF com múltiplos quadros de forma nativa, com uma única chamada de carregamento.

Abordagem do Tesseract de Charlesw:

// 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

Abordagem 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

O loop de extração de arquivos temporários e a cadeia de descarte por quadro foram removidos. A detecção de contagem de quadros via FrameDimension.Page desaparece.IronOCR mapeia quadros TIFF para OcrResult.Pages, então o acesso ao texto por quadro não requer lógica de iteração adicional. O guia de entrada TIFF/GIF aborda opções adicionais para seleção de quadros e processamento parcial de TIFF.

Geração de PDF pesquisável

O wrapper charlesw produz apenas saída de texto. Converter um documento escaneado para um PDF pesquisável — um requisito comum para sistemas de gerenciamento de documentos — requer uma biblioteca PDF secundária (IronPDF, PDFSharp ou similar) para sobrepor o texto extraído nas páginas de imagem originais. O IronOCR gera PDFs pesquisáveis ​​em uma única chamada de método, sem necessidade de bibliotecas secundárias.

Abordagem do Tesseract de Charlesw:

// 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

Abordagem IronOCR:

// SaveAsSearchablePdf produces a PDF/A-compatible searchable document
// Não 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
// Não 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
' Não 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() incorpora o texto OCR como uma camada invisível alinhada às palavras reconhecidas, tornando o documento pesquisável em texto completo sem alterar sua aparência visual. O guia prático em PDF com função de busca aborda a seleção de intervalo de páginas e opções de compressão. Um exemplo funcional está disponível na página de exemplos em PDF com função de busca .

Referência de mapeamento da API doCharlesw Tesseractpara o IronOCR

Charlesw Tesseract Equivalente de 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 (escala de 0–100)
page.GetIterator() result.Pages, result.Words (coleções diretas)
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 (iterar diretamente)
EngineMode.Default Automático (padrão Tesseract 5 LSTM)
EngineMode.TesseractOnly ocr.Configuration.PageSegmentationMode
Arquivo .traineddata tessdata manual dotnet add package IronOcr.Languages.French
Constante TessDataPath + entrada de cópia .csproj Não aplicável — incluído
Pix.LoadFromFile() via DLL Leptonica input.LoadImage() — nenhuma DLL nativa necessária
Método GetTessDataPath() de plataforma Não aplicável — eliminado
leptonica-1.82.0.dll / libleptonica-dev Não aplicável — sem dependência de Leptonica
Extração manual de frames de arquivos temporários para TIFF input.LoadImageFrames(tiffPath)
Não há saída em PDF pesquisável. result.SaveAsSearchablePdf(outputPath)
new TesseractEngine() por thread Um IronTesseract — seguro para threads

Problemas e soluções comuns em migrações

Problema 1: DllNotFoundException para binários Leptonica ou Tesseract

Charlesw Tesseract: System.DllNotFoundException: Unable to load DLL 'leptonica-1.82.0': The specified module could not be found. Esta exceção é lançada quando a DLL nativa da Leptonica não está no local esperado. É comum em contêineres Docker frescos, agentes CI, ou qualquer ambiente onde a pasta runtimes/ do pacote NuGet não foi copiada corretamente.

Solução: Remova o pacote Tesseract. Instale IronOcr. O IronOCR inclui todos os binários nativos internamente e não utiliza P/Invoke no Leptonica do sistema. A exceção não pode ocorrer porque não há dependência externa do Leptonica:

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

Não é necessário apt-get install libleptonica-dev. Não são necessárias entradas <CopyToOutputDirectory> para DLLs nativas.

Problema 2: Erros no caminho do Tessdata após a implantação

Charlesw Tesseract: Tesseract.TesseractException: Failed to initialise tesseract engine. Isso dispara quando TessDataPath não resolve em tempo de execução. Ele compila sem erro, falha apenas em tempo de execução, e o caminho de falha depende do ambiente de implantação.

Solução: O conceito de caminho tessdata não existe no IronOCR. Delete a constante, apague o XML CopyToOutputDirectory em .csproj, e delete o método de fábrica que o constrói. Os dados de idioma são distribuídos como pacotes 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

O guia de vários idiomas mostra como configurar o reconhecimento multilíngue após adicionar pacotes de idiomas.

Problema 3: A criação do contêiner falha quando a imagem base é atualizada.

Charlesw Tesseract: O Dockerfile inclui apt-get install -y libleptonica-dev para satisfazer a dependência nativa da Leptonica. Quando a imagem base passa de Debian Bullseye para Bookworm, ou quando o nome do pacote Leptonica muda entre distribuições, a compilação falha com um erro do apt. Para corrigir isso, é necessário saber qual nome de pacote usar na nova distribuição.

Solução: Remova completamente a linha apt-get da Leptonica. O IronOCR no Linux requer apenas o pacote padrão libgdiplus que qualquer aplicação .NET usando System.Drawing já necessita:

# 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

O guia de implantação do Docker fornece modelos de Dockerfile testados para imagens base comuns. Não é necessário nenhum código de infraestrutura específico para Charlesw.

Problema 4: O padrão Iterator apresenta problemas em páginas vazias ou com espaços em branco.

Charlesw Tesseract: O ResultIterator retorna null de iter.GetText() em alguns segmentos de página, exigindo verificações explícitas de nulidade em todo o loop. Deixar de fazer verificação de nulidade causa NullReferenceException em páginas em branco ou imagens sem texto reconhecível.

Solução: As coleções de resultados do IronOCR nunca são nulas. Páginas vazias retornam coleções vazias. Verifique o conteúdo do texto em vez de referências nulas:

// 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

Problema 5: Violações de segurança da rosca sob carga

Charlesw Tesseract: TesseractEngine não é seguro para threads. Compartilhar uma única instância entre solicitações simultâneas em uma aplicação ASP.NET causa violações de acesso ou resultados corrompidos. A solução padrão é criar um mecanismo por thread, mas isso não é óbvio pela API e as mensagens de erro quando algo dá errado são exceções nativas enigmáticas.

Solução: IronTesseract é seguro para threads. Uma instância pode atender a solicitações concorrentes, ou para máxima taxa de transferência, crie uma por thread em um Parallel.ForEach — ambos os padrões funcionam sem modificação:

// 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

O guia de OCR assíncrono aborda padrões assíncronos para controladores ASP.NET Core onde o bloqueio de threads não é aceitável.

Problema 6: Binário ARM64 ausente em tempo de execução

Charlesw Tesseract: Em agentes de CI do AWS Graviton (Linux ARM64) ou Apple Silicon, o pacote arquivado pode não incluir um binário nativo para ARM64. A falha é um DllNotFoundException ou um BadImageFormatException na criação do motor — um erro em tempo de execução em uma plataforma que o pacote não tem caminho para suportar.

Solução: O IronOCR fornece binários ARM64 validados para Linux e macOS. Implantação em ARM64 sem alterações de código. O guia de implantação do Linux e o guia de implantação do macOS confirmam os identificadores de tempo de execução suportados.

Lista de verificação de migração do Tesseract de Charlesw

Pré-migração

Analise o código-fonte para identificar todos os padrões que serão alterados:

# 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

Observe quais ambientes de implantação o projeto visa (Docker, Linux, ARM64, Azure, AWS) — esses são os ambientes em que o charlesw/tesseract requer mais configuração, algo que o IronOCR elimina.

Migração de código

  1. Execute dotnet remove package Tesseract para desinstalar o wrapper charlesw
  2. Execute dotnet add package IronOcr para instalar o IronOCR
  3. Adicione IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; na inicialização do aplicativo
  4. Substitua todas as instruções using Tesseract; por using IronOcr;
  5. Exclua a constante de caminho tessdata e qualquer método que construa o caminho por ambiente.
  6. Remova todos os blocos RuntimeInformation.IsOSPlatform() escritos para seleção de caminho tessdata
  7. Remova as entradas <CopyToOutputDirectory> para arquivos tessdata de todos os arquivos .csproj
  8. Exclua os arquivos .traineddata tessdata do controle de origem ou das lojas de artefatos de implantação
  9. Adicione dotnet add package IronOcr.Languages.* para cada idioma anteriormente implantado como um arquivo .traineddata
  10. Substitua as cadeias TesseractEngine + Pix.LoadFromFile() + engine.Process() por new IronTesseract().Read()
  11. Substitua todas as chamadas Pix.LoadFromFile() e Pix.LoadFromMemory() por input.LoadImage()
  12. Substitua todas as chamadas page.GetText() por result.Text
  13. Substitua a extração de palavras/linhas baseada em iterador pelo acesso direto a coleções em result.Pages
  14. Substitua a lógica de limiar iter.GetConfidence() pelo LINQ em result.Words ou result.Lines
  15. Remova libleptonica-dev / leptonica-1.82.0.dll de Dockerfiles e scripts de implantação

Pós-migração

Verifique o seguinte após concluir as atualizações de código:

  • O OCR funciona corretamente no Windows, sem erros de DLL nativos.
  • O OCR é executado com sucesso em um contêiner Docker Linux sem quaisquer alterações de apt-get além de libgdiplus
  • O OCR gera saída de texto em ARM64 se essa plataforma estiver na matriz de implantação. Arquivos TIFF com várias páginas retornam o texto de todos os quadros, não apenas do primeiro.
  • A filtragem por confiança retorna o mesmo conjunto lógico de palavras de alta confiança que a implementação do iterador anterior.
  • Os documentos específicos de cada idioma (francês, alemão, etc.) são reconhecidos corretamente após a instalação dos pacotes NuGet de idioma.
  • As operações OCR paralelas foram concluídas sem exceções ou resultados corrompidos.
  • Agora é gerado um PDF pesquisável, enquanto a implementação anterior retornava apenas texto.
  • Construções de pipeline CI/CD sem etapas de download do tessdata ou comandos de instalação do Leptonica
  • Teste de fumaça com o mesmo conjunto de imagens usado para validar a implementação anterior.

Principais benefícios da migração para o IronOCR

Modelo de Implantação Autocontido. Após a migração, a dependência do OCR é totalmente descrita por uma única referência de pacote NuGet . Nenhum arquivo tessdata no controle de origem, sem entradas CopyToOutputDirectory, sem etapas de implantação de DLLs nativas, sem pacotes de sistema Leptonica. Pipelines CI/CD que anteriormente requeriam gerenciamento de artefatos em várias etapas se reduzem a dotnet publish. O código relacionado à implantação que se acumulou para dar suporte ao wrapper charlesw foi removido permanentemente.

Portabilidade de plataforma sem lógica condicional. O mesmo binário de aplicação funciona em Windows x64, Linux x64, Linux ARM64, macOS x64 e macOS ARM64 sem modificações. As equipes que adicionam um destino de implantação ARM64 — seja AWS Graviton, Apple Silicon CI ou Raspberry Pi — não precisam escrever um novo código de detecção de plataforma. O guia de implantação do Linux e o guia de implantação da AWS confirmam as configurações testadas.

Precisão do Tesseract 5 com pré-processamento integrado. A transição do Tesseract 4.1.1 para o Tesseract 5 aprimora o reconhecimento em documentos degradados. O IronOCR adiciona pré-processamento automático à atualização do mecanismo, aplicando correção de distorção, redução de ruído, normalização de contraste e binarização antes que o mecanismo processe cada imagem. Documentos que antes exigiam um pipeline de pré-processamento personalizado para atingir níveis de precisão aceitáveis ​​agora atingem esses níveis sem código adicional. O guia de correção da qualidade da imagem documenta opções explícitas de pré-processamento para casos que necessitam de ajustes além das configurações padrão.

Navegação Direta ao Resultado Substitui Boilerplate do Iterador. O padrão de iterador charlesw — GetIterator(), Begin(), Next(), IsAtBeginningOf(), verificações de nulidade ao longo — é substituído por coleções simples. Palavras, linhas, parágrafos e páginas são propriedades do objeto de resultado. A filtragem baseada em confiança é uma expressão LINQ. O código que extraía dados em nível de palavra anteriormente exigia de 15 a 30 linhas de gerenciamento de iteradores; O equivalente em IronOCR é de 2 a 3 linhas. A página de resultados do OCR resume o modelo completo de saída estruturada.

Saída de PDF Pesquisável Sem uma Biblioteca Secundária. result.SaveAsSearchablePdf() produz um PDF com uma camada de texto alinhada às palavras reconhecidas, não requerendo uma biblioteca PDF secundária. Sistemas de gerenciamento de documentos que importam PDFs pesquisáveis ​​não exigem mais uma etapa separada de geração de PDF. O mesmo objeto de resultado que fornece o texto extraído também grava o arquivo pesquisável, mantendo os fluxos de processamento de documentos em uma única dependência de biblioteca.

Manutenção ativa e cobertura de patches de segurança. O IronOCR recebe atualizações regulares que acompanham as melhorias do modelo Tesseract 5, a validação de compatibilidade com o runtime do .NET e a cobertura de patches de segurança para o mecanismo C++ subjacente. A dependência não apresenta mais o perfil de risco de um pacote arquivado — as revisões de conformidade não geram resultados para caminhos de patches de segurança ausentes. À medida que o .NET 10 atinge a disponibilidade geral até 2026, o hub de documentação do IronOCR refletirá a compatibilidade atual sem exigir soluções alternativas ou versões modificadas.

ObservePDFSharp e Tesseract são marcas registradas de seus respectivos proprietários. Este site não é afiliado, endossado ou patrocinado pelo Google ou empira Software GmbH. Todos os nomes de produtos, logotipos e marcas são propriedade de seus respectivos proprietários. As comparações são apenas para fins informativos e refletem informações disponíveis publicamente no momento da redação.

Perguntas frequentes

Por que eu deveria migrar do charlesw/tesseract (wrapper .NET do Tesseract) para o IronOCR?

Entre os principais motivos, incluem-se a eliminação da complexidade da interoperabilidade COM, a substituição do gerenciamento de licenças baseado em arquivos, a eliminação da cobrança por página, a viabilização da implantação em Docker/contêineres e a adoção de um fluxo de trabalho nativo do NuGet que se integra às ferramentas padrão do .NET.

Quais são as principais alterações de código ao migrar de charlesw/tesseract (wrapper .NET do Tesseract) para IronOCR?

Substitua as sequências de inicialização do charlesw/tesseract pela instanciação do IronTesseract, remova o gerenciamento do ciclo de vida COM (padrões explícitos de Criação/Carregamento/Fechamento) e atualize os nomes das propriedades de resultado. O resultado é uma redução significativa no número de linhas de código repetitivo.

Como faço para instalar o IronOCR para iniciar a migração?

Execute 'Install-Package IronOcr' no Console do Gerenciador de Pacotes ou 'dotnet add package IronOcr' na CLI. Os pacotes de idiomas são pacotes separados: 'dotnet add package IronOcr.Languages.French' para francês, por exemplo.

O IronOCR atinge a mesma precisão de OCR que o charlesw/tesseract (wrapper .NET do Tesseract) para documentos comerciais padrão?

O IronOCR alcança alta precisão para conteúdo comercial padrão, incluindo faturas, contratos, recibos e formulários digitados. Filtros de pré-processamento de imagem (correção de distorção, remoção de ruído, aprimoramento de contraste) melhoram ainda mais o reconhecimento em entradas de baixa qualidade.

Como o IronOCR lida com os dados de idioma que o charlesw/tesseract (wrapper do Tesseract for .NET) instala separadamente?

Os dados de idioma no IronOCR são distribuídos como pacotes NuGet. O comando 'dotnet add package IronOcr.Languages.German' instala o suporte ao alemão. Não é necessário inserir arquivos manualmente nem configurar caminhos de diretório.

A migração do charlesw/tesseract (wrapper .NET do Tesseract) para o IronOCR requer alterações na infraestrutura de implantação?

O IronOCR requer menos alterações de infraestrutura do que o charlesw/tesseract (wrapper do Tesseract for .NET). Não há caminhos binários do SDK, necessidade de instalar arquivos de licença ou configurar servidores de licença. O pacote NuGet contém o mecanismo OCR completo e a chave de licença é uma string definida no código do aplicativo.

Como configuro o licenciamento do IronOCR após a migração?

Atribua `IronOcr.License.LicenseKey = "YOUR-KEY"` no código de inicialização do aplicativo. No Docker ou Kubernetes, armazene a chave como uma variável de ambiente e leia-a na inicialização. Use `License.IsValidLicense` para validar a licença antes de aceitar o tráfego.

O IronOCR consegue processar PDFs da mesma forma que o charlesw/tesseract?

Sim. O IronOCR lê PDFs nativos e digitalizados. Instancie o IronTesseract, chame ocr.Read(input) onde input é um caminho para um PDF ou OcrPdfInput, e itere pelas páginas do OcrResult. Não é necessário um pipeline de renderização de PDF separado.

Como o IronOCR lida com multithreading em processamento de alto volume?

O IronTesseract pode ser instanciado com segurança por thread. Crie uma instância por thread em um Parallel.ForEach ou pool de Tasks, execute o OCR simultaneamente e descarte cada instância ao terminar. Não é necessário nenhum estado global ou bloqueio.

Quais formatos de saída o IronOCR suporta após a extração de texto?

O IronOCR retorna resultados estruturados, incluindo texto, coordenadas de palavras, níveis de confiança e estrutura da página. As opções de exportação incluem texto simples, PDF pesquisável e objetos de resultados estruturados para processamento posterior.

O preço do IronOCR é mais previsível do que o do charlesw/tesseract (wrapper .NET do Tesseract) para dimensionamento de cargas de trabalho?

O IronOCR utiliza licenciamento perpétuo com preço fixo, sem cobranças por página ou volume. Independentemente de você processar 10.000 ou 10 milhões de páginas, o custo da licença permanece constante. As opções de licenciamento por volume e para equipes estão disponíveis na página de preços do IronOCR.

O que acontece com meus testes existentes após a migração do charlesw/tesseract (wrapper do Tesseract for .NET) para o IronOCR?

Os testes que verificam o conteúdo de texto extraído devem continuar a ser aprovados após a migração. Os testes que validam padrões de chamadas de API ou o ciclo de vida de objetos COM precisarão ser atualizados para refletir o modelo de inicialização e resultados mais simples do IronOCR.

Kannaopat Udonpant
Engenheiro de Software
Antes de se tornar Engenheiro de Software, Kannapat concluiu um doutorado em Recursos Ambientais pela Universidade de Hokkaido, no Japão. Durante o doutorado, Kannapat também integrou o Laboratório de Robótica Veicular, que faz parte do Departamento de Engenharia de Bioprodução. Em 2022, ele utilizou suas habilidades ...
Leia mais

Equipe de Suporte Iron

Estamos online 24 horas por dia, 5 dias por semana.
Bater papo
E-mail
Liga para mim