Porównanie pomiędzy IronOCR a Nanonets OCR
Model wycenyAWS Textractza strone moze wydawac sie niedrogi przy małej objętości, ale koszty nieustannie rosną na dużą skalę. Każdy dokument przetwarzany przez aplikację opuszcza twoją sieć, podróżuje do centrum danych Amazon, jest przetwarzany przez infrastrukturę Amazon, a rachunek nieustannie rośnie. Dla zespołów oceniających opcje OCR w .NET pytanie nie dotyczy tylko tego, czy Textract zapewnia dokładne wyniki — bo zapewnia — ale czy model kosztów na stronę, obowiązkowa transmisja do chmury i architektura asynchronicznego odpytywania dla dokumentów wielostronicowych odpowiadają rzeczywistym potrzebom aplikacji.
Zrozumienie AWS Textract
AWS Textract to zarządzana usługa analizy dokumentów Amazona, dostępna przez AWS SDK dla .NET za pośrednictwem pakietu AWSSDK.Textract NuGet. Działa jako interfejs API w chmurze: aplikacja wysyła dane dokumentu do infrastruktury Amazon i otrzymuje ustrukturyzowane wyniki. Usługa wymaga konta AWS, poświadczeń IAM z uprawnieniami Textract oraz połączenia internetowego dla każdej operacji OCR.
Textract oferuje kilka różnych trybów analizy, z których każdy jest wyceniany osobno:
- DetectDocumentText: Podstawowe wyodrębnianie tekstu (zobacz AWS Textract cennik dla bieżących stawek za stronę)
- AnalyzeDocument (Tabele): Podwyższony poziom za strone dla wyodrębniania strukturalnego tabel
- AnalyzeDocument (Formularze): Wyższy poziom za stronę dla wyodrębniania par klucz-wartość niż wyodrębnianie tabel
- AnalyzeExpense: Analiza faktur i paragonów za 0,01 USD za stronę
- AnalyzeID: Pobieranie danych z dokumentów tożsamości za 0,025 USD za stronę
- StartDocumentTextDetection / StartDocumentAnalysis: Asynchroniczny interfejs API wymagany dla dowolnego wielostronicowego pliku PDF, wymagający kontenera przejściowego S3, odpytywania zadań i paginacji wyników
Model wyników używa płaskiej listy obiektów Block z identyfikatorami relacji, które muszą być przeszukane, aby odtworzyć tabele, formularze lub dowolny ustrukturyzowany wynik. Proste wyodrębnianie tabeli wymaga iteracji przez bloki BlockType.TABLE, znalezienia bloków potomnych BlockType.CELL poprzez identyfikatory relacji RelationshipType.CHILD, a następnie pobrania bloków BlockType.WORD dla tekstu każdej komórki. Ten model grafu relacji obsługuje złożone struktury dokumentów, ale nie jest lekki.
Pipeline S3-Async
Pojedyncze obrazy OCR przez DetectDocumentTextAsync mogą przesyłać bajty dokumentu bezpośrednio w żądaniu. Dokumenty wielostronicowe nie mogą. Każdy plik PDF wymaga pełnego asynchronicznego potoku:
// AWS Textract: Wielostronicowy plik PDF 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: Zawsze clean up S3
await _s3Client.DeleteObjectAsync(_bucketName, key);
}
}
// AWS Textract: Wielostronicowy plik PDF 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: Zawsze 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 PdfProcessor
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: Zawsze clean up S3
Await _s3Client.DeleteObjectAsync(_bucketName, key)
End Try
End Function
End Class
To jest minimalna wykonalna implementacja do niezawodnego przetwarzania PDF — pięć odrębnych faz, dwóch klientów usług AWS i logika czyszczenia w bloku finally. Pełna wersja produkcyjna z odpowiednią obsługą błędów, logiką ponownych prób przy ograniczeniu częstotliwości oraz zarządzaniem limitami czasu ma długość 150–300 wierszy.
Zrozumienie IronOCR
IronOCR to komercyjna biblioteka OCR dla platformy .NET, która działa w całości na infrastrukturze użytkownika. Zawiera zoptymalizowany silnik Tesseract 5 z automatycznym przetwarzaniem wstępnym obrazów, natywną obsługą plików PDF oraz synchronicznym interfejsem API, który generuje wyniki bezpośrednio, bez wywoływania usług zewnętrznych lub etapów pośrednich.
Kluczowe cechy architektury IronOCR:
- Tylko przetwarzanie lokalne: żadne dane dokumentów nie opuszczają komputera, na którym działa aplikacja
- Pojedynczy pakiet NuGet:
dotnet add package IronOcrinstaluje wszystko, w tym natywne pliki binarne - Automatyczne przetwarzanie wstępne: prostowanie, usuwanie szumów, wzmocnienie kontrastu, binarizacja i skalowanie rozdzielczości odbywają się automatycznie w przypadku danych wejściowych o niskiej jakości
- Natywna obsługa plików PDF: odczytuje pliki PDF bezpośrednio poprzez ścieżkę pliku lub strumień bez pośrednictwa S3 lub zadań asynchronicznych
- Bezpieczne dla wątków: Jeden egzemplarz
IronTesseractobsługuje równoczesne żądania w wielu wątkach bez kolizji - Licencjonowanie wieczyste: $999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited — jednorazowa płatność, brak opłat za stronę, brak limitów użycia
- Ponad 125 pakietów językowych: instalowanych jako oddzielne pakiety NuGet, ładowanych lokalnie, bez połączeń sieciowych
Porównanie funkcji
| Funkcja | AWS Textract | IronOCR |
|---|---|---|
| Miejsce przetwarzania | Amazon Cloud (obowiązkowe) | Lokalne / na miejscu |
| Wielostronicowy plik PDF | Wymagane S3 + zadanie asynchroniczne | Bezpośrednie wywołanie synchroniczne |
| Model kosztowy | Za stronę (kontaktuj się z AWS w celu uzyskania bieżących cen) | Licencja wieczysta, brak opłat za stronę |
| Wymagane połączenie z Internetem | Zawsze | Nigdy |
| Konfiguracja poświadczeń | Użytkownik/rola IAM + opcjonalnie S3 | Pojedynczy ciąg klucza licencyjnego |
| Wdrożenie w środowisku izolowanym | Niemożliwe | W pełni obsługiwane |
| Obsługa zaszyfrowanych plików PDF | Nieobsługiwane | Wbudowane (parametr hasła) |
Szczegółowe porównanie funkcji
| Funkcja | AWS Textract | IronOCR |
|---|---|---|
| Wyodrębnianie tekstu | ||
| Podstawowe OCR (obrazy) | Tak — DetectDocumentTextAsync |
Tak — ocr.Read(path) |
| Wielostronicowy plik PDF | Wymaga S3 + asynchronicznego odpytywania | Bezpośredni input.LoadPdf(path) |
| Plik PDF chroniony hasłem | Nieobsługiwane | input.LoadPdf(path, Password: "x") |
| Dane wejściowe strumienia | Tak (tablica bajtów w żądaniu) | Tak — input.LoadImage(stream) |
| Pobieranie danych ustrukturyzowanych | ||
| Wyodrębnianie tabel | AnalyzeDocument + przeszukiwanie wykresu blokowego |
Rekonstrukcja oparta na pozycji słów WORD |
| Pobieranie danych z pól formularzy | AnalyzeDocument + bloki KEY_VALUE_SET |
Strefy CropRectangle oparte na regionach |
| Wyniki na poziomie wiersza | Filtracja Block według BlockType.LINE |
Bezpośrednia kolekcja result.Lines |
| Na poziomie WORD z koordynatami | Filtracja Block według BlockType.WORD |
result.Words z .X, .Y, .Width |
| Wyniki pewności | Pewność dla poszczególnych bloków | Po słowie i całkowity result.Confidence |
| Model przetwarzania | ||
| Synchroniczne (obrazy) | Tak (tylko jedna strona) | Tak (wszystkie typy dokumentów) |
| Asynchroniczny | Wymagane dla plików PDF | Opcjonalnie — opakowanie Task.Run() |
| Przetwarzanie wsadowe | Wymaga zarządzania limitami szybkości (domyślnie 5 TPS) | Niezwiązane Parallel.ForEach |
| Przetwarzanie wstępne | ||
| Automatyczna korekcja przekrzywienia | Nieujawnione | input.Deskew() |
| Usuwanie szumów | Wewnętrzne (niekonfigurowalne) | input.DeNoise() |
| Wzmocnienie kontrastu | Wewnętrzne (niekonfigurowalne) | input.Contrast() |
| Poprawa rozdzielczości | Wewnętrzne (niekonfigurowalne) | input.EnhanceResolution(300) |
| Binaryzacja | Wewnętrzne | input.Binarize() |
| Formaty wyjściowe | ||
| Zwykły tekst | Tak | Tak |
| PDF z funkcją wyszukiwania | Nie | result.SaveAsSearchablePdf(path) |
| hOCR | Nie | result.SaveAsHocrFile(path) |
| Strukturalny JSON | Poprzez serializację blokową | result.Words / result.Lines |
| Wdrożenie | ||
| Lokalnie | Nie | Tak |
| Odizolowane | Nie | Tak |
| Docker | Tak (z wstawionymi danymi uwierzytelniającymi AWS) | Tak (nie są wymagane dane uwierzytelniające) |
| AWS Lambda | Język ojczysty | Obsługiwane |
| Azure | Tak | Tak |
| Linux | Tak (zarządzane przez AWS) | Tak — get-started/linux/ |
| Zgodność | ||
| HIPAA | Wymagana umowa BAA z AWS | Brak zewnętrznego procesora |
| RODO | Przenoszenie danych do regionów AWS | Dane pozostają w granicach |
| ITAR | Zabronione bez specjalnego upoważnienia | W całości na miejscu |
| Odizolowane/CMMC poziom 3 | Niemożliwe | Obsługiwane |
Koszt w skali
Model cenowy oparty na liczbie stron stanowi podstawowe ograniczenie strukturalne usługi AWS Textract. Koszty, które wydają się małe za stronę, znacznie się kumulują przy rzeczywistym przepływie dokumentów.
Podejście 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
Skonsultuj stronę cennika AWS Textract dla bieżących stawek za stronę. Różne funkcje API (podstawowe wykrywanie tekstu, wyodrębnianie tabel, wyodrębnianie formularzy) mają różne stawki. Dokument zawierajacy tabele i pola formularza generuje wyzsze oplaty niz podstawowe wykrywanie tekstu, a koszty rosna wraz z objetością bez gornych limitow i bez mozliwosci zapłaty z góry.
Przy wysokich objetościach stron, całkowite koszty trzech lat mogą być znaczne, a miernik wciąż biegnie.
Podejście IronOCR
// One license. Nie 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. Nie 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. Nie 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
Licencja $2,999 Professional obejmuje 10 programistów, nieograniczoną liczbę projektów i nieograniczoną liczbę stron. Po pierwszym roku bieżący koszt przetwarzania stron wynosi zero. Dla zespołów przetwarzających duże ilości stron, licencja IronOCR szybko się zwraca w porównaniu z trwającymi opłatami za przetwarzanie w chmurze na stronę.
Strona licencyjna IronOCR zawiera szczegółowe informacje na temat poziomów licencji, opcji subskrypcji SaaS w scenariuszach rozliczeń opartych na wykorzystaniu oraz warunków redystrybucji OEM.
Suwerenność danych i zgodność z przepisami
ArchitekturaAWS Textractuniemożliwia spełnienie jednej gwarancji: że dokumenty pozostaną w ramach infrastruktury użytkownika. Każda operacja OCR przesyła zawartość dokumentu na serwery Amazon.
Podejście 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
AWS oferuje umowęHIPAABusiness Associate Agreement dla podmiotów objętych przepisami, a regiony GovCloud zapewniają autoryzację FedRAMP High. Frameworki te nie zmieniają podstawowej architektury: dokumenty opuszczają infrastrukturę użytkownika przy każdej operacji. W przypadku danych technicznych podlegających przepisomITARnie jest to kwestia niuansów zgodności — jest to zakaz. W przypadku obciążeń CMMC poziomu 3 z CUI transmisja w chmurze wymaga specjalnych uprawnień, których większość wykonawców z sektóra obronnego nie posiada. W przypadku systemów odizolowanych — sieci badawczych, przemysłowych środowisk kontrolnych, obiektów o ograniczonym dostępie — Textract jest po prostu niedostępny.
AWS Textract jest dostępny w sześciu regionach: us-east-1, us-west-2, eu-west-1, eu-west-2, ap-southeast-1 i ap-southeast-2. Organizacje, które muszą spełniać wymogi dotyczące lokalizacji danych poza tymi regionami, nie mają żadnej opcji zgodnej z przepisami.
Podejście 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
PonieważIronOCR działa lokalnie, naturalnie wpisuje się w procesy opieki zdrowotnej przetwarzające dane medyczne (PHI), systemy dokumentów prawnych obsługujące poufną korespondencję, aplikacje finansowe przetwarzające obrazy kart płatniczych oraz procesy wykonawców z sektóra obronnego przetwarzające informacje o znaczeniu krytycznym (CUI). Nie ma żadnego zewnętrznego procesora do audytu, żadnej umowy BAA do negocjacji, żadnych ograniczeń dotyczących lokalizacji danych, które należałoby spełnić. Zakres zgodności obejmuje infrastrukturę Twojej organizacji.
Dla zespołów wdrażających rozwiązania w infrastrukturze AWS, ale wymagających lokalnego przetwarzania,IronOCRdziała na AWS (EC2, Lambda) bez żadnej zależności od Textract — przetwarzanie odbywa się w ramach własnego konta AWS, a nie w ramach usługi zarządzanej przez Amazon.
Pobieranie asynchroniczne a przetwarzanie synchroniczne
Podział architektury między synchronicznymi (pojedynczy obraz) i asynchronicznymi (wielostronicowy plik PDF) interfejsami API Textract nie jest drobnym szczegółem API. To one kształtują sposób tworzenia usług, sposób obsługi błędów oraz to, ile kodu muszą przeczytać i przeanalizować osoby odpowiedzialne za utrzymanie oprogramowania.
Podejście 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
Nie jest to szablon, który można wygenerować i o nim zapomnieć. Gdy zadanie Textract zakończy się niepowodzeniem w trakcie wykonywania, czyszczenie S3 musi nadal przebiegać. Gdy zadanie wygaśnie po 10 minutach, wywołujący potrzebuje jasnego komunikatu o błędzie. W przypadku utraty połączenia sieciowego podczas odpytywania strategia ponownych prób nie może powodować tworzenia zduplikowanych zadań. Każdy z tych trybów awarii wymaga wyraźnego obsługi — struktura pokazana powyżej stanowi minimalną odpowiedzialną implementację.
Przetwarzanie wsadowe dodaje kolejną warstwę: domyślny limit StartDocumentTextDetection TPS dla Textract to 5 żądań na sekundę. Przetworzenie 100 dokumentów wymaga ograniczenia SemaphoreSlim, zegara odnawiania szybkości i logiki ponownego próbowania dla ProvisionedThroughputExceededException.
Podejście 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
Nie ma pętli odpytywania, śledzenia identyfikatorów zadań, zasobnika S3 ani paginacji wyników. Ten sam kod obsługuje zarówno pojedynczy plik JPEG, jak i 200-stronicowy plik PDF. Przetwarzanie kończy się powodzeniem lub generuje wyjątek — nie ma pośredniego stanu "w toku", którym trzeba by zarządzać. Do przetwarzania wsadowego, IronOCR działa w trybie bezpiecznym dla wątków, a jeden egzemplarz IronTesseract obsługuje Parallel.ForEach bez blokad ani semaforów.
Podręcznik konfiguracji IronTesseract obejmuje ustawienia, a podręcznik dotyczący plików PDF opisuje wybór zakresu stron, pliki PDF chronione hasłem oraz wprowadzanie strumieniowe plików PDF pobranych z baz danych lub odpowiedzi HTTP.
Nakład związany z zarządzaniem poświadczeniami
Rozpoczęcie operacji OCR za pomocąAWS Textractwymaga konfiguracji IAM przed przetworzeniem pierwszej strony.
Podejście AWS Textract
Zanim wywołasz DetectDocumentTextAsync, programista musi:
- Utwórz konto AWS lub uzyskaj dostęp do istniejącego konta
- Utwórz użytkownika IAM lub rolę z pozwoleniami
textract:DetectDocumentTextitextract:AnalyzeDocument - Generowanie i bezpieczne przechowywanie identyfikatora klucza dostępu oraz tajnego klucza dostępu
- Skonfiguruj rozpoznawanie poświadczeń — zmienne środowiskowe, plik poświadczeń AWS lub profil instancji EC2
- Jeśli przetwarzane są PDF-y: utwórz kubeł S3, skonfiguruj politykę kubełka, dodaj uprawnienia
s3:PutObjectis3:DeleteObject - Wdrożenie zasad rotacji poświadczeń w celu spełnienia standardów bezpieczeństwa
- Bezpieczne przechowywanie danych uwierzytelniających w każdym środowisku wdrożeniowym — sekrety Docker, sekrety Kubernetes, AWS Secrets Manager lub zmienne potoku 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
Gdy dane uwierzytelniające wygasają, są obracane lub nie są poprawnie skonfigurowane, każde wywołanie OCR kończy się niepowodzeniem z AmazonTextractException zawierającymi ErrorCode == "AccessDeniedException". W systemie produkcyjnym oznacza to wdrożenie konkretnych bloków catch na wypadek niepowodzeń związanych z poświadczeniami oraz monitorowanie odchyleń od zasad IAM.
Podejście 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")
Klucz licencyjny jest ciągiem statycznym. Nie wygasa w trakcie działania, nie wymaga rotacji i nie wymaga zarządzania uprawnieniami. KontenerDockerprzetwarzający dokumenty nie wymaga wstrzykiwania poświadczeń AWS, roli IAM powiązanej z kontekstem wykonania ani dostępu sieciowego do AWS STS w celu odświeżenia tokenu.
Całkowite zmniejszenie obciążenia związanego z poświadczeniami przy przejściu z Textract na IronOCR: usunięto trzy pakiety NuGet (AWSSDK.Textract, AWSSDK.S3, AWSSDK.Core), usunięto wszystkie zmienne środowiskowe AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_DEFAULT_REGION, a role IAM i konfiguracje kubełków S3 zostały zlikwidowane. Przewodnik po wprowadzaniu obrazów i przewodnik po wprowadzaniu strumieniowym obejmują pełen zakres metod wprowadzania danych, które zastępują modele dokumentów Textract oparte na tablicach bajtów i obiektach S3.
Przewodnik po mapowaniu API
| AWS Textract API | Odpowiednik IronOCR |
|---|---|
AmazonTextractClient |
IronTesseract |
AmazonS3Client |
Nie jest wymagane |
DetectDocumentTextRequest |
OcrInput |
DetectDocumentTextResponse |
OcrResult |
AnalyzeDocumentRequest |
OcrInput z CropRectangle dla stref |
StartDocumentTextDetectionRequest |
OcrInput — synchroniczne, nie wymaga uruchamiania |
GetDocumentTextDetectionRequest |
Nie jest wymagane — wyniki natychmiastowe |
Document.Bytes |
input.LoadImage(bytes) lub input.LoadImage(stream) |
S3Object (przechowywanie dokumentów) |
Ciąg znaków ścieżki pliku lub strumień |
Block (BlockType.LINE) |
result.Lines |
Block (BlockType.WORD) |
result.Words |
Block (BlockType.TABLE) |
Grupowanie pozycji słów przez result.Words |
Block (BlockType.KEY_VALUE_SET) |
Ekstrakcja regionu CropRectangle |
Block.Confidence |
word.Confidence / result.Confidence |
JobStatus.SUCCEEDED |
Nie dotyczy — zwrot synchroniczny |
JobStatus.IN_PROGRESS |
Nie dotyczy — brak stanu asynchronicznego |
response.NextToken (paginacja) |
Nie dotyczy — wyniki nie są podzielone na strony |
ProvisionedThroughputExceededException |
Nie dotyczy — brak limitów TPS |
client.DetectDocumentTextAsync(request) |
ocr.Read(path) |
client.AnalyzeDocumentAsync(request) |
ocr.Read(input) |
client.StartDocumentTextDetectionAsync(request) |
ocr.Read(input) |
client.GetDocumentTextDetectionAsync(request) |
Nie dotyczy |
Kiedy zespoły rozważają przejście zAWS Textractna IronOCR
Kiedy miesięczny rachunek staje się pozycją w budżecie
Zespoły, które zaczynały korzystać z Textract przy niewielkich wolumenach, często stają przed pewnym dylematem: podczas kwartalnego przeglądu budżetu pojawia się rachunek AWS za przetwarzanie OCR i ktoś pyta, czy ten koszt jest stały. Nie jest. Przy dużych ilościach stron, roczne koszty Textract mogą być znaczące — skonsultuj stronę z wyceną AWS Textract dla aktualnych stawek. Licencja IronOCR Professional w $2,999 jednorazowego zakupu szybko przynosi zwrot przy średnich i wysokich objętościach stron.
Kiedy wymogi zgodności blokują przetwarzanie w chmurze
Organizacje opieki zdrowotnej wdrażające procesy digitalizacji dokumentów często w trakcie projektu odkrywają, że daneHIPAAPHI nie mogą przepływać przez usługi w chmurze bez umowy BAA i dodatkowej weryfikacji prawnej, lub że ich zespół ds. bezpieczeństwa całkowicie zabrania transmisji w chmurze. Wykonawcy z branży obronnej zajmujący się rysunkami technicznymi, specyfikacjami lub dowolnymi informacjami o ograniczonym dostępie (CUI) podlegają ograniczeniomITARi CMMC, które wykluczająAWS Textractz rozważań. Kancelarie prawne przetwarzające poufną korespondencję mają podobne obawy. Nie są to teoretyczne skrajne przypadki zgodności — pojawiają się one regularnie podczas przeglądów zamówień, audytów bezpieczeństwa i negocjacji umów.IronOCR przetwarza dane lokalnie, więc kwestia zgodności w odniesieniu do danych dokumentów sprowadza się do tego, czy w zakresie znajduje się Twoja własna infrastruktura, a nie infrastruktura Amazon.
Kiedy złożoność asynchronicznego PDF przewyższa jego wartość
Pięciofazowy potok S3-async — przesyłanie, uruchamianie zadania, odpytywanie, paginacja wyników, czyszczenie — nie jest trudny do wdrożenia pod względem technicznym. Trudno jest go utrzymywać, testować i obsługiwać. Każda faza jest punktem awarii. Błędy przesyłania do S3 wymagają logiki ponownej próby. W przypadku niepowodzeń zadań Textract należy odróżnić błędy przejściowe od trwałych. Limity czasu na pobieranie danych wymagają obsługi limitów czasu niezależnej od anulowania. Paginacja wyników wymaga gromadzenia stanu w wielu wywołaniach API. Błędy czyszczenia S3 wymagają powiadomienia, ponieważ osierocone obiekty generują koszty. Zespoły, które wdrożyły ten proces do produkcji, zazwyczaj poświęcają więcej czasu na jego utrzymanie niż na jego stworzenie. Odpowiednik IronOCR— input.LoadPdf(path), a następnie ocr.Read(input) — eliminuje wszystkie pięć faz i związane z nimi tryby awarii.
Gdy środowiska wdrożeniowe nie mają dostępu do Internetu
KonteneryDockerdziałające w izolowanych segmentach sieci, serwery lokalne bez dostępu do Internetu, środowiska badawcze odizolowane oraz systemy przemysłowe z rygorystycznymi kontrolami sieciowymi mają jedną wspólną cechę:AWS Textractnie jest dostępny.IronOCR instaluje się jako standardowy pakiet NuGet i po instalacji działa bez żadnych połączeń sieciowych. Zespoły korzystające z aplikacji .NET w tych środowiskach nie mają dostępu do opcji Textract i potrzebują biblioteki, która działa lokalnie. Przewodnik wdrażania Docker oraz przewodnik wdrażania Linux obejmują konkretną konfigurację dla środowisk kontenerowych.
Kiedy ograniczanie przepustowości zakłóca przepływ pracy w trybie wsadowym
Domyślny limit TPS dla StartDocumentTextDetection wynosi 5 żądań na sekundę. Synchroniczne wywołania DetectDocumentText są również ograniczone szybkością. Zadania wsadowe przetwarzające setki lub tysiące dokumentów muszą implementować ograniczenie SemaphoreSlim, wykładnicze wycofanie przy ProvisionedThroughputExceededException i zegary odnawiania szybkości. AWS obsługuje wnioski o zwiększenie limitu TPS, ale wymagają one uzasadnienia, weryfikacji i nie są gwarantowane.IronOCR przetwarza dane tak szybko, jak pozwala na to lokalny procesor — 32-rdzeniowy serwer przetwarza jednocześnie 32 dokumenty bez konfiguracji ograniczania przepustowości ani negocjacji poziomu usługi.
Typowe kwestie związane z migracją
Zastąpienie wykresu blokowego bezpośrednimi kolekcjami
Textract przedstawia wszystkie wyniki jako płaską strukturę List<Block>, gdzie linie, słowa, komórki, tabele i pary klucz-wartość są rozróżniane przez BlockType i powiązane przez tablice identyfikatorów relacji.IronOCR udostępnia bezpośrednie kolekcje danych wpisanych.
// 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
Przewodnik po strukturach wyników obejmuje result.Pages, result.Paragraphs, result.Lines, result.Words oraz dostęp do współrzędnych do budowania przetwarzania dokumentów świadomego układu.
Zastąpienie przetwarzania plików PDF w S3-Staged przez Direct LoadPdf
Każdy kod Textract, który przesyła dane do S3 przed rozpoczęciem zadania wykrywania, można zastąpić bezpośrednim wczytaniem pliku PDF. Bez zasobnika przejściowego, bez synchronizacji przesyłania, bez logiki czyszczenia.
// 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
Dodanie przetwarzania wstępnego dla dokumentów, które wygenerowały niski poziom pewności w Textract
Przetwarzanie wstępne w Textract jest wewnętrzne i nie można go konfigurować. Gdy zeskanowany dokument daje słabe wyniki, jedyne opcje to ponowna próba lub zaakceptowanie wyników o niskim poziomie pewności.IronOCR udostępnia bezpośrednio potok przetwarzania wstępnego.
// 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}%")
Przewodnik po korekcji jakości obrazu i samouczek o filtrach obrazów dokumentują pełny potok wstępnego przetwarzania i kombinacje, które najlepiej sprawdzają się dla określonych typów dokumentów. W celu interpretacji wyników zaufania i dostępu do wartości zaufania dla poszczególnych elementów, przewodnik po wynikach zaufania obejmuje właściwość result.Confidence i wartości zaufania dla poszczególnych słów.
Obsługa zmiany wzorca z asynchronicznego na synchroniczny
Istniejący kod Textract jest koniecznie async Task<t> wszędzie, ponieważ SDK jest tylko asynchroniczny. Operacje IronOCRsą synchroniczne. Dla kodu aplikacji, który już ma asynchroniczny łańcuch wywołań, obwiąż wywołanie IronOCR w Task.Run, aby zachować asynchroniczną granicę.
// 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
Jest to wygodna nakładka, a nie wymóg. W przypadku przetwarzania po stronie serwera, gdzie kod wywołujący znajduje się już w wątku w tle, preferowane jest bezpośrednie wywołanie synchroniczne.
Dodatkowe możliwości IronOCR
Oprócz powyższych punktów porównawczych,IronOCR oferuje funkcje, które nie mają odpowiednika w AWS Textract:
- Odczyt kodów kreskowych podczas OCR: Ustaw
ocr.Configuration.ReadBarCodes = true, a kody kreskowe w dokumencie są wyodrębniane wraz z tekstem w jednym przejściu — brak oddzielnego etapu skanowania kodów kreskowych - Śledzenie postępów w przypadku długotrwałych zadań: subskrybuj zdarzenia postępu dla przetwarzania wielostronicowego bez odpytywania usługi zewnętrznej
- Przetwarzanie zeskanowanych dokumentów: zoptymalizowany proces dla typowych wyników skanowania biurowego, w tym skanów dwustronnych i stron o zróżnicowanej orientacji
- Jednoczesne wyodrębnianie wielojęzyczne: Połącz pakiety językowe podczas odczytu —
OcrLanguage.French + OcrLanguage.German— bez zmiany poziomu API - Odczytywanie paszportów i dowodów osobistych: dedykowany potok dla stref nadających się do odczytu maszynowego w dokumentach tożsamości, wyodrębniający pola ustrukturyzowane bez ręcznego definiowania obszarów
Zgodność z platformą .NET i gotowość na przyszłość
IronOCR jest przeznaczony dla platform .NET 8 i .NET 9, z aktywną kompatybilnością dla projektów .NET Standard 2.0 oraz .NET Framework 4.6.2 do 4.8. Biblioteka zawiera natywne pliki binarne dla systemów Windows x64, Windows x86,Linuxx64 i macOS w jednym pakiecie NuGet — bez konieczności zmiany identyfikatora środowiska uruchomieniowego ani odwołań do pakietów specyficznych dla danej platformy. Pakiet AWSSDK.TextractAWS Textractobsługuje te same nowoczesne cele .NET, ale model wdrażania zawiera całą strukturę zależności AWS SDK, infrastrukturę poświadczeń IAM i ograniczenia architektoniczne udokumentowane w całym tym artykule.IronOCR jest aktywnie rozwijany, a regularne wydania śledzą aktualizacje silnika Tesseract 5 oraz postępy środowiska uruchomieniowego .NET, w tym kompatybilność z .NET 10 po jego wydaniu.
Wnioski
AWS Textract i IronOCR rozwiązują ten sam problem — wyodrębnianie tekstu z dokumentów w aplikacjach .NET — przy zasadniczo niekompatybilnych założeniach architektonicznych. Textract zakłada, że dokumenty mogą opuszczać Twoją sieć, że koszty usług w chmurze rosną liniowo wraz z wolumenem oraz że wielostronicowe pliki PDF uzasadniają pięciofazowy asynchroniczny proces z wykorzystaniem S3.IronOCR zakłada, że dokumenty pozostają tam, gdzie są przetwarzane, że koszty licencji powinny być niezależne od wielkości, a przetwarzanie plików PDF powinno wymagać tych samych trzech linii kodu, co przetwarzanie obrazów.
Aritmetyka kosztów to najjasniejsza linia podziału. Przy niskich wolumenach, opłaty na stronę w Textract są do opanowania. W miarę wzrostu wolumenu, roczne koszty kumulują się znacząco. Przy dużych objętościach stron z wyodrębnianiem tabel, wieloletnie koszty Textract mogą zdecydowanie przekroczyć nawet nieograniczoną licencjęIronOCR w $5,999. Początkowe rachunki się utrzymują: model na stronę szybko się sumuje i nigdy nie przestaje.
Suwerenność danych stanowi drugie ograniczenie strukturalne. W przypadku zadań związanych z opieką zdrowotną, prawem, finansami i administracją publiczną kwestia miejsca przetwarzania dokumentów nie jest kwestią preferencji — jest to wymóg zgodności z przepisami.IronOCR przetwarza dane lokalnie z założenia, a nie z powodu konfiguracji. Nie ma "trybu lokalnego", który można by włączyć; Jedynym trybem jest przetwarzanie lokalne. To sprawia, że odpowiedź dotycząca zgodności jest prosta: dokumenty pozostają w Twojej infrastrukturze, ponieważ nie ma gdzie indziej ich umieścić.
Dla zespołów oceniających OCR na prawdziwą skalę lub działających w środowiskach, w których dane dokumentów nie mogą opuszczać wewnętrznej infrastruktury, dokumentacja IronOCR zawiera kompletną Dokumentację API, przewodniki wdrożeniowe dla Docker, AWS,AzureiLinuxoraz samouczki obejmujące pełen zakres zastosowań OCR, od podstawowego odczytu obrazów po generowanie przeszukiwalnych plików PDF i ekstrakcję wielojęzyczną.
Często Zadawane Pytania
Czym jest Amazon Textract?
Amazon Textract to rozwiązanie OCR wykorzystywane przez programistów i przedsiębiorstwa do wyodrębniania tekstu z obrazów i dokumentów. Jest to jedna z kilku opcji OCR ocenianych obok IronOCR for .NET pod kątem tworzenia aplikacji .NET.
Jak IronOCR wypada w porównaniu z Amazon Textract dla programistów .NET?
IronOCR to natywna dla NuGet biblioteka OCR dla platformy .NET, wykorzystująca IronTesseract jako główny silnik. W porównaniu z Amazon Textract oferuje prostsze wdrożenie (brak instalatorów SDK), ryczałtowe ceny oraz przejrzysty interfejs API w języku C# bez interoperacyjności COM i zależności od chmury.
Czy IronOCR jest łatwiejszy w konfiguracji niż Amazon Textract?
IronOCR instaluje się za pomocą jednego pakietu NuGet. Nie ma żadnych instalatorów SDK, plików licencyjnych do skopiowania, komponentów COM do zarejestrowania ani oddzielnych plików binarnych środowiska uruchomieniowego, którymi trzeba by zarządzać. Cały silnik OCR jest zawarty w pakiecie.
Jakie różnice w dokładności występują między Amazon Textract a IronOCR?
IronOCR osiąga wysoką dokładność rozpoznawania standardowych dokumentów biznesowych, faktur, paragonów i zeskanowanych formularzy. W przypadku dokumentów o bardzo niskiej jakości lub rzadkich skryptów dokładność zależy od jakości źródła. IronOCR zawiera filtry wstępnego przetwarzania obrazu, które poprawiają rozpoznawanie danych wejściowych o niskiej jakości.
Czy IronOCR obsługuje wyodrębnianie tekstu z plików PDF?
Tak. IronOCR wyodrębnia tekst zarówno z natywnych plików PDF, jak i ze skanowanych obrazów PDF za pomocą jednego wywołania. Obsługuje również wielostronicowe pliki TIFF, obrazy i strumienie. W przypadku skanowanych plików PDF OCR jest stosowany strona po stronie, z obiektami wynikowymi dla każdej strony.
Jak wygląda licencjonowanie Amazon Textract w porównaniu z IronOCR?
IronOCR korzysta z licencji wieczystej o stałej stawce, bez opłat za stronę lub skan. Organizacje przetwarzające duże ilości dokumentów płacą ten sam koszt licencji niezależnie od ilości. Szczegóły i ceny hurtowe znajdują się na stronie licencji IronOCR.
Jakie języki obsługuje IronOCR?
IronOCR obsługuje 127 języków za pośrednictwem oddzielnych pakietów językowych NuGet. Dodanie języka wymaga wykonania pojedynczego polecenia „dotnet add package IronOcr.Languages.{Language}”. Nie jest wymagane ręczne umieszczanie plików ani konfiguracja ścieżek.
Jak zainstalować IronOCR w projekcie .NET?
Instalacja przez NuGet: „Install-Package IronOcr” w konsoli menedżera pakietów lub „dotnet add package IronOcr” w CLI. Dodatkowe pakiety językowe instaluje się w ten sam sposób. Nie jest wymagany natywny instalator SDK.
Czy IronOCR nadaje się do wdrożeń w Dockerze i kontenerach, w przeciwieństwie do Amazon Textract?
Tak. IronOCR działa w kontenerach Docker za pośrednictwem pakietu NuGet. Klucz licencyjny jest ustawiany za pomocą zmiennej środowiskowej. Silnik OCR nie wymaga żadnych plików licencyjnych, ścieżek SDK ani montowania woluminów.
Czy przed zakupem mogę wypróbować IronOCR w porównaniu z Amazon Textract?
Tak. Tryb próbny IronOCR przetwarza dokumenty i zwraca wyniki OCR z nakładką znaku wodnego na wyjściu. Przed zakupem licencji można sprawdzić dokładność na własnych dokumentach.
Czy IronOCR obsługuje odczytywanie kodów kreskowych oprócz wyodrębniania tekstu?
IronOCR koncentruje się na wyodrębnianiu tekstu i OCR. Do odczytu kodów kreskowych firma Iron Software udostępnia bibliotekę IronBarcode jako dodatek. Obie biblioteki są dostępne osobno lub w ramach pakietu Iron Suite.
Czy łatwo jest przejść z Amazon Textract na IronOCR?
Migracja z Amazon Textract do IronOCR zazwyczaj polega na zastąpieniu sekwencji inicjalizacyjnych instancjonowaniem IronTesseract, usunięciu zarządzania cyklem życia COM oraz aktualizacji wywołań API. Większość migracji znacznie zmniejsza złożoność kodu.

