Uma comparação entre IronOCR e Nanonets OCR
O modelo de preços por página doAWS Textractpode parecer barato em baixo volume, mas os custos se acumulam indefinidamente em escala. Cada documento processado pelo seu aplicativo sai da sua rede, é enviado para um data center Amazon, é processado pela infraestrutura Amazon, e a conta se acumula indefinidamente. Para equipes que avaliam opções de OCR em .NET, a questão não é apenas se o Textract produz resultados precisos — ele produz —, mas se o modelo de custo por página, a transmissão obrigatória para a nuvem e a arquitetura de polling assíncrono para documentos com várias páginas correspondem ao que sua aplicação realmente precisa.
Entendendo o AWS Textract
AWS Textract é o serviço gerenciado de análise de documentos da Amazon, acessível via o AWS SDK for .NET através do pacote NuGet AWSSDK.Textract. Funciona como uma API em nuvem: seu aplicativo envia dados de documentos para a infraestrutura da Amazon e recebe resultados estruturados. O serviço requer uma conta AWS, credenciais IAM com permissões Textract e uma conexão com a internet para cada operação de OCR.
O Textract oferece diversos modos de análise distintos, cada um com preço separado:
- DetectDocumentText: Extração de texto básico (veja preços AWS Textract para tarifas atuais por página)
- AnalyzeDocument (Tables): Extração de tabelas estruturadas a uma tarifa maior por página do que texto básico
- AnalyzeDocument (Forms): Extração de formulários de chave-valor a uma tarifa maior por página do que extração de tabelas
- AnalyzeExpense: Análise de faturas e recibos a US$ 0,01 por página
- AnalyzeID: Extração de documentos de identidade a US$ 0,025 por página
- StartDocumentTextDetection / StartDocumentAnalysis: API assíncrona necessária para qualquer PDF com várias páginas, exigindo um bucket de preparação no S3, polling de tarefas e paginação de resultados.
O modelo de resultado usa uma lista plana de objetos Block com IDs de relacionamento que devem ser percorridos para reconstruir tabelas, formulários ou qualquer saída estruturada. Uma extração de tabela simples requer iterar blocos BlockType.TABLE, encontrando blocos filhos BlockType.CELL via IDs de relacionamento RelationshipType.CHILD, e depois buscar blocos BlockType.WORD para o texto de cada célula. Este modelo de grafo de relacionamento lida com estruturas de documentos complexas, mas não é leve.
O Pipeline S3-Assíncrono
OCR de imagem única via DetectDocumentTextAsync pode passar bytes do documento diretamente na solicitação. PDFs de várias páginas não. Qualquer PDF requer o pipeline assíncrono completo:
// AWS Textract: PDF com várias páginas requires S3 + async job
public async Task<string> ProcessPdfAsync(string pdfPath)
{
// Step 1: Upload to S3 — credentials for two services required
var key = $"uploads/{Guid.NewGuid()}.pdf";
using (var fileStream = File.OpenRead(pdfPath))
{
await _s3Client.PutObjectAsync(new PutObjectRequest
{
BucketName = _bucketName,
Key = key,
InputStream = fileStream
});
}
try
{
// Step 2: Start async Textract job
var startResponse = await _textractClient.StartDocumentTextDetectionAsync(
new StartDocumentTextDetectionRequest
{
DocumentLocation = new DocumentLocation
{
S3Object = new S3Object { Bucket = _bucketName, Name = key }
}
});
var jobId = startResponse.JobId;
// Step 3: Poll every 5 seconds until complete
GetDocumentTextDetectionResponse getResponse;
do
{
await Task.Delay(5000);
getResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId });
} while (getResponse.JobStatus == JobStatus.IN_PROGRESS);
if (getResponse.JobStatus != JobStatus.SUCCEEDED)
throw new Exception($"Textract job failed: {getResponse.StatusMessage}");
// Step 4: Paginate through result blocks
var allText = new StringBuilder();
string nextToken = null;
do
{
var pageResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest
{
JobId = jobId,
NextToken = nextToken
});
foreach (var block in pageResponse.Blocks.Where(b => b.BlockType == BlockType.LINE))
allText.AppendLine(block.Text);
nextToken = pageResponse.NextToken;
} while (nextToken != null);
return allText.ToString();
}
finally
{
// Step 5: Sempre clean up S3
await _s3Client.DeleteObjectAsync(_bucketName, key);
}
}
// AWS Textract: PDF com várias páginas requires S3 + async job
public async Task<string> ProcessPdfAsync(string pdfPath)
{
// Step 1: Upload to S3 — credentials for two services required
var key = $"uploads/{Guid.NewGuid()}.pdf";
using (var fileStream = File.OpenRead(pdfPath))
{
await _s3Client.PutObjectAsync(new PutObjectRequest
{
BucketName = _bucketName,
Key = key,
InputStream = fileStream
});
}
try
{
// Step 2: Start async Textract job
var startResponse = await _textractClient.StartDocumentTextDetectionAsync(
new StartDocumentTextDetectionRequest
{
DocumentLocation = new DocumentLocation
{
S3Object = new S3Object { Bucket = _bucketName, Name = key }
}
});
var jobId = startResponse.JobId;
// Step 3: Poll every 5 seconds until complete
GetDocumentTextDetectionResponse getResponse;
do
{
await Task.Delay(5000);
getResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId });
} while (getResponse.JobStatus == JobStatus.IN_PROGRESS);
if (getResponse.JobStatus != JobStatus.SUCCEEDED)
throw new Exception($"Textract job failed: {getResponse.StatusMessage}");
// Step 4: Paginate through result blocks
var allText = new StringBuilder();
string nextToken = null;
do
{
var pageResponse = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest
{
JobId = jobId,
NextToken = nextToken
});
foreach (var block in pageResponse.Blocks.Where(b => b.BlockType == BlockType.LINE))
allText.AppendLine(block.Text);
nextToken = pageResponse.NextToken;
} while (nextToken != null);
return allText.ToString();
}
finally
{
// Step 5: Sempre clean up S3
await _s3Client.DeleteObjectAsync(_bucketName, key);
}
}
Imports System
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Imports Amazon.S3
Imports Amazon.Textract
Imports Amazon.Textract.Model
Public Class TextractProcessor
Private _s3Client As IAmazonS3
Private _textractClient As IAmazonTextract
Private _bucketName As String
Public Async Function ProcessPdfAsync(pdfPath As String) As Task(Of String)
' Step 1: Upload to S3 — credentials for two services required
Dim key As String = $"uploads/{Guid.NewGuid()}.pdf"
Using fileStream As FileStream = File.OpenRead(pdfPath)
Await _s3Client.PutObjectAsync(New PutObjectRequest With {
.BucketName = _bucketName,
.Key = key,
.InputStream = fileStream
})
End Using
Try
' Step 2: Start async Textract job
Dim startResponse = Await _textractClient.StartDocumentTextDetectionAsync(
New StartDocumentTextDetectionRequest With {
.DocumentLocation = New DocumentLocation With {
.S3Object = New S3Object With {.Bucket = _bucketName, .Name = key}
}
})
Dim jobId As String = startResponse.JobId
' Step 3: Poll every 5 seconds until complete
Dim getResponse As GetDocumentTextDetectionResponse
Do
Await Task.Delay(5000)
getResponse = Await _textractClient.GetDocumentTextDetectionAsync(
New GetDocumentTextDetectionRequest With {.JobId = jobId})
Loop While getResponse.JobStatus = JobStatus.IN_PROGRESS
If getResponse.JobStatus <> JobStatus.SUCCEEDED Then
Throw New Exception($"Textract job failed: {getResponse.StatusMessage}")
End If
' Step 4: Paginate through result blocks
Dim allText As New StringBuilder()
Dim nextToken As String = Nothing
Do
Dim pageResponse = Await _textractClient.GetDocumentTextDetectionAsync(
New GetDocumentTextDetectionRequest With {
.JobId = jobId,
.NextToken = nextToken
})
For Each block In pageResponse.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
allText.AppendLine(block.Text)
Next
nextToken = pageResponse.NextToken
Loop While nextToken IsNot Nothing
Return allText.ToString()
Finally
' Step 5: Always clean up S3
Await _s3Client.DeleteObjectAsync(_bucketName, key)
End Try
End Function
End Class
Esta é a implementação mínima viável para um processamento confiável de PDF — cinco fases distintas, dois clientes de serviço AWS e lógica de limpeza em um bloco finally. A versão completa de produção, com tratamento de erros adequado, lógica de repetição com limite de taxa e gerenciamento de tempo limite, possui entre 150 e 300 linhas de código.
Entendendo o IronOCR
IronOCR é uma biblioteca OCR comercial para .NET que funciona inteiramente na sua infraestrutura. Ele integra um mecanismo Tesseract 5 otimizado com pré-processamento automático de imagens, suporte nativo a PDF e uma API síncrona que produz resultados diretamente, sem chamadas a serviços externos ou etapas de preparação.
Principais características da arquitetura IronOCR:
- Processamento local apenas: nenhum dado do documento sai da máquina que executa seu aplicativo.
- Pacote NuGet único:
dotnet add package IronOcrinstala tudo, incluindo binários nativos - Pré-processamento automático: Correção de distorção, redução de ruído, aprimoramento de contraste, binarização e ajuste de resolução ocorrem automaticamente em entradas de baixa qualidade.
- Suporte nativo a PDF: Lê PDFs diretamente pelo caminho do arquivo ou fluxo, sem necessidade de armazenamento temporário no S3 ou tarefas assíncronas.
- Seguro para threads: Uma única instância
IronTesseractlida com solicitações simultâneas através de threads sem contenção - Licenciamento perpétuo: $999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited — um pagamento, sem cobranças por página, sem medições de uso
- Mais de 125 pacotes de idiomas: instalados como pacotes NuGet separados, carregados localmente, sem chamadas de rede.
Comparação de recursos
| Recurso | AWS Textract | IronOCR |
|---|---|---|
| Local de processamento | Nuvem da Amazon (obrigatório) | Local / no local |
| PDF com várias páginas | Requer S3 + tarefa assíncrona | Chamada síncrona direta |
| Modelo de custo | Por página (contate AWS para preços atuais) | Licença perpétua, sem taxa por página. |
| É necessário ter acesso à internet. | Sempre | Nunca |
| Configuração de credenciais | Usuário/função do IAM + S3 opcional | string de chave de licença única |
| Implantação isolada da internet | Não é possível. | Suporte completo |
| Suporte para PDF criptografado | Não suportado | Integrado (parâmetro de senha) |
Comparação Detalhada de Recursos
| Recurso | AWS Textract | IronOCR |
|---|---|---|
| Extração de texto | ||
| OCR básico (imagens) | Sim — DetectDocumentTextAsync |
Sim — ocr.Read(path) |
| PDF com várias páginas | Requer S3 + polling assíncrono | Direto input.LoadPdf(path) |
| PDF protegido por senha | Não suportado | input.LoadPdf(path, Password: "x") |
| Entrada de fluxo | Sim (matriz de bytes na solicitação) | Sim — input.LoadImage(stream) |
| Extração Estruturada | ||
| Extração de tabela | AnalyzeDocument + percurso gráfico de bloco |
Reconstrução baseada na posição das palavras |
| Extração de campos de formulário | AnalyzeDocument + blocos KEY_VALUE_SET |
Zonas baseadas em região CropRectangle |
| Resultados por linha | Block filtrando por BlockType.LINE |
Coleta direta result.Lines |
| Nível de palavra com coordenadas | Block filtrando por BlockType.WORD |
result.Words com .X, .Y, .Width |
| Pontuações de confiança | Confiança por bloco | Por palavra e geral result.Confidence |
| Modelo de Processamento | ||
| Síncrono (imagens) | Sim (apenas uma página) | Sim (todos os tipos de documento) |
| Assíncrono | Necessário para PDFs | Opcional — Task.Run() wrapper |
| Processamento em lote | Requer gerenciamento de limite de taxa (5 TPS por padrão) | Parallel.ForEach sem restrições |
| Pré-processamento | ||
| Desalinhamento automático | Não exposto | input.Deskew() |
| Remoção de ruído | Interno (não configurável) | input.DeNoise() |
| Aprimoramento de contraste | Interno (não configurável) | input.Contrast() |
| Melhoria de resolução | Interno (não configurável) | input.EnhanceResolution(300) |
| Binarização | Interno | input.Binarize() |
| Formatos de saída | ||
| Texto simples | Sim | Sim |
| PDF pesquisável | Não | result.SaveAsSearchablePdf(path) |
| hOCR | Não | result.SaveAsHocrFile(path) |
| JSON estruturado | Por meio de serialização em bloco | result.Words / result.Lines |
| Implantação | ||
| No local | Não | Sim |
| Com espaço de ar | Não | Sim |
| Docker | Sim (com credenciais da AWS inseridas) | Sim (não são necessárias credenciais) |
| AWS Lambda | Nativo | Apoiado |
| Azure | Sim | Sim |
| Linux | Sim (gerenciado pela AWS) | Sim — get-started/linux/ |
| Conformidade | ||
| HIPAA | Requer BAA com a AWS. | Sem processador externo |
| RGPD | Os dados são transferidos para regiões da AWS. | Os dados permanecem dentro dos limites. |
| ITAR | Proibido sem autorização especial. | Totalmente no local |
| Com espaço de ar / CMMC Nível 3 | Não é possível. | Apoiado |
Custo em escala
O modelo de precificação por página é a principal restrição estrutural do AWS Textract. Custos que parecem pequenos por página se acumulam significativamente em um fluxo de trabalho de documento real.
Abordagem AWS Textract
// Every call to this method costs money — per page, permanently
public async Task<string> DetectTextAsync(string imagePath)
{
var imageBytes = File.ReadAllBytes(imagePath); // Image leaves your network
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
var response = await _client.DetectDocumentTextAsync(request); // per-page charge
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
// Every call to this method costs money — per page, permanently
public async Task<string> DetectTextAsync(string imagePath)
{
var imageBytes = File.ReadAllBytes(imagePath); // Image leaves your network
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
var response = await _client.DetectDocumentTextAsync(request); // per-page charge
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
Imports System.IO
Imports System.Threading.Tasks
' Every call to this method costs money — per page, permanently
Public Async Function DetectTextAsync(imagePath As String) As Task(Of String)
Dim imageBytes = File.ReadAllBytes(imagePath) ' Image leaves your network
Dim request = New DetectDocumentTextRequest With {
.Document = New Document With {
.Bytes = New MemoryStream(imageBytes)
}
}
Dim response = Await _client.DetectDocumentTextAsync(request) ' per-page charge
Return String.Join(vbLf, response.Blocks _
.Where(Function(b) b.BlockType = BlockType.LINE) _
.Select(Function(b) b.Text))
End Function
Consulte a página de preços do AWS Textract para tarifas atuais por página. Diferentes recursos da API (detecção básica de texto, extração de tabelas, extração de formulários) têm taxas diferentes. Um documento contendo tabelas e campos de formulário incorreria em cobranças maiores do que a detecção básica de texto, e os custos cresceriam com o volume sem limite superior e sem maneira de pagar adiantado.
Em volumes altos de páginas, o custo total de três anos pode ser substancial, e o medidor continua a correr.
Abordagem IronOCR
// One license. Não per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
// One license. Não per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
Imports IronOcr
' One license. Não per-page cost. Same code handles 1 page or 1,000,000.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text = New IronTesseract().Read("document.jpg").Text
A licença $2,999 Professional cobre 10 desenvolvedores, projetos ilimitados e volume de página ilimitado. Após o primeiro ano, o custo contínuo por página processada é zero. Para equipes processando volumes de páginas significativos, a licença IronOCR se paga rapidamente em comparação aos custos crescentes por página na nuvem.
A página de licenciamento do IronOCR aborda detalhes dos níveis de licenciamento, opções de assinatura SaaS para cenários de cobrança baseada no uso e termos de redistribuição para OEMs.
Soberania e Conformidade de Dados
A arquitetura doAWS Textracttorna uma garantia impossível: que seus documentos permaneçam dentro da sua infraestrutura. Cada operação de OCR transmite o conteúdo do documento para os servidores da Amazon.
Abordagem AWS Textract
// This code sends PHI, legal documents, financial records — whatever is in
// the file — to Amazon Web Services infrastructure
public async Task<string> ProcessSensitiveDocumentAsync(string documentPath)
{
var imageBytes = File.ReadAllBytes(documentPath);
// Data crosses your security perimeter here
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
// Amazon processes it; you receive text back
var response = await _client.DetectDocumentTextAsync(request);
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
// This code sends PHI, legal documents, financial records — whatever is in
// the file — to Amazon Web Services infrastructure
public async Task<string> ProcessSensitiveDocumentAsync(string documentPath)
{
var imageBytes = File.ReadAllBytes(documentPath);
// Data crosses your security perimeter here
var request = new DetectDocumentTextRequest
{
Document = new Document
{
Bytes = new MemoryStream(imageBytes)
}
};
// Amazon processes it; you receive text back
var response = await _client.DetectDocumentTextAsync(request);
return string.Join("\n", response.Blocks
.Where(b => b.BlockType == BlockType.LINE)
.Select(b => b.Text));
}
Imports System.IO
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.Textract.Model
Public Class DocumentProcessor
Private _client As AmazonTextractClient
Public Sub New(client As AmazonTextractClient)
_client = client
End Sub
' This code sends PHI, legal documents, financial records — whatever is in
' the file — to Amazon Web Services infrastructure
Public Async Function ProcessSensitiveDocumentAsync(documentPath As String) As Task(Of String)
Dim imageBytes = File.ReadAllBytes(documentPath)
' Data crosses your security perimeter here
Dim request As New DetectDocumentTextRequest With {
.Document = New Document With {
.Bytes = New MemoryStream(imageBytes)
}
}
' Amazon processes it; you receive text back
Dim response = Await _client.DetectDocumentTextAsync(request)
Return String.Join(vbLf, response.Blocks _
.Where(Function(b) b.BlockType = BlockType.LINE) _
.Select(Function(b) b.Text))
End Function
End Class
A AWS oferece um Acordo de Parceiro ComercialHIPAApara entidades abrangidas, e as regiões GovCloud fornecem autorização FedRAMP High. Essas estruturas não alteram a arquitetura fundamental: os documentos saem da sua infraestrutura para cada operação. Para dados técnicos controlados pelo ITAR, isso não é uma nuance de conformidade — é uma proibição. Para cargas de trabalho CMMC Nível 3 com CUI (Informações Não Classificadas Controladas), a transmissão em nuvem requer autorizações específicas que a maioria dos contratados da área de defesa não possui. Para sistemas isolados da internet — redes de pesquisa, ambientes de controle industrial, instalações confidenciais — o Textract simplesmente não está disponível.
AWS Textract está disponível em seis regiões: us-east-1, us-west-2, eu-west-1, eu-west-2, ap-southeast-1 e ap-southeast-2. Organizações com requisitos de residência de dados fora dessas regiões não têm uma opção compatível.
Abordagem IronOCR
// IronOCR: document bytes never leave this process
public string ProcessSensitiveDocument(string documentPath)
{
// Processes entirely on local hardware — no network call
var ocr = new IronTesseract();
return ocr.Read(documentPath).Text;
}
// IronOCR: document bytes never leave this process
public string ProcessSensitiveDocument(string documentPath)
{
// Processes entirely on local hardware — no network call
var ocr = new IronTesseract();
return ocr.Read(documentPath).Text;
}
' IronOCR: document bytes never leave this process
Public Function ProcessSensitiveDocument(documentPath As String) As String
' Processes entirely on local hardware — no network call
Dim ocr As New IronTesseract()
Return ocr.Read(documentPath).Text
End Function
Como o IronOCR é executado localmente, ele se integra naturalmente aos fluxos de trabalho da área da saúde que processam informações de saúde protegidas (PHI), aos sistemas de documentos jurídicos que lidam com comunicações privilegiadas, aos aplicativos financeiros que processam imagens de cartões de pagamento e aos sistemas de processamento de informações controladas não classificadas (CUI) de contratados da área de defesa. Não há processador externo para auditar, nenhum BAA para negociar, nenhuma restrição de residência de dados a cumprir. O âmbito de conformidade abrange a infraestrutura da sua própria organização.
Para equipes que implantam na infraestrutura da AWS, mas precisam de processamento local, o IronOCRé executado no AWS EC2 e no Lambda sem qualquer dependência do Textract — o processamento ocorre dentro dos limites da sua própria conta da AWS, em vez do serviço gerenciado da Amazon.
Sondagem assíncrona vs. Processamento síncrono
A divisão arquitetônica entre as APIs síncronas (imagem única) e assíncronas (PDF de várias páginas) do Textract não é um detalhe de API menor. Isso define como os serviços são construídos, como os erros são tratados e o quanto os responsáveis pela manutenção do código precisam ler e analisar.
Abordagem AWS Textract
// Full production-grade async processor for Textract PDF handling
public class TextractAsyncProcessor
{
private readonly AmazonTextractClient _textractClient;
private readonly AmazonS3Client _s3Client;
private readonly string _bucketName;
private readonly TimeSpan _pollInterval = TimeSpan.FromSeconds(5);
private readonly TimeSpan _maxWaitTime = TimeSpan.FromMinutes(10);
public async Task<DocumentResult> ProcessDocumentAsync(
string localFilePath,
CancellationToken cancellationToken = default)
{
var s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}";
try
{
// Phase 1: Upload to S3
await UploadToS3Async(localFilePath, s3Key, cancellationToken);
// Phase 2: Start Textract job
var jobId = await StartTextractJobAsync(s3Key, cancellationToken);
// Phase 3: Poll until complete (up to 10 minutes)
var pollResult = await PollForCompletionAsync(jobId, cancellationToken);
if (!pollResult.Success)
throw new Exception($"Textract job failed: {pollResult.ErrorMessage}");
// Phase 4: Retrieve paginated results
return await GetAllResultsAsync(jobId, cancellationToken);
}
finally
{
// Phase 5: S3 cleanup — must succeed or storage costs accumulate
await DeleteFromS3Async(s3Key, cancellationToken);
}
}
private async Task<(bool Success, string ErrorMessage)> PollForCompletionAsync(
string jobId, CancellationToken cancellationToken)
{
var startTime = DateTime.UtcNow;
int pollCount = 0;
while (DateTime.UtcNow - startTime < _maxWaitTime)
{
cancellationToken.ThrowIfCancellationRequested();
var response = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId }, cancellationToken);
pollCount++;
switch (response.JobStatus)
{
case JobStatus.SUCCEEDED: return (true, null);
case JobStatus.FAILED: return (false, response.StatusMessage ?? "Unknown error");
case JobStatus.IN_PROGRESS:
await Task.Delay(_pollInterval, cancellationToken);
break;
default:
throw new Exception($"Unknown job status: {response.JobStatus}");
}
}
return (false, "Job timed out");
}
}
// Full production-grade async processor for Textract PDF handling
public class TextractAsyncProcessor
{
private readonly AmazonTextractClient _textractClient;
private readonly AmazonS3Client _s3Client;
private readonly string _bucketName;
private readonly TimeSpan _pollInterval = TimeSpan.FromSeconds(5);
private readonly TimeSpan _maxWaitTime = TimeSpan.FromMinutes(10);
public async Task<DocumentResult> ProcessDocumentAsync(
string localFilePath,
CancellationToken cancellationToken = default)
{
var s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}";
try
{
// Phase 1: Upload to S3
await UploadToS3Async(localFilePath, s3Key, cancellationToken);
// Phase 2: Start Textract job
var jobId = await StartTextractJobAsync(s3Key, cancellationToken);
// Phase 3: Poll until complete (up to 10 minutes)
var pollResult = await PollForCompletionAsync(jobId, cancellationToken);
if (!pollResult.Success)
throw new Exception($"Textract job failed: {pollResult.ErrorMessage}");
// Phase 4: Retrieve paginated results
return await GetAllResultsAsync(jobId, cancellationToken);
}
finally
{
// Phase 5: S3 cleanup — must succeed or storage costs accumulate
await DeleteFromS3Async(s3Key, cancellationToken);
}
}
private async Task<(bool Success, string ErrorMessage)> PollForCompletionAsync(
string jobId, CancellationToken cancellationToken)
{
var startTime = DateTime.UtcNow;
int pollCount = 0;
while (DateTime.UtcNow - startTime < _maxWaitTime)
{
cancellationToken.ThrowIfCancellationRequested();
var response = await _textractClient.GetDocumentTextDetectionAsync(
new GetDocumentTextDetectionRequest { JobId = jobId }, cancellationToken);
pollCount++;
switch (response.JobStatus)
{
case JobStatus.SUCCEEDED: return (true, null);
case JobStatus.FAILED: return (false, response.StatusMessage ?? "Unknown error");
case JobStatus.IN_PROGRESS:
await Task.Delay(_pollInterval, cancellationToken);
break;
default:
throw new Exception($"Unknown job status: {response.JobStatus}");
}
}
return (false, "Job timed out");
}
}
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Imports Amazon.Textract
Imports Amazon.S3
Imports Amazon.Textract.Model
' Full production-grade async processor for Textract PDF handling
Public Class TextractAsyncProcessor
Private ReadOnly _textractClient As AmazonTextractClient
Private ReadOnly _s3Client As AmazonS3Client
Private ReadOnly _bucketName As String
Private ReadOnly _pollInterval As TimeSpan = TimeSpan.FromSeconds(5)
Private ReadOnly _maxWaitTime As TimeSpan = TimeSpan.FromMinutes(10)
Public Async Function ProcessDocumentAsync(localFilePath As String, Optional cancellationToken As CancellationToken = Nothing) As Task(Of DocumentResult)
Dim s3Key = $"textract-uploads/{Guid.NewGuid()}{Path.GetExtension(localFilePath)}"
Try
' Phase 1: Upload to S3
Await UploadToS3Async(localFilePath, s3Key, cancellationToken)
' Phase 2: Start Textract job
Dim jobId = Await StartTextractJobAsync(s3Key, cancellationToken)
' Phase 3: Poll until complete (up to 10 minutes)
Dim pollResult = Await PollForCompletionAsync(jobId, cancellationToken)
If Not pollResult.Success Then
Throw New Exception($"Textract job failed: {pollResult.ErrorMessage}")
End If
' Phase 4: Retrieve paginated results
Return Await GetAllResultsAsync(jobId, cancellationToken)
Finally
' Phase 5: S3 cleanup — must succeed or storage costs accumulate
Await DeleteFromS3Async(s3Key, cancellationToken)
End Try
End Function
Private Async Function PollForCompletionAsync(jobId As String, cancellationToken As CancellationToken) As Task(Of (Success As Boolean, ErrorMessage As String))
Dim startTime = DateTime.UtcNow
Dim pollCount As Integer = 0
While DateTime.UtcNow - startTime < _maxWaitTime
cancellationToken.ThrowIfCancellationRequested()
Dim response = Await _textractClient.GetDocumentTextDetectionAsync(New GetDocumentTextDetectionRequest With {.JobId = jobId}, cancellationToken)
pollCount += 1
Select Case response.JobStatus
Case JobStatus.SUCCEEDED
Return (True, Nothing)
Case JobStatus.FAILED
Return (False, If(response.StatusMessage, "Unknown error"))
Case JobStatus.IN_PROGRESS
Await Task.Delay(_pollInterval, cancellationToken)
Case Else
Throw New Exception($"Unknown job status: {response.JobStatus}")
End Select
End While
Return (False, "Job timed out")
End Function
End Class
Isto não é um texto padrão que pode ser gerado e esquecido. Quando uma tarefa do Textract falha durante a execução, a limpeza do S3 ainda precisa ser realizada. Quando uma tarefa expira após 10 minutos, o solicitante precisa de uma mensagem de erro clara. Quando a rede cai durante a sondagem, a estratégia de repetição não deve criar tarefas duplicadas. Cada um desses modos de falha requer tratamento explícito — a estrutura mostrada acima é a implementação mínima responsável.
O processamento em lote adiciona outra camada: o limite padrão de TPS StartDocumentTextDetection do Textract é de 5 solicitações por segundo. Processar 100 documentos exige uma limitação de SemaphoreSlim, um temporizador de reabastecimento de taxa e lógica de repetição para ProvisionedThroughputExceededException.
Abordagem IronOCR
// IronOCR: same synchronous API regardless of document type or size
public string ProcessDocument(string filePath)
{
using var input = new OcrInput();
if (Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
input.LoadPdf(filePath);
else
input.LoadImage(filePath);
return new IronTesseract().Read(input).Text;
}
// IronOCR: same synchronous API regardless of document type or size
public string ProcessDocument(string filePath)
{
using var input = new OcrInput();
if (Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase))
input.LoadPdf(filePath);
else
input.LoadImage(filePath);
return new IronTesseract().Read(input).Text;
}
Imports System.IO
' IronOCR: same synchronous API regardless of document type or size
Public Function ProcessDocument(filePath As String) As String
Using input As New OcrInput()
If Path.GetExtension(filePath).Equals(".pdf", StringComparison.OrdinalIgnoreCase) Then
input.LoadPdf(filePath)
Else
input.LoadImage(filePath)
End If
Return New IronTesseract().Read(input).Text
End Using
End Function
Não há loop de polling, rastreamento de ID de tarefa, bucket S3 ou paginação de resultados. O mesmo código processa tanto um único arquivo JPEG quanto um PDF de 200 páginas. O processamento é concluído ou rejeitado — não há estado intermediário "em andamento" para gerenciar. Para processamento em lote, IronOCR é seguro para threads e uma única instância IronTesseract lida com Parallel.ForEach sem bloqueios ou semáforos.
O guia de configuração do IronTesseract aborda a configuração, e o guia de entrada de PDF documenta a seleção de intervalo de páginas, PDFs protegidos por senha e entrada baseada em fluxo para PDFs recuperados de bancos de dados ou respostas HTTP.
Custos indiretos de gerenciamento de credenciais
Para iniciar uma operação de OCR com o AWS Textract, é necessário configurar o IAM antes que qualquer página seja processada.
Abordagem AWS Textract
Antes de chamar DetectDocumentTextAsync, um desenvolvedor deve:
- Crie uma conta da AWS ou obtenha acesso a uma conta existente.
- Criar um usuário ou função IAM com permissões
textract:DetectDocumentTextetextract:AnalyzeDocument - Gere e armazene com segurança o ID da chave de acesso e a chave de acesso secreta.
- Configure a resolução de credenciais — variáveis de ambiente, arquivo de credenciais da AWS ou perfil de instância EC2.
- Se estiver processando PDFs: criar um bucket S3, configurar a política do bucket, adicionar permissões
s3:PutObjectes3:DeleteObject - Implementar políticas de rotação de credenciais para atender aos padrões de segurança.
- Armazene as credenciais com segurança em cada ambiente de implantação — segredos do Docker, segredos do Kubernetes, AWS Secrets Manager ou variáveis do pipeline de CI/CD.
// Every environment needs these configured before this constructor succeeds
public TextractOcrService()
{
// Reads credentials from environment, ~/.aws/credentials, or IAM role
_client = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
}
// Every environment needs these configured before this constructor succeeds
public TextractOcrService()
{
// Reads credentials from environment, ~/.aws/credentials, or IAM role
_client = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
}
' Every environment needs these configured before this constructor succeeds
Public Sub New()
' Reads credentials from environment, ~/.aws/credentials, or IAM role
_client = New AmazonTextractClient(Amazon.RegionEndpoint.USEast1)
End Sub
Quando as credenciais expiram, são giradas ou estão configuradas incorretamente, todas as chamadas OCR falham com AmazonTextractException carregando ErrorCode == "AccessDeniedException". Em um sistema de produção, isso significa implementar blocos de tratamento específicos para falhas de credenciais e monitorar desvios nas políticas de IAM.
Abordagem IronOCR
// One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' One-time setup at application startup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
' Or from environment — recommended for deployments
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
A chave de licença é uma sequência estática. Não expira durante a operação, não requer rotação e não possui permissões de gerenciamento. Um contêinerDockerque processa documentos não precisa de credenciais AWS injetadas, uma função IAM vinculada a um contexto de execução ou acesso à rede do AWS STS para atualização de token.
A redução completa de sobrecarga de credenciais ao mudar do Textract para IronOCR: três pacotes NuGet removidos (AWSSDK.Textract, AWSSDK.S3, AWSSDK.Core), todas as variáveis de ambiente AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_DEFAULT_REGION removidas, e funções IAM e configurações de bucket S3 descomissionadas. O guia de entrada de imagem e o guia de entrada de fluxo abrangem toda a gama de métodos de entrada que substituem os modelos de documento de matriz de bytes e objeto S3 do Textract.
Referência de Mapeamento de API
| APIAWS Textract | Equivalente de IronOCR |
|---|---|
AmazonTextractClient |
IronTesseract |
AmazonS3Client |
Não é necessário |
DetectDocumentTextRequest |
OcrInput |
DetectDocumentTextResponse |
OcrResult |
AnalyzeDocumentRequest |
OcrInput com CropRectangle para zonas |
StartDocumentTextDetectionRequest |
OcrInput — síncrono, sem necessidade de iniciar |
GetDocumentTextDetectionRequest |
Não é necessário — resultados imediatos |
Document.Bytes |
input.LoadImage(bytes) ou input.LoadImage(stream) |
S3Object (estágio de documentos) |
string ou fluxo de caminho de arquivo |
Block (BlockType.LINE) |
result.Lines |
Block (BlockType.WORD) |
result.Words |
Block (BlockType.TABLE) |
Agrupamento de posições de palavras via result.Words |
Block (BlockType.KEY_VALUE_SET) |
Extração de região CropRectangle |
Block.Confidence |
word.Confidence / result.Confidence |
JobStatus.SUCCEEDED |
Não aplicável — retorno síncrono |
JobStatus.IN_PROGRESS |
Não aplicável — nenhum estado assíncrono |
response.NextToken (paginação) |
Não aplicável — resultados não paginados |
ProvisionedThroughputExceededException |
Não aplicável — sem limites de TPS |
client.DetectDocumentTextAsync(request) |
ocr.Read(path) |
client.AnalyzeDocumentAsync(request) |
ocr.Read(input) |
client.StartDocumentTextDetectionAsync(request) |
ocr.Read(input) |
client.GetDocumentTextDetectionAsync(request) |
Não aplicável |
Quando as equipes consideram migrar doAWS Textractpara o IronOCR
Quando a conta mensal se torna uma despesa do orçamento
As equipes que começaram a usar o Textract em baixo volume frequentemente se deparam com um momento específico: a fatura da AWS para processamento de OCR aparece em uma revisão orçamentária trimestral e alguém pergunta se esse custo é fixo. Não é. Em altos volumes de páginas, os custos anuais do Textract podem ser substanciais — consulte a página de preços do AWS Textract para tarifas atuais. A licença IronOCR Professional por $2,999 paga por si mesma rapidamente em volumes de páginas moderados a altos.
Quando um requisito de conformidade bloqueia o processamento em nuvem
Organizações de saúde que implementam fluxos de trabalho de digitalização de documentos frequentemente descobrem, no meio do projeto, que as informações de saúde protegidas pelaHIPAA(PHI-PHI) não podem ser transmitidas por serviços em nuvem sem um Acordo de Parceiro Comercial (BAA) e uma revisão jurídica adicional, ou que sua equipe de segurança proíbe completamente a transmissão para a nuvem. Os contratados da área de defesa que lidam com desenhos técnicos, especificações ou qualquer informação controlada não classificada (CUI) estão sujeitos a restrições doITARe do CMMC que excluem oAWS Textractde sua consideração. Escritórios de advocacia que processam comunicações confidenciais têm preocupações semelhantes. Esses não são casos extremos teóricos de conformidade — eles aparecem regularmente em revisões de compras, auditorias de segurança e negociações de contratos. O IronOCR processa os dados localmente, portanto, a questão de conformidade para dados de documentos se resume a saber se sua própria infraestrutura está dentro do escopo, e não se a infraestrutura da Amazon está.
Quando a complexidade do PDF assíncrono excede seu valor
O pipeline assíncrono do S3 de cinco fases — upload, início da tarefa, polling, paginação dos resultados, limpeza — não é tecnicamente difícil de implementar. É difícil de manter, testar e operar. Cada fase é um ponto de falha. Falhas no envio de arquivos para o S3 exigem lógica de repetição. As falhas nos trabalhos do Textract exigem a distinção entre erros transitórios e permanentes. Os tempos limite de sondagem exigem um tratamento de tempo limite separado do cancelamento. A paginação de resultados requer o acúmulo de estado ao longo de múltiplas chamadas de API. Falhas na limpeza do S3 exigem alertas porque objetos órfãos acumulam custos. As equipes que implementaram esse pipeline em produção normalmente gastam mais tempo de engenharia contínua em sua manutenção do que gastaram em sua construção. O equivalente IronOCR— input.LoadPdf(path) seguido por ocr.Read(input) — elimina todas as cinco fases e seus modos de falha associados.
Quando os ambientes de implantação não têm acesso à Internet
ContêineresDockerexecutados em segmentos de rede isolados, servidores locais sem acesso à internet, ambientes de pesquisa isolados da internet e sistemas industriais com controles de rede rigorosos compartilham uma característica: oAWS Textractnão está disponível. O IronOCR é instalado como um pacote NuGet padrão e funciona sem qualquer chamada de rede após a instalação. As equipes que executam aplicativos .NET nesses ambientes não têm a opção do Textract e precisam de uma biblioteca que processe os dados localmente. O guia de implantação do Docker e o guia de implantação do Linux abordam a configuração específica para ambientes conteinerizados.
Quando a limitação de taxa interrompe os fluxos de trabalho em lote
O limite padrão de TPS StartDocumentTextDetection é de 5 solicitações por segundo. Chamadas síncronas DetectDocumentText também têm limite de taxa. Os trabalhos em lote que processam centenas ou milhares de documentos devem implementar limitação SemaphoreSlim, recuo exponencial em ProvisionedThroughputExceededException, e temporizadores de reabastecimento de taxa. A AWS aceita solicitações de aumento de limite de TPS, mas elas exigem justificativa, análise e não são garantidas. O IronOCR processa os dados na velocidade máxima permitida pela CPU local — um servidor de 32 núcleos processa 32 documentos simultaneamente, sem necessidade de configuração de limitação de capacidade ou negociação de nível de serviço.
Considerações Comuns de Migração
Substituindo o grafo de blocos por coleções diretas
Textract representa todos os resultados como um List<Block> plano onde linhas, palavras, células, tabelas e pares chave-valor são distinguidos por BlockType e vinculados por matrizes de ID de relacionamento. O IronOCR fornece coleções digitadas diretamente.
// Textract: filter flat block list by type
var lines = response.Blocks.Where(b => b.BlockType == BlockType.LINE);
var words = response.Blocks.Where(b => b.BlockType == BlockType.WORD);
// IronOCR: direct access to typed collections
var result = ocr.Read(imagePath);
var lines = result.Lines; // IEnumerable<OcrResult.OcrResultLine>
var words = result.Words; // IEnumerable<OcrResult.OcrResultWord>
foreach (var word in result.Words)
Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%");
// Textract: filter flat block list by type
var lines = response.Blocks.Where(b => b.BlockType == BlockType.LINE);
var words = response.Blocks.Where(b => b.BlockType == BlockType.WORD);
// IronOCR: direct access to typed collections
var result = ocr.Read(imagePath);
var lines = result.Lines; // IEnumerable<OcrResult.OcrResultLine>
var words = result.Words; // IEnumerable<OcrResult.OcrResultWord>
foreach (var word in result.Words)
Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%");
' Textract: filter flat block list by type
Dim lines = response.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
Dim words = response.Blocks.Where(Function(b) b.BlockType = BlockType.WORD)
' IronOCR: direct access to typed collections
Dim result = ocr.Read(imagePath)
Dim lines = result.Lines ' IEnumerable(Of OcrResult.OcrResultLine)
Dim words = result.Words ' IEnumerable(Of OcrResult.OcrResultWord)
For Each word In result.Words
Console.WriteLine($"'{word.Text}' at ({word.X},{word.Y}) confidence {word.Confidence}%")
Next
O guia de resultados estruturados cobre result.Pages, result.Paragraphs, result.Lines, result.Words e acesso a coordenadas para construção de processamento de documentos consciente do layout.
Substituindo o processamento de PDF em estágios S3 pelo carregamento direto de PDF.
Qualquer código Textract que faça upload para o S3 antes de iniciar uma tarefa de detecção pode ser substituído por um carregamento direto de PDF. Sem ambiente de preparação (staging bucket), sem agendamento de uploads, sem lógica de limpeza.
// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
//IronOCR equivalent:
public string ProcessPdf(string pdfPath)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return ocr.Read(input).Text;
}
// Specific page ranges (no Textract equivalent without async job per range)
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return ocr.Read(input).Text;
}
// Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
//IronOCR equivalent:
public string ProcessPdf(string pdfPath)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return ocr.Read(input).Text;
}
// Specific page ranges (no Textract equivalent without async job per range)
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return ocr.Read(input).Text;
}
Imports IronOcr
Public Class PdfProcessor
' Textract: upload to S3 → start job → poll → paginate → cleanup (50+ lines)
' IronOCR equivalent:
Public Function ProcessPdf(pdfPath As String) As String
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadPdf(pdfPath)
Return ocr.Read(input).Text
End Using
End Function
' Specific page ranges (no Textract equivalent without async job per range)
Public Function ProcessPdfPages(pdfPath As String, startPage As Integer, endPage As Integer) As String
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadPdfPages(pdfPath, startPage, endPage)
Return ocr.Read(input).Text
End Using
End Function
End Class
Adicionando pré-processamento para documentos que produziram baixa confiança no Textract
O pré-processamento do Textract é interno e não configurável. Quando um documento digitalizado produz resultados insatisfatórios, as únicas opções são tentar novamente ou aceitar um resultado com baixa confiabilidade. O IronOCR expõe diretamente o pipeline de pré-processamento.
// For documents that returned low-confidence results from Textract
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew(); // Fix rotation from scanner misalignment
input.DeNoise(); // Remove scanner noise artifacts
input.Contrast(); // Boost faint text
input.EnhanceResolution(300); // Scale to optimal OCR resolution
var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
// For documents that returned low-confidence results from Textract
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew(); // Fix rotation from scanner misalignment
input.DeNoise(); // Remove scanner noise artifacts
input.Contrast(); // Boost faint text
input.EnhanceResolution(300); // Scale to optimal OCR resolution
var result = new IronTesseract().Read(input);
Console.WriteLine($"Confidence: {result.Confidence}%");
Imports IronOcr
Dim input As New OcrInput()
input.LoadImage("low-quality-scan.jpg")
input.Deskew() ' Fix rotation from scanner misalignment
input.DeNoise() ' Remove scanner noise artifacts
input.Contrast() ' Boost faint text
input.EnhanceResolution(300) ' Scale to optimal OCR resolution
Dim result = New IronTesseract().Read(input)
Console.WriteLine($"Confidence: {result.Confidence}%")
O guia de correção de qualidade de imagem e o tutorial de filtros de imagem documentam o pipeline completo de pré-processamento e combinações que funcionam melhor para tipos de documentos específicos. Para interpretação de pontuação de confiança e acesso de confiança por elemento, o guia de pontuações de confiança cobre a propriedade result.Confidence e valores de confiança por palavra.
Lidando com a mudança de padrão de assíncrono para síncrono
O código existente do Textract é necessariamente async Task<t> por todo o SDK porque é apenas assíncrono. As operações do IronOCR são síncronas. Para código de aplicativo que já possui uma cadeia de chamadas assíncronas, envolva a chamada IronOCR em Task.Run para manter o limite assíncrono.
// Preserves async call site for minimal refactoring
public async Task<string> ExtractTextAsync(string path)
{
return await Task.Run(() => new IronTesseract().Read(path).Text);
}
// Preserves async call site for minimal refactoring
public async Task<string> ExtractTextAsync(string path)
{
return await Task.Run(() => new IronTesseract().Read(path).Text);
}
Imports System.Threading.Tasks
' Preserves async call site for minimal refactoring
Public Async Function ExtractTextAsync(path As String) As Task(Of String)
Return Await Task.Run(Function() New IronTesseract().Read(path).Text)
End Function
Esta é uma embalagem para facilitar o uso, não um requisito. Para processamento no lado do servidor, onde o código de chamada já está em uma thread em segundo plano, a chamada síncrona direta é preferível.
Funcionalidades adicionais do IronOCR
Além dos pontos de comparação acima, o IronOCR oferece recursos que não têm equivalente no AWS Textract:
- Leitura de código de barras durante OCR: Configure
ocr.Configuration.ReadBarCodes = truee códigos de barras no documento são extraídos junto com o texto em uma única passagem — sem etapa separada de digitalização de código de barras - Acompanhamento do progresso de tarefas longas : Inscreva-se para receber notificações de progresso para processamento de várias páginas sem consultar um serviço externo.
- Processamento de documentos digitalizados : Fluxo de trabalho otimizado para a saída típica de scanners de escritório, incluindo digitalizações frente e verso e páginas com orientações mistas.
- Extração simultânea de múltiplos idiomas: Combine pacotes de idiomas no momento da leitura —
OcrLanguage.French + OcrLanguage.German— sem mudança de nível de API Leitura de passaportes e documentos de identidade : Pipeline dedicado para zonas legíveis por máquina em documentos de identidade, extraindo campos estruturados sem definição manual de regiões.
Compatibilidade com .NET e Preparação para o Futuro
O IronOCR é compatível com .NET 8 e .NET 9, com suporte ativo para projetos .NET Standard 2.0 e .NET Framework 4.6.2 a 4.8. A biblioteca inclui binários nativos para Windows x64, Windows x86,Linuxx64 e macOS em um único pacote NuGet — sem necessidade de troca de identificadores de tempo de execução ou referências a pacotes específicos da plataforma. O pacote AWSSDK.Textract doAWS Textractsuporta os mesmos destinos .NET modernos, mas o modelo de implantação carrega toda a árvore de dependência do SDK AWS, infraestrutura de credenciais IAM, e as restrições arquitetônicas documentadas ao longo deste artigo. O IronOCR mantém um desenvolvimento ativo com lançamentos regulares que acompanham as atualizações do mecanismo Tesseract 5 e os avanços do ambiente de execução .NET , incluindo a compatibilidade com o .NET 10 quando este for lançado.
Conclusão
OAWS Textracte o IronOCR resolvem o mesmo problema — extrair texto de documentos em aplicações .NET — com pressupostos arquitetônicos fundamentalmente incompatíveis. O Textract pressupõe que os documentos possam sair da sua rede, que os custos do serviço em nuvem aumentem linearmente com o volume e que PDFs com várias páginas justifiquem um pipeline assíncrono de cinco fases com armazenamento temporário no S3. O IronOCR parte do princípio de que os documentos permanecem no local onde são processados, que os custos de licenciamento devem ser dissociados do volume e que o processamento de PDFs deve exigir as mesmas três linhas de código que o processamento de imagens.
A aritmética de custo é a linha divisória mais clara. Em baixos volumes, as taxas por página do Textract são manejáveis. À medida que o volume cresce, os custos anuais aumentam significativamente. Em volumes de páginas altos com extração de tabelas, os custos do Textract ao longo de vários anos podem exceder em muito até mesmo a licença Unlimited do IronOCR em $5,999. A matemática inicial se mantém: o modelo por página soma rápido, e nunca para.
A soberania dos dados é a segunda restrição estrutural. Para as áreas da saúde, jurídica, financeira e governamental, a questão de onde os documentos são processados não é uma preferência — é uma exigência de conformidade. O IronOCR processa os dados localmente por padrão, não por configuração. Não existe um "modo local" que possa ser ativado; O processamento local é o único modo. Isso torna a resposta sobre conformidade simples: seus documentos permanecem em sua infraestrutura porque não há outro lugar para onde eles possam ir.
Para equipes que avaliam o OCR em escala real ou que operam em ambientes onde os dados dos documentos não podem sair da infraestrutura interna, a documentação do IronOCR fornece a referência completa da API, guias de implantação para Docker, AWS,Azuree Linux, além de tutoriais que abrangem toda a gama de casos de uso de OCR, desde a leitura básica de imagens até a geração de PDFs pesquisáveis e a extração multilíngue.
Perguntas frequentes
O que é o Amazon Textract?
O Amazon Textract é uma solução de OCR usada por desenvolvedores e empresas para extrair texto de imagens e documentos. É uma das várias opções de OCR avaliadas juntamente com o IronOCR para desenvolvimento de aplicações .NET.
Como o IronOCR se compara ao Amazon Textract para desenvolvedores .NET?
IronOCR é uma biblioteca OCR .NET nativa do NuGet que utiliza o IronTesseract como mecanismo principal. Comparada ao Amazon Textract, oferece implantação mais simples (sem instaladores de SDK), preço fixo e uma API C# limpa, sem interoperabilidade COM ou dependências de nuvem.
O IronOCR é mais fácil de configurar do que o Amazon Textract?
O IronOCR é instalado por meio de um único pacote NuGet. Não há instaladores de SDK, arquivos de licença para copiar, componentes COM para registrar ou binários de tempo de execução separados para gerenciar. Todo o mecanismo de OCR está incluído no pacote.
Quais são as diferenças de precisão entre o Amazon Textract e o IronOCR?
O IronOCR alcança alta precisão de reconhecimento para documentos comerciais padrão, faturas, recibos e formulários digitalizados. Para documentos muito degradados ou com escritas incomuns, a precisão varia de acordo com a qualidade da fonte. O IronOCR inclui filtros de pré-processamento de imagem para melhorar o reconhecimento em entradas de baixa qualidade.
O IronOCR suporta extração de texto de PDFs?
Sim. O IronOCR extrai texto tanto de PDFs nativos quanto de imagens digitalizadas de PDFs em uma única chamada. Ele também suporta arquivos TIFF com várias páginas, imagens e fluxos de dados. Para PDFs digitalizados, o OCR é aplicado página por página, com objetos de resultado por página.
Como se compara o licenciamento do Amazon Textract ao do IronOCR?
O IronOCR utiliza uma licença perpétua com preço fixo, sem cobranças por página ou por digitalização. Organizações que processam grandes volumes de documentos pagam o mesmo valor de licença, independentemente do volume. Detalhes e preços por volume estão disponíveis na página de licenciamento do IronOCR.
Quais idiomas o IronOCR suporta?
O IronOCR suporta 127 idiomas através de pacotes de idiomas NuGet separados. Adicionar um idioma requer um único comando 'dotnet add package IronOcr.Languages.{Idioma}'. Não é necessário inserir arquivos manualmente nem configurar caminhos.
Como faço para instalar o IronOCR em um projeto .NET ?
Instale via NuGet: 'Install-Package IronOcr' no Console do Gerenciador de Pacotes ou 'dotnet add package IronOcr' na CLI. Pacotes de idiomas adicionais são instalados da mesma forma. Não é necessário instalar o SDK nativo.
O IronOCR é adequado para implantações em Docker e contêineres, ao contrário do Amazon Textract?
Sim. O IronOCR funciona em contêineres Docker por meio de seu pacote NuGet. A chave de licença é definida por meio de uma variável de ambiente. Não são necessários arquivos de licença, caminhos de SDK ou montagens de volume para o próprio mecanismo de OCR.
Posso experimentar o IronOCR antes de comprar, em comparação com o Amazon Textract?
Sim. O modo de avaliação do IronOCR processa documentos e retorna resultados de OCR com uma marca d'água sobreposta. Você pode verificar a precisão em seus próprios documentos antes de adquirir uma licença.
O IronOCR suporta leitura de código de barras juntamente com extração de texto?
O IronOCR concentra-se na extração de texto e OCR. Para leitura de código de barras, a Iron Software fornece o IronBarcode como uma biblioteca complementar. Ambos estão disponíveis individualmente ou como parte do pacote Iron Suite.
É fácil migrar do Amazon Textract para o IronOCR?
A migração do Amazon Textract para o IronOCR normalmente envolve a substituição das sequências de inicialização pela instanciação do IronTesseract, a remoção do gerenciamento do ciclo de vida COM e a atualização das chamadas de API. A maioria das migrações reduz significativamente a complexidade do código.

