Jak wykonać OCR tablic rejestracyjnych w języku C#
Ten przewodnik jest przeznaczony dla programistów .NET, którzy przenoszą zadania związane z OCR zKofax OmniPageCapture SDK (obecnie sprzedawanego jako Tungsten Automation) do IronOCR. Obejmuje to pełną ścieżkę migracji: usunięcie zależności od instalatora SDK, wyeliminowanie procedur związanych z cyklem życia silnika, zastąpienie wzorców rozpoznawania opartych na strefach oraz unowocześnienie obsługi błędów. Nie jest wymagana wcześniejsza lektura artykułu porównawczego.
Dlaczego warto przejść zKofax OmniPage(Tungsten)
OmniPage Capture SDK został zaprojektowany z myślą o infrastrukturze zarządzania dokumentami w przedsiębiorstwie w czasach przed pojawieniem się NuGet, Docker i potoków CI/CD. Każdy z wyborów architektonicznych, które miały sens w 2005 roku, powoduje tarcia w 2026 roku.
Instalator SDK nie ma miejsca w świecie NuGet. Każda maszyna programistyczna, agent kompilacji i serwer produkcyjny, na którym działa kod OmniPage, wymaga uruchomienia instalatora Tungsten SDK przed kompilacją. Nie ma .csproj referencji pakietu do przywrócenia. Aktualizacja wersji SDK oznacza ponowne uruchomienie instalatora na całej flocie. Nowy programista nie może uruchomić projektu bez skontaktowania się z osobą zarządzającą licencją SDK i oczekiwania na dostęp do instalatora.
Plik licencyjny jest operacyjną odpowiedzialnością. Plik .lic musi znajdować się na konkretnej ścieżce na każdej maszynie, która wywołuje engine.Initialize(). Wystarczy wdrożyć na nowym serwerze i zapomnieć o pliku, a każde wywołanie OCR zakończy się niepowodzeniem z wyjątkiem licencji — a nie błędem OCR. Użycie licencji pływających i podziały sieci między serwerem aplikacji a serwerem licencji oznacza, że każde wywołanie Initialize() się nie powiedzie, dopóki połączenie nie zostanie przywrócone, niezależnie od tego, czy maszyna pomyślnie zweryfikowała swoją licencję wczoraj.
Zarządzanie cyklem życia silnika powoduje przecieki zasobów na ścieżkach błędów. OmniPageEngine.Shutdown() musi być wywołany na każdej możliwej ścieżce kodu - włącznie z obsługą wyjątków, wczesnymi zwrotami i limitami czasowymi - w przeciwnym razie fotel licencji pływającej pozostanie zablokowany, dopóki nie wygaśnie limit czasowy wypożyczenia serwera licencji. Pisanie obronne wokół tego ograniczenia oznacza otaczanie każdego punktu integracji IDisposable wzorcami istniejącymi wyłącznie w celu ochrony przed pominięciem wyłączenia silnika.
Identyfikacja sprzętowa koliduje z nowoczesnym wdrażaniem. Aktywacja OmniPage jest powiązana ze sprzętem. Ponowne uruchamianie kontenerów, migracje maszyn wirtualnych i automatyczne skalowanie w chmurze wiążą się ze zmianami tożsamości sprzętu, które powodują konieczność ponownej aktywacji. Model wdrożenia niezgodny z autoskalowaniem to model wdrożenia niezgodny z infrastrukturą chmury.
Ceny za stronę są nieprzewidywalne w przypadku dużych projektów. Nagły wzrost liczby przetwarzanych dokumentów — na przykład w wyniku pozyskania nowego klienta lub przesłania partii zaległych zadań — generuje fakturę za przekroczenie limitu, którego nikt nie uwzględnił w budżecie.IronOCR jest bezterminowy i nieograniczony w ramach danego poziomu licencji: bez liczenia stron, bez limitów, bez faktur za przekroczenie limitu.
Proces zamówień blokuje wysyłkę. Pakiet OmniPage SDK jest dostępny wyłącznie w ramach sprzedaży. Dostęp do wersji testowej, ceny i warunki umowy wymagają kontaktu z działem sprzedaży, który trwa od 4 do 12 tygodni. Zespoły tworzące funkcje OCR, które mają termin dostawy produktu, nie mogą czekać na cykl zakupowy w firmie Enterprise. dotnet add package IronOcr rozwiązuje się w 30 sekund. Zobacz stronę licencyjną IronOCR po opublikowane, samoobsługowe ceny — $999 Lite do $2,999 Enterprise, wszystko wieczyste.
Podstawowy problem
OmniPage wymaga pełnej procedury inicjalizacji przed odczytaniem pierwszego bajtu oraz procedury zamknięcia po odczytaniu ostatniego — każde miejsce wywołania musi zarządzać obiema:
// OmniPage: Ceremony required on EVERY entry point — init, process, shutdown
using var engine = new OmniPageEngine();
engine.SetLicenseFile(@"C:\Program Files\OmniPage\license.lic"); // File must exist here
engine.Initialize(); // Network call to license server — can fail for license reasons, not OCR reasons
var document = engine.CreateDocument();
document.AddPage("invoice.jpg");
document.Recognize(new RecognitionSettings { Language = "English" });
string text = document.GetText();
document.Dispose(); // Must not be skipped
engine.Shutdown(); // Must not be skipped — omitting this locks a floating seat
// IronOCR: One NuGet package, one line at startup, one call to read
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; // At app startup — once, ever
var text = new IronTesseract().Read("invoice.jpg").Text;
Wersja OmniPage składa się z ośmiu odrębnych etapów, dwóch obowiązkowych wywołań czyszczących, zależności sieciowej oraz zależności od systemu plików. Wersja IronOCR ma dwie.
##IronOCR aKofax OmniPage(Tungsten): porównanie funkcji
Poniższa tabela przedstawia funkcje najbardziej istotne dla zespołów rozważających tę migrację.
| Funkcja | Kofax OmniPage SDK | IronOCR |
|---|---|---|
| Sposób instalacji | Niestandardowy instalator SDK (bez NuGet) | dotnet add package IronOcr |
| Czas do pierwszego wywołania OCR | 4–12 tygodni (zamówienie) + godziny (konfiguracja) | 30 sekund |
| Mechanizm licencji | Plik .lic na dysku + opcjonalny serwer licencji | Klucz ciągu znaków przy uruchomieniu aplikacji |
| Identyfikacja sprzętu | Tak (reaktywacja po migracji maszyny wirtualnej) | Nie |
| Wymagany serwer licencji | Tak (w przypadku licencji pływających) | Nie |
| Rozliczenie według czasu pracy na stronę | Dostępne (zmienne) | Nie |
| Opublikowane ceny | Nie (skontaktuj się z działem sprzedaży) | Tak ($999 / $1,499 / $2,999 wieczyste) |
| Roczne opłaty za utrzymanie | 18–25% kosztu licencji | Opcjonalnie |
| Zarządzanie cyklem życia silnika | Wymagane (Initialize / Shutdown) | Nie jest wymagane |
| Windows x64 | Tak | Tak |
| Linux | Tak (dodano w styczniu 2026 r.) | Tak (wszystkie wersje) |
| macOS | Nie | Tak |
| Docker / Kubernetes | Trudne (instalator + plik licencji na obrazku) | Proste (tylko pakiet NuGet) |
| Azure / AWS Lambda | Złożone (dostępność serwera licencji) | Proste |
| Formaty obrazów | Tak | JPG, PNG, BMP, TIFF, GIF i inne |
| Natywne wprowadzanie plików PDF | Tak (może wymagać licencji modułowej) | Tak (wbudowane, bez dodatkowej licencji) |
| Wielostronicowy plik TIFF | Tak | Tak |
| Wynik w formacie PDF z możliwością wyszukiwania | Tak | Tak (result.SaveAsSearchablePdf()) |
| Automatyczne przetwarzanie wstępne | Konfiguracja obiektu Settings | Wbudowany + jawny interfejs API potoku |
| Obsługiwane języki | 120+ | Ponad 125 (oddzielne pakiety NuGet) |
| Wyjście danych ustrukturyzowanych | Tak (koordynaty słów) | Strony, akapity, wiersze, słowa, znaki z współrzędnymi |
| Ocena pewności | Tak | Tak (result.Confidence, na słowo) |
| Odczytywanie BarCode | Moduł dodatkowy (oddzielna licencja) | Wbudowane (ocr.Configuration.ReadBarCodes = true) |
| Bezpieczeństwo wątków | Złożone (ograniczenia związane z współdzieleniem silnika) | Pełne (jeden IronTesseract na wątek) |
| Obsługa potoku CI/CD | Wymaga instalatora na każdym agencie | Standardowy dotnet restore |
Szybki start: Migracja zKofax OmniPagedo IronOCR
Krok 1: Zastąp SDK pakietem NuGet
OmniPage nie posiada pakietu NuGet, który można by usunąć. Usuń ręczne referencje DLL z pliku .csproj i odinstaluj SDK z maszyn deweloperskich po zakończeniu migracji. Następnie zainstaluj IronOCR:
Pakiet IronOCR NuGet zawiera silnik OCR, filtry przetwarzania wstępnego oraz komponenty środowiska uruchomieniowego. Bez oddzielnego instalatora, bez natywnego zarządzania bibliotekami DLL, bez rejestracji komponentów.
Krok 2: Aktualizacja przestrzeni nazw
// Before (Kofax OmniPage)
using Kofax.OmniPage.CSDK;
using Kofax.OmniPageCSDK;
using CSDK;
// After (IronOCR)
using IronOcr;
Krok 3: Inicjalizacja licencji
Dodaj jedną linię podczas uruchamiania aplikacji. Zastępuje to ścieżkę pliku .lic, konfigurację serwera licencji i wywołanie engine.Initialize():
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"Przechowuj klucz w zmiennej środowiskowej (IRONOCR_LICENSE_KEY) lub appsettings.json zamiast w kodzie źródłowym. Klucz jest odczytywany w trybie offline — w czasie wykonywania nie następuje żadne połączenie sieciowe.
Przykłady migracji kodu
Błąd inicjalizacji silnika Zastąpienie ścieżki
Najbardziej niebezpiecznym aspektem modelu cyklu życia OmniPage nie jest ścieżka pomyślna — jest to ścieżka błędów. Każdy wyjątek rzucony między engine.Initialize() a engine.Shutdown() może pozostawić zablokowane miejsce licencji pływającej, jeśli Shutdown() nie zostanie osiągnięty. Kod produkcyjny wymaga bloków try/finally wokół każdego wywołania przetwarzania dokumentu:
Podejście Kofax OmniPage:
// OmniPage: try/finally required everywhere to protect license seat release
public string ProcessInvoice(string imagePath)
{
var engine = new OmniPageEngine();
engine.SetLicenseFile(@"C:\Program Files\OmniPage\license.lic");
try
{
engine.Initialize(); // Contacts license server — failure here locks nothing
var document = engine.CreateDocument();
try
{
document.AddPage(imagePath);
document.Recognize(new RecognitionSettings { Language = "English" });
return document.GetText();
}
catch (RecognitionException ex)
{
// Log, rethrow — but Shutdown must still be called
throw new OcrProcessingException("Recognition failed", ex);
}
finally
{
document.Dispose(); // Inner finally: release document
}
}
catch (LicenseValidationException ex)
{
throw new OcrProcessingException("License validation failed", ex);
}
finally
{
engine.Shutdown(); // Outer finally: release license seat — MUST execute
}
}
Podejście IronOCR:
// IronOCR: Nie license seat to release, no engine to shut down
public string ProcessInvoice(string imagePath)
{
using var input = new OcrInput();
input.LoadImage(imagePath);
var ocr = new IronTesseract();
var result = ocr.Read(input);
return result.Text;
// OcrInput disposal is automatic — no license implications on any code path
}
Blok using na OcrInput obsługuje oczyszczanie pamięci dla załadowanych danych obrazowych. Nie istnieje try/finally, aby chronić miejsce licencji. Wyjątek w dowolnym miejscu tej metody nie ma skutków ubocznych poza zakresem samej metody. Opcje konfiguracyjne, w tym instancje lokalne dla wątków, można znaleźć w przewodniku konfiguracji IronTesseract.
Migracja oparta na rozpoznawaniu stref
Głównym mechanizmem ekstrakcji ustrukturyzowanych danych w OmniPage jest definiowanie stref: obszary dokumentu są deklarowane za pomocą granic współrzędnych i typu rozpoznawania dla każdej strefy (OCR, ICR, OMR, BarCode). Deweloperzy definiują obiekty FormZone na dokument szablonu i przekazują je do maszyny rozpoznawania.IronOCR używa CropRectangle, aby osiągnąć tę samą docelową ekstrakcję bez zarządzania szablonami lub deklaracji typów stref:
Podejście Kofax OmniPage:
// OmniPage: Zone-based form extraction with template management
public Dictionary<string, string> ExtractInvoiceFields(string invoicePath)
{
using var engine = new OmniPageEngine();
engine.SetLicenseFile(licensePath);
engine.Initialize();
// Define zones per document template
var zones = new List<FormZone>
{
new FormZone { Name = "InvoiceNumber", Type = "OCR",
X = 520, Y = 80, Width = 200, Height = 30 },
new FormZone { Name = "InvoiceDate", Type = "OCR",
X = 520, Y = 120, Width = 200, Height = 30 },
new FormZone { Name = "TotalAmount", Type = "OCR",
X = 520, Y = 580, Width = 200, Height = 30 },
new FormZone { Name = "VendorName", Type = "OCR",
X = 50, Y = 80, Width = 300, Height = 40 }
};
var template = new FormTemplate { Name = "StandardInvoice", Zones = zones };
var settings = new RecognitionSettings { Language = "English" };
var document = engine.CreateDocument();
document.AddPage(invoicePath);
document.ApplyTemplate(template);
document.Recognize(settings);
var fields = new Dictionary<string, string>();
foreach (var zone in zones)
fields[zone.Name] = document.GetZoneText(zone.Name);
document.Dispose();
engine.Shutdown();
return fields;
}
Podejście IronOCR:
// IronOCR: CropRectangle targets specific regions — no template management
public Dictionary<string, string> ExtractInvoiceFields(string invoicePath)
{
var fields = new Dictionary<string, string>();
var ocr = new IronTesseract();
// Extract each field by reading only the target region
var fieldRegions = new Dictionary<string, CropRectangle>
{
["InvoiceNumber"] = new CropRectangle(520, 80, 200, 30),
["InvoiceDate"] = new CropRectangle(520, 120, 200, 30),
["TotalAmount"] = new CropRectangle(520, 580, 200, 30),
["VendorName"] = new CropRectangle(50, 80, 300, 40)
};
foreach (var (fieldName, region) in fieldRegions)
{
using var input = new OcrInput();
input.LoadImage(invoicePath, region);
fields[fieldName] = ocr.Read(input).Text.Trim();
}
return fields;
}
Każdy CropRectangle określa (x, y, width, height) w pikselach. Silnik OCR przetwarza tylko wyznaczony obszar, a nie całą stronę — zapewnia to taką samą wydajność, jaką zapewnia przetwarzanie strefowe w programie OmniPage. Przewodnik po OCR oparty na regionach obejmuje wzorce wyboru współrzędnych, w tym jak wyodrębnić wiele regionów z jednego załadunku obrazu, korzystając z API wielu regionów OcrInput.
Migracja danych strukturalnych
OmniPage udostępnia strukturę dokumentu poprzez własny proces eksportu: ustawienia formatu są stosowane do rozpoznanego dokumentu, a wynik jest zapisywany do pliku w określonym formacie (RTF, XML, CSV, PDF z możliwością wyszukiwania). Dostęp do współrzędnych na poziomie WORD wymaga iteracji iteratora wyników z jawnymi zapytaniami o pozycję.IronOCR udostępnia te same dane strukturalne bezpośrednio w obiekcie wynikowym bez konieczności dodatkowego eksportu:
Podejście Kofax OmniPage:
// OmniPage: Structured output requires format configuration and file export
public void ExtractStructuredContent(string imagePath, string outputDir)
{
using var engine = new OmniPageEngine();
engine.SetLicenseFile(licensePath);
engine.Initialize();
var settings = new RecognitionSettings { Language = "English" };
var document = engine.CreateDocument();
document.AddPage(imagePath);
document.Recognize(settings);
// Word-level coordinates through result iterator
var iterator = document.GetResultIterator(ResultIteratorLevel.Word);
while (iterator.MoveNext())
{
string word = iterator.GetText();
var bounds = iterator.GetBoundingBox();
double confidence = iterator.GetConfidence();
Console.WriteLine($"Word: {word} at ({bounds.X},{bounds.Y}) conf:{confidence:F1}%");
}
// Structured export requires separate output format configuration
var outputSettings = new OutputSettings
{
Format = OutputFormat.XML,
IncludeCoordinates = true,
IncludeConfidence = true
};
document.SaveAs(Path.Combine(outputDir, "output.xml"), outputSettings);
document.Dispose();
engine.Shutdown();
}
Podejście IronOCR:
// IronOCR: Structured data directly on OcrResult — no export step
public void ExtractStructuredContent(string imagePath)
{
var result = new IronTesseract().Read(imagePath);
Console.WriteLine($"Confidence: {result.Confidence:F1}%");
Console.WriteLine($"Pages: {result.Pages.Length}");
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"[Paragraph at ({paragraph.X},{paragraph.Y})]");
Console.WriteLine(paragraph.Text);
foreach (var word in paragraph.Words)
{
// Per-word confidence and coordinates — no iterator needed
Console.WriteLine(
$" Word: '{word.Text}' " +
$"at ({word.X},{word.Y}) " +
$"conf: {word.Confidence:F1}%");
}
}
}
}
Hierarchia obiektu OcrResult — Strony, Akapity, Linie, Słowa, Znaki — dostarcza te same dane pozycyjne, które iteracja wyników OmniPage ujawnia, ale jako nawigowalną strukturę obiektów zamiast sekwencyjnego kursora. Wyniki oceny pewności są dostępne na poziomie wyników, stron, akapitów i słów bez dodatkowej konfiguracji. Przewodnik po wynikach odczytu obejmuje wszystkie właściwości danych strukturalnych, a przewodnik po wynikach pewności obejmuje wzorce walidacji dla poszczególnych WORDów.
Migracja przetwarzania wielostronicowych plików TIFF
Wielostronicowy przepływ pracy OmniPage z plikami TIFF wymaga wyodrębniania stron pojedynczo z kontenera TIFF, z oddzielnym wywołaniem funkcji rozpoznawania i usuwaniem dokumentu dla każdej strony. Powoduje to powstanie zarówno szablonów, jak i obszaru zarządzania zasobami proporcjonalnego do liczby stron.IronOCRładuje wielo-ramkowe pliki TIFF za pomocą jednego wywołania:
Podejście Kofax OmniPage:
// OmniPage: Page-by-page TIFF extraction with per-page lifecycle
public List<string> ExtractFromMultiPageTiff(string tiffPath)
{
var pageTexts = new List<string>();
using var engine = new OmniPageEngine();
engine.SetLicenseFile(licensePath);
engine.Initialize();
// Open TIFF and iterate frames
var tiffContainer = engine.OpenTiff(tiffPath);
int pageCount = tiffContainer.GetPageCount();
var settings = new RecognitionSettings { Language = "English" };
for (int i = 0; i < pageCount; i++)
{
var page = tiffContainer.GetPage(i); // Extract frame
var document = engine.CreateDocument();
try
{
document.AddPage(page);
document.Recognize(settings);
pageTexts.Add(document.GetText());
}
finally
{
document.Dispose(); // Dispose per page to manage memory
}
}
tiffContainer.Dispose();
engine.Shutdown();
return pageTexts;
}
Podejście IronOCR:
// IronOCR: Multi-frame TIFF loaded in one call — all pages in one result
public List<string> ExtractFromMultiPageTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // All frames loaded automatically
var result = new IronTesseract().Read(input);
// Each TIFF frame becomes a page in the result
return result.Pages.Select(page => page.Text).ToList();
}
LoadImageFrames odczytuje każdą klatkę z pojemnika TIFF w jednym wywołaniu. Wynik ujawnia jeden OcrResult.Page na klatkę, zachowując strukturę strona po stronie bez konieczności ręcznego pętlenia iteracyjnego lub oczyszczania na stronę. Dla produkcyjnych przepływów pracy wsadowych TIFF zobacz przewodnik po wejściu TIFF i GIF.
Migracja przetwarzania równoległego bezpiecznego dla wątków
Silnik OmniPage jest współdzielonym zasobem ze stanem. Dzielenie jednej instancji OmniPageEngine przez wątki wymaga zewnętrznej synchronizacji, ponieważ wiele wątków wywołujących CreateDocument() równocześnie może wywołać splątany stan. Bezpieczny wzorzec — jedna instancja silnika na wątek — stoi w konflikcie z dużym kosztem inicjalizacji silnika. Instancje IronOCR nie posiadają współdzielonego stanu: twórz jedną IronTesseract na wątek bez zera nakładu na koordynację:
Podejście Kofax OmniPage:
// OmniPage: Shared engine with locking to serialize document operations
public ConcurrentDictionary<string, string> ProcessBatchWithEngine(
string[] imagePaths, string licensePath)
{
var results = new ConcurrentDictionary<string, string>();
var engineLock = new object();
// One engine — document operations must be serialized
using var engine = new OmniPageEngine();
engine.SetLicenseFile(licensePath);
engine.Initialize();
var settings = new RecognitionSettings { Language = "English" };
Parallel.ForEach(imagePaths, imagePath =>
{
lock (engineLock) // Serialize: one recognition at a time
{
var document = engine.CreateDocument();
try
{
document.AddPage(imagePath);
document.Recognize(settings);
results[imagePath] = document.GetText();
}
finally
{
document.Dispose();
}
}
});
engine.Shutdown();
return results;
}
Podejście IronOCR:
// IronOCR: One IronTesseract per thread — no locking, genuine parallelism
public ConcurrentDictionary<string, string> ProcessBatchInParallel(string[] imagePaths)
{
var results = new ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, imagePath =>
{
// Each thread creates its own instance — no shared state, no locks
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = ocr.Read(input);
results[imagePath] = result.Text;
});
return results;
}
Wersja OmniPage serializuje całe rozpoznawanie za pomocą blokady, co uniemożliwia równoległość. Wersja IronOCR przetwarza dokumenty równolegle, bez konieczności koordynacji. W przypadku obciążeń wsadowych o dużej przepustowości zapoznaj się z przykładem wielowątkowości oraz przewodnikiem po optymalizacji szybkości.
Generowanie plików PDF z możliwością wyszukiwania na podstawie zeskanowanego archiwum
Wyjście PDF wyszukiwalnego OmniPage wymaga złożenia potoku rozpoznawania z wyraźną konfiguracją OutputSettings i OutputFormat przed zapisaniem.IronOCR tworzy pliki PDF z możliwością wyszukiwania na podstawie pojedynczego wywołania metody na obiekcie wynikowym:
Podejście Kofax OmniPage:
// OmniPage: Searchable PDF requires OutputSettings configuration before save
public void ConvertArchiveToSearchable(string[] scannedPdfPaths, string outputDirectory)
{
using var engine = new OmniPageEngine();
engine.SetLicenseFile(licensePath);
engine.Initialize();
var recognitionSettings = new RecognitionSettings
{
Language = "English",
AccuracyMode = "Maximum",
PreserveLayout = true
};
var outputSettings = new OutputSettings
{
Format = OutputFormat.SearchablePDF,
Compression = PDFCompression.Standard,
ImageQuality = 85,
EmbedFonts = true
};
foreach (var pdfPath in scannedPdfPaths)
{
var document = engine.OpenPDF(pdfPath);
document.RecognizeAll(recognitionSettings);
string outputPath = Path.Combine(
outputDirectory,
Path.GetFileNameWithoutExtension(pdfPath) + "_searchable.pdf");
document.SaveAs(outputPath, outputSettings);
document.Dispose();
}
engine.Shutdown();
}
Podejście IronOCR:
// IronOCR: Searchable PDF output is one method call on the result
public void ConvertArchiveToSearchable(string[] scannedPdfPaths, string outputDirectory)
{
var ocr = new IronTesseract();
foreach (var pdfPath in scannedPdfPaths)
{
using var input = new OcrInput();
input.LoadPdf(pdfPath); // All pages loaded automatically
var result = ocr.Read(input);
string outputPath = Path.Combine(
outputDirectory,
Path.GetFileNameWithoutExtension(pdfPath) + "_searchable.pdf");
result.SaveAsSearchablePdf(outputPath);
Console.WriteLine($"Processed: {Path.GetFileName(pdfPath)} ({result.Pages.Length} pages)");
}
}
SaveAsSearchablePdf osadza warstwę tekstową w PDF, czyniąc ją indeksowalną w systemach zarządzania dokumentami, bez zmiany wyglądu oryginalnego skanu. Przewodnik w formacie PDF z funkcją wyszukiwania obejmuje opcje warstw tekstowych, a przykład OCR dla plików PDF ilustruje kompleksowe przetwarzanie zeskanowanych plików PDF.
Dokumentacja APIKofax OmniPagedo IronOCR
| Kofax OmniPage | Odpowiednik IronOCR |
|---|---|
using Kofax.OmniPage.CSDK; | using IronOcr; |
using Kofax.OmniPageCSDK; | using IronOcr; |
using CSDK; | using IronOcr; |
new OmniPageEngine() | Nie jest wymagane — brak obiektu silnika |
engine.SetLicenseFile(path) | IronOcr.License.LicenseKey = "key"; |
engine.Initialize() | Nie jest wymagane |
engine.Shutdown() | Nie jest wymagane |
engine.CreateDocument() | new OcrInput() |
document.AddPage(imagePath) | input.LoadImage(imagePath) |
engine.OpenPDF(pdfPath) | input.LoadPdf(pdfPath) |
engine.OpenTiff(tiffPath) | input.LoadImageFrames(tiffPath) |
document.Recognize(settings) | new IronTesseract().Read(input) |
document.RecognizeAll(settings) | new IronTesseract().Read(input) (wszystkie strony na raz) |
document.GetText() | result.Text |
document.GetZoneText(zoneName) | input.LoadImage(path, cropRectangle) + result.Text |
document.Dispose() | using var input = new OcrInput() (automatycznie) |
iterator.GetText() | result.Pages[n].Words[m].Text |
iterator.GetBoundingBox() | result.Pages[n].Words[m].X / Y / Width / Height |
iterator.GetConfidence() | result.Pages[n].Words[m].Confidence |
engine.LoadLanguageDictionary("German") | dotnet add package IronOcr.Languages.German |
settings.PrimaryLanguage = "English" | ocr.Language = OcrLanguage.English; |
settings.SecondaryLanguages = new[] {"German"} | ocr.Language = OcrLanguage.English + OcrLanguage.German; |
settings.DeskewImage = true | input.Deskew(); |
settings.DespeckleLevel = 2 | input.DeNoise(); |
settings.ContrastEnhancement = true | input.Contrast(); |
settings.AutoRotate = true | input.Deskew(); (obejmuje korekcję obrotową) |
document.SaveAs(path, outputSettings) | result.SaveAsSearchablePdf(path) |
OutputFormat.SearchablePDF | result.SaveAsSearchablePdf(path) |
OutputFormat.XML (ze współrzędnymi) | result.Pages / .Paragraphs / .Words struktura obiektowa |
FormZone z granicami współrzędnych | new CropRectangle(x, y, width, height) |
| Licencjonowanie na stronę | Nie dotyczy |
.lic wdrożenie pliku | Nie dotyczy |
| Konfiguracja serwera licencji | Nie dotyczy |
Typowe problemy związane z migracją i ich rozwiązania
Problem 1: Wyjątki związane z brakiem pliku licencji w środowisku produkcyjnym
Kofax OmniPage: Każde wdrożenie wymaga, aby plik .lic istniał na konkretnej ścieżce dostępnej dla procesu aplikacji. Pipeline wdrożeniowy, który nie kopiuje wyraźnie pliku licencji na serwer docelowy, powoduje FileNotFoundException lub LicenseException podczas inicjalizacji silnika. Zespoły ds. bezpieczeństwa często zaznaczają osadzanie plików .lic w obrazach kontenerów lub ich commitowanie w kontrolę źródła.
**Rozwiązanie:**IronOCR odczytuje swoją licencję z ciągu znaków. Zapisz klucz jako zmienną środowiskową i odczytaj go podczas uruchamiania — bez konieczności wdrażania pliku ani konfigurowania ścieżki:
// At application startup — reads IRONOCR_LICENSE_KEY from environment
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
?? throw new InvalidOperationException("IronOCR license key not configured.");
W Dockerze przekaż --env IRONOCR_LICENSE_KEY=YOUR-KEY. W usłudze Azure App Service należy ustawić to jako ustawienie aplikacji. W Kubernetes należy wprowadzić to za pomocą Secret. Brak montowania plików, brak konfiguracji ścieżek, brak weryfikacji bezpieczeństwa wbudowanych plików licencyjnych.
Problem 2: Blokada licencji typu floating po awarii procesu
Kofax OmniPage: Kiedy proces aplikacji ulega awarii, jest zabijany przez watchdog, lub kończy się przez Environment.FailFast, engine.Shutdown() nie wykonuje się. Licencje typu floating pozostają wypożyczone do momentu wygaśnięcia limitu czasu serwera licencji — zazwyczaj 30–60 minut. W środowisku kontenerowym, gdzie pody często się restartują, takie zachowanie wyczerpuje pulę licencji.
**Rozwiązanie:**IronOCR nie obsługuje koncepcji wypożyczonych licencji. Awaria procesu nie zwalnia żadnych zasobów i nie blokuje żadnego systemu zewnętrznego. Kolejny proces rozpoczyna się natychmiast, bez czekania na dostępność miejsc:
// IronOCR: Process crash has no license implications whatsoever
// Start processing immediately after any failure
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var result = new IronTesseract().Read("document.jpg"); // Nie seat to check out
Aby uzyskać informacje na temat odpornych usług .NET Core, zapoznaj się z przewodnikiem dotyczącym asynchronicznego OCR, w którym opisano wzorce umożliwiające płynną integrację z usługami hostowanymi oraz płynne wyłączanie.
Problem 3: Błąd tworzenia obrazu Docker — instalator nie może działać w trybie nieinteraktywnym
Kofax OmniPage: Instalator OmniPage SDK jest interaktywnym lub półinteraktywnym instalatorem, który nie działa poprawnie w kontekście docker build. Zespoły próbujące wbudować SDK w obraz kontenera napotykają błędy w umowie licencyjnej instalatora lub na etapach wyboru komponentów. Rozwiązania alternatywne (parametry cichej instalacji, wstępnie wyodrębnione kopie bibliotek DLL) nie są udokumentowane i zależą od konkretnej wersji.
Rozwiązanie: Dockerfile z IronOCR to trzy linie:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y libgdiplus # Single Linux dependency
COPY --from=build /app/publish /app
WORKDIR /app
ENTRYPOINT ["dotnet", "YourApp.dll"]
libgdiplus jest jedyną zależnością systemową. Pakiet NuGet IronOCR jest przywracany przez dotnet restore wewnątrz etapu budowy jak każda inna referencja pakietu. Przewodnik wdrażania Docker obejmuje zarówno obrazy bazowe Debian, jak i Alpine, a przewodnik wdrażania Linux obejmuje nazwy pakietów specyficzne dla danej dystrybucji.
Problem 4: Konieczna reaktywacja po migracji maszyny wirtualnej lub automatycznym skalowaniu w chmurze
Kofax OmniPage: Aktywacja OmniPage jest powiązana z identyfikatorem sprzętu. Środowiska chmurowe, które migrują maszyny wirtualne między hostami fizycznymi, automatycznie skalują się do nowych instancji lub zastępują kontenery nowymi obrazami, powodują zmiany tożsamości sprzętu, które wymagają ponownej aktywacji. Kontaktowanie się z pomocą techniczną Tungsten w celu ponownej aktywacji w trakcie zdarzenia zwiększa ryzyko operacyjne.
Rozwiązanie: Klucz licencyjny IronOCR jest niezależny od sprzętu. Ten sam klucz działa na dowolnej maszynie, w dowolnym kontenerze, w dowolnym regionie chmury oraz dla dowolnej liczby instancji skalowanych automatycznie w ramach licencjonowanego poziomu. Bez ponownej aktywacji, bez kontaktowania się z pomocą techniczną, bez przestojów:
// Identical startup code on any hardware topology
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
bool valid = IronOcr.License.IsLicensed; // Verify without a network call
Problem 5: Obiekt RecognitionSettings nie ma odpowiednika w IronOCR
Kofax OmniPage: OmniPage używa obiektu RecognitionSettings (lub PreprocessingSettings w zależności od wersji SDK) do konfiguracji zachowania silnika na dokument. Zespoły migrujące oczekują obiektu konfiguracyjnego typu równoległego w IronOCR.
**Rozwiązanie:**IronOCR dzieli konfigurację na dwie powierzchnie: operacje wstępne na OcrInput i ustawienia silnika na IronTesseract. Nie ma obiektu ustawień do instancjonowania:
// OmniPage settings object →IronOCR method calls on OcrInput
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English; // RecognitionSettings.Language
// ocr.Configuration.TesseractVersion = ... // Engine version already optimized
using var input = new OcrInput();
input.LoadImage(imagePath);
input.Deskew(); // settings.DeskewImage = true
input.DeNoise(); // settings.DespeckleLevel = 2
input.Contrast(); // settings.ContrastEnhancement = true
var result = ocr.Read(input);
W przewodniku po korekcji jakości obrazu wymieniono wszystkie dostępne metody przetwarzania wstępnego wraz z wskazówkami dotyczącymi tego, które filtry mają zastosowanie do poszczególnych profili jakości dokumentów.
Problem 6: Pliki szablonów stref nie mogą być przenoszone bezpośrednio
Kofax OmniPage: Szablony formularzy OmniPage przechowują definicje stref w zastrzeżonych plikach szablonów .fdt lub .fpf, które definiują pozycje pól, typy rozpoznawania i zasady walidacji dla klasy dokumentu. Pliki te nie mogą być importowane przez IronOCR.
Rozwiązanie: Wyodrębnij dane współrzędnych z plików szablonów (są oparte na XML) i przekształć każdą strefę na CropRectangle. Nazwy pól stają się kluczami słownika; współrzędne stref mapują bezpośrednio na parametry (x, y, width, height):
// Convert OmniPage zone definition to IronOCR CropRectangle
// OmniPage zone: Name="TotalDue" X="490" Y="612" Width="180" Height="28"
//IronOCR equivalent:
var totalDueRegion = new CropRectangle(490, 612, 180, 28);
using var input = new OcrInput();
input.LoadImage(invoicePath, totalDueRegion);
string totalDue = new IronTesseract().Read(input).Text.Trim();
Dla dokumentów, w których strefy różnią się na stronę, załaduj ten sam obraz z różnymi wartościami CropRectangle na region, zamiast ponownie ładować plik. Przykład przycinania regionu demonstruje wiele odczytów regionów z jednego źródła obrazu.
Lista kontrolna migracji Kofax OmniPage
Przed migracją
Zidentyfikuj wszystkie punkty integracji OmniPage w kodzie źródłowym:
# Find all OmniPage namespace references
grep -r "Kofax\|OmniPage\|CSDK" --include="*.cs" --include="*.csproj" .
# Find engine lifecycle calls
grep -r "Initialize\|Shutdown\|SetLicenseFile" --include="*.cs" .
# Find document and zone creation patterns
grep -r "CreateDocument\|AddPage\|FormZone\|RecognitionSettings\|PreprocessingSettings" --include="*.cs" .
# Find output format configuration
grep -r "OutputSettings\|OutputFormat\|SaveAs\|GetText" --include="*.cs" .
# Find license file path references
grep -r "\.lic\|license\.lic\|licensePath" --include="*.cs" --include="*.config" --include="*.json" .
Sprawdź zasoby przed rozpoczęciem:
- Zliczanie plików z importami przestrzeni nazw OmniPage
- Wymienienie wszystkich definicji
FormTemplateiFormZoneoraz wyodrębnienie ich danych współrzędnych - Identyfikacja, które słowniki językowe są załadowane i mapowane na pakiety NuGet
IronOcr.Languages.* - Zwróć uwagę, jakie formaty wyjściowe są używane (PDF z możliwością wyszukiwania, zwykły tekst, XML) oraz ich odpowiedniki w IronOCR
- Zlokalizowanie wszystkich referencji plików
.licw skryptach wdrożeniowych i konfiguracji
Migracja kodu
- Usuń odniesienia DLL OmniPage ze wszystkich plików
.csproj - Uruchom
dotnet add package IronOcrw każdym projekcie, który wykonuje OCR - Dodaj pakiety językowe dla każdego używanego języka:
dotnet add package IronOcr.Languages.[Language] - Dodaj
IronOcr.License.LicenseKey = ...;w każdym punkcie wejścia aplikacji (Program.cs, Startup.cs lub host usługi) - Zastąp wszystkie
using Kofax.OmniPage.CSDK;,using CSDK;i powiązane importy przestrzeni nazw przezusing IronOcr; - Usuń wszystkie konstrukcje
OmniPageEngine,SetLicenseFilei wywołaniaInitialize - Usuń wszystkie wywołania
engine.Shutdown()i implementacjeIDisposableistniejące wyłącznie w celu zapewnienia zamknięcia - Zastąp
engine.CreateDocument()+document.AddPage()przeznew OcrInput()+input.LoadImage() - Zastąp
engine.OpenPDF()+ iterację na stronę przezinput.LoadPdf()(wszystkie strony w jednym wywołaniu) - Zastąp
engine.OpenTiff()+ pętle na klatkę przezinput.LoadImageFrames() - Zastąp
document.Recognize(settings)przeznew IronTesseract().Read(input) - Przekształć współrzędne
FormZonena instancjeCropRectangle(x, y, width, height) - Zastąp
document.GetZoneText()zinput.LoadImage(path, cropRectangle)+result.Textdla każdego regionu - Zastąp
document.SaveAs(path, outputSettings)dla wyszukiwalnego PDF przezresult.SaveAsSearchablePdf(path) - Zastąp wzorce iteratora wyników przez przejścia właściwościowe
result.Pages/.Paragraphs/.Words - Usuń obiekty
PreprocessingSettingsi zastąp flagi boolowskie wyraźnymi wywołaniami metodinput.Deskew(),input.DeNoise(),input.Contrast() - Usuń ścieżki do plików licencji ze skryptów wdrażania, plików konfiguracyjnych i szablonów infrastruktury jako kodu
Po migracji
- Sprawdź dokładność OCR na reprezentatywnej próbie ponad 100 dokumentów z rzeczywistego korpusu — porównaj z wynikami programu OmniPage wiersz po wierszu dla faktur, umów i formularzy
- Potwierdź, że ekstrakcja strefowa oparta na
CropRectanglezwraca tekst, który pasuje do wyjściaGetZoneText()OmniPage dla każdego mapowanego pola - Przetestuj przetwarzanie wielostronicowych plików PDF: sprawdź liczbę stron, kolejność stron i ciągłość tekstu
- Przetestuj przetwarzanie plików TIFF zawierających wiele klatek: upewnij się, że wszystkie klatki zostały przetworzone, a kolejność klatek została zachowana
- Sprawdź, czy pliki PDF z funkcją wyszukiwania są indeksowalne w używanym systemie zarządzania dokumentami (SharePoint, OpenText itp.)
- Przeprowadź test przetwarzania równoległego z ponad 50 dokumentami jednocześnie i upewnij się, że nie ma żadnych problemów z bezpieczeństwem wątków
- Przetestuj pokrycie pakietów językowych: załaduj każdy wcześniej używany słownik językowy przez
IronOcr.Languages.*i zweryfikuj jakość rozpoznawania - Upewnij się, że awarie procesu i ponowne uruchomienie kontenera nie wymagają żadnych działań związanych z odzyskiwaniem licencji
- Uruchom budowanie Docker na agencie CI — potwierdź, że
dotnet restorerozwiązuje IronOCR bez kroków instalacyjnych - Wyniki oceny pewności są dostępne dla każdego WORD-a i odpowiadają oczekiwaniom dotyczącym jakości danych w każdym dalszym etapie procesu walidacji
- Sprawdź, czy aplikacja uruchamia się bez obecności pliku
.licna jakiejkolwiek ścieżce
Kluczowe korzyści z migracji do IronOCR
Stopień skomplikowania wdrożenia spada z tygodni na minuty. Projekt, który wcześniej wymagał dostępu do instalatora SDK, wdrożenia pliku .lic, konfiguracji zapory sieciowej dla serwera licencji i koordynacji z zespołem infrastruktury, teraz wdraża się przez dotnet restore. Nowy programista klonuje repozytorium i uruchamia projekt. Nowy serwer produkcyjny jest udostępniany przez potok CI/CD. Obrazy kontenerów są kompilowane bez konieczności wykonywania czynności instalacyjnych.
Ryzyko licencyjne znika całkowicie. Nie ma pływających miejsc do wyczerpania, nie ma limitów czasowych na zakończenie, nie ma odcisków palców sprzętu do ponownej aktywacji i żadnych plików .lic do ochrony w potokach wdrożeniowych. Awaria aplikacji o 3 nad ranem nie powoduje zwolnienia ani zablokowania żadnych danych. Inżynier dyżurny ponownie uruchamia proces; Rozpoznawanie OCR zostanie wznowione natychmiast. Strona produktu IronOCR obejmuje wszystkie poziomy licencji.
Wdrażanie wielopłatformowe staje się standardowym celem NuGet. Komputery programistyczne z systemem macOS działają bez wyjątków platformowych. Serwery produkcyjne z systemem Linux nie wymagają wersji SDK ze stycznia 2026 r. Kontenery Docker budowane są z bazowego obrazu mcr.microsoft.com/dotnet/aspnet z jedną zależnością systemową. Ta sama referencja pakietowa IronOcr w .csproj produkuje działający build na Windows, Linux i macOS. Aby uzyskać informacje na temat konfiguracji specyficznej dla chmury, zapoznaj się z przewodnikiem wdrażania platformy Azure oraz przewodnikiem wdrażania AWS.
Równoległa przepustowość skaluje się wraz ze sprzętem. Architektura współdzielonego silnika OmniPage wymaga blokowania, które serializuje równoczesne rozpoznawanie. Stateless instancje IronTesseractIronOCR skalują się liniowo wraz z dostępnymi rdzeniami CPU. Podwojenie liczby rdzeni serwera przetwarzania wsadowego podwaja przepustowość bez zmian w konfiguracji i dodatkowych licencji.
Dostęp do danych strukturalnych jest natychmiastowy. OcrResult.Pages, Paragraphs, Lines, Words i Characters ujawniają kompletną strukturę dokumentu jako nawigowalną strukturę obiektów .NET. Pewność co do poszczególnych słów oraz współrzędne to właściwości każdego obiektu słowa. Nie ma dodatkowego potoku eksportu, konfiguracji formatu ani konieczności generowania plików wyjściowych w celu uzyskania dostępu do danych pozycyjnych.
Koszt jest stały i przewidywalny. Połączenie licencji SDK, rocznej konserwacji i opłat za wykonanie na stronę w ramach OmniPage tworzy koszt, który skaluje się wraz z wykorzystaniem i powtarza się co roku.IronOCR przy $999–$2,399 wieczyste to jednorazowy zakup. Przepustowość 500 000 stron rocznie, za które naliczane były opłaty za stronę, pozwala na zwrot kosztów licencji IronOCR w ciągu kilku tygodni. Centrum dokumentacji i samouczki IronOCR są dostępne bez umowy wsparcia technicznego.
