Migracja z RapidOCR.NET do IronOCR
Ten przewodnik obejmuje pełną ścieżkę migracji z RapidOCR.NET (RapidOcrNet) do IronOCR dla programistów .NET, którzy muszą wyeliminować zarządzanie plikami modelu ONNX z ich kanału OCR. Przechodzi przez zamienianie pakietów, tłumaczenie kodu i zmiany operacyjne, które następują, gdy zewnętrzne zależności modelu są całkowicie usunięte.
Dlaczego warto przejść z RapidOCR.NET
RapidOCR.NET działa — w wąskim zakresie zastosowań, w kontrolowanych środowiskach, gdzie ktoś już rozwiązał problem dystrybucji modelu. Gdy którykolwiek z tych warunków ulegnie zmianie, ograniczenia architektoniczne biblioteki stają się kosztami inżynieryjnymi.
Pliki modelu ONNX to artefakt wdrożenia, nie pakiet. RapidOCR.NET wymaga czterech zewnętrznych plików — det.onnx, cls.onnx, rec.onnx i słownik znaków — zanim można rozpoznać pojedynczy znak. Pliki te nie są dołączone do pakietu NuGet. Znajdują się one na stronach wydania GitHub, wymagają ręcznego pobrania, wyraźnej konfiguracji ścieżki w kodzie oraz niestandardowych reguł MSBuild do skopiowania podczas kompilacji. Każdy nowy programista, każdy proces CI, każde środowisko wdrożeniowe powtarza tę procedurę.
Zmiana języka oznacza wymianę pliku, a nie konfigurację. Zmiana z angielskiego OCR na chiński OCR w RapidOCR.NET wymaga pobrania innego modelu rozpoznawania i innego słownika znaków, a następnie przebudowy instancji silnika. W katalogu modeli RapidOCR nie ma w ogóle modeli dla języków hiszpańskiego, francuskiego, niemiećkiego, rosyjskiego, arabskiego i ponad 100 innych języków. Aplikacja, która musi przetwarzać dokumenty w różnych językach, nie ma w RapidOCR.NET realnej możliwości obsługi tych języków, które nie są obsługiwane.
Aktualizacje wersji modeli wymagają ręcznej interwencji. Gdy projekt RapidOCR udostępnia ulepszone wagi modeli, zespoły muszą pobrać nowe pliki, zastąpić nimi pliki w każdym środowisku, zweryfikować ścieżki i ponownie wdrożyć. Nie ma etapu przywracania pakietu, który obsługuje to automatycznie. W środowisku wielosystemowym, obejmującym środowisko programistyczne, testowe i produkcyjne, propagacja ta jest za każdym razem operacją ręczną.
Zależność ONNX Runtime zwiększa złożoność platformy. RapidOCR.NET zależy od Microsoft.ML.OnnxRuntime, pakietu z natywnymi binariami specyficznymi dla platformy. Warianty z procesorem CPU i GPU wymagają różnych pakietów. Obraz kontenera zbudowany dla linux/amd64 wymaga innych binariów niż ten zbudowany dla linux/arm64. Każdy cel wdrożenia wymaga sprawdzenia, czy dostępna jest właściwa wersja środowiska uruchomieniowego i czy jest ona zgodna z zainstalowanymi plikami modeli.
Opóźnienie przy zimnym starcie i zużycie pamięci to koszty stałe. Ładowanie trzech modeli ONNX podczas uruchamiania trwa 2–5 sekund i zajmuje 300–500 MB pamięci na czas trwania procesu. Koszt ten jest ponoszony niezależnie od wielkości przetwarzania OCR, co sprawia, że biblioteka ta nie nadaje się do funkcji bezserwerowych, lekkich kontenerów lub usług o niskim natężeniu ruchu, gdzie koszt uruchomienia jest nieproporcjonalny do przepustowości.
Brak komercyjnego wsparcia technicznego. RapidOCR.NET jest utrzymywany przez jednego programistę społecznościowego na licencji Apache 2.0. Incydenty produkcyjne — konflikty wersji ONNX Runtime, błędy wnioskowania w przypadku nietypowych formatów obrazów, wzrost zużycia pamięci przy długotrwałym obciążeniu — trafiają do kolejki zgłoszeń na GitHubie bez gwarantowanego terminu odpowiedzi i bez umowy SLA.
Podstawowy problem
Trzy pliki modeli ONNX Plus oraz słownik znaków, wszystkie pobrane osobno, wszystkie skonfigurowane według ścieżki:
// RapidOcrNet: 4 external files required before any OCR can execute
var engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = "./models/det.onnx", // ~3 MB — downloaded from GitHub
ClsModelPath = "./models/cls.onnx", // ~1 MB — downloaded from GitHub
RecModelPath = "./models/rec_en.onnx", // ~2-10 MB — language-specific download
KeysPath = "./models/en_keys.txt" // character dictionary — language-specific
});
IronOCR nie wymaga plików modeli, konfiguracji ścieżek ani pobierania:
// IronOCR: install the NuGet package, write one line
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
##IronOCR vs RapidOCR.NET: Porównanie funkcji
IronOCR i RapidOCR.NET pokrywają się w zakresie podstawowego OCR obrazów. Luka pojawia się w każdej kwestii z tym związanej.
| Funkcja | RapidOCR.NET | IronOCR |
|---|---|---|
| Instalacja NuGet | Tak (RapidOcrNet) | Tak (IronOcr) |
| Wymagane zewnętrzne pliki modeli | Tak (4 pliki, ręczne pobieranie) | Nie |
| Wymagana konfiguracja ścieżki | Tak | Nie |
| Wymagane reguły kopiowania MSBuild | Tak | Nie |
| Działa natychmiast po instalacji z NuGet | Nie | Tak |
| Zależność od środowiska uruchomieniowego ONNX | Tak (~30–50 MB) | Nie |
| Obsługiwane języki | ~5 (tylko CJK + angielski) | Ponad 125 pakietów językowych dostępnych za pośrednictwem NuGet |
| Zmiana języka | Wymiana plików + przebudowa silnika | Przypisanie właściwości |
| Obsługa języków europejskich | Nie | Tak (30+) |
| Obsługa języków arabskiego i hebrajskiego | Nie | Tak |
| Obsługa cyrylicy (rosyjski, ukraiński) | Nie | Tak |
| Natywne wprowadzanie plików PDF | Nie | Tak |
| Plik PDF chroniony hasłem | Nie | Tak |
| Wynik w formacie PDF z możliwością wyszukiwania | Nie | Tak |
| Wielostronicowy plik wejściowy w formacie TIFF | Nie | Tak |
| Wejście strumieniowe i tablica bajtów | Ograniczone | Tak |
| Wbudowane przetwarzanie wstępne obrazów | Nie | Tak (filtry automatyczne + ręczne) |
| Filtry Deskew / DeNoise / Contrast | Nie | Tak |
| Strukturalny format wyjściowy (akapity, wiersze, słowa) | Częściowe (tylko bloki) | Tak, z współrzędnymi |
| Wyniki pewności dla poszczególnych słów | Tak (na blok) | Tak |
| Odczytywanie BarCode podczas OCR | Nie | Tak |
| eksport hOCR | Nie | Tak |
| Przetwarzanie równoległe bezpieczne dla wątków | Ograniczone | Tak (jedna instancja na wątek) |
| Wdrażanie wielopłatformowe | Wymagane są pliki binarne ONNX Runtime dla każdej platformy | Tak (Windows, Linux, macOS, Docker) |
| Wdrożenie Docker | Wymagane instrukcje dotyczące modelu ręcznego COPY | Gotowe do użycia |
| Obstawę przy zimnym starcie | 2–5 sekund (ładowanie modelu) | Minimalne |
| Wsparcie komercyjne | Nie | Tak |
| Licencja | Apache 2.0 (bezpłatna) | Perpetual ($999 Lite, $1,499 Pro, $2,999 Enterprise) |
Szybki start: Migracja z RapidOCR.NET do IronOCR
Krok 1: Zastąp pakiet NuGet
Usuń RapidOCR.NET i zależność od ONNX Runtime:
dotnet remove package RapidOcrNet
dotnet remove package Microsoft.ML.OnnxRuntime
Zainstaluj IronOCR z NuGet:
Krok 2: Aktualizacja przestrzeni nazw
Zastąp przestrzeń nazw RapidOCR.NET przestrzenią nazw IronOCR:
// Before (RapidOCR.NET)
using RapidOcrNet;
// After (IronOCR)
using IronOcr;
Krok 3: Inicjalizacja licencji
Dodaj inicjalizację licencji przy starcie aplikacji, przed jakimikolwiek wywołaniami IronTesseract:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"Bezpłatny klucz próbny jest dostępny na stronie licencyjnej IronOCR.
Przykłady migracji kodu
Usunięcie konfiguracji ścieżki modelu ONNX
Najbardziej mechaniczna zmiana w tej migracji to usunięcie bloku konfiguracyjnego RapidOcrOptions i zastąpienie go konstruktorem bez argumentów.
Podejście RapidOCR.NET:
using RapidOcrNet;
// Startup validation — written because a missing model crashes at runtime, not at install
private static void EnsureModelsPresent(string modelDir)
{
var required = new[]
{
Path.Combine(modelDir, "det.onnx"),
Path.Combine(modelDir, "cls.onnx"),
Path.Combine(modelDir, "rec_en.onnx"),
Path.Combine(modelDir, "en_keys.txt")
};
var missing = required.Where(f => !File.Exists(f)).ToList();
if (missing.Any())
throw new FileNotFoundException(
$"Missing model files: {string.Join(", ", missing)}\n" +
"Download from: https://github.com/RapidAI/RapidOCR/releases");
}
// Engine factory — called once at startup, held for lifetime of service
public RapidOcrEngine CreateEngine(string modelDir)
{
EnsureModelsPresent(modelDir);
return new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"),
ClsModelPath = Path.Combine(modelDir, "cls.onnx"),
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(modelDir, "en_keys.txt"),
UseGpu = false,
NumThreads = Environment.ProcessorCount
});
}
Podejście IronOCR:
using IronOcr;
// Nie model validation, no path configuration, no GPU flags
// IronTesseract is thread-safe; create one per thread or on demand
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
Cała metoda walidacji EnsureModelsPresent, obiekt konfiguracyjny RapidOcrOptions i klasa fabryki silników mogą zostać usunięte. Nie ma plików modelowych do sprawdzenia, ponieważIronOCR dostarcza swój silnik wewnętrznie jako część pakietu NuGet. Podręcznik konfiguracji IronTesseract szczegółowo opisuje opcje inicjalizacji oraz umieszczenie klucza licencyjnego.
Konsolidacja procesu wykrywania, klasyfikacji i rozpoznawania
RapidOCR.NET uruchamia trzyetapowy potok ONNX — wykrywanie, klasyfikację kierunku, a następnie rozpoznawanie — i zwraca nieuporządkowaną płaską listę bloków tekstu, które wywołujący musi posortować i złożyć.IronOCR udostępnia jedną wywołanie .Read() wspierane przez wewnętrzny silnik Tesseract 5, zwracając uporządkowane strukturalnie dane wyjściowe zgodnie z kolejnością czytania.
Podejście RapidOCR.NET:
using RapidOcrNet;
public class InvoiceTextExtractor
{
private readonly RapidOcrEngine _engine;
public InvoiceTextExtractor(string modelDir)
{
// Three separate ONNX models run in sequence on every call
_engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"), // Stage 1: detect text regions
ClsModelPath = Path.Combine(modelDir, "cls.onnx"), // Stage 2: classify direction
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),// Stage 3: recognize characters
KeysPath = Path.Combine(modelDir, "en_keys.txt")
});
}
public string ExtractInvoiceText(string imagePath)
{
var result = _engine.Run(imagePath);
// Blocks are unordered — must sort by vertical position, then horizontal
var orderedBlocks = result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.ThenBy(b => b.BoundingBox.Left)
.ToList();
// Manual assembly — no paragraph or line structure
return string.Join(Environment.NewLine,
orderedBlocks.Select(b => b.Text));
}
}
Podejście IronOCR:
using IronOcr;
public class InvoiceTextExtractor
{
private readonly IronTesseract _ocr = new IronTesseract();
public string ExtractInvoiceText(string imagePath)
{
// Single call — detection, recognition, reading order all internal
var result = _ocr.Read(imagePath);
return result.Text; // Already in reading order
}
public IEnumerable<string> ExtractInvoiceParagraphs(string imagePath)
{
var result = _ocr.Read(imagePath);
// Structured paragraphs with coordinates — no sorting or assembly needed
foreach (var page in result.Pages)
foreach (var paragraph in page.Paragraphs)
yield return paragraph.Text;
}
}
Trzyetapowy proces jest w całości realizowany wewnętrznie przez IronOCR. Lista result.TextBlocks z jej ręcznym łańcuchem OrderBy zbiega się do result.Text. Dla wywołujących potrzebujących danych o obszarze ograniczającym z TextBlocks, kolekcje result.Pages[i].Paragraphs, .Lines i .Words dostarczają równoważne współrzędne poprzez ustrukturyzowane API. Dokumentacja dotycząca instrukcji obsługi wyników odczytu oraz funkcji wyników OCR przedstawia pełny model wyników w formacie strukturalnym.
Zastąpienie ładowania modelu niestandardowego
Aplikacje, które muszą przełączać konfiguracje OCR w trakcie działania — na przykład kierując dokumenty przez różne parametry rozpoznawania w zależności od rodzaju dokumentu — muszą odbudować cały RapidOcrEngine w RapidOCR.NET, ponieważ konfiguracja jest związana z konstruktorem.IronOCR udostępnia konfigurację silnika jako właściwości, które można dostosowywać dla każdego odczytu w ramach pojedynczej instancji.
Podejście RapidOCR.NET:
using RapidOcrNet;
public class DocumentRouter
{
private readonly string _modelDir;
public DocumentRouter(string modelDir) => _modelDir = modelDir;
// Must create separate engine instances per configuration
// Each engine holds ~300-500 MB of loaded model weights
private RapidOcrEngine BuildEnglishEngine() =>
new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(_modelDir, "det.onnx"),
ClsModelPath = Path.Combine(_modelDir, "cls.onnx"),
RecModelPath = Path.Combine(_modelDir, "en_rec.onnx"),
KeysPath = Path.Combine(_modelDir, "en_keys.txt")
});
private RapidOcrEngine BuildChineseEngine() =>
new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(_modelDir, "det.onnx"),
ClsModelPath = Path.Combine(_modelDir, "cls.onnx"),
RecModelPath = Path.Combine(_modelDir, "ch_rec.onnx"), // separate download
KeysPath = Path.Combine(_modelDir, "ch_keys.txt") // separate download
});
public string ProcessDocument(string imagePath, string language)
{
// Rebuild engine for each language — model reload cost on every switch
using var engine = language == "chinese"
? BuildChineseEngine()
: BuildEnglishEngine();
var result = engine.Run(imagePath);
return string.Join("\n", result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.Select(b => b.Text));
}
}
Podejście IronOCR:
using IronOcr;
public class DocumentRouter
{
// One instance handles all languages — language is a property, not a constructor param
private readonly IronTesseract _ocr = new IronTesseract();
public string ProcessDocument(string imagePath, string language)
{
// Language switch requires no model reload, no rebuild
_ocr.Language = language switch
{
"chinese" => OcrLanguage.ChineseSimplified,
"japanese" => OcrLanguage.Japanese,
"arabic" => OcrLanguage.Arabic,
"russian" => OcrLanguage.Russian,
_ => OcrLanguage.English
};
return _ocr.Read(imagePath).Text;
}
}
Bez przebudowy silnika, bez ponownego ładowania modelu, bez oddzielnego pobierania dla każdego języka. Pakiety językowe dla celów nieanglojęzycznych instalują się przez NuGet — dotnet add package IronOcr.Languages.ChineseSimplified — a krok przywracania obsługuje wdrożenie automatycznie. Wielojęzyczny poradnik obejmuje instalację pakietów językowych, a indeks języków zawiera listę wszystkich ponad 125 dostępnych pakietów.
Migracja przetwarzania wsadowego
RapidOCR.NET nie ma gwarancji bezpieczeństwa wątku na jednej instancji RapidOcrEngine. Przetwarzanie wsadowe wymaga albo kolejki jednowątkowej, albo instancji silnika na każdy wątek, z których każda zajmuje od 300 do 500 MB pamięci.IronOCR jest wyraźnie bezpieczny względem wątku: utwórz jeden IronTesseract na wątek i uruchamiaj je równolegle bez blokad.
Podejście RapidOCR.NET:
using RapidOcrNet;
public class BatchOcrProcessor
{
private readonly string _modelDir;
public BatchOcrProcessor(string modelDir) => _modelDir = modelDir;
// Thread-pool processing — each thread needs its own engine copy
// 4 threads × 300-500 MB model footprint = 1.2-2 GB RAM minimum
public Dictionary<string, string> ProcessBatch(IReadOnlyList<string> imagePaths)
{
var results = new System.Collections.Concurrent.ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, new ParallelOptions { MaxDegreeOfParallelism = 4 },
imagePath =>
{
// Each thread must create its own engine — not safe to share
using var engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(_modelDir, "det.onnx"),
ClsModelPath = Path.Combine(_modelDir, "cls.onnx"),
RecModelPath = Path.Combine(_modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(_modelDir, "en_keys.txt")
});
var result = engine.Run(imagePath);
results[imagePath] = string.Join("\n",
result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.Select(b => b.Text));
});
return new Dictionary<string, string>(results);
}
}
Podejście IronOCR:
using IronOcr;
public class BatchOcrProcessor
{
// Thread-safe: create IronTesseract per thread, no shared state required
public Dictionary<string, string> ProcessBatch(IReadOnlyList<string> imagePaths)
{
var results = new System.Collections.Concurrent.ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, imagePath =>
{
// Lightweight construction — no model loading overhead per thread
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
});
return new Dictionary<string, string>(results);
}
}
Instancja RapidOcrEngine per wątek znika. Instancje wątków IronOCRsą lekkie — nie wymagają ładowania zewnętrznego modelu podczas tworzenia. Przykład wielowątkowości ilustruje wzorce przetwarzania współbieżnego dla potoków o wysokiej przepustowości.
Przetwarzanie plików TIFF z wieloma ramkami
RapidOCR.NET akceptuje wyłącznie pojedyncze pliki graficzne. Przetwarzanie wielostronicowego TIFF — standardowego formatu dla dokumentów odebranych faksem i archiwów skanowanych — wymaga podziału go na pojedyncze ramki przy użyciu osobnej biblioteki obrazów, zapisania tych ramek do plików tymczasowych, uruchomienia engine.Run() na każdej z nich i potem ich usunięcia.IronOCR obsługuje wielo-ramkowy TIFF natywnie przez OcrInput.LoadImageFrames.
Podejście RapidOCR.NET:
using RapidOcrNet;
// Also requires: SixLabors.ImageSharp or System.Drawing for TIFF frame extraction
public class TiffOcrProcessor
{
private readonly RapidOcrEngine _engine;
public TiffOcrProcessor(string modelDir)
{
_engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"),
ClsModelPath = Path.Combine(modelDir, "cls.onnx"),
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(modelDir, "en_keys.txt")
});
}
public string ProcessMultiPageTiff(string tiffPath)
{
var pageTexts = new List<string>();
var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
try
{
// External library required to split TIFF frames
var framePaths = SplitTiffIntoFrames(tiffPath, tempDir); // not in RapidOcrNet
foreach (var framePath in framePaths)
{
var result = _engine.Run(framePath);
pageTexts.Add(string.Join("\n",
result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.Select(b => b.Text)));
}
}
finally
{
// Clean up temp frame files
Directory.Delete(tempDir, recursive: true);
}
return string.Join("\n\n", pageTexts);
}
private IEnumerable<string> SplitTiffIntoFrames(string tiffPath, string outputDir)
{
// Requires external library — implementation depends on what is installed
throw new NotImplementedException("Add SixLabors.ImageSharp or similar");
}
}
Podejście IronOCR:
using IronOcr;
public class TiffOcrProcessor
{
private readonly IronTesseract _ocr = new IronTesseract();
public string ProcessMultiPageTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // All frames loaded — no external library needed
var result = _ocr.Read(input);
return result.Text; // Pages assembled in order automatically
}
public IEnumerable<(int PageNumber, string Text, double Confidence)> ProcessTiffWithPageData(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
var result = _ocr.Read(input);
foreach (var page in result.Pages)
yield return (page.PageNumber, page.Text, page.Confidence);
}
}
Bez zewnętrznej biblioteki obrazów, bez plików tymczasowych, bez logiki czyszczenia. LoadImageFrames odczytuje wszystkie ramki TIFF do kanału OcrInput w jednym wywołaniu. Instrukcja obsługi plików TIFF i GIF obejmuje wybór klatek, filtrowanie zakresu stron oraz oszczędną pod względem pamięci obsługę dużych dokumentów zawierających wiele klatek.
Pobieranie danych strukturalnych ze skanowanych formularzy
RapidOCR.NET zwraca bloki tekstu z ramkami ograniczającymi, ale bez struktury dokumentu wyższego poziomu — bez pojęcia akapitów, wierszy czy słów. Wyodrębnianie poszczególnych pól ze skanowanego formularza wymaga napisania logiki przecięcia współrzędnych względem surowej listy bloków.IronOCR zapewnia ustrukturyzowane drzewo wyników aż do poziomu znaków, z współrzędnymi na każdym poziomie.
Podejście RapidOCR.NET:
using RapidOcrNet;
public class FormFieldExtractor
{
private readonly RapidOcrEngine _engine;
public FormFieldExtractor(string modelDir)
{
_engine = new RapidOcrEngine(new RapidOcrOptions
{
DetModelPath = Path.Combine(modelDir, "det.onnx"),
ClsModelPath = Path.Combine(modelDir, "cls.onnx"),
RecModelPath = Path.Combine(modelDir, "rec_en.onnx"),
KeysPath = Path.Combine(modelDir, "en_keys.txt")
});
}
// Extract text within a defined region by filtering block coordinates manually
public string ExtractFieldByRegion(string imagePath, float regionLeft, float regionTop,
float regionRight, float regionBottom)
{
var result = _engine.Run(imagePath);
// Filter blocks whose bounding box intersects the target region
var blocksInRegion = result.TextBlocks
.Where(b =>
b.BoundingBox.Left < regionRight &&
b.BoundingBox.Right > regionLeft &&
b.BoundingBox.Top < regionBottom &&
b.BoundingBox.Bottom > regionTop)
.OrderBy(b => b.BoundingBox.Top)
.ThenBy(b => b.BoundingBox.Left);
return string.Join(" ", blocksInRegion.Select(b => b.Text));
}
}
Podejście IronOCR:
using IronOcr;
public class FormFieldExtractor
{
private readonly IronTesseract _ocr = new IronTesseract();
// Use CropRectangle to OCR only the target region — no post-filter needed
public string ExtractFieldByRegion(string imagePath, int x, int y, int width, int height)
{
var region = new CropRectangle(x, y, width, height);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
return _ocr.Read(input).Text;
}
// Extract all fields with their coordinates from a full-page scan
public IEnumerable<(string Text, int X, int Y, double Confidence)> ExtractAllWords(string imagePath)
{
var result = _ocr.Read(imagePath);
foreach (var page in result.Pages)
foreach (var word in page.Words)
yield return (word.Text, word.X, word.Y, word.Confidence);
}
}
CropRectangle ogranicza OCR do dokładnego regionu zainteresowania, co jest szybsze i dokładniejsze niż uruchamianie OCR pełnostronicowego i filtrowanie wyników później. Współrzędne i wartości zaufania są dostępne bezpośrednio na result.Pages[i].Words bez żadnego kodu zajmującego się przecięciem obszarów ograniczających. Szczegółowo omówiono ten wzorzec w poradniku dotyczącym OCR opartego na regionach oraz w przykładzie z prostokątem do przycinania.
RapidOCR.NET API do IronOCR– dokumentacja API
| RapidOCR.NET | Odpowiednik IronOCR |
|---|---|
using RapidOcrNet | using IronOcr |
new RapidOcrEngine(new RapidOcrOptions { ... }) | new IronTesseract() |
RapidOcrOptions.DetModelPath | Niepotrzebne — dołączone wewnętrznie |
RapidOcrOptions.ClsModelPath | Niepotrzebne — dołączone wewnętrznie |
RapidOcrOptions.RecModelPath | Niepotrzebne — dołączone wewnętrznie |
RapidOcrOptions.KeysPath | Niepotrzebne — dołączone wewnętrznie |
RapidOcrOptions.UseGpu | Nie dotyczy — zoptymalizowane wewnętrznie pod kątem procesora |
RapidOcrOptions.NumThreads | Użyj Parallel.ForEach z jednym IronTesseract na wątek |
engine.Run(imagePath) | ocr.Read(imagePath) |
engine.Dispose() | using var ocr = new IronTesseract() |
result.TextBlocks | result.Pages[i].Words / .Lines / .Paragraphs |
result.TextBlocks[i].Text | result.Words[i].Text |
result.TextBlocks[i].Confidence | result.Words[i].Confidence |
result.TextBlocks[i].BoundingBox.Top | result.Words[i].Y |
result.TextBlocks[i].BoundingBox.Left | result.Words[i].X |
Ręczne sortowanie OrderBy(b => b.BoundingBox.Top) | Niepotrzebne — result.Text jest w kolejności czytania |
string.Join("\n", result.TextBlocks.Select(b => b.Text)) | result.Text |
| Zmiana pliku językowego (pobierz inny model) | ocr.Language = OcrLanguage.French |
| Przebudowa silnika w celu zmiany języka | Niepotrzebne — ustaw ocr.Language na wywołanie |
PDF do obrazu + engine.Run() pętla | ocr.Read("document.pdf") |
| Ręczne dzielenie ramek w pliku TIFF z wieloma ramkami | input.LoadImageFrames("document.tiff") |
| Brak możliwości wyszukiwania w plikach PDF | result.SaveAsSearchablePdf("output.pdf") |
| Brak funkcji obsługi BarCodes | ocr.Configuration.ReadBarCodes = true |
Typowe problemy związane z migracją i ich rozwiązania
Problem 1: Katalog modeli nadal istnieje po migracji
RapidOCR.NET: Katalog models/ w projekcie zawiera det.onnx, cls.onnx, rec_en.onnx oraz en_keys.txt, wraz z wpisami MSBuild <Content>, które je kopiują podczas kompilacji. Po przejściu na IronOCR ten katalog i te wpisy pozostają i nadal zwiększają rozmiar pliku kompilacji.
Rozwiązanie: Usuń katalog models/, usuń odpowiadające mu <ItemGroup> z .csproj i usuń wszelką logikę walidacji uruchomieniowej, która sprawdzała brakujące pliki. Usuń również odwołanie do NuGet Microsoft.ML.OnnxRuntime, jeśli było zainstalowane osobno. Opublikowany wynik działania aplikacji .NET korzystającej z IronOCR nie zawiera żadnych zewnętrznych plików modeli.
<!-- Remove this entire block from .csproj -->
<ItemGroup>
<Content Include="models\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Problem 2: Wzorzec konstrukcji silnika na wątek
RapidOCR.NET: Kod równoległego przetwarzania, który tworzył nową RapidOcrEngine na wątek, aby uniknąć problemów z dzieleniem stanu, miał znaczący koszt pamięciowy: każda instancja silnika ładowała 300–500 MB wag modeli ONNX niezależnie.
Rozwiązanie: Instancje IronTesseractIronOCRsą bezpieczne względem wątku i lekkie. Utwórz jedną na wątek w Parallel.ForEach bez martwienia się o koszt ładowania modelu na instancję. Podejście IronOCR jest identyczne do przykładu migracji przetwarzania wsadowego powyżej — IronTesseract obsługuje ten scenariusz z tym samym wzorcem konstrukcji na wątek, ale bez kosztu ładowania modelu 300–500 MB, jaki każda instancja RapidOcrEngine ponosiła. Przykład wielowątkowości pokazuje standardowy wzorzec dla potoków o wysokiej przepustowości.
Problem 3: Wyjątek "Język nieobsługiwany"
RapidOCR.NET: Kod, który przekierowywał dokumenty inne niż CJK przez RapidOCR.NET — lub próbował zbudować silnik z nieistniejącym modelem hiszpańskim/francuskim/niemiećkim — powodowałby w czasie wykonywania błąd "nie znaleziono pliku" lub generowałby puste wyniki.
Rozwiązanie: Zainstaluj odpowiedni pakiet NuGet dla pakietu językowego i ustaw ocr.Language na wartość enum celu OcrLanguage. Bez pobierania modeli, bez przebudowywania silnika, bez dodatkowej ścieżki kodu dla każdego języka:
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.Spanish;
var result = ocr.Read("spanish-document.jpg");
Przewodnik po niestandardowych pakietach językowych obejmuje zaawansowaną konfigurację języków wykraczającą poza standardowe ponad 125 pakietów.
Problem 4: Logika sortowania bloków tekstu przestaje działać po migracji
RapidOCR.NET: Ponieważ result.TextBlocks był nieuporządkowaną płaską listą, bazy kodu typowo zawierały łańcuchy .OrderBy(b => b.BoundingBox.Top).ThenBy(b => b.BoundingBox.Left) rozproszone w całym kodzie przetwarzania wyników.
Rozwiązanie: Całkowicie usuń tę logikę sortowania. result.Text w IronOCR jest już posortowane w naturalnej kolejności czytania. Dla kodu, który również spożywał współrzędne obszaru ograniczającego, zamień odniesienie do bloku na result.Pages[i].Words[j]:
// Before: manual sort + coordinate extraction
var sorted = result.TextBlocks
.OrderBy(b => b.BoundingBox.Top)
.ThenBy(b => b.BoundingBox.Left);
foreach (var block in sorted)
Console.WriteLine($"{block.Text} at ({block.BoundingBox.Left}, {block.BoundingBox.Top})");
// After: structured access, already in order
foreach (var page in result.Pages)
foreach (var word in page.Words)
Console.WriteLine($"{word.Text} at ({word.X}, {word.Y})");
Problem 5: Awaria potoku CI/CD po usunięciu plików modeli
RapidOCR.NET: Budowane potoki, które buforowały lub pobierały katalog models/ jako osobny krok — albo ze sklepu artefaktów, wspólnego koszyka S3, albo repozytorium Git LFS — nie powiodą się, gdy te kroki nic nie znajdą do przywrócenia po migracji.
Rozwiązanie: Całkowicie usuń etapy pobierania pliku modelu i buforowania z potoku CI. Silnik IronOCR jest przywracany jako część standardowego etapu dotnet restore. Nie są wymagane dodatkowe etapy potoku. Dla wdrożeń kontenerowych usuń wszelkie instrukcje Docker COPY models/ ./models/ — przewodnik wdrożenia Docker dla IronOCRdokumentuje jedyny wymagany pakiet systemowy (libgdiplus na obrazach Debian/Ubuntu) i nic więcej.
Problem 6: Konflikty wersji środowiska uruchomieniowego ONNX po częściowej migracji
RapidOCR.NET: Aplikacje, które również używają innych pakietów ML oparte na ONNX (ML.NET, ONNX detekcja obiektów itp.) mogły mieć Microsoft.ML.OnnxRuntime przypięte do konkretnej wersji dla zgodności z RapidOCR.NET. Usunięcie RapidOCR.NET może spowodować konflikty wersji w tych innych pakietach.
Rozwiązanie: Usuń Microsoft.ML.OnnxRuntime z explicytnej listy pakietów.IronOCR nie ma zależności ONNX Runtime, więc usunięcie odwołania RapidOCR.NET eliminuje całkowicie przypięcie wersji. Inne pakiety ML, które rzeczywiście wymagają środowiska uruchomieniowego ONNX, mogą następnie znaleźć swoją własną kompatybilną wersję poprzez standardowe rozwiązywanie zależności NuGet bez ograniczeń RapidOCR.NET.
Lista kontrolna migracji RapidOCR.NET
Zadania przed migracją
Przed wprowadzeniem zmian należy sprawdzić kod źródłowy pod kątem wszystkich miejsc użycia RapidOCR.NET:
# Find all files that reference RapidOcrNet
grep -r "RapidOcrNet\|RapidOcrEngine\|RapidOcrOptions" --include="*.cs" .
# Find model path configuration
grep -r "DetModelPath\|ClsModelPath\|RecModelPath\|KeysPath" --include="*.cs" .
# Find MSBuild model copy entries
grep -r "det\.onnx\|cls\.onnx\|rec.*\.onnx\|keys\.txt" --include="*.csproj" .
# Find model validation logic
grep -r "ValidateModel\|models/" --include="*.cs" .
# Find ONNX Runtime references
grep -r "OnnxRuntime\|Microsoft\.ML" --include="*.csproj" .
# Find language-switching patterns (multiple engine instances per language)
grep -r "CreateEnglishEngine\|CreateChineseEngine\|rec_en\|ch_rec\|en_keys\|ch_keys" --include="*.cs" .
Sporządź inwentarz wyników: zanotuj każde miejsce, w którym tworzony jest silnik, każde miejsce, w którym konfigurowane są ścieżki modeli, każde miejsce, w którym sortowane są bloki tekstu i każde miejsce, w którym konwersja PDF do obrazu wchodzi w engine.Run().
Zadania związane z aktualizacją kodu
- Usuń odniesienie do pakietu NuGet
RapidOcrNetz wszystkich plików.csproj. - Usuń odniesienie do pakietu NuGet
Microsoft.ML.OnnxRuntimez wszystkich plików.csproj. - Zainstaluj pakiet NuGet
IronOcr. - Zainstaluj pakiety językowe NuGet dla wszystkich języków innych niż angielski, których wymaga aplikacja.
- Usuń katalog
models/z projektu i repozytorium. - Usuń wpisy MSBuild
<Content Include="models\**\*.*">z wszystkich plików.csproj. - Usuń metody walidacji modelu startowego (metody stylu
EnsureModelsPresent). - Zastąp
using RapidOcrNetusing IronOcrwe wszystkich plikach źródłowych. - Zastąp
new RapidOcrEngine(new RapidOcrOptions { ... })withnew IronTesseract(). - Zastąp
engine.Run(imagePath)ocr.Read(imagePath). - Zastąp łańcuchy assemblerowe
result.TextBlocks(.OrderBy().Select(b => b.Text))result.Text. - Zastąp wyciąganie pola filtrującego współrzędne
CropRectanglewejściem z regionu. - Zastąp konstrukcję silnika na wątek konstrukcją
IronTesseractna wątek. - Zastąp metody fabryki silnika specyficzne dla języka
ocr.Language = OcrLanguage.Xprzypisaniami. - Usuń kod konwersji PDF do obrazu i zastąp go bezpośrednimi wywołaniami
ocr.Read("file.pdf"). - Usuń kod dzielenia ramki dla wielo-ramki TIFF i zastąp go
input.LoadImageFrames("file.tiff"). - Dodaj
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"przy starcie aplikacji. - Usuń etapy pobierania plików modeli i buforowania z definicji potoku CI/CD.
- Usuń instrukcje modelu ONNX
COPYz plików Dockerfile.
Testy po migracji
- Sprawdź, czy wszystkie istniejące ścieżki OCR obrazów zwracają tekst o dokładności równej lub lepszej niż wynik RapidOCR.NET.
- Potwierdź, że
result.Textkolejność czytania pasuje do oczekiwanej sekwencji pól dla każdego rodzaju dokumentu. - Przetestuj przełączane odczyty językowe dla każdej wartości
OcrLanguage, którą używa aplikacja. - Uruchom równoległy procesor wsadowy i upewnij się, że nie występują błędy konfliktu wątków ani problemy z nieaktualnymi wynikami.
- Sprawdź, czy przetwarzanie plików TIFF z wieloma ramkami zwraca prawidłową liczbę stron z poprawnym tekstem na każdej stronie.
- Przetestuj wyciąganie pól formularza przez
CropRectangledla oczekiwanych regionów współrzędnych. - Potwierdź, że katalog
models/jest nieobecny w wynikach kompilacji i pakietach wdrożeniowych. - Uruchom potok CI od początku do końca i upewnij się, że nie pozostały żadne etapy pobierania modelu.
- Zbuduj i uruchom kontener Docker i potwierdź brak warstwy
COPY models/lub błędów plików nie znalezionych przy starcie. - Przeprowadź pomiar czasu uruchamiania, aby sprawdzić, czy opóźnienie przy zimnym starcie uległo zmniejszeniu.
Kluczowe korzyści z migracji do IronOCR
Deployment jest teraz deterministyczny. dotnet restore i dotnet publish tworzą kompletne, działające wdrożenie OCR bez zewnętrznych zależności plikowych. To samo przywrócenie NuGet, które instaluje wersję pakietu, instaluje wszystko, czego silnik potrzebuje do działania. Nie ma plików wzorcowych, które trzeba by wersjonować osobno, nie ma etapów konfiguracji pamięci podręcznej CI ani skryptów do sprawdzania poprawności wdrożenia, które trzeba by utrzymywać. Proces ten jest tak samo prosty, jak w przypadku każdej innej zależności pakietu .NET.
Skala wsparcia językowego zależna od wymagań biznesowych. Dodanie wsparcia dla nowego języka dokumentu oznacza uruchomienie dotnet add package IronOcr.Languages.X i ustawienie ocr.Language. Nie ma sprawdzania dostępności modelu upstream, pobierania modelu ani refaktoryzacji silnika. Zespoły, które zaczynają od angielskiego OCR, a później muszą przetwarzać niemiećkie umowy, arabskie faktury lub rosyjskie zamówienia, rozszerzają zakres działania bez ingerencji w architekturę aplikacji. Wszystkie ponad 125 pakietów językowych ma ten sam schemat instalacji.
Strukturalne dane wyjściowe eliminują kod montujący współrzędne. Hierarchia result.Pages, .Paragraphs, .Lines, .Words i .Characters zastępuje płaską listę TextBlocks i logikę sortowania, która działała wokół jej braku struktury. Kod, który wyodrębniał tekst w kolejności czytania poprzez sortowanie współrzędnych bloków, został usunięty. Kod, który potrzebował ograniczających prostokątów na słowo, uzyskuje je z word.X, word.Y, word.Width, word.Height bez filtrowania przecięć. Strona z wynikami OCR dokumentuje pełny model wyjściowy.
Przetwarzanie plików PDF i TIFF nie wymaga żadnych zewnętrznych bibliotek. Dwa najpopularniejsze formaty dokumentów, poza pojedynczymi obrazami JPG — wielostronicowe pliki PDF i wieloklatkowe pliki TIFF — są obsługiwane natywnie przez IronOCR. Każda zewnętrzna biblioteka, która została dodana do drzewa zależności w celu wsparcia engine.Run() z wejściem PDF lub TIFF, może zostać usunięta. Wynik netto: mniej pakietów do aktualizacji, mniej problemów z kompatybilnością wersji i prostsze pliki projektowe. Instrukcje dotyczące plików PDF i TIFF szczegółowo opisują oba formaty.
Incydenty produkcyjne mają ścieżkę wsparcia. Licencje komercyjne obejmują bezpośrednie wsparcie e-mailowe z punktem kontaktowym dla spraw, które nie mogą czekać na odpowiedź na zgłoszenie w serwisie GitHub. Zespoły zobowiązane umową SLA lub posiadające procesy przetwarzania dokumentów o znaczeniu krytycznym dla działalności mogą zgłaszać incydenty inżynierom odpowiedzialnym za utrzymanie biblioteki, zamiast czekać na odpowiedź społeczności. Centrum dokumentacji IronOCR udostępnia dokumentację referencyjną wraz z ścieżką pomocy technicznej.
Wieczysta Licencja $999 jest jednorazowym kosztem. Nie ma wyceny za stronę, rozliczenia za transakcję ani corocznego odnowienia, które ponownie otwierałoby rozmowę o kosztach. Zespoły programistów, które oszacowały koszt godzin pracy inżynierów poświęconych na zarządzanie modelami, obejścia związane z konwersją plików PDF, utrzymanie potoku CI oraz eskalacje związane z językami nieobsługiwanymi, konsekwentnie uznają to porównanie za korzystne w stosunku do kosztu licencji.
