Migracja z XImage.OCR do IronOCR
Ten przewodnik jest przeznaczony dla programistów .NET, którzy przenoszą istniejącą integrację XImage.OCR do IronOCR. Obejmuje proces konsolidacji pakietów, zmiany w przestrzeni nazw i API oraz konkretne przykłady migracji kodu dla scenariuszy, w których fragmentaryczna architektura XImage.OCR powoduje największe utrudnienia. Nie jest wymagana wcześniejsza lektura artykułu porównawczego.
Dlaczego warto przejść z XImage.OCR
XImage.OCR to komercyjna nakładka na Tesseract firmy RasterEdge, która rozdziela swoją funkcjonalność na łańcuch skoordynowanych pakietów NuGet. Architektura ta sprawdza się na małą skalę, ale wraz z rozwojem aplikacji powoduje narastanie kosztów utrzymania.
Liczba pakietów rośnie wraz z każdym językiem. Dodanie języka oznacza dodanie pakietu NuGet. Aplikacja pięciojęzyczna zawiera sześć pakietów w swoim .csproj. Aplikacja obsługująca dziesięć języków obsługuje jedenaście. Każdy pakiet musi być przypisany do tej samej wersji co rdzeń — jest to ograniczenie, które powoduje ciche błędy uruchomieniowe, gdy programista aktualizuje tylko część łańcucha.IronOCR oferuje jeden pakiet obsługujący ponad 125 języków.
Synchronizacja wersji jest stałym ryzykiem. dotnet outdated aktualizuje pakiety chciwie. Gdy RasterEdge.XImage.OCR przechodzi na 12.5.0, ale XImage.OCR.Language.French pozostaje na 12.4.0, błąd pojawia się w czasie wykonywania, a nie w czasie kompilacji, a komunikat rzadko wskazuje synchronizację wersji jako przyczynę. Zespoły korzystające z procesów CI/CD uczą się dodawać wyraźne przypisanie wersji dla każdego pakietu XImage.OCR — jest to dodatkowy wysiłek, który nie służy niczym innym niż kompensacją fragmentarycznego modelu.
Brak wbudowanego przetwarzania wstępnego ogranicza dokładność w przypadku prawdziwych dokumentów. XImage.OCR przekazuje obrazy bezpośrednio do silnika Tesseract. Skan o rozdzielczości 150 DPI z dwustopniowym przekrzywieniem trafia do Tesseract bez zmian. Maksymalny poziom dokładności dla takich danych wejściowych wynosi 60–75%, niezależnie od tego, która nakładka Tesseract jest używana.IronOCR dostarcza potok przetwarzania wstępnego — Deskew(), DeNoise(), Contrast(), Binarize(), Sharpen() — który rozwiązuje te problemy przed rozpoczęciem rozpoznawania.
Strukturalny wynik wymaga ręcznego parsowania. XImage.OCR zwraca zwykły ciąg znaków. Wyodrębnianie pozycji słów, granic wierszy lub pewności dla poszczególnych słów wymaga samodzielnego parsowania tego ciągu znaków.IronOCR zwraca obiekt OcrResult z Pages, Paragraphs, Lines, Words, oraz dane dotyczące pojedynczych znaków z współrzędnymi pikseli i ocenami pewności.
Formaty wyjściowe ograniczają się do zwykłego tekstu. Utworzenie pliku PDF z możliwością wyszukiwania na podstawie wyników XImage.OCR wymaga RasterEdge PDF SDK — drugiego zakupu komercyjnego.IronOCR generuje przeszukiwalne pliki PDF za pomocą result.SaveAsSearchablePdf() bez dodatkowych zależności.
Wdrażanie na wielu platformach nie jest obsługiwane. XImage.OCR jest przeznaczony dla systemu Windows. Kontenery Linux, środowiska programistyczne macOS oraz wdrożenia natywne dla chmury na platformach Azure lub AWS wymagają innej biblioteki.IronOCR działa na systemach Windows, Linux, macOS, Docker, Azure App Service i AWS Lambda z tego samego pakietu.
Podstawowy problem
XImage.OCR wymaga jednego pakietu NuGet na każdy język. Dziesięć języków oznacza jedenaście pakietów, wszystkie wersje są zablokowane względem siebie:
<!-- XImage.OCR: 11 packages to support 10 languages — every version must match -->
<PackageReference Include="RasterEdge.XImage.OCR" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.English" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.German" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.French" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Spanish" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Italian" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Portuguese" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.ChineseSimplified" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Japanese" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Korean" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Arabic" Version="12.4.0" />
IronOCR zastępuje cały blok jedną linią:
<!-- IronOCR: One package. 125+ languages. Nie version coordination. -->
<PackageReference Include="IronOcr" Version="2024.x.x" />
##IronOCR a XImage.OCR: porównanie funkcji
Poniższa tabela przedstawia funkcje, które mają największe znaczenie przy podejmowaniu decyzji o migracji.
| Funkcja | XImage.OCR | IronOCR |
|---|---|---|
| Pakiety NuGet dostępne wyłącznie w języku angielskim | 2 (podstawowy + pakiet językowy) | 1 |
| Pakiety NuGet w 10 językach | 11 | 1 |
| Wymagana synchronizacja wersji | Tak — wszystkie pakiety muszą być zgodne | Nie |
| Dostępne języki | ~15 jako oddzielne pakiety | Ponad 125 w pakiecie |
| Wbudowane przetwarzanie wstępne | None | Wyrównanie, Usuwanie szumów, Kontrast, Binaryzacja, Wyostrzanie, Skalowanie, Rozszerzanie, Erodowanie, Odwracanie |
| Głębokie usuwanie szumów | None | Tak (DeepCleanBackgroundNoise()) |
| Natywne wprowadzanie plików PDF | Wymagane jest RasterEdge PDF SDK | Tak (input.LoadPdf()) |
| Wynik w formacie PDF z możliwością wyszukiwania | Wymagane jest RasterEdge PDF SDK | Tak (result.SaveAsSearchablePdf()) |
| Wielostronicowy plik wejściowy w formacie TIFF | Ograniczone | Tak (input.LoadImageFrames()) |
| Wejście tablicy bajtów | Podręcznik za pośrednictwem MemoryStream | Tak (input.LoadImage(bytes)) |
| Dane wejściowe strumienia | Podręcznik | Tak (input.LoadImage(stream)) |
| Strukturalny wynik | Zwykły ciąg znaków | Strony, akapity, wiersze, słowa, znaki z współrzędnymi |
| Wyniki pewności dla poszczególnych słów | Niedostępne | Tak |
| Odczytywanie BarCode | Niedostępne | Tak (ocr.Configuration.ReadBarCodes = true) |
| eksport hOCR | Niedostępne | Tak |
| Bezpieczeństwo wątków | Nie jest bezpieczne dla wątków | Pełna bezpieczeństwo wątków |
| Model pamięci (równoległy) | Jedna instancja obsługi na wątek | Pojedyncza instancja współdzielona |
| Wielopłatformowe | Głównie Windows | Windows, Linux, macOS, Docker, Azure, AWS |
| Kompatybilność z platformą .NET | .NET Standard 2.0, .NET Framework 4.5+ | .NET Framework 4.6.2+, .NET Core, .NET 5/6/7/8/9 |
| Rodzaj licencji | Komercjalne (RasterEdge) | Perpetual (Lite $999, Pro $1,499, Enterprise $2,999) |
| Wsparcie komercyjne | Pomoc techniczna RasterEdge | Tak, w podziale na poziomy licencji |
Szybki start: Migracja z XImage.OCR do IronOCR
Krok 1: Zastąp pakiety NuGet
Usuń wszystkie pakiety XImage.OCR. Liczba poleceń odpowiada liczbie zainstalowanych pakietów językowych:
dotnet remove package RasterEdge.XImage.OCR
dotnet remove package XImage.OCR.Language.English
dotnet remove package XImage.OCR.Language.German
dotnet remove package XImage.OCR.Language.French
# Repeat for every language pack in your project
Zainstaluj IronOCR z NuGet:
Krok 2: Aktualizacja przestrzeni nazw
Zastąp importy przestrzeni nazw RasterEdge pojedynczą przestrzenią nazw IronOCR:
// Before (XImage.OCR)
using RasterEdge.XImage.OCR;
using RasterEdge.Imaging.Basic;
// After (IronOCR)
using IronOcr;
Krok 3: Inicjalizacja licencji
Dodaj inicjalizację licencji raz podczas uruchamiania aplikacji, przed jakimikolwiek wywołaniami OCR:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"Klucz należy zapisać w zmiennej środowiskowej lub menedżerze sekretów, zamiast wpisywać go na stałe w kodzie:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY");Imports System
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")Przykłady migracji kodu
Konsolidacja inicjalizacji wielu pakietów
Pierwszym zadaniem migracji jest przekształcenie bloku inicjalizacji XImage.OCR — aktywacji licencji, tworzenia obsługi i przypisywania języka na podstawie ciągu znaków — na odpowiednik w IronOCR.
Podejście XImage.OCR:
// Requires: RasterEdge.XImage.OCR + one XImage.OCR.Language.* package per language
// Language strings must exactly match installed package names or OCR fails at runtime
RasterEdge.XImage.OCR.License.LicenseManager.SetLicense("your-ximage-license-key");
var ocrHandler = new OCRHandler();
// String codes — typo "enh" instead of "eng" silently fails or throws at runtime
ocrHandler.Languages = new[] { "eng", "deu", "fra", "spa", "ita" };
// Process returns a plain string — no structure, no confidence
string extractedText = ocrHandler.Process("document.png");
Console.WriteLine(extractedText);
Podejście IronOCR:
// Requires: IronOcr (single package — all languages included)
IronOcr.License.LicenseKey = "YOUR-IRONOCR-LICENSE-KEY";
var ocr = new IronTesseract();
// Type-safe enum — compiler catches typos, no runtime surprises
ocr.Language = OcrLanguage.English + OcrLanguage.German +
OcrLanguage.French + OcrLanguage.Spanish + OcrLanguage.Italian;
using var input = new OcrInput();
input.LoadImage("document.png");
var result = ocr.Read(input);
Console.WriteLine(result.Text);
Console.WriteLine($"Confidence: {result.Confidence}%");
Kody językowe oparte na stringach w XImage.OCR ("eng", "deu") zawodzą w czasie wykonywania, gdy odpowiedni pakiet NuGet jest nieobecny lub w nieodpowiedniej wersji. OcrLanguage enum w IronOCR uniemożliwia kompilację nieprawidłowych kombinacji językowych. Przewodnik konfiguracji IronTesseract obejmuje opcje konfiguracji silnika w całości, a wielojęzyczny przewodnik dokumentuje, jak działają kombinacje języków głównych i pomocniczych w dokumentach wielojęzycznych.
Ujednolicenie obsługi formatów obrazów
XImage.OCR obsługuje każde źródło obrazu w inny sposób, w zależności od formatu. Tablice bajtów, strumienie i ścieżki plików wymagają nieco różnych ścieżek kodu.IronOCR akceptuje je wszystkie poprzez te same metody OcrInput.
Podejście XImage.OCR:
// XImage.OCR: different handling per image source type
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
// File path — works directly
string resultFromFile = ocrHandler.Process("invoice.jpg");
// Byte array — must write to temp file first, then process
byte[] imageBytes = File.ReadAllBytes("invoice.jpg");
string tempPath = Path.GetTempFileName() + ".jpg";
File.WriteAllBytes(tempPath, imageBytes);
try
{
string resultFromBytes = ocrHandler.Process(tempPath);
Console.WriteLine(resultFromBytes);
}
finally
{
File.Delete(tempPath); // Podręcznik cleanup — easy to forget
}
// Multi-page TIFF — must split frames manually
// Nie built-in TIFF frame iteration in base XImage.OCR
Podejście IronOCR:
// IronOCR: unified OcrInput accepts all source types identically
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
// File path
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg");
var result = ocr.Read(input);
Console.WriteLine($"From file: {result.Text}");
}
// Byte array — no temp file needed
byte[] imageBytes = File.ReadAllBytes("invoice.jpg");
using (var input = new OcrInput())
{
input.LoadImage(imageBytes);
var result = ocr.Read(input);
Console.WriteLine($"From bytes: {result.Text}");
}
// Multi-page TIFF — all frames processed in one call
using (var input = new OcrInput())
{
input.LoadImageFrames("scanned-archive.tiff");
var result = ocr.Read(input);
Console.WriteLine($"TIFF pages: {result.Pages.Count}");
foreach (var page in result.Pages)
Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
}
Wzorzec plików tymczasowych dla tablic bajtów w XImage.OCR jest częstym źródłem nadmiernego obciążenia dysku i wycieku plików w ścieżkach błędów. LoadImage(byte[]) w IronOCR eliminuje całkowicie pośredni plik. Przewodnik dotyczący obrazów oraz przewodnik dotyczący plików TIFF/GIF obejmują wszystkie obsługiwane typy źródeł, w tym strumienie i przetwarzanie wielu klatek.
Usprawnienie formatu wyjściowego
XImage.OCR zwraca zwykły ciąg znaków. Generowanie pliku PDF z możliwością wyszukiwania wymaga drugiego produktu RasterEdge.IronOCR generuje zwykły tekst, pliki PDF z możliwością wyszukiwania oraz dane strukturalne z tego samego obiektu wynikowego bez dodatkowych pakietów.
Podejście XImage.OCR:
// XImage.OCR: plain text output only
// Searchable PDF requires purchasing the RasterEdge PDF SDK separately
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
string plainText = ocrHandler.Process("scanned-contract.jpg");
// To produce a searchable PDF from this text, you would need:
// 1. Purchase RasterEdge PDF SDK (separate commercial license)
// 2. Create a PDF document programmatically
// 3. Embed the extracted text as invisible text layer over the image
// 4. Manage the PDF document lifecycle manually
// Nie built-in path from OCR result to searchable PDF in XImage.OCR alone
Console.WriteLine(plainText);
Podejście IronOCR:
// IronOCR: plain text, searchable PDF, and structured data from one result
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("scanned-contract.jpg");
var result = ocr.Read(input);
// Plain text
Console.WriteLine(result.Text);
// Searchable PDF — no extra package required
result.SaveAsSearchablePdf("searchable-contract.pdf");
// Structured data: paragraphs with bounding box coordinates
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}");
}
}
// Per-word confidence for quality gating
var lowConfidenceWords = result.Pages
.SelectMany(p => p.Words)
.Where(w => w.Confidence < 70)
.ToList();
Console.WriteLine($"Words below 70% confidence: {lowConfidenceWords.Count}");
Wywołanie SaveAsSearchablePdf() osadza rozpoznany tekst jako ukrytą warstwę pod oryginalnym obrazem, co sprawia, że dokument jest w pełni przeszukiwalny tekstowo bez zmiany jego wyglądu. W instrukcji w formacie PDF z funkcją wyszukiwania omówiono opcje zakresu stron i ustawienia DPI. W przypadku wzorców ekstrakcji danych strukturalnych przewodnik odczytu wyników dokumentuje pełną hierarchię OcrResult, w tym współrzędne słów i dostęp do ocen pewności. Przykładowy plik PDF z funkcją wyszukiwania zawiera kompletną, działającą implementację.
Przetwarzanie dokumentów w trybie wsadowym
XImage.OCR nie jest bezpieczny dla wątków. Każdy współbieżny wątek roboczy musi utworzyć własną instancję OCRHandler, zwiększając zużycie pamięci przez ilość wątków.IronOCR wykorzystuje jedną wspólną instancję dla wszystkich wątków.
Podejście XImage.OCR:
// XImage.OCR: one handler per thread — memory multiplies with concurrency
// 4 threads processing English documents: 4 x ~100MB = ~400MB for OCR alone
// 4 threads processing 5 languages: 4 x ~250MB = ~1GB just for OCR handlers
var results = new ConcurrentDictionary<string, string>();
string[] documentPaths = Directory.GetFiles("./incoming", "*.png");
Parallel.ForEach(documentPaths,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
documentPath =>
{
// Each thread must create and dispose its own handler
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
try
{
string text = ocrHandler.Process(documentPath);
results[documentPath] = text;
}
finally
{
// Podręcznik disposal required — no using statement support shown
ocrHandler.Dispose();
}
});
foreach (var kvp in results)
Console.WriteLine($"{Path.GetFileName(kvp.Key)}: {kvp.Value.Length} chars");
Podejście IronOCR:
// IronOCR: single IronTesseract instance shared across all threads
// Memory stays flat regardless of thread count
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract(); // Create once outside the parallel loop
var results = new ConcurrentDictionary<string, string>();
string[] documentPaths = Directory.GetFiles("./incoming", "*.png");
Parallel.ForEach(documentPaths, documentPath =>
{
// OcrInput is created per thread — IronTesseract instance is shared
using var input = new OcrInput();
input.LoadImage(documentPath);
input.Deskew(); // Preprocessing runs per-document, not per-thread engine
input.DeNoise();
var result = ocr.Read(input);
results[documentPath] = result.Text;
});
foreach (var kvp in results)
Console.WriteLine($"{Path.GetFileName(kvp.Key)}: {kvp.Value.Length} chars");
Wzorzec obsługi XImage.OCR na wątek oznacza, że czterowątkowe zadanie wsadowe obsługujące pięć języków zajmuje około 1 GB pamięci obsługi OCR przed przetworzeniem pojedynczego dokumentu. Współdzielona instancja IronOCR ogranicza zużycie pamięci do rozmiaru pojedynczej instancji, niezależnie od stopnia równoległości. Przykład wielowątkowości w pełni ilustruje ten wzorzec, a przewodnik po optymalizacji szybkości obejmuje dostosowywanie konfiguracji dla obciążeń wsadowych zorientowanych na przepustowość.
Wydobywanie BarCode i tekstu łącznie
XImage.OCR nie posiada funkcji odczytu kodów BarCode. Dokumenty zawierające zarówno tekst, jak i BARCODES wymagają dwóch oddzielnych bibliotek i dwóch oddzielnych przejść.IronOCR wyodrębnia oba elementy w ramach jednej operacji odczytu.
Podejście XImage.OCR:
// XImage.OCR: text only — barcodes require a separate library and second pass
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
// Pass 1: text extraction with XImage.OCR
string documentText = ocrHandler.Process("warehouse-label.png");
Console.WriteLine($"Text: {documentText}");
// Pass 2: barcode reading requires a completely separate library
// e.g., ZXing.Net, Dynamsoft Barcode Reader, or another commercial SDK
// - Additional NuGet package required
// - Additional license required
// - Additional code for result merging
// Nie combined text + barcode result object exists in XImage.OCR
Podejście IronOCR:
// IronOCR: text and barcodes from a single Read() call
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
ocr.Configuration.ReadBarCodes = true; // Enable barcode extraction
using var input = new OcrInput();
input.LoadImage("warehouse-label.png");
var result = ocr.Read(input);
// Text and barcodes in one result object
Console.WriteLine($"Document text:\n{result.Text}");
if (result.Barcodes.Any())
{
Console.WriteLine($"\nBarcodes found: {result.Barcodes.Count}");
foreach (var barcode in result.Barcodes)
Console.WriteLine($" [{barcode.BarcodeType}] {barcode.Value}");
}
Ustawienie ReadBarCodes = true dodaje wykrywanie kodów kreskowych do przetwarzania, bez konieczności stosowania drugiej biblioteki lub drugiego odczytu. Poradnik odczytu kodów kreskowych i przykład OCR kodów kreskowych obejmują obsługiwane formaty kodów kreskowych oraz opcje konfiguracyjne dla dokumentów o mieszanej zawartości.
Odnośnik do dokumentacji API XImage.OCR do IronOCR
| XImage.OCR | Odpowiednik IronOCR |
|---|---|
new OCRHandler() | new IronTesseract() |
RasterEdge.XImage.OCR.License.LicenseManager.SetLicense("key") | IronOcr.License.LicenseKey = "key" |
ocrHandler.Language = "eng" | ocr.Language = OcrLanguage.English |
ocrHandler.Languages = new[] { "eng", "deu" } | ocr.Language = OcrLanguage.English + OcrLanguage.German |
ocrHandler.Process(imagePath) | ocr.Read(input).Text (po input.LoadImage(path)) |
ocrHandler.Process(image) (z obiektu) | input.LoadImage(bytes) lub input.LoadImage(stream) |
ocrHandler.ProcessRegion(path, rect) | input.LoadImage(path, new CropRectangle(x, y, w, h)) |
ocrHandler.SetVariable("tessedit_char_whitelist", "0-9") | ocr.Configuration.WhiteListCharacters = "0123456789" |
result (czysty string) | result.Text |
result.MeanConfidence | result.Confidence |
| Brak odpowiednika | result.Pages / result.Paragraphs / result.Lines |
| Brak odpowiednika | result.Words (z .X, .Y, .Confidence) |
| Brak odpowiednika | result.SaveAsSearchablePdf("output.pdf") |
| Brak odpowiednika | input.Deskew() |
| Brak odpowiednika | input.DeNoise() |
| Brak odpowiednika | input.Contrast() |
| Brak odpowiednika | input.Binarize() |
| Brak odpowiednika | input.Sharpen() |
| Brak odpowiednika | input.LoadImageFrames("file.tiff") (wieloklatkowy) |
| Wymagane jest RasterEdge PDF SDK | input.LoadPdf(pdfPath) |
| Wymagane jest RasterEdge PDF SDK | result.SaveAsSearchablePdf("output.pdf") |
| Niedostępne | ocr.Configuration.ReadBarCodes = true |
Instancje OCRHandler na wątek | Pojedyncza współdzielona instancja IronTesseract |
Typowe problemy związane z migracją i ich rozwiązania
Problem 1: Błędy uruchomieniowe po częściowej aktualizacji pakietu
XImage.OCR: Uruchomienie dotnet outdated lub dotnet restore z przestarzałą pamięcią podręczną pakietów może doprowadzić RasterEdge.XImage.OCR do nowej wersji, pozostawiając pakiety językowe w poprzedniej wersji. Błąd występuje w czasie wykonywania podczas pierwszego wywołania OCR, a komunikat o błędzie nie wskazuje wyraźnie, że przyczyną jest niezgodność wersji. Znalezienie rozbieżności wymaga ręcznego sprawdzenia wszystkich wpisów PackageReference.
Rozwiązanie: Po usunięciu pakietów XImage.OCR i zainstalowaniu IronOCR nie ma potrzeby synchronizacji wersji. Pojedynczy pakiet IronOcr zawiera wszystko. Jeśli potrzebujesz pakietów językowych poza domyślnymi, zainstaluj IronOcr.Languages.* pakiety niezależnie — nie muszą one odpowiadać wersji rdzenia:
Problem 2: Kody języków w ciągach znaków powodują ciche błędy OCR
XImage.OCR: Kody językowe to strings ("eng", "deu", "fra"). Literówka w kodzie językowym — "engg", "ger" zamiast "deu" — albo cicho wraca do domyślnego języka, albo zgłasza wyjątek w czasie wykonania w zależności od wersji XImage.OCR. Żadna z tych sytuacji nie jest wykrywana w czasie kompilacji.
**Rozwiązanie:**IronOCR używa OcrLanguage enum. Nieprawidłowe wartości to błędy kompilacji, a nie niespodzianki w czasie wykonywania. Przeniesienie tablic ciągów znaków do wyrażeń enum:
// Before (XImage.OCR) — typos compile fine, fail at runtime
ocrHandler.Languages = new[] { "eng", "deu", "fra" };
// After (IronOCR) — typos are compile errors
ocr.Language = OcrLanguage.English + OcrLanguage.German + OcrLanguage.French;
Zapoznaj się z przewodnikiem dotyczącym wielu języków, aby dowiedzieć się, jak łączyć języki główne i dodatkowe w dokumentach zawierających treści w różnych językach.
Problem 3: Pliki tymczasowe pozostawione na dysku po przetwarzaniu tablicy bajtów
XImage.OCR: Przetwarzanie obrazów z tablicy bajtów wymaga zapisu pliku tymczasowego, ponieważ OCRHandler.Process() akceptuje ścieżkę do pliku, a nie bufor. Ścieżki wyjątków, które omijają blok finally, pozostawiają te pliki tymczasowe na dysku. W aplikacjach o dużej przepustowości szybko się to kumuluje.
Rozwiązanie: OcrInput.LoadImage() akceptuje bezpośrednio byte[]. Nie jest tworzony żaden plik tymczasowy:
// Before (XImage.OCR) — temp file required
string tempPath = Path.GetTempFileName() + ".png";
File.WriteAllBytes(tempPath, imageBytes);
try { text = ocrHandler.Process(tempPath); }
finally { File.Delete(tempPath); }
// After (IronOCR) — direct byte array loading, no disk I/O
using var input = new OcrInput();
input.LoadImage(imageBytes);
var result = ocr.Read(input);
string text = result.Text;
Problem 4: Wyczerpanie pamięci przy obciążeniu równoległym
XImage.OCR: Przetwarzanie równoległe wymaga jednego OCRHandler na wątek. Osiem wątków przetwarzających dokumenty w pięciu językach ładuje osiem oddzielnych instancji silnika, z których każda zawiera wszystkie pięć pakietów językowych. Przy około 50 MB na język na instancję, osiem wątków zużywa około 2 GB pamięci silnika OCR, zanim pojawią się jakiekolwiek dane dokumentu.
Rozwiązanie: Jedna instancja IronTesseract obsługuje wszystkie wątki. Utwórz OcrInput na dokument (jest to zasób jednorazowy i lekki), używaj ponownie IronTesseract przez czas trwania aplikacji:
// Single instance — shared safely across all threads
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English + OcrLanguage.German +
OcrLanguage.French + OcrLanguage.Spanish + OcrLanguage.Italian;
Parallel.ForEach(documentPaths, path =>
{
using var input = new OcrInput(); // Per-document, lightweight
input.LoadImage(path);
var result = ocr.Read(input); // Thread-safe call on shared instance
ProcessResult(result.Text);
});
Problem 5: Przerwanie działania potoku CI/CD po częściowym przywróceniu
XImage.OCR: Agent CI/CD z podgrzaną pamięcią podręczną pakietów często ma w pamięci podręcznej pakiety językowe OCR w starej wersji. Gdy w pliku projektu zaktualizowano tylko pakiet podstawowy, przywracanie przebiega pomyślnie, ale środowisko uruchomieniowe ładuje niezgodne zestawy. Kompilacja przebiega pomyślnie; wdrożenie kończy się niepowodzeniem.
Rozwiązanie: Po migracji do IronOCR potok CI/CD przywraca jeden pakiet. Dodaj etap weryfikacji, aby potwierdzić obecność oczekiwanej wersji:
# In your CI pipeline — verify single package restore
dotnet restore
dotnet list package | grep IronOcr
# Nie version coordination logic needed — only one package to check
Problem 6: Brak danych strukturalnych do dalszego parsowania
XImage.OCR: Zwraca zwykły ciąg znaków. Aplikacje, które potrzebują informacji o pozycjach słów, grupach wierszy lub pewności dla poszczególnych słów, muszą analizować ciąg znaków przy użyciu heurystyki spacji lub niestandardowej logiki. Dokładność parsowania pogarsza się w przypadku dokumentów o układzie wielokolumnowym, zawierających tabele lub tekst obrócony.
Rozwiązanie: OcrResult w IronOCR bezpośrednio udostępnia pełną hierarchię dokumentów. Nie jest wymagana analiza ciągów znaków:
var result = ocr.Read(input);
// Direct access to structured data — no string manipulation
foreach (var page in result.Pages)
{
foreach (var line in page.Lines)
{
// Line text, bounding box, and per-word data all available
Console.WriteLine($"Line [{line.X},{line.Y}]: {line.Text}");
foreach (var word in line.Words)
Console.WriteLine($" Word '{word.Text}' confidence: {word.Confidence}%");
}
}
Aby uzyskać pełny opis API danych strukturalnych, zapoznaj się z instrukcją odczytu wyników oraz stroną poświęconą funkcjom wyników OCR.
Lista kontrolna migracji XImage.OCR
Przed migracją
Przed wprowadzeniem zmian należy przeprowadzić audyt kodu źródłowego w celu znalezienia wszystkich punktów styku z XImage.OCR:
# Find all XImage.OCR namespace imports
grep -r "RasterEdge.XImage.OCR\|Yiigo.Image.Ocr\|XImage.OCR" --include="*.cs" .
# Find all OCRHandler usages
grep -r "OCRHandler\|ocrHandler" --include="*.cs" .
# Find all string-based language assignments
grep -r "\.Language\s*=\s*\"" --include="*.cs" .
grep -r "\.Languages\s*=\s*new\[\]" --include="*.cs" .
# Find all XImage.OCR package references in project files
grep -r "RasterEdge.XImage.OCR\|XImage.OCR.Language" --include="*.csproj" .
# Count distinct language packs installed
grep "XImage.OCR.Language" --include="*.csproj" -r . | wc -l
Zwróć uwagę, jakie typy źródeł obrazów są używane (ścieżki do plików, tablice bajtów, strumienie, TIFF), i zidentyfikuj wszystkie miejsca, w których używane są pliki tymczasowe do przetwarzania tablic bajtów. Są to priorytetowe elementy wymagające poprawek.
Migracja kodu
- Usuń wszystkie odniesienia do pakietów
RasterEdge.XImage.OCRiXImage.OCR.Language.*z każdego pliku.csproj - Dodaj odniesienie do pakietu
IronOcr(dotnet add package IronOcr) - Zamień
using RasterEdge.XImage.OCRnausing IronOcrwe wszystkich plikach - Dodaj
IronOcr.License.LicenseKey = ...przy uruchomieniu aplikacji (raz na proces) - Zamień
new OCRHandler()nanew IronTesseract() - Zamień przypisania językowe w postaci stringów (
"eng","deu") na wartości enumOcrLanguage - Zamień
ocrHandler.Process(path)nainput.LoadImage(path)+ocr.Read(input).Text - Zamień wzorce tablica-bajtów-plik-tymczasowy na
input.LoadImage(byte[]) - Zamień ręczne dzielenie klatek w wielostronicowych plikach TIFF na
input.LoadImageFrames("file.tiff") - Usuń tworzenie instancji
OCRHandlerna wątek zParallel.ForEachpętli — użyj jednej współdzielonej instancjiIronTesseract - Dodaj wywołania przetwarzania wstępnego (
input.Deskew(),input.DeNoise()) po każdejLoadImage()dla dokumentów z różnych źródeł jakościowych - Zamień obsługę wyników w postaci stringów na
result.Textdla tekstu lubresult.SaveAsSearchablePdf()dla wyjścia PDF - Zamień
ocrHandler.SetVariable("tessedit_char_whitelist", ...)naocr.Configuration.WhiteListCharacters = ... - Zaktualizuj potok CI/CD: usuń kroki przywracania wielu pakietów, usuń logikę synchronizacji wersji, zweryfikuj przywrócenie pojedynczego pakietu
IronOcr
Po migracji
- Sprawdź, czy podstawowe wyodrębnianie tekstu daje poprawny wynik na znanym, dobrym obrazie testowym
- Sprawdź, czy dokumenty wielojęzyczne zwracają tekst dla wszystkich skonfigurowanych języków
- Testowe ścieżki wejściowe tablicy bajtów generują poprawny wynik bez tworzenia plików tymczasowych na dysku
- Potwierdź, że dokumenty wielostronicowe TIFF zwracają poprawną liczbę stron w
result.Pages - Uruchom równoległe przetwarzanie wsadowe pod obciążeniem i zmierz szczytowe zużycie pamięci — powinno być znacznie niższe niż wartość bazowa XImage.OCR
- Sprawdź, czy plik PDF z możliwością wyszukiwania otwiera się poprawnie w programie Adobe Acrobat lub przeglądarce plików PDF oraz czy tekst można zaznaczyć
- Przetestuj przetwarzanie wstępne na skanie niskiej jakości lub zniekształconym i porównaj dokładność wyodrębnionego tekstu z wartością odniesienia XImage.OCR
- Sprawdź, czy inicjalizacja klucza licencyjnego przebiega przed pierwszym wywołaniem OCR i nie powoduje wyjątku
- Sprawdź, czy przywracanie CI/CD przebiega pomyślnie w czystym środowisku bez pakietów w pamięci podręcznej
- Sprawdź, czy strukturalne wyjście danych (
result.Words,result.Paragraphs) odpowiada oczekiwanej strukturze dokumentu
Kluczowe korzyści z migracji do IronOCR
Pojedynczy pakiet zastępuje całą zależność grafu. Każdy pakiet XImage.OCR.Language.*, rdzeń RasterEdge.XImage.OCR pakiet, i nadmiar synchronizacji wersji między nimi, kolapsuje do jednego polecenia dotnet add package IronOcr. Liczba wpisów .csproj spada z jedenastu do jednego. Etap przywracania w ramach CI/CD zmienia się z operacji obejmującej wiele pakietów z jedenastoma niezależnymi punktami awarii na przywracanie pojedynczego pakietu. To uproszczenie ma wiele zalet: mniej pakietów do sprawdzania pod kątem luk w zabezpieczeniach, mniej wpisów do aktualizacji w przypadku zmian w kompatybilności .NET oraz brak konieczności utrzymywania logiki koordynacji wersji w zautomatyzowanych procesach aktualizacji. Strona produktu IronOCR oraz centrum dokumentacji zawierają pełny opis funkcji i wskazówki dotyczące wdrażania.
Poprawa dokładności przetwarzania wstępnego jest natychmiastowa. Migracja nie jest zwykłą zamianą — to ulepszenie dokładności. Każdy dokument przetworzony przez XImage.OCR z obniżoną dokładnością z powodu pochylenia, szumu lub niskiej rozdzielczości, teraz ma bezpośrednią drogę do poprawy dzięki input.Deskew(), input.DeNoise() i input.Contrast(). Brak zewnętrznej biblioteki do przetwarzania obrazów, brak wiedzy specjalistycznej w zakresie przetwarzania obrazów w zespole programistów, brak oddzielnych zależności wymagających licencjonowania i utrzymania. Dodanie trzech linii po LoadImage() przywraca od 20 do 35 punktów procentowych dokładności w dokumentach zeskanowanych, które wcześniej były akceptowane jako "wystarczająco dobre". Przewodnik korekcji jakości obrazu i strona funkcji przetwarzania wstępnego obejmują wpływ różnych filtrów na różne scenariusze jakości dokumentu.
PDF-y z funkcją wyszukiwania i dane ustrukturyzowane eliminują koszty związane z drugim zestawem SDK. Dwa najczęstsze żądania użytkowników XImage.OCR — pliki PDF z funkcją wyszukiwania oraz dane na poziomie słów z współrzędnymi — wymagają dodatkowych produktów RasterEdge, które wiążą się z oddzielnymi licencjami komercyjnymi. Po migracji result.SaveAsSearchablePdf() produkuje dokumenty przeszukiwalne o jakości archiwalnej bez dodatkowych pakietów, a result.Words zapewniają dane strukturalne z ramkami i ocenami pewności. Funkcjonalność, która wcześniej wymagała dwóch licencji, jest teraz dostępna w ramach jednej. Pełna dokumentacja formatu wyjściowego znajduje się na stronie funkcji wyników OCR.
Przetwarzanie równoległe skaluje się bez utraty pamięci. Model obsługi na wątek w XImage.OCR sprawia, że skalowanie jest kosztowne. Podwojenie liczby wątków podwaja ilość pamięci zużywanej przez instancje silnika OCR. Model współdzielonej instancji IronOCR oznacza, że pamięć pozostaje ograniczona do rozmiaru pojedynczej instancji, niezależnie od stopnia równoległości. Serwer przetwarzający partie dokumentów w ośmiu równoległych wątkach zużywa tyle samo pamięci silnika OCR, co serwer przetwarzający po jednym dokumencie na raz. Przekłada się to bezpośrednio na niższe koszty hostingu i większy zapas przepustowości w ramach stałej infrastruktury.
Wdrożenie Cross-Platform otwiera się bez zmian w kodzie. Ten sam pakiet IronOcr i ten sam kod aplikacji działają na Windows, Linux, macOS, Docker, Azure App Service i AWS Lambda. Brak kodu uzależnionego od platformy, brak wariantów pakietów specyficznych dla platformy, brak testów wdrożeniowych warstwy OCR w poszczególnych środowiskach. Zespoły, które konteneryzują obciążenia, korzystają ze środowisk programistycznych macOS lub wdrażają rozwiązania w infrastrukturze chmurowej opartej na systemie Linux, zyskują natychmiastową kompatybilność. Przewodnik wdrażania Docker, przewodnik wdrażania Azure oraz przewodnik wdrażania Linux dokumentują konfigurację dla każdego środowiska docelowego.
Ponad 125 języków znosi ograniczenia dotyczące obsługiwanych języków. XImage.OCR oferuje maksymalnie około piętnastu języków dostępnych w pakietach komercyjnych. Standardowe dystrybucje tessdata obejmują ponad 100 języków bez dodatkowych kosztów.IronOCR dostarcza ponad 125 języków i udostępnia je poprzez opcjonalne pakiety IronOcr.Languages.*, które stosują czysty wzorzec instalacji bez wymogu synchronizacji wersji. Dostępnych jest 24 języków urzędowych UE, wszystkie główne języki chińskie, japońskie i koreańskie, arabski, hebrajski oraz specjalistyczne alfabety. Indeks języków zawiera listę wszystkich obsługiwanych języków wraz z odpowiadającymi im nazwami pakietów.
