Migracja z Windows.Media.OCR do IronOCR
Niniejszy przewodnik zawiera szczegółową ścieżkę migracji dla programistów .NET przechodzących z Windows.Media.OCR na IronOCR. Obejmuje on usuwanie przestrzeni nazw, zmiany w plikach projektowych, przykłady migracji kodu dla wzorców, które pojawiają się najczęściej podczas migracji, oraz praktyczną listę kontrolną do weryfikacji zakończonego przejścia.
Dlaczego warto przejść z Windows.Media.OCR (UWP/WinRT OCR)
Windows.Media.OCR działa dobrze w ramach swoich ograniczeń. Te granice są wąskie, a projekty rutynowo je przekraczają. Powody, dla których zespoły decydują się na migrację, można podzielić na przewidywalne kategorie.
Blokada TFM systemu Windows dla wszystkich celów niezwiązanych z Windows. Plik projektu musi zadeklarować net*-windows* Target Framework Moniker przed rozpoznaniem przestrzeni nazw Windows.Media.Ocr na etapie kompilacji. Deklaracja ta nie jest flagą czasu wykonania — jest to ograniczenie budowy, które propaguje się do każdego projektu, który się na użytkownika powołuje. Wspólna biblioteka usług OCR, interfejs API sieci Web, proces działający w tle w systemie Linux — wszystkie one podlegają tym samym ograniczeniom. Usunięcie tego oznacza usunięcie Windows.Media.OCR.
Dostępność języka jest określana w czasie wykonania przez system operacyjny, a nie w czasie budowania przez dewelopera. OcrEngine.TryCreateFromLanguage zwraca null, gdy żądany pakiet językowy nie jest obecny na komputerze hosta. Deweloper nie może zainstalować pakietu językowego z kodu, dołączyć go do binarnego pliku aplikacji lub zapewnić modelu zapasowego. W środowiskach zautomatyzowanych — agentach kompilacji, programach do ciągłego wdrażania, minimalnych maszynach wirtualnych w chmurze, kontenerach — pakiety językowe są rzadko instalowane. Awarie produkcyjne spowodowane brakującym pakietem językowym nie są możliwe do odtworzenia na podstawie kodu; wymagają sprawdzenia konfiguracji systemu operacyjnego na komputerze docelowym.
Brak wstępnego przetwarzania oznacza brak ścieżki odzyskiwania dla suboptymalnego wejścia. API akceptuje SoftwareBitmap i generuje tekst. Poprawa jakości obrazu między tymi dwoma punktami leży całkowicie w gestii programisty, który korzysta z oddzielnych interfejsów API Windows Imaging Component, dostępnych wyłącznie w systemie Windows. Zdjęcia z telefonów komórkowych, źle wyrównane skany płaskie i fotokopie dokumentów w sposób niezauważalny obniżają dokładność, a nie ma wbudowanego mechanizmu do diagnozowania lub poprawiania wyników.
PDF jest najpopularniejszym formatem dokumentów w procesach Enterprise. Windows.Media.OCR nie obsługuje plików PDF jako danych wejściowych. Przetwarzanie zeskanowanego pliku PDF wymaga zewnętrznego renderera, rasteryzacji strona po stronie oraz ręcznego montażu wyników. Ten renderer dodaje zależność, kwestie licencyjne i oddzielny obszar awarii — dokładnie taką złożoność, której miała uniknąć "bezpłatna i wbudowana" biblioteka.
Wdrożenie po stronie serwera nie jest strukturalnie obsługiwane. Windows.Media.OCR jest przeznaczony dla aplikacji klienckich. Uruchomienie go na Windows Server wymaga pakietu funkcji Desktop Experience, co zwiększa koszt maszyny wirtualnej i złożoność infrastruktury. Wdrożenie w Dockerze jest niemożliwe. Azure Functions na systemie Linux, AWS Lambda i dowolne obciążenia kontenerowe oparte na systemie Linux po prostu nie mogą odwoływać się do tego API.
Asynchroniczny stos WinRT jest niekompatybilny ze standardowymi wzorcami .NET. Sześć lub więcej połączonych wywołań await — StorageFile, strumień, BitmapDecoder, SoftwareBitmap, sprawdzenie wartości null, RecognizeAsync — jest wymaganych, zanim zostanie odczytany pojedynczy znak. Włączenie tego łańcucha do usługi działającej w tle, pętli Parallel.ForEach lub standardowego kontrolera ASP.NET jest kłopotliwe. Mechanizmy WinRT IAsyncOperation znajdują się pod spodem, a interakcja z modelem Task .NET tworzy subtelne przypadki brzegowe w kontekstach niezwiązanych z interfejsem użytkownika.
Podstawowy problem
Dostępność języka w Windows.Media.OCR jest nieznaną zmienną środowiska uruchomieniowego, której nie można rozwiązać w momencie wdrażania:
// Windows.Media.Ocr: language availability decided by OS admin, not the developer
// Returns null on any machine without the language pack installed
var engine = OcrEngine.TryCreateFromLanguage(
new Windows.Globalization.Language("ja-JP"));
if (engine == null)
throw new InvalidOperationException(
"Japanese OCR unavailable — install the Japanese language pack in Windows Settings.");
// Nie recovery path. Nie bundled model. Nie fallback.
// IronOCR: language availability is a NuGet package, not an OS configuration
// dotnet add package IronOcr.Languages.Japanese
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.Japanese;
var result = ocr.Read("invoice.jpg"); // Works on any OS, any machine
Console.WriteLine(result.Text);
##IronOCR a Windows.Media.Ocr (UWP/WinRT OCR): Porównanie funkcji
Poniższa tabela przedstawia pełen zakres możliwości istotnych dla decyzji dotyczących migracji.
| Funkcja | Windows.Media.Ocr | IronOCR |
|---|---|---|
| Platforma: Windows 10/11 | Tak | Tak |
| Platforma: Windows Server | Ograniczone (wymagane doświadczenie w pracy z komputerami stacjonarnymi) | Tak |
| Platforma: Linux | Nie | Tak |
| Platforma: macOS | Nie | Tak |
| Platforma: kontenery Docker | Nie | Tak |
| Platforma: Azure Functions (Linux) | Nie | Tak |
| Platforma: AWS Lambda | Nie | Tak |
| Wymagania projektu TFM | net*-windows* wymagany | Brak (standardowe pliki TFM) |
| Instalacja | Wbudowane w system Windows (bez NuGet) | Pojedynczy pakiet NuGet (IronOcr) |
| Pliki graficzne (JPG, PNG, BMP) | Tak (poprzez potok WinRT) | Tak |
| Plik wejściowy PDF | Nie | Tak (język ojczysty) |
| Wielostronicowy plik wejściowy w formacie TIFF | Nie | Tak |
| Wejście strumieniowe i tablica bajtów | Nie (tylko StorageFile) | Tak |
| Język źródłowy | Pakiety językowe zainstalowane w systemie operacyjnym | Ponad 125 pakietów NuGet w pakiecie |
| Przenośność językowa | Nie (zależne od urządzenia) | Tak (wdrożenie wraz z aplikacją) |
| Wielojęzyczne tłumaczenie symultaniczne | Nie | Tak |
| Przetwarzanie wstępne: prostowanie | Nie | Tak (input.Deskew()) |
| Przetwarzanie wstępne: usuwanie szumów | Nie | Tak (input.DeNoise()) |
| Przetwarzanie wstępne: kontrast | Nie | Tak (input.Contrast()) |
| Przetwarzanie wstępne: binarizacja | Nie | Tak (input.Binarize()) |
| Wynik w formacie PDF z możliwością wyszukiwania | Nie | Tak (result.SaveAsSearchablePdf()) |
| Wyniki pewności dla poszczególnych słów | Nie | Tak (word.Confidence) |
| Strukturalny format wyjściowy (akapity, wiersze, słowa) | Tylko wiersze | Strony, akapity, wiersze, słowa, znaki |
| Odczytywanie BarCode podczas OCR | Nie | Tak |
| OCR oparte na regionie | Nie | Tak (CropRectangle) |
| Ścieżka synchronicznego OCR | Nie | Tak |
| Przetwarzanie równoległe bezpieczne dla wątków | Ograniczone | Pełna |
| Wsparcie komercyjne | Nie (zespół ds. platformy Windows) | Tak |
| Model licencyjny | Bezpłatne (wbudowane w system Windows) | Wieczyste ($999 Lite, $1,499 Pro, $2,999 Enterprise) |
Szybki start: Migracja z Windows.Media.OCR (UWP/WinRT OCR) do IronOCR
Krok 1: Zastąp pakiet NuGet
Windows.Media.OCR nie ma pakietu NuGet — jest częścią środowiska uruchomieniowego Windows i jest rozwiązywany przez Windows TFM. Usunięcie tego oznacza usunięcie odniesień do przestrzeni nazw specyficznych dla systemu Windows oraz, w miarę możliwości, pliku Windows TFM z pliku projektu.
Usuń przestrzenie nazw Windows.Media.OCR ze wszystkich plików źródłowych:
# Audit all files referencing Windows OCR namespaces
grep -r "Windows.Media.Ocr\|Windows.Graphics.Imaging\|Windows.Storage" --include="*.cs" .
Zainstaluj IronOCR:
Pakiet NuGet IronOCR celuje w net6.0, net7.0, net8.0, i net9.0 bez platformowo specyficznych TFM-ów. Po usunięciu przestrzeni nazw OCR systemu Windows, zaktualizuj <TargetFramework> w pliku projektu z net8.0-windows10.0.19041.0 do net8.0 (lub odpowiedniej wersji), o ile w projekcie nie pozostają inne API WinRT.
Krok 2: Aktualizacja przestrzeni nazw
Zastąp trzy przestrzenie nazw Windows OCR jedną przestrzenią nazw IronOCR:
// Before (Windows.Media.Ocr)
using Windows.Media.Ocr;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Globalization;
// After (IronOCR)
using IronOcr;
Krok 3: Inicjalizacja licencji
Dodaj wywołanie inicjalizacji licencji raz przy uruchomieniu aplikacji — w Program.cs, Startup.cs lub budowniczym hosta aplikacji:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"Na stronie licencyjnej IronOCR dostępny jest bezpłatny klucz próbny, który usuwa znak wodny wersji próbnej w celach ewaluacyjnych.
Przykłady migracji kodu
Zastąpienie łańcucha asynchronicznego WinRT w usłudze działającej w tle
Windows.Media.OCR wymaga co najmniej sześciu połączonych operacji asynchronicznych przed rozpoczęciem rozpoznawania. W usłudze w tle, która przetwarza kolejkę dokumentów, ten łańcuch działa wewnątrz pętli — a usuwanie SoftwareBitmap, sprawdzanie wartości null i współpraca z WinRT IAsyncOperation dodają tarcie przy każdej iteracji.
Podejście Windows.Media.OCR:
// Windows.Media.Ocr: full async chain required per document
// Requires net8.0-windows10.0.19041.0 TFM — cannot deploy to Linux workers
public async Task<List<string>> ProcessQueueAsync(IEnumerable<string> imagePaths)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language pack installed on this machine.");
var results = new List<string>();
foreach (var path in imagePaths)
{
// Each document: 4 async steps before RecognizeAsync
var file = await StorageFile.GetFileFromPathAsync(path);
using var stream = await file.OpenAsync(FileAccessMode.Read);
var decoder = await BitmapDecoder.CreateAsync(stream);
var bitmap = await decoder.GetSoftwareBitmapAsync();
var ocrResult = await engine.RecognizeAsync(bitmap);
results.Add(ocrResult.Text);
bitmap.Dispose();
}
return results;
}
Podejście IronOCR:
// IronOCR: one call per document, no WinRT, no SoftwareBitmap, no null checks
// Runs on Windows, Linux, macOS, Docker — same binary, no TFM change
public List<string> ProcessQueue(IEnumerable<string> imagePaths)
{
var results = new List<string>();
foreach (var path in imagePaths)
{
var result = new IronTesseract().Read(path);
results.Add(result.Text);
}
return results;
}
Wersja IronOCR eliminuje StorageFile round-trip, BitmapDecoder, cykl życia SoftwareBitmap oraz zabezpieczenie ze sprawdzeniem null. Dla usług natywnych async, IronOCR zapewnia ścieżkę async integrującą się płynnie z pipeline'ami opartymi na Task bez narzutu interoperacyjnego WinRT. Przewodnik konfiguracji IronTesseract zawiera zalecenia dotyczące cyklu życia instancji w scenariuszach z kolejkami o dużej przepustowości.
Eliminacja konwersji SoftwareBitmap dla danych obrazów przechowywanych w pamięci
Aplikacje, które już mają dane obrazowe w pamięci — z pobierania sieciowego, blob bazy danych lub zwrotnym wywołaniem z kamery — muszą przekształcić te dane w SoftwareBitmap przed przetworzeniem przez Windows.Media.Ocr. Ścieżka tej konwersji przebiega przez BitmapDecoder, co wymaga strumienia, co oznacza kopiowanie tablicy bajtów do MemoryStream.IronOCR akceptuje bezpośrednio tablice bajtów i strumienie.
Podejście Windows.Media.OCR:
// Windows.Media.Ocr: byte array must travel through WinRT stream → BitmapDecoder → SoftwareBitmap
public async Task<string> RecognizeFromBytesAsync(byte[] imageBytes)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language available.");
// Copy byte array into InMemoryRandomAccessStream (WinRT type)
using var ras = new Windows.Storage.Streams.InMemoryRandomAccessStream();
using var writer = new Windows.Storage.Streams.DataWriter(ras);
writer.WriteBytes(imageBytes);
await writer.StoreAsync();
ras.Seek(0);
var decoder = await BitmapDecoder.CreateAsync(ras);
var bitmap = await decoder.GetSoftwareBitmapAsync();
var result = await engine.RecognizeAsync(bitmap);
bitmap.Dispose();
return result.Text;
}
Podejście IronOCR:
// IronOCR: byte array loads directly into OcrInput — no conversion, no WinRT types
public string RecognizeFromBytes(byte[] imageBytes)
{
using var input = new OcrInput();
input.LoadImage(imageBytes); // direct byte array load
var result = new IronTesseract().Read(input);
return result.Text;
}
Ścieżka Windows.Media.Ocr wymaga InMemoryRandomAccessStream — typu WinRT, którego nie można utworzyć poza Windows — oraz DataWriter, BitmapDecoder, i SoftwareBitmap. Ścieżka IronOCR wykorzystuje OcrInput.LoadImage(byte[]) i generuje wynik w dwóch liniach. Zobacz przewodnik wprowadzania strumienia dla wzorców ładowania opartych na Stream, które są równie proste jak wejście tablicy bajtów.
Wielojęzyczne przetwarzanie dokumentów bez koordynacji z systemem operacyjnym
Wielojęzyczny system przetwarzania faktur, który musi rozpoznawać tekst w języku angielskim, francuskim i niemiećkim w jednym przebiegu, napotyka ślepą uliczkę architektoniczną w przypadku Windows.Media.OCR. API pozwala na użycie tylko jednego języka na instancję silnika. Przetwarzanie dokumentu zawierającego różne języki wymaga albo silnika obsługującego jeden język, który dokonuje najlepszego przypuszczenia, albo trzykrotnego uruchomienia rozpoznawania i połączenia wyników — żadna z tych metod nie zapewnia wiarygodnego wyniku.
Podejście Windows.Media.OCR:
// Windows.Media.Ocr: one language per engine, no simultaneous multi-language support
// Each language requires a separate language pack installed on the machine
public async Task<string> RecognizeMultiLanguageAsync(SoftwareBitmap bitmap)
{
// Must pick ONE language — no simultaneous recognition
var engine = OcrEngine.TryCreateFromLanguage(
new Windows.Globalization.Language("en-US"));
if (engine == null)
throw new InvalidOperationException("English language pack not installed.");
// French and German text on the same document will be misrecognized
var result = await engine.RecognizeAsync(bitmap);
return result.Text;
}
Podejście IronOCR:
// IronOCR: simultaneous multi-language recognition in a single pass
// Language packs are NuGet packages — no OS coordination required
// dotnet add package IronOcr.Languages.French
// dotnet add package IronOcr.Languages.German
public string RecognizeMultiLanguage(string documentPath)
{
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English + OcrLanguage.French + OcrLanguage.German;
var result = ocr.Read(documentPath);
// Structured output: walk paragraphs with location data
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"[{paragraph.X},{paragraph.Y}] {paragraph.Text}");
}
}
return result.Text;
}
IronOCR łączy modele językowe w jednym cyklu rozpoznawania, eliminując konieczność zgadywania, jakiego języka używa dany region. Przewodnik po OCR wielu języków obejmuje instalację pakietów językowych i wartości wyliczenia OcrLanguage dla wszystkich 125+ obsługiwanych języków. Indeks języków zawiera pełny katalog, w tym skrypty CJK, arabski, hebrajski, dewanagari i cyrylicę.
Włączanie OCR po stronie serwera z przetwarzaniem równoległym
Windows.Media.OCR nie może działać w kontekście serwera w systemie Linux, nie można go wywołać ze standardowego kontrolera ASP.NET Core na hoście wielopłatformowym, a jego zachowanie jest nieokreślone, gdy jest wywoływany z wątków innych niż UI w scenariuszach serwerowych. Zespół przenoszący punkt końcowy OCR z aplikacji desktopowej działającej wyłącznie w systemie Windows do skalowalnego interfejsu API natrafia jednocześnie na wszystkie trzy ograniczenia.
Podejście Windows.Media.OCR:
// Windows.Media.Ocr: cannot run on Linux, Docker, or Azure Functions on Linux
// UWP/WinRT assumptions about thread context cause failures in ASP.NET pipelines
// The entire approach below is non-deployable outside Windows with Desktop Experience
[HttpPost("ocr")]
public async Task<IActionResult> RecognizeDocument(IFormFile file)
{
// WinRT requires STA thread context in some scenarios — not guaranteed in ASP.NET
// Cannot deploy this controller to a Linux App Service plan
using var stream = file.OpenReadStream();
// InMemoryRandomAccessStream is a WinRT type — does not exist on Linux
// var ras = new InMemoryRandomAccessStream(); // compile error on net8.0 TFM
return StatusCode(503, "Windows-only — cannot deploy cross-platform.");
}
Podejście IronOCR:
// IronOCR: ASP.NET Core controller running on Linux, Docker, or Windows — same code
[HttpPost("ocr")]
public async Task<IActionResult> RecognizeDocument(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file provided.");
using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream);
var imageBytes = memoryStream.ToArray();
using var input = new OcrInput();
input.LoadImage(imageBytes);
input.Deskew(); // straighten uploaded scans automatically
input.DeNoise(); // remove mobile camera noise
var result = new IronTesseract().Read(input);
return Ok(new
{
Text = result.Text,
Confidence = result.Confidence,
Pages = result.Pages.Count
});
}
Ten kontroler można wdrożyć w usłudze Linux App Service, Dockerze i AWS Lambda bez modyfikacji. Przewodnik wdrażania Docker obejmuje jedyną zależność apt-get wymaganą na obrazie bazowym Linux. Przewodnik wdrożeniowy Azure i przewodnik AWS zawierają instrukcje dotyczące konfiguracji specyficznej dla chmury.
Generowanie plików PDF z możliwością wyszukiwania na podstawie zeskanowanych archiwów
Windows.Media.OCR generuje ciągi tekstu zwykłego. Nie ma formatu wyjściowego poza OcrResult.Text i geometrią linii w OcrResult.Lines. Konwersja zeskanowanego archiwum na pliki PDF z możliwością wyszukiwania — powszechne wymaganie w systemach zarządzania dokumentami i procesach zapewniania zgodności — wymaga trzeciej biblioteki do utworzenia warstwy wyjściowej PDF.IronOCR natywnie tworzy pliki PDF z możliwością wyszukiwania.
Podejście Windows.Media.OCR:
// Windows.Media.Ocr: plain text output only
// Searchable PDF requires external PDF library + manual text layer construction
public async Task<string> GetTextOnlyAsync(SoftwareBitmap bitmap)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language available.");
var result = await engine.RecognizeAsync(bitmap);
// result.Text is all you get
// Producing a searchable PDF requires an entirely separate library
return result.Text;
}
Podejście IronOCR:
// IronOCR: searchable PDF output is one method call on OcrResult
public void ProcessScannedArchive(IEnumerable<string> pdfPaths, string outputDirectory)
{
foreach (var sourcePdf in pdfPaths)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(sourcePdf); // native PDF input — no external renderer
input.Deskew(); // correct scan misalignment per page
input.DeNoise(); // remove scanner speckle
var result = ocr.Read(input);
var outputFileName = Path.Combine(
outputDirectory,
Path.GetFileNameWithoutExtension(sourcePdf) + "-searchable.pdf");
result.SaveAsSearchablePdf(outputFileName);
Console.WriteLine($"Processed: {sourcePdf} → {outputFileName} " +
$"({result.Pages.Count} pages, {result.Confidence:F1}% confidence)");
}
}
Wywołanie SaveAsSearchablePdf osadza warstwę tekstową nad oryginalnym zeskanowanym obrazem, zachowując wizualną wierność przy umożliwieniu pełnotekstowego wyszukiwania i Ctrl+F w dowolnym przeglądarce PDF. Przewodnik w formacie PDF z funkcją wyszukiwania obejmuje opcje osadzania czcionek, pozycjonowania warstw tekstowych oraz generowania wielostronicowych plików wyjściowych. Przewodnik dotyczący plików PDF obejmuje pliki PDF chronione hasłem oraz wybór zakresu stron w przypadku dużych archiwów.
Pobieranie danych strukturalnych za pomocą współrzędnych na poziomie słów WORD
Windows.Media.Ocr udostępnia OcrResult.Lines z tekstem na poziomie linii i prostokątami ograniczającymi. Geometria per słowo istnieje w OcrLine.Words z OcrWord.BoundingRect, ale nie ma akapitów, nie ma wyników pewności oraz brak danych na poziomie znaków. W przypadku wyodrębniania pól formularzy lub analizowania pozycji faktur geometria linii jest niewystarczająca — do odróżnienia pól ustrukturyzowanych od otaczającego tekstu potrzebne są granice akapitów i wskaźniki pewności słów.
Podejście Windows.Media.OCR:
// Windows.Media.Ocr: line-level geometry, no paragraph grouping, no confidence scores
public async Task<List<string>> ExtractLineTextAsync(SoftwareBitmap bitmap)
{
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("No OCR language available.");
var result = await engine.RecognizeAsync(bitmap);
var lineTexts = new List<string>();
foreach (var line in result.Lines)
{
// Line text + word bounding rects — no paragraph grouping, no confidence
lineTexts.Add(line.Text);
}
return lineTexts;
}
Podejście IronOCR:
// IronOCR: full hierarchy — pages, paragraphs, lines, words, characters
// Each element carries coordinates and confidence for downstream validation
public void ExtractStructuredData(string documentPath)
{
var result = new IronTesseract().Read(documentPath);
Console.WriteLine($"Overall confidence: {result.Confidence:F1}%");
foreach (var page in result.Pages)
{
Console.WriteLine($"\n--- Page {page.PageNumber} ---");
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X},{paragraph.Y}): {paragraph.Text}");
// Filter words below confidence threshold for validation workflows
var lowConfidence = paragraph.Words
.Where(w => w.Confidence < 70)
.ToList();
if (lowConfidence.Any())
{
Console.WriteLine($" Low-confidence words: " +
string.Join(", ", lowConfidence.Select(w => $"'{w.Text}' ({w.Confidence:F0}%)")));
}
}
}
}
Ustrukturyzowany model wyników — Pages, Paragraphs, Lines, Words, Characters — dostarcza dane o współrzędnych i pewności potrzebne do ekstrakcji pól formularza, parsowania faktur oraz analizy układu dokumentów. Podręcznik odczytu wyników dokumentuje pełny graf obiektu OcrResult. Przewodnik dotyczący wskaźnika pewności wyjaśnia, jak wykorzystać wartości pewności dla poszczególnych WORDów do oznaczania niepewnych wyników w celu ich weryfikacji przez człowieka.
Odnośnik do dokumentacji API Windows.Media.OCR do IronOCR
| Windows.Media.Ocr | IronOCR |
|---|---|
OcrEngine.TryCreateFromLanguage(lang) | new IronTesseract() + ocr.Language = OcrLanguage.X |
OcrEngine.TryCreateFromUserProfileLanguages() | new IronTesseract() (domyślny angielski; (bez zwracania wartości null) |
engine.RecognizeAsync(softwareBitmap) | ocr.Read("image.jpg") lub ocr.Read(ocrInput) |
StorageFile.GetFileFromPathAsync(path) | ocr.Read("path") bezpośrednio (nie jest potrzebny uchwyt pliku) |
file.OpenAsync(FileAccessMode.Read) | Wyeliminowane — OcrInput ładuje się bezpośrednio |
BitmapDecoder.CreateAsync(stream) | input.LoadImage(stream) za pośrednictwem OcrInput |
decoder.GetSoftwareBitmapAsync() | Wyeliminowane — brak SoftwareBitmap w IronOCR |
SoftwareBitmap (typ WinRT) | Wyeliminowane — OcrInput akceptuje bajty, strumienie, ścieżki plików |
InMemoryRandomAccessStream (typ WinRT) | new MemoryStream() + input.LoadImage(stream) |
OcrResult.Text | OcrResult.Text |
OcrResult.Lines | OcrResult.Lines (także Pages, Paragraphs, Words, Characters) |
OcrLine.Text | OcrResult.Lines[i].Text |
OcrLine.Words | OcrResult.Words lub page.Paragraphs[i].Words |
OcrWord.BoundingRect | word.X, word.Y, word.Width, word.Height |
| Brak odpowiednika | result.Confidence (ogólnie) / word.Confidence (na słowo) |
| Brak odpowiednika | result.SaveAsSearchablePdf("output.pdf") |
| Brak odpowiednika | input.LoadPdf("document.pdf") |
| Brak odpowiednika | input.Deskew(), input.DeNoise(), input.Contrast() |
| Brak odpowiednika | ocr.Language = OcrLanguage.A + OcrLanguage.B (jednoczesne) |
| Brak odpowiednika | ocr.Configuration.ReadBarCodes = true |
| Brak odpowiednika | input.LoadImage(byteArray) |
Typowe problemy związane z migracją i ich rozwiązania
Problem 1: Plik projektu nadal wymaga Windows TFM po migracji
Windows.Media.Ocr: Deklaracja <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> jest wymagana do rozpoznania typów WinRT. Usunięcie odwołań do Windows.Media.OCR bez sprawdzenia innych zależności WinRT w tym samym projekcie może spowodować pozostawienie pliku TFM, uniemożliwiając kompilację międzyplatformową.
Rozwiązanie: Po usunięciu odniesień do przestrzeni nazw Windows OCR należy przeszukać projekt w poszukiwaniu wszelkich pozostałych przypadków użycia interfejsu API WinRT przed zmianą pliku TFM:
# Find remaining WinRT API usage before removing the Windows TFM
grep -r "Windows\." --include="*.cs" .
grep -r "WinRT\|IAsyncOperation\|StorageFile\|SoftwareBitmap" --include="*.cs" .
Jeśli nie pozostały żadne odniesienia do WinRT, zaktualizuj plik projektu:
<!-- Before -->
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<!-- After -->
<TargetFramework>net8.0</TargetFramework>
Jeśli inne funkcje WinRT (powiadomienia systemu Windows, integracja z powłoką, XAML) pozostają w użyciu, należy wyodrębnić wywołanie OCR za interfejsem i zapewnić implementacje specyficzne dla platformy, zamiast usuwać TFM z całego projektu.
Problem 2: Sprawdzanie silnika Null nie ma odpowiednika w IronOCR
Windows.Media.Ocr: Każde wywołanie do TryCreateFromLanguage i TryCreateFromUserProfileLanguages może zwrócić null. Cały istniejący kod zawiera klauzule zabezpieczające przed wartością null, które generują wyjątek lub powodują rozgałęzienie w przypadku silnika null.
**Rozwiązanie:**IronOCR zgłasza ustrukturyzowane wyjątki w przypadku niepowodzeń inicjalizacji zamiast zwracać wartość null. Usuń klauzule zabezpieczające przed wartością null. Użyj standardowej konstrukcji try/catch, jeśli chcesz zgłosić błędy inicjalizacji do wywołującego:
// Before: null-check pattern
var engine = OcrEngine.TryCreateFromUserProfileLanguages();
if (engine == null)
throw new InvalidOperationException("OCR unavailable.");
// After: no null — IronTesseract throws if misconfigured
try
{
var result = new IronTesseract().Read("document.jpg");
}
catch (IronOcr.Exceptions.OcrException ex)
{
// structured exception with diagnostic message
logger.LogError("OCR failed: {Message}", ex.Message);
}
Problem 3: Parametry SoftwareBitmap w istniejących sygnaturach metod
Windows.Media.Ocr: Metody pomocnicze, usługi i klasy repozytorium mogą akceptować SoftwareBitmap jako typ parametru. Te sygnatury metod nie mogą zostać skompilowane po usunięciu biblioteki Windows TFM.
Rozwiązanie: Zastąp parametry SoftwareBitmap za pomocą byte[] lub Stream. OcrInput z IronOCR akceptuje oba bezpośrednio. Miejsca wywołań, które wcześniej konstruowały SoftwareBitmap mogą zamiast tego przekazać swoje dane bazowe:
// Before: SoftwareBitmap parameter — cannot compile cross-platform
public async Task<string> RecognizeAsync(SoftwareBitmap bitmap) { ... }
// After: byte array parameter — compiles on all platforms
public string Recognize(byte[] imageBytes)
{
using var input = new OcrInput();
input.LoadImage(imageBytes);
return new IronTesseract().Read(input).Text;
}
Problem 4: Wywołujące wyłącznie asynchronicznie nie mogą bezpośrednio korzystać z synchronicznego IronOCR
Windows.Media.Ocr: Każde wywołanie rozpoznawania jest async. Wywołujący w całej bazie kodu używają await i zwracają Task<string>. Przełączenie na synchroniczną metodę Read z IronOCR wewnątrz metody async działa, ale może wprowadzić blokujące wywołania w kontekstach, w których async był architektoniczny.
**Rozwiązanie:**IronOCR zapewnia ścieżkę asynchroniczną dla wywołujących, którzy jej potrzebują. Użyj Task.Run do obliczeń wymagających CPU w istniejących metodach async, lub użyj natywnego async API:
// Option A: wrap synchronous call in Task.Run for async callers
public async Task<string> RecognizeAsync(string imagePath)
{
return await Task.Run(() => new IronTesseract().Read(imagePath).Text);
}
// Option B:IronOCR async path
// See: https://ironsoftware.com/csharp/ocr/how-to/async/
Przewodnik po asynchronicznym OCR dokumentuje wbudowany asynchroniczny interfejs API dla kontekstów, w których potrzebne są wzorce typu "fire-and-forget" lub raportowania postępów.
Problem 5: Format tagu językowego systemu Windows nie ma bezpośredniego odpowiednika
Windows.Media.Ocr: Języki są określane przy użyciu tagów string BCP-47 przekazywanych do Windows.Globalization.Language("fr-FR"). Te tagi ciągów znaków nie mają bezpośredniego odpowiednika w IronOCR.
Rozwiązanie: Mapuj języki BCP-47 do wyliczenia OcrLanguage. Mapowanie jest proste w przypadku popularnych języków:
// Before: BCP-47 string tags
var engine = OcrEngine.TryCreateFromLanguage(
new Windows.Globalization.Language("fr-FR"));
// After: OcrLanguage enum
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.French;
// Also: OcrLanguage.German, OcrLanguage.Japanese, OcrLanguage.Arabic, etc.
Pełne mapowanie jest dostępne w katalogu językowym IronOCR. Dla języków nie wymienionych w głównym wyliczeniu, wsparcie dla niestandardowych pakietów językowych obejmuje ładowanie plików .traineddata bezpośrednio.
Problem 6: FileAccessMode.Read nie ma zamiennika
Windows.Media.Ocr: file.OpenAsync(FileAccessMode.Read) to specyficzny dla WinRT wzorzec otwierania plików. Wyliczenie FileAccessMode nie istnieje w standardowym .NET.
Rozwiązanie: Zastąp standardowym System.IO.File.ReadAllBytes lub FileStream. OcrInput akceptuje obu:
// Before: WinRT file access
using var stream = await file.OpenAsync(FileAccessMode.Read);
// After: standard .NET
var imageBytes = File.ReadAllBytes(imagePath);
using var input = new OcrInput();
input.LoadImage(imageBytes);
Lista kontrolna migracji Windows.Media.OCR (UWP/WinRT OCR)
Przed migracją
Przed wprowadzeniem zmian należy przeprowadzić audyt kodu źródłowego:
# Find all Windows OCR namespace usages
grep -rn "using Windows.Media.Ocr" --include="*.cs" .
grep -rn "using Windows.Graphics.Imaging" --include="*.cs" .
grep -rn "using Windows.Storage" --include="*.cs" .
grep -rn "using Windows.Globalization" --include="*.cs" .
# Find WinRT type usages
grep -rn "OcrEngine\|SoftwareBitmap\|BitmapDecoder\|StorageFile" --include="*.cs" .
grep -rn "TryCreateFromLanguage\|TryCreateFromUserProfileLanguages\|RecognizeAsync" --include="*.cs" .
grep -rn "InMemoryRandomAccessStream\|DataWriter\|FileAccessMode" --include="*.cs" .
# Find project files with Windows TFM
grep -rn "net.*-windows" --include="*.csproj" .
# Count files requiring changes
grep -rl "Windows.Media.Ocr\|Windows.Graphics.Imaging\|SoftwareBitmap" --include="*.cs" . | wc -l
Zanotuj liczbę dotkniętych plików, używane tagi językowe ("en-US", "fr-FR", itp.) oraz czy jakiekolwiek typy WinRT pojawiają się w publicznych sygnaturach metod (wymagają one zmian w powierzchni API oprócz wewnętrznych przepisów).
Migracja kodu
- Zainstaluj pakiet NuGet
IronOcr:dotnet add package IronOcr - Dodaj wywołanie inicjalizacji licencji w
Program.cslubStartup.cs:IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; - Usuń
using Windows.Media.Ocr;ze wszystkich plików źródłowych - Usuń
using Windows.Graphics.Imaging;ze wszystkich plików źródłowych - Usuń
using Windows.Storage;ze wszystkich plików źródłowych - Usuń
using Windows.Globalization;ze wszystkich plików źródłowych - Dodaj
using IronOcr;do wszystkich plików wykonujących OCR - Zastąp każde wywołanie
OcrEngine.TryCreateFromLanguage(new Language("xx-XX"))za pomocąnew IronTesseract()i ustawocr.Language = OcrLanguage.X - Zastąp każde wywołanie
OcrEngine.TryCreateFromUserProfileLanguages()za pomocąnew IronTesseract() - Usuń wszystkie klauzule zabezpieczające przed wartością null w wynikach tworzenia silnika
- Zastąp parametry
SoftwareBitmapw sygnaturach metod za pomocąbyte[]lubStream - Zastąp łańcuchy konstrukcji
StorageFile+BitmapDecoder+SoftwareBitmapza pomocąOcrInput.LoadImage(path),OcrInput.LoadImage(bytes)lubOcrInput.LoadImage(stream) - Zastąp
engine.RecognizeAsync(bitmap)za pomocąocr.Read(path)lubocr.Read(input) - Zastąp użycie
InMemoryRandomAccessStreamiDataWriterza pomocąMemoryStream - Zastąp ciągi tagów językowych BCP-47 Windows za pomocą wartości wyliczenia
OcrLanguage; zainstaluj wymagane pakiety NuGet dla danego języka - Zaktualizuj
<TargetFramework>w plikach.csproj, aby usunąć końcówkę-windowsX.Y.Z, jeśli nie pozostały inne API WinRT
Po migracji
- Potwierdź, że projekt kompiluje się z targetem
net8.0(lub twoją wersją docelową) bez końcówki TFM Windows - Potwierdź, że projekt kompiluje się i działa w środowisku Linux lub kontenerze Docker za pomocą
mcr.microsoft.com/dotnet/aspnet:8.0 - Sprawdź, czy tekst wyjściowy OCR odpowiada oczekiwanym wynikom dla każdego typu dokumentu w Suite testów
- Sprawdź, czy wszystkie wcześniej obsługiwane języki generują poprawny wynik przy użyciu pakietów NuGet języka IronOCR
- Sprawdź, czy dokumenty wielojęzyczne dają poprawne wyniki po jednym przebiegu rozpoznawania
- Potwierdź, że nie występuje
NullReferenceExceptionaniInvalidOperationExceptionprzy inicjalizacji silnika na maszynach bez zainstalowanych pakietów językowych Windows - Zweryfikuj, że wartości
result.Confidencemieszczą się w oczekiwanych zakresach dla czystych i niskiej jakości dokumentów wejściowych - Jeśli aplikacja generuje dokumenty, zweryfikuj, że wyjście
SaveAsSearchablePdfotwiera się poprawnie w przeglądarkach PDF i obsługuje wyszukiwanie tekstu - Uruchom dowolne istniejące ścieżki przetwarzania równoległego lub wielowątkowego i sprawdź bezpieczeństwo wątków pod obciążeniem
- Wdrożenie w środowisku docelowym (Docker, Azure App Service, AWS, serwer Linux) i wykonanie co najmniej jednej pełnej operacji OCR od początku do końca
Kluczowe korzyści z migracji do IronOCR
Wdrażanie wielopłatformowe staje się decyzją konfiguracyjną, a nie koniecznością przepisywania kodu. Po migracji komponent OCR działa identycznie w systemach Windows, Linux, macOS, Docker oraz u wszystkich głównych dostawców usług w chmurze. Przeniesienie obciążenia OCR z maszyny wirtualnej Windows do kontenera Linux w celu obniżenia kosztów hostingu jest operacją wdrożeniową. Przewodnik wdrażania w systemie Linux oraz przewodnik wdrażania w Dockerze obejmują dodanie jednej linii zależności wymaganej w obrazach bazowych systemu Linux.
Obsługa języków jest dostarczana wraz z plikiem binarnym aplikacji. Pakiety językowe instaluje się jako pakiety NuGet i są one powiązane z wersją pakietu IronOCR. Zestaw języków rozpoznawanych przez aplikację jest zdefiniowany w pliku projektu i jest identyczny na każdym komputerze — stacji roboczej programisty, serwerze CI, serwerze stagingowym i hoście produkcyjnym. Nie wymaga koordynacji ze strony administratora systemu operacyjnego, wyjątków w zasadach grupy ani sprawdzania wartości null w czasie wykonywania.
Dokładność OCR poprawia się bez narzędzi zewnętrznych. Pipeline przetwarzania wstępnego — Deskew, DeNoise, Contrast, Binarize, Sharpen, Scale — działa wewnątrz IronOCR przed tym, jak silnik rozpoznawania widzi obraz. Dokumenty, które dawały gorsze wyniki przy użyciu Windows.Media.OCR z powodu niewłaściwego ustawienia skanera lub szumów, są poprawiane bez dodawania zewnętrznych zależności związanych z przetwarzaniem obrazu. Przewodnik po korekcji jakości obrazu i kreator filtrów pomagają dobrać odpowiednią kombinację filtrów dla każdego typu dokumentu.
Przepływy pracy z plikami PDF zostały skonsolidowane w jednej bibliotece. Zewnętrzny renderer PDF, który był wymagany do połączenia Windows.Media.OCR i danych wejściowych PDF, nie jest już potrzebny. Archiwa zeskanowanych PDF przetwarzane są przez to samo wywołanie IronTesseract.Read co obrazy. Wyjście w formacie PDF z możliwością wyszukiwania jest metodą obiektu wynikowego. Architektura oparta na dwóch bibliotekach znika, a wraz z nią zarządzanie wersjami, obciążenia związane z licencjonowaniem oraz powierzchnia wdrożeniowa.
Ustrukturyzowane dane wyjściowe umożliwiają pipeline'y inteligencji dokumentów. Hierarchia OcrResult — Pages, Paragraphs, Lines, Words, Characters — z współrzędnymi i wynikami pewności per element dostarcza danych wymaganych do ekstrakcji pól faktur, parsowania formularzy i klasyfikacji dokumentów. Wynik na poziomie wiersza generowany przez Windows.Media.OCR jest niewystarczający dla tych procesów. Dzięki IronOCR ekstrakcja słów z filtrowaniem pewności, wykrywanie granic akapitów oraz mapowanie pól oparte na współrzędnych to funkcje najwyższej klasy, dostępne bez dodatkowych bibliotek.
Licencja wieczysta zastępuje nieograniczoną zależność od infrastruktury. Koszt utrzymania instalacji pakietów językowych Windows na heterogenicznej flocie komputerów, licencji Windows Server Desktop Experience oraz infrastruktury CI przeznaczonej wyłącznie dla systemu Windows jest realny, ale rozproszony — pojawia się w zgłoszeniach IT i budżetach infrastrukturalnych, a nie jako pozycja w budżecie OCR. Licencja IronOCR Lite $999 eliminuje ten narzut dla projektu jednego dewelopera. Professional License w cenie 1499 USD obejmuje dziesięciu programistów. Oba produkty są dostępne w ramach jednorazowego zakupu z roczną aktualizacją w cenie.
