Jak poprawić jakość obrazu, aby uzyskać lepsze wyniki OCR przy użyciu języka C#
Ten przewodnik przeprowadza programistów .NET przez kompletną migrację z rodziny pakietów Sdcb.PaddleOCR do IronOCR. Obejmuje to pełną ścieżkę zastąpienia: usunięcie wielopakietowego stosu PaddlePaddle, wyeliminowanie zarządzania plikami modeli i konfiguracji GPU oraz zastąpienie zależnego od OpenCV potoku wnioskowania pojedynczą instalacją NuGet. Każda sekcja jest samodzielna — nie jest wymagana wcześniejsza lektura artykułu porównawczego.
Dlaczego warto przejść z PaddleOCR
Powłoka Sdcb.PaddleOCR jest mostem utrzymywanym przez społeczność między ekosystemem Python głębokiego uczenia PaddlePaddle a .NET. Spełnia swoje zadanie, ale dźwiga na sobie cały ciężar tego mostu — pliki modeli, natywne pliki binarne do wnioskowania, OpenCV do ładowania obrazów oraz opcjonalną infrastrukturę CUDA. W przypadku większości zadań OCR w środowisku .NET jest to infrastruktura, której projekt nigdy nie potrzebował.
Trzy katalogi modeli, zanim odczytany zostanie choćby jeden znak. Potok wnioskowania PaddleOCR łączy trzy sieci neuronowe: model wykrywania, model klasyfikacji kierunku oraz model rozpoznawania. Każda sieć to osobny katalog plików .pdmodel i .pdiparams, które muszą istnieć na dysku, zanim new PaddleOcrAll(models) skompiluje się do działającego silnika. Czy te pliki dotrą za pośrednictwem wywołania pobierania asynchronicznego — które łączy się z magazynem bj.bcebos.com firmy Baidu w Chinach — czy poprzez ręcznie utrzymywane drzewo katalogów models/, programista jest stale odpowiedzialny za wersjonowanie modelu. Gdy Sdcb.PaddleOCR aktualizuje się, modele pobrane wcześniej mogą wymagać ponownego pobierania.IronOCR nie ma plików modeli, katalogów modeli ani problemów z synchronizacją wersji. Silnik jest dołączony do pakietu NuGet.
OpenCV nie jest opcjonalne. Nie ma ścieżki od ścieżki pliku do wnioskowania PaddleOCR, która omija OpenCvSharp. Każdy obraz, niezależnie od formatu, musi przejść przez Cv2.ImRead(path), aby stać się obiektem Mat, zanim ocr.Run(mat) zaakceptuje go. Oznacza to dwa dodatkowe pakiety NuGet (OpenCvSharp4 i OpenCvSharp4.runtime.win), natywne biblioteki DLL specyficzne dla platformy w wyniku wdrożenia oraz linię apt-get install libopencv-dev w pliku Dockerfile.IronOCR akceptuje ścieżki plików, strumienie, tablice bajtów i bezpośrednio System.Drawing.Bitmap. Pośrednik Mat nie istnieje.
Konfiguracja GPU to projekt trwający kilka dni. Podawane przez PaddleOCR dane dotyczące wydajności GPU — 50–100 ms na obraz w porównaniu z 300–500 ms na CPU — są prawdziwe. Aby to osiągnąć, potrzebne są sterowniki NVIDIA w określonej wersji, zestaw narzędzi CUDA 11.8 (nie 12.x), cuDNN 8.6+ umieszczone w odpowiednich lokalizacjach PATH oraz oddzielny pakiet NuGet środowiska uruchomieniowego GPU. W Dockerze obrazem bazowym musi być nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04, a host musi mieć zainstalowane nvidia-container-toolkit. Zespoły, które nie dysponują istniejącą infrastrukturą GPU, poświęcają od 2 do 8 godzin na konfigurację CUDA w każdym środowisku.IronOCR jest zaprojektowany do przetwarzania na procesorze, zapewnia czas przetwarzania 150–300 ms na obraz na standardowym sprzęcie i nie wymaga żadnej konfiguracji karty graficznej.
Artefakty wdrożenia są 4-6 razy większe. Wydajność wdrożenia PaddleOCR obejmuje paddle_inference.dll (~200MB), paddle2onnx.dll (~5MB), pliki opencv_world*.dll (~50MB łącznie) oraz katalogi modeli (~21MB). Obraz Docker zajmuje około 1,5 GB. Wdrożenie IronOCR zajmuje łącznie około 80 MB; Obraz Docker ma około 400 MB. Różnica ta ma znaczenie w CI/CD: każde uruchomienie potoku, które przywraca pakiety NuGet, musi albo pobrać modele z Baidu, albo pobrać je z oddzielnie utrzymywanej warstwy pamięci podręcznej.
Brak możliwości tworzenia plików PDF z funkcją wyszukiwania. PaddleOCR zwraca fragmenty tekstu z obrazów i nie posiada mechanizmu umożliwiającego osadzenie rozpoznanego tekstu z powrotem w pliku PDF jako warstwy z funkcją wyszukiwania. Utworzenie pliku PDF z możliwością wyszukiwania na podstawie danych wyjściowych PaddleOCR wymaga biblioteki PDF innej firmy, wstawiania warstwy tekstowej strona po stronie oraz ponownego mapowania współrzędnych.IronOCR produkuje w pełni przeszukiwalne PDF za pomocą jednej linii: result.SaveAsSearchablePdf("output.pdf").
Podstawowy problem
PaddleOCR wymaga skonfigurowania trzech katalogów modeli, zanim będzie można rozpocząć wnioskowanie:
// PaddleOCR: three model directories, all must exist and match the wrapper version
FullOcrModel models = new FullOcrModel(
LocalDetectionModel.FromDirectory("models/ch_PP-OCRv4_det_infer"), // ~5MB
LocalClassificationModel.FromDirectory("models/ch_ppocr_mobile_v2.0_cls_infer"), // ~2MB
LocalRecognitionModel.FromDirectory("models/ch_PP-OCRv4_rec_infer") // ~15MB
);
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead("document.png"); // OpenCvSharp required for every image
PaddleOcrResult result = ocr.Run(mat);
// PaddleOCR: three model directories, all must exist and match the wrapper version
FullOcrModel models = new FullOcrModel(
LocalDetectionModel.FromDirectory("models/ch_PP-OCRv4_det_infer"), // ~5MB
LocalClassificationModel.FromDirectory("models/ch_ppocr_mobile_v2.0_cls_infer"), // ~2MB
LocalRecognitionModel.FromDirectory("models/ch_PP-OCRv4_rec_infer") // ~15MB
);
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead("document.png"); // OpenCvSharp required for every image
PaddleOcrResult result = ocr.Run(mat);
Imports OpenCvSharp
Imports PaddleOCR
' PaddleOCR: three model directories, all must exist and match the wrapper version
Dim models As New FullOcrModel(
LocalDetectionModel.FromDirectory("models/ch_PP-OCRv4_det_infer"), ' ~5MB
LocalClassificationModel.FromDirectory("models/ch_ppocr_mobile_v2.0_cls_infer"), ' ~2MB
LocalRecognitionModel.FromDirectory("models/ch_PP-OCRv4_rec_infer") ' ~15MB
)
Using ocr As New PaddleOcrAll(models)
Using mat As Mat = Cv2.ImRead("document.png") ' OpenCvSharp required for every image
Dim result As PaddleOcrResult = ocr.Run(mat)
End Using
End Using
IronOCR nie posiada plików modeli, katalogów modeli ani zależności od OpenCV:
// IronOCR: one package, zero model management
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("document.png");
var result = ocr.Read(input);
Console.WriteLine(result.Text);
// IronOCR: one package, zero model management
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("document.png");
var result = ocr.Read(input);
Console.WriteLine(result.Text);
Imports IronOcr
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("document.png")
Dim result = ocr.Read(input)
Console.WriteLine(result.Text)
End Using
IronOCR vs PaddleOCR (.NET): Porównanie funkcji
Poniższa tabela przedstawia aspekty, które mają największe znaczenie podczas planowania migracji.
| Funkcja | PaddleOCR (Sdcb) | IronOCR |
|---|---|---|
| Wymagane pakiety NuGet | 4-5 | 1 |
| Wymagane pliki wzorcowe | Tak (3 katalogi, ~21 MB) | Nie (w pakiecie) |
| Źródło pobierania modelu | Serwery Baidu (bj.bcebos.com) | Przywracanie NuGet (Iron Software) |
| Zależność od OpenCV | Wymagane (OpenCvSharp4) | None |
| Obraz wejściowy | Poprzez Mat mat = Cv2.ImRead() |
Bezpośrednia ścieżka do pliku, strumień, tablica bajtów |
| Natywne wprowadzanie plików PDF | Nie | Tak (input.LoadPdf()) |
| Wynik w formacie PDF z możliwością wyszukiwania | Nie | Tak (result.SaveAsSearchablePdf()) |
| Wprowadzanie plików TIFF z wieloma ramkami | Ręczna pętla dla poszczególnych klatek | input.LoadImageFrames() |
| Obsługa GPU | Tak (wymagane CUDA 11.8 + cuDNN) | Zoptymalizowane pod kątem procesora (nie wymaga karty graficznej) |
| Wbudowane przetwarzanie wstępne | Nie (sieć neuronowa radzi sobie z odchyleniami/szumami) | Tak (Deskew, DeNoise, Contrast, Binarize, Sharpen) |
| Obsługiwane języki | 14 | 125+ |
| Metoda instalacji języka | DownloadAsync() na model językowy |
dotnet add package IronOcr.Languages.* |
| Wielojęzyczne tłumaczenie symultaniczne | Nie (oddzielny model dla każdego języka) | Tak (OcrLanguage.English + OcrLanguage.French) |
| Strukturalny wynik | result.Regions (przestrzenny, nieposortowany) |
Strony, akapity, wiersze, słowa, znaki |
| Ocena pewności | Wartość zmiennoprzecinkowa dla regionu (0-1) | Procentowy wynik za WORD (0–100) |
| Odczytywanie BarCode | Nie | Tak (ocr.Configuration.ReadBarCodes = true) |
| eksport hOCR | Nie | Tak |
| Rozmiar wdrożenia | 300–500 MB | ~80 MB |
| Rozmiar obrazu Docker | ~1,5 GB (z bazą CUDA) | ~400 MB |
| Czas rozruchu | 3–5 sekund (ładowanie modelu) | Mniej niż 1 sekunda |
| Wielopłatformowe | Windows, Linux (częściowo) | Windows, Linux, macOS, Docker, Azure, AWS |
| Kompatybilność z platformą .NET | .NET 6+ (opakowanie społecznościowe) | .NET Framework 4.6.2+, .NET 5/6/7/8/9 |
| Wsparcie komercyjne | Sprawy społeczności / GitHub | Tak (Iron Software, z umową SLA) |
| Licencja | Apache 2.0 (bezpłatna) | Perpetual ($999 Lite / $1,499 Pro / $2,999 Enterprise) |
Szybki start: Migracja z PaddleOCR (.NET) do IronOCR
Krok 1: Zastąp pakiety NuGet
Usuń wszystkie pięć pakietów związanych z PaddleOCR:
dotnet remove package Sdcb.PaddleOCR
dotnet remove package Sdcb.PaddleOCR.Models.Online
dotnet remove package Sdcb.PaddleInference.runtime.win64.mkl
dotnet remove package OpenCvSharp4
dotnet remove package OpenCvSharp4.runtime.win
dotnet remove package Sdcb.PaddleOCR
dotnet remove package Sdcb.PaddleOCR.Models.Online
dotnet remove package Sdcb.PaddleInference.runtime.win64.mkl
dotnet remove package OpenCvSharp4
dotnet remove package OpenCvSharp4.runtime.win
Jeśli zainstalowano środowisko uruchomieniowe GPU, należy je również usunąć:
dotnet remove package Sdcb.PaddleInference.runtime.win64.cuda118
dotnet remove package Sdcb.PaddleInference.runtime.win64.cuda118
Zainstaluj IronOCR ze strony pakietu NuGet:
dotnet add package IronOcr
Krok 2: Aktualizacja przestrzeni nazw
Zastąp wszystkie importy przestrzeni nazw PaddleOCR i OpenCvSharp:
// Before (PaddleOCR)
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models;
using Sdcb.PaddleOCR.Models.Online;
using Sdcb.PaddleInference;
using OpenCvSharp;
// After (IronOCR)
using IronOcr;
// Before (PaddleOCR)
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models;
using Sdcb.PaddleOCR.Models.Online;
using Sdcb.PaddleInference;
using OpenCvSharp;
// After (IronOCR)
using IronOcr;
Imports IronOcr
Imports Sdcb.PaddleOCR
Imports Sdcb.PaddleOCR.Models
Imports Sdcb.PaddleOCR.Models.Online
Imports Sdcb.PaddleInference
Imports OpenCvSharp
Krok 3: Inicjalizacja licencji
Dodaj inicjalizację licencji raz na początek aplikacji, zanim utworzona zostanie jakakolwiek instancja IronTesseract:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Bezpłatny klucz próbny jest dostępny na stronie licencyjnej IronOCR. Wersja próbna generuje pliki z znakiem wodnym i umożliwia przetestowanie wszystkich funkcji przed zakupem.
Przykłady migracji kodu
Eliminacja konfiguracji lokalnej ścieżki modelu
Projekty, które pobierają pliki modeli PaddleOCR z wyprzedzeniem, aby uniknąć połączeń z serwerami Baidu w czasie wykonywania, muszą skonfigurować trzy oddzielne ścieżki katalogów. Konfiguracja ta musi być aktualizowana przy każdej zmianie wersji opakowania.
Podejście PaddleOCR:
// Local model configuration — developer owns the directory structure
// Each wrapper update may require re-downloading model files
string modelsRoot = Path.Combine(AppContext.BaseDirectory, "models");
FullOcrModel models = new FullOcrModel(
LocalDetectionModel.FromDirectory(
Path.Combine(modelsRoot, "ch_PP-OCRv4_det_infer")),
LocalClassificationModel.FromDirectory(
Path.Combine(modelsRoot, "ch_ppocr_mobile_v2.0_cls_infer")),
LocalRecognitionModel.FromDirectory(
Path.Combine(modelsRoot, "ch_PP-OCRv4_rec_infer"))
);
// Fails at runtime if any of the three directories is missing or stale
using PaddleOcrAll ocr = new PaddleOcrAll(models)
{
AllowRotateDetection = true,
Enable180Classification = true
};
using Mat mat = Cv2.ImRead("document.png");
PaddleOcrResult result = ocr.Run(mat);
Console.WriteLine(result.Text);
// Local model configuration — developer owns the directory structure
// Each wrapper update may require re-downloading model files
string modelsRoot = Path.Combine(AppContext.BaseDirectory, "models");
FullOcrModel models = new FullOcrModel(
LocalDetectionModel.FromDirectory(
Path.Combine(modelsRoot, "ch_PP-OCRv4_det_infer")),
LocalClassificationModel.FromDirectory(
Path.Combine(modelsRoot, "ch_ppocr_mobile_v2.0_cls_infer")),
LocalRecognitionModel.FromDirectory(
Path.Combine(modelsRoot, "ch_PP-OCRv4_rec_infer"))
);
// Fails at runtime if any of the three directories is missing or stale
using PaddleOcrAll ocr = new PaddleOcrAll(models)
{
AllowRotateDetection = true,
Enable180Classification = true
};
using Mat mat = Cv2.ImRead("document.png");
PaddleOcrResult result = ocr.Run(mat);
Console.WriteLine(result.Text);
Imports System
Imports System.IO
' Local model configuration — developer owns the directory structure
' Each wrapper update may require re-downloading model files
Dim modelsRoot As String = Path.Combine(AppContext.BaseDirectory, "models")
Dim models As New FullOcrModel(
LocalDetectionModel.FromDirectory(
Path.Combine(modelsRoot, "ch_PP-OCRv4_det_infer")),
LocalClassificationModel.FromDirectory(
Path.Combine(modelsRoot, "ch_ppocr_mobile_v2.0_cls_infer")),
LocalRecognitionModel.FromDirectory(
Path.Combine(modelsRoot, "ch_PP-OCRv4_rec_infer"))
)
' Fails at runtime if any of the three directories is missing or stale
Using ocr As New PaddleOcrAll(models) With {
.AllowRotateDetection = True,
.Enable180Classification = True
}
Using mat As Mat = Cv2.ImRead("document.png")
Dim result As PaddleOcrResult = ocr.Run(mat)
Console.WriteLine(result.Text)
End Using
End Using
Podejście IronOCR:
// Nie model directories, no path configuration, no version matching
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("document.png");
var result = ocr.Read(input);
Console.WriteLine(result.Text);
// Nie model directories, no path configuration, no version matching
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("document.png");
var result = ocr.Read(input);
Console.WriteLine(result.Text);
Imports IronOcr
' Nie model directories, no path configuration, no version matching
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("document.png")
Dim result = ocr.Read(input)
Console.WriteLine(result.Text)
End Using
Drzewo katalogów models/, trzy wywołania FromDirectory() i problem synchronizacji wersji znikają. Silnik IronOCR jest dołączony do pakietu NuGet w momencie przywracania i nie wymaga rozpoznawania ścieżki uruchomieniowej. Zobacz przewodnik po instalacji IronTesseract dla opcji inicjalizacji, w tym umieszczania klucza licencyjnego w appsettings.json.
Dwustopniowa konsolidacja procesu wykrywania i rozpoznawania
Potok rotacji i orientacji PaddleOCR jest konfigurowany poprzez właściwości na PaddleOcrAll. Replikacja tego zachowania w IronOCR używa metod przetwarzania wstępnego OcrInput, które radzą sobie z tymi samymi problemami z dokumentem za pomocą prostszej powierzchni wywołania.
Podejście PaddleOCR:
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
// Separate async initialization step — blocks startup for 3-5 seconds on cold run
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models)
{
AllowRotateDetection = true, // Enables 0/90/180/270 degree rotation detection
Enable180Classification = true // Additional pass for upside-down text
};
// OpenCV Mat required — no direct file path support
using Mat mat = Cv2.ImRead("rotated-scan.png");
if (mat.Empty())
{
throw new FileNotFoundException("Image could not be loaded by OpenCvSharp");
}
// Three neural network passes: detection → classification → recognition
PaddleOcrResult result = ocr.Run(mat);
// Regions arrive in spatial order, not reading order
// Manual sort required for top-to-bottom, left-to-right output
var orderedRegions = result.Regions
.OrderBy(r => r.Rect.Center.Y)
.ThenBy(r => r.Rect.Center.X);
foreach (var region in orderedRegions)
{
Console.WriteLine($"{region.Text} (confidence: {region.Score:P1})");
}
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
// Separate async initialization step — blocks startup for 3-5 seconds on cold run
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models)
{
AllowRotateDetection = true, // Enables 0/90/180/270 degree rotation detection
Enable180Classification = true // Additional pass for upside-down text
};
// OpenCV Mat required — no direct file path support
using Mat mat = Cv2.ImRead("rotated-scan.png");
if (mat.Empty())
{
throw new FileNotFoundException("Image could not be loaded by OpenCvSharp");
}
// Three neural network passes: detection → classification → recognition
PaddleOcrResult result = ocr.Run(mat);
// Regions arrive in spatial order, not reading order
// Manual sort required for top-to-bottom, left-to-right output
var orderedRegions = result.Regions
.OrderBy(r => r.Rect.Center.Y)
.ThenBy(r => r.Rect.Center.X);
foreach (var region in orderedRegions)
{
Console.WriteLine($"{region.Text} (confidence: {region.Score:P1})");
}
Imports Sdcb.PaddleOCR
Imports Sdcb.PaddleOCR.Models.Online
Imports OpenCvSharp
' Separate async initialization step — blocks startup for 3-5 seconds on cold run
Dim models As FullOcrModel = Await OnlineFullModels.EnglishV4.DownloadAsync()
Using ocr As New PaddleOcrAll(models) With {
.AllowRotateDetection = True, ' Enables 0/90/180/270 degree rotation detection
.Enable180Classification = True ' Additional pass for upside-down text
}
' OpenCV Mat required — no direct file path support
Using mat As Mat = Cv2.ImRead("rotated-scan.png")
If mat.Empty() Then
Throw New FileNotFoundException("Image could not be loaded by OpenCvSharp")
End If
' Three neural network passes: detection → classification → recognition
Dim result As PaddleOcrResult = ocr.Run(mat)
' Regions arrive in spatial order, not reading order
' Manual sort required for top-to-bottom, left-to-right output
Dim orderedRegions = result.Regions _
.OrderBy(Function(r) r.Rect.Center.Y) _
.ThenBy(Function(r) r.Rect.Center.X)
For Each region In orderedRegions
Console.WriteLine($"{region.Text} (confidence: {region.Score:P1})")
Next
End Using
End Using
Podejście IronOCR:
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("rotated-scan.png");
input.Deskew(); // Corrects rotation and skew automatically
var result = ocr.Read(input);
// Output is already in reading order — no sort needed
foreach (var page in result.Pages)
{
foreach (var line in page.Lines)
{
Console.WriteLine($"{line.Text} (confidence: {line.Confidence}%)");
}
}
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("rotated-scan.png");
input.Deskew(); // Corrects rotation and skew automatically
var result = ocr.Read(input);
// Output is already in reading order — no sort needed
foreach (var page in result.Pages)
{
foreach (var line in page.Lines)
{
Console.WriteLine($"{line.Text} (confidence: {line.Confidence}%)");
}
}
Imports IronOcr
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("rotated-scan.png")
input.Deskew() ' Corrects rotation and skew automatically
Dim result = ocr.Read(input)
' Output is already in reading order — no sort needed
For Each page In result.Pages
For Each line In page.Lines
Console.WriteLine($"{line.Text} (confidence: {line.Confidence}%)")
Next
Next
End Using
Metoda Deskew()IronOCR obsługuje wykrywanie rotacji jako część potoku przetwarzania wstępnego. Kolekcja Lines wyników jest dostarczana w kolejności czytania przez silnik układu Tesseract, eliminując manualny wzorzec sortowania. Przewodnik po korekcji orientacji obrazu dokumentuje pełen zakres opcji obrotu i prostowania.
Usunięcie wyboru urządzeń GPU i CPU
Aplikacje PaddleOCR, które działają na wnioskowaniu GPU, niosą największą powierzchnię migracji: pakiet NuGet czasu wykonania GPU, wstępne wymagania środowiska CUDA/cuDNN i wywołanie konfiguracji PaddleDevice.Gpu(). Wszystko to jest usuwane podczas migracji.
Podejście PaddleOCR:
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using Sdcb.PaddleInference; // GPU configuration namespace
using OpenCvSharp;
// Prerequisites must exist on every deployment environment:
// - NVIDIA Driver 452.39+ (Windows) / 450.80.02+ (Linux)
// - CUDA Toolkit 11.8 (not 12.x — version must match exactly)
// - cuDNN 8.6.0+ placed in CUDA bin directory
// - dotnet add package Sdcb.PaddleInference.runtime.win64.cuda118
FullOcrModel models = await OnlineFullModels.ChineseV4.DownloadAsync();
// GPU device 0, 1000MB initial memory pool
// Throws native load exception if CUDA_PATH not set or cuDNN DLL missing
using PaddleOcrAll ocr = new PaddleOcrAll(models, PaddleDevice.Gpu(deviceId: 0))
{
AllowRotateDetection = true,
Enable180Classification = true
};
using Mat mat = Cv2.ImRead("scanned-batch.png");
PaddleOcrResult result = ocr.Run(mat);
Console.WriteLine($"Text regions: {result.Regions.Length}");
Console.WriteLine(result.Text);
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using Sdcb.PaddleInference; // GPU configuration namespace
using OpenCvSharp;
// Prerequisites must exist on every deployment environment:
// - NVIDIA Driver 452.39+ (Windows) / 450.80.02+ (Linux)
// - CUDA Toolkit 11.8 (not 12.x — version must match exactly)
// - cuDNN 8.6.0+ placed in CUDA bin directory
// - dotnet add package Sdcb.PaddleInference.runtime.win64.cuda118
FullOcrModel models = await OnlineFullModels.ChineseV4.DownloadAsync();
// GPU device 0, 1000MB initial memory pool
// Throws native load exception if CUDA_PATH not set or cuDNN DLL missing
using PaddleOcrAll ocr = new PaddleOcrAll(models, PaddleDevice.Gpu(deviceId: 0))
{
AllowRotateDetection = true,
Enable180Classification = true
};
using Mat mat = Cv2.ImRead("scanned-batch.png");
PaddleOcrResult result = ocr.Run(mat);
Console.WriteLine($"Text regions: {result.Regions.Length}");
Console.WriteLine(result.Text);
Imports Sdcb.PaddleOCR
Imports Sdcb.PaddleOCR.Models.Online
Imports Sdcb.PaddleInference ' GPU configuration namespace
Imports OpenCvSharp
' Prerequisites must exist on every deployment environment:
' - NVIDIA Driver 452.39+ (Windows) / 450.80.02+ (Linux)
' - CUDA Toolkit 11.8 (not 12.x — version must match exactly)
' - cuDNN 8.6.0+ placed in CUDA bin directory
' - dotnet add package Sdcb.PaddleInference.runtime.win64.cuda118
Dim models As FullOcrModel = Await OnlineFullModels.ChineseV4.DownloadAsync()
' GPU device 0, 1000MB initial memory pool
' Throws native load exception if CUDA_PATH not set or cuDNN DLL missing
Using ocr As New PaddleOcrAll(models, PaddleDevice.Gpu(deviceId:=0)) With {
.AllowRotateDetection = True,
.Enable180Classification = True
}
Using mat As Mat = Cv2.ImRead("scanned-batch.png")
Dim result As PaddleOcrResult = ocr.Run(mat)
Console.WriteLine($"Text regions: {result.Regions.Length}")
Console.WriteLine(result.Text)
End Using
End Using
Podejście IronOCR:
Podejście IronOCR jest identyczne jak w powyższym przykładzie — IronTesseract obsługuje ten scenariusz w tym samym wywołaniu interfejsu API. Nie są wymagane żadne pakiety GPU, żadne wymagania wstępne CUDA ani wybór urządzenia. Zamień new PaddleOcrAll(models, PaddleDevice.Gpu(deviceId: 0)) na new IronTesseract() i usuń całą konfigurację związaną z GPU.
IronOCR przetwarza jeden obraz w 150–300 ms na procesorze — szybciej niż PaddleOCR na procesorze (300–500 ms) i wystarczająco szybko dla większości obciążeń związanych z interfejsami API sieci Web i przetwarzaniem dokumentów bez infrastruktury GPU. W przypadku scenariuszy o dużej przepustowości przewodnik po optymalizacji szybkości obejmuje opcje konfiguracyjne, w tym zarządzanie wątkami i dostosowywanie trybu segmentacji stron.
Pobieranie ustrukturyzowanych danych z dokumentów
PaddleOCR zwraca płaską tablicę obiektów PaddleOcrResultRegion uporządkowanych przestrzennie, a nie według przepływu czytania. Wyodrębnianie struktury na poziomie akapitu lub wiersza wymaga ręcznej logiki grupowania opartej na bliskości ramki ograniczającej.IronOCR zapewnia hierarchiczne drzewo wyników z gwarantowaną kolejnością odczytu.
Podejście PaddleOCR:
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
using System.Collections.Generic;
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead("invoice.png");
PaddleOcrResult result = ocr.Run(mat);
// Nie paragraph or line grouping — must implement manually
// Group regions into lines by proximity on the Y axis
var lineGroups = new Dictionary<int, List<PaddleOcrResultRegion>>();
foreach (var region in result.Regions)
{
// Round Y center to nearest 15 pixels to approximate line grouping
int lineKey = (int)(region.Rect.Center.Y / 15) * 15;
if (!lineGroups.ContainsKey(lineKey))
lineGroups[lineKey] = new List<PaddleOcrResultRegion>();
lineGroups[lineKey].Add(region);
}
// Sort lines top to bottom, then regions left to right within each line
foreach (var line in lineGroups.OrderBy(kv => kv.Key))
{
var lineText = string.Join(" ", line.Value
.OrderBy(r => r.Rect.Center.X)
.Select(r => r.Text));
Console.WriteLine(lineText);
}
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
using System.Collections.Generic;
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead("invoice.png");
PaddleOcrResult result = ocr.Run(mat);
// Nie paragraph or line grouping — must implement manually
// Group regions into lines by proximity on the Y axis
var lineGroups = new Dictionary<int, List<PaddleOcrResultRegion>>();
foreach (var region in result.Regions)
{
// Round Y center to nearest 15 pixels to approximate line grouping
int lineKey = (int)(region.Rect.Center.Y / 15) * 15;
if (!lineGroups.ContainsKey(lineKey))
lineGroups[lineKey] = new List<PaddleOcrResultRegion>();
lineGroups[lineKey].Add(region);
}
// Sort lines top to bottom, then regions left to right within each line
foreach (var line in lineGroups.OrderBy(kv => kv.Key))
{
var lineText = string.Join(" ", line.Value
.OrderBy(r => r.Rect.Center.X)
.Select(r => r.Text));
Console.WriteLine(lineText);
}
Imports Sdcb.PaddleOCR
Imports Sdcb.PaddleOCR.Models.Online
Imports OpenCvSharp
Imports System.Collections.Generic
Dim models As FullOcrModel = Await OnlineFullModels.EnglishV4.DownloadAsync()
Using ocr As New PaddleOcrAll(models)
Using mat As Mat = Cv2.ImRead("invoice.png")
Dim result As PaddleOcrResult = ocr.Run(mat)
' Nie paragraph or line grouping — must implement manually
' Group regions into lines by proximity on the Y axis
Dim lineGroups As New Dictionary(Of Integer, List(Of PaddleOcrResultRegion))()
For Each region In result.Regions
' Round Y center to nearest 15 pixels to approximate line grouping
Dim lineKey As Integer = CInt(region.Rect.Center.Y / 15) * 15
If Not lineGroups.ContainsKey(lineKey) Then
lineGroups(lineKey) = New List(Of PaddleOcrResultRegion)()
End If
lineGroups(lineKey).Add(region)
Next
' Sort lines top to bottom, then regions left to right within each line
For Each line In lineGroups.OrderBy(Function(kv) kv.Key)
Dim lineText As String = String.Join(" ", line.Value _
.OrderBy(Function(r) r.Rect.Center.X) _
.Select(Function(r) r.Text))
Console.WriteLine(lineText)
Next
End Using
End Using
Podejście IronOCR:
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("invoice.png");
var result = ocr.Read(input);
// Hierarchical structure: Pages → Paragraphs → Lines → Words → Characters
// All delivered in reading order by the layout engine
foreach (var page in result.Pages)
{
Console.WriteLine($"Page {page.PageNumber} — {page.Words.Count} words");
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($" Paragraph at ({paragraph.X}, {paragraph.Y}):");
Console.WriteLine($" {paragraph.Text}");
}
}
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("invoice.png");
var result = ocr.Read(input);
// Hierarchical structure: Pages → Paragraphs → Lines → Words → Characters
// All delivered in reading order by the layout engine
foreach (var page in result.Pages)
{
Console.WriteLine($"Page {page.PageNumber} — {page.Words.Count} words");
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($" Paragraph at ({paragraph.X}, {paragraph.Y}):");
Console.WriteLine($" {paragraph.Text}");
}
}
Imports IronOcr
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("invoice.png")
Dim result = ocr.Read(input)
' Hierarchical structure: Pages → Paragraphs → Lines → Words → Characters
' All delivered in reading order by the layout engine
For Each page In result.Pages
Console.WriteLine($"Page {page.PageNumber} — {page.Words.Count} words")
For Each paragraph In page.Paragraphs
Console.WriteLine($" Paragraph at ({paragraph.X}, {paragraph.Y}):")
Console.WriteLine($" {paragraph.Text}")
Next
Next
End Using
Ręczne przybliżanie grupowania wierszy — zaokrąglanie współrzędnych Y do rozmiaru piksela — zostało zastąpione przez wbudowaną segmentację akapitów silnika układu Tesseract. Współrzędne ramki ograniczającej są dostępne na każdym poziomie hierarchii przez paragraph.X, paragraph.Y, paragraph.Width i paragraph.Height. Aby zapoznać się z pełnym drzewem wyników, zapoznaj się z przewodnikiem po wynikach strukturalnych oraz samouczkiem dotyczącym odczytywania tekstu z obrazów.
Generowanie plików PDF z możliwością wyszukiwania
PaddleOCR nie generuje plików PDF. Generowanie przeszukiwalnego PDF z wyników PaddleOCR wymaga oddzielnej biblioteki PDF, ręcznego mapowania współrzędnych z region.Rect na jednostki strony PDF i wstrzyknięcia niewidocznej warstwy tekstowej.IronOCR generuje plik PDF z możliwością wyszukiwania bezpośrednio na podstawie wyników OCR.
Podejście PaddleOCR:
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
// Requires additional package: PdfSharp, iTextSharp, or similar
// Manual coordinate remapping from OpenCV pixel space to PDF point space
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead("scanned-page.png");
PaddleOcrResult paddleResult = ocr.Run(mat);
// Nie built-in searchable PDF output — must build with external library
// region.Rect coordinates are in pixel space, PDF uses points (1 point = 1/72 inch)
// DPI conversion required for coordinate mapping
float dpiScale = 72.0f / 96.0f; // Assuming 96 DPI source image
// ... hundreds of lines of PDF construction code using external library ...
// This is permanent maintenance, not a one-time cost
Console.WriteLine("Searchable PDF output requires external PDF library and coordinate mapping.");
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
// Requires additional package: PdfSharp, iTextSharp, or similar
// Manual coordinate remapping from OpenCV pixel space to PDF point space
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead("scanned-page.png");
PaddleOcrResult paddleResult = ocr.Run(mat);
// Nie built-in searchable PDF output — must build with external library
// region.Rect coordinates are in pixel space, PDF uses points (1 point = 1/72 inch)
// DPI conversion required for coordinate mapping
float dpiScale = 72.0f / 96.0f; // Assuming 96 DPI source image
// ... hundreds of lines of PDF construction code using external library ...
// This is permanent maintenance, not a one-time cost
Console.WriteLine("Searchable PDF output requires external PDF library and coordinate mapping.");
Imports Sdcb.PaddleOCR
Imports Sdcb.PaddleOCR.Models.Online
Imports OpenCvSharp
' Requires additional package: PdfSharp, iTextSharp, or similar
' Manual coordinate remapping from OpenCV pixel space to PDF point space
Dim models As FullOcrModel = Await OnlineFullModels.EnglishV4.DownloadAsync()
Using ocr As New PaddleOcrAll(models)
Using mat As Mat = Cv2.ImRead("scanned-page.png")
Dim paddleResult As PaddleOcrResult = ocr.Run(mat)
' Nie built-in searchable PDF output — must build with external library
' region.Rect coordinates are in pixel space, PDF uses points (1 point = 1/72 inch)
' DPI conversion required for coordinate mapping
Dim dpiScale As Single = 72.0F / 96.0F ' Assuming 96 DPI source image
' ... hundreds of lines of PDF construction code using external library ...
' This is permanent maintenance, not a one-time cost
Console.WriteLine("Searchable PDF output requires external PDF library and coordinate mapping.")
End Using
End Using
Podejście IronOCR:
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("scanned-page.png");
input.Deskew();
input.DeNoise();
var result = ocr.Read(input);
// Searchable PDF in one line — no external PDF library, no coordinate mapping
result.SaveAsSearchablePdf("searchable-output.pdf");
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%");
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("scanned-page.png");
input.Deskew();
input.DeNoise();
var result = ocr.Read(input);
// Searchable PDF in one line — no external PDF library, no coordinate mapping
result.SaveAsSearchablePdf("searchable-output.pdf");
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%");
Imports IronOcr
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("scanned-page.png")
input.Deskew()
input.DeNoise()
Dim result = ocr.Read(input)
' Searchable PDF in one line — no external PDF library, no coordinate mapping
result.SaveAsSearchablePdf("searchable-output.pdf")
Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%")
End Using
Problem mapowania współrzędnych — konwersja współrzędnych pikseli OpenCV na przestrzeń punktową PDF przy prawidłowej rozdzielczości DPI — nie występuje w IronOCR. Przewodnik w formacie PDF z funkcją wyszukiwania obejmuje wydruki wielostronicowe, pliki PDF chronione hasłem oraz ustawienia jakości wydruku. Dla zespołów zajmujących się digitalizacją zeskanowanych archiwów lub tworzeniem procesów przekształcania faksów w przeszukiwalne pliki PDF to pojedyncze wywołanie metody zastępuje projekt integracji, który w innym przypadku byłby bardzo rozbudowany.
Wieloklatkowe przetwarzanie partii plików TIFF
Wielostronicowe pliki TIFF często pojawiają się w procesach skanowania dokumentów. PaddleOCR nie ma bezpośredniego wsparcia dla wielu klatek TIFF — każda klatka musi być ekstraktowana indywidualnie przy użyciu zewnętrznej biblioteki obrazów i ładowana jako oddzielny Mat.IronOCR obsługuje natywnie pliki TIFF zawierające wiele klatek.
Podejście PaddleOCR:
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
using System.Drawing; // For multi-frame TIFF extraction
using System.Drawing.Imaging;
using System.Text;
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
var fullText = new StringBuilder();
// Must use System.Drawing to extract individual TIFF frames
// OpenCvSharp cannot enumerate TIFF frames directly
using var tiff = Image.FromFile("multipage-scan.tiff");
FrameDimension dimension = new FrameDimension(tiff.FrameDimensionsList[0]);
int frameCount = tiff.GetFrameCount(dimension);
for (int i = 0; i < frameCount; i++)
{
tiff.SelectActiveFrame(dimension, i);
// Save frame to temp file — OpenCvSharp needs a file path
string tempPath = Path.GetTempFileName() + ".png";
tiff.Save(tempPath, ImageFormat.Png);
try
{
using Mat mat = Cv2.ImRead(tempPath);
PaddleOcrResult result = ocr.Run(mat);
fullText.AppendLine($"=== Frame {i + 1} ===");
fullText.AppendLine(result.Text);
}
finally
{
File.Delete(tempPath); // Must clean up temp files
}
}
Console.WriteLine(fullText.ToString());
using Sdcb.PaddleOCR;
using Sdcb.PaddleOCR.Models.Online;
using OpenCvSharp;
using System.Drawing; // For multi-frame TIFF extraction
using System.Drawing.Imaging;
using System.Text;
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
var fullText = new StringBuilder();
// Must use System.Drawing to extract individual TIFF frames
// OpenCvSharp cannot enumerate TIFF frames directly
using var tiff = Image.FromFile("multipage-scan.tiff");
FrameDimension dimension = new FrameDimension(tiff.FrameDimensionsList[0]);
int frameCount = tiff.GetFrameCount(dimension);
for (int i = 0; i < frameCount; i++)
{
tiff.SelectActiveFrame(dimension, i);
// Save frame to temp file — OpenCvSharp needs a file path
string tempPath = Path.GetTempFileName() + ".png";
tiff.Save(tempPath, ImageFormat.Png);
try
{
using Mat mat = Cv2.ImRead(tempPath);
PaddleOcrResult result = ocr.Run(mat);
fullText.AppendLine($"=== Frame {i + 1} ===");
fullText.AppendLine(result.Text);
}
finally
{
File.Delete(tempPath); // Must clean up temp files
}
}
Console.WriteLine(fullText.ToString());
Imports Sdcb.PaddleOCR
Imports Sdcb.PaddleOCR.Models.Online
Imports OpenCvSharp
Imports System.Drawing ' For multi-frame TIFF extraction
Imports System.Drawing.Imaging
Imports System.Text
Dim models As FullOcrModel = Await OnlineFullModels.EnglishV4.DownloadAsync()
Using ocr As New PaddleOcrAll(models)
Dim fullText As New StringBuilder()
' Must use System.Drawing to extract individual TIFF frames
' OpenCvSharp cannot enumerate TIFF frames directly
Using tiff As Image = Image.FromFile("multipage-scan.tiff")
Dim dimension As New FrameDimension(tiff.FrameDimensionsList(0))
Dim frameCount As Integer = tiff.GetFrameCount(dimension)
For i As Integer = 0 To frameCount - 1
tiff.SelectActiveFrame(dimension, i)
' Save frame to temp file — OpenCvSharp needs a file path
Dim tempPath As String = Path.GetTempFileName() & ".png"
tiff.Save(tempPath, ImageFormat.Png)
Try
Using mat As Mat = Cv2.ImRead(tempPath)
Dim result As PaddleOcrResult = ocr.Run(mat)
fullText.AppendLine($"=== Frame {i + 1} ===")
fullText.AppendLine(result.Text)
End Using
Finally
File.Delete(tempPath) ' Must clean up temp files
End Try
Next
End Using
Console.WriteLine(fullText.ToString())
End Using
Podejście IronOCR:
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImageFrames("multipage-scan.tiff"); // All frames in one call
var result = ocr.Read(input);
foreach (var page in result.Pages)
{
Console.WriteLine($"=== Frame {page.PageNumber} ===");
Console.WriteLine(page.Text);
}
// Optionally save the entire multi-frame result as searchable PDF
result.SaveAsSearchablePdf("multipage-searchable.pdf");
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImageFrames("multipage-scan.tiff"); // All frames in one call
var result = ocr.Read(input);
foreach (var page in result.Pages)
{
Console.WriteLine($"=== Frame {page.PageNumber} ===");
Console.WriteLine(page.Text);
}
// Optionally save the entire multi-frame result as searchable PDF
result.SaveAsSearchablePdf("multipage-searchable.pdf");
Imports IronOcr
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImageFrames("multipage-scan.tiff") ' All frames in one call
Dim result = ocr.Read(input)
For Each page In result.Pages
Console.WriteLine($"=== Frame {page.PageNumber} ===")
Console.WriteLine(page.Text)
Next
' Optionally save the entire multi-frame result as searchable PDF
result.SaveAsSearchablePdf("multipage-searchable.pdf")
End Using
Pętla ekstrakcji klatek, zależność System.Drawing, tworzenie plików tymczasowych i logika czyszczenia są usunięte.IronOCRładuje wszystkie klatki w jednym wywołaniu LoadImageFrames() i ujawnia każdą klatkę jako Page w wyniku. Przewodnik dotyczący plików wejściowych TIFF i GIF obejmuje opcje ładowania wielu klatek, selektywne zakresy klatek oraz kwestie związane z pamięcią w przypadku dużych archiwów TIFF.
Dokumentacja API PaddleOCR (.NET) do IronOCR
| PaddleOCR (Sdcb) | IronOCR | Uwagi |
|---|---|---|
Sdcb.PaddleOCR |
IronOcr |
Przestrzeń nazw |
Sdcb.PaddleOCR.Models.Online |
Nie dotyczy | Nie jest wymagana przestrzeń nazw do pozyskiwania modeli |
Sdcb.PaddleInference |
Nie dotyczy | Nie jest wymagana przestrzeń nazw backendowa |
FullOcrModel |
Nie dotyczy | Brak odpowiednika — modele są w pakiecie |
OnlineFullModels.ChineseV4.DownloadAsync() |
dotnet add package IronOcr.Languages.ChineseSimplified |
Pozyskiwanie modeli zastąpione przez NuGet |
LocalDetectionModel.FromDirectory(path) |
Nie dotyczy | Brak zarządzania ścieżkami modeli |
LocalClassificationModel.FromDirectory(path) |
Nie dotyczy | Brak zarządzania ścieżkami modeli |
LocalRecognitionModel.FromDirectory(path) |
Nie dotyczy | Brak zarządzania ścieżkami modeli |
new PaddleOcrAll(models) |
new IronTesseract() |
Instancjonowanie silnika |
new PaddleOcrAll(models, PaddleDevice.Gpu(0)) |
Nie dotyczy | Całkowicie usunięto wybór urządzeń GPU |
PaddleDevice.Cpu() |
Nie dotyczy | CPU jest jedynym trybem; nie jest potrzebny wybór |
ocr.AllowRotateDetection = true |
input.Deskew() |
Korekta rotacji |
ocr.Enable180Classification = true |
Automatyczne | Wbudowana funkcja wykrywania odwrócenia |
Cv2.ImRead(path) |
input.LoadImage(path) |
Ładowanie obrazów — nie wymaga OpenCV |
ocr.Run(mat) |
ocr.Read(input) |
Uruchom OCR |
result.Text |
result.Text |
Pełny tekst dokumentu |
result.Regions |
result.Pages[0].Lines lub .Words |
Obszary tekstu ustrukturyzowanego |
region.Text |
word.Text / line.Text |
Treść tekstowa regionu |
region.Score (float 0-1) |
word.Confidence (int 0-100) |
Wartość pewności — skala się różni |
region.Rect.Center.X |
word.X |
Pozycja pozioma |
region.Rect.Center.Y |
word.Y |
Pozycja pionowa |
region.Rect.Size.Width |
word.Width |
Szerokość ramki ograniczającej |
region.Rect.Size.Height |
word.Height |
Wysokość ramki ograniczającej |
| Nie dotyczy | input.LoadPdf(path) |
Natywne wprowadzanie plików PDF (bez odpowiednika PaddleOCR) |
| Nie dotyczy | input.LoadImageFrames(path) |
Wielokadrowy plik TIFF (brak odpowiednika w PaddleOCR) |
| Nie dotyczy | result.SaveAsSearchablePdf(path) |
Wynik w formacie PDF z możliwością wyszukiwania (bez odpowiednika PaddleOCR) |
Typowe problemy związane z migracją i ich rozwiązania
Problem 1: Niezgodność skali pewności
PaddleOCR: Pewność obszaru to float od 0,0 do 1,0. Powszechnym progiem jest region.Score >= 0.8, aby odfiltrować niskiej jakości wykrycia.
Rozwiązanie: PewnośćIronOCR to int procent od 0 do 100. Pomnóż próg PaddleOCR przez 100:
// PaddleOCR: filter at 0.8
var highConfidence = result.Regions.Where(r => r.Score >= 0.8);
//IronOCR equivalent: filter at 80
var highConfidence = result.Pages
.SelectMany(p => p.Words)
.Where(w => w.Confidence >= 80);
// PaddleOCR: filter at 0.8
var highConfidence = result.Regions.Where(r => r.Score >= 0.8);
//IronOCR equivalent: filter at 80
var highConfidence = result.Pages
.SelectMany(p => p.Words)
.Where(w => w.Confidence >= 80);
' PaddleOCR: filter at 0.8
Dim highConfidence = result.Regions.Where(Function(r) r.Score >= 0.8)
' IronOCR equivalent: filter at 80
Dim highConfidence = result.Pages _
.SelectMany(Function(p) p.Words) _
.Where(Function(w) w.Confidence >= 80)
Pewność na poziomie dokumentu jest dostępna jako result.Confidence dla szybkiej bramki jakości. Przewodnik po wskaźnikach pewności zawiera progi dla poszczególnych słów i dla całego dokumentu.
Problem 2: Założenia dotyczące kolejności czytania
PaddleOCR: result.Regions jest uporządkowana według sekwencji wykrycia, a nie kolejności czytania. Jakikolwiek kod konsumujący result.Text oczekujący wyjścia od góry do dołu, od lewej do prawej polega na ręcznym wzorze sortowania używanym w całych przykładach PaddleOCR.
Rozwiązanie: result.TextIronOCR jest już w kolejności czytania. Usuń ręczne sortowanie. W przypadku, gdy sortowanie było używane do budowania wyniku linia po linii, użyj bezpośrednio result.Pages[0].Lines:
// PaddleOCR: manual sort required for reading order
var lines = result.Regions
.OrderBy(r => r.Rect.Center.Y)
.ThenBy(r => r.Rect.Center.X)
.Select(r => r.Text);
// IronOCR: reading order is the default
var lines = result.Pages[0].Lines.Select(l => l.Text);
// PaddleOCR: manual sort required for reading order
var lines = result.Regions
.OrderBy(r => r.Rect.Center.Y)
.ThenBy(r => r.Rect.Center.X)
.Select(r => r.Text);
// IronOCR: reading order is the default
var lines = result.Pages[0].Lines.Select(l => l.Text);
Imports System.Linq
' PaddleOCR: manual sort required for reading order
Dim lines = result.Regions _
.OrderBy(Function(r) r.Rect.Center.Y) _
.ThenBy(Function(r) r.Rect.Center.X) _
.Select(Function(r) r.Text)
' IronOCR: reading order is the default
Dim lines = result.Pages(0).Lines.Select(Function(l) l.Text)
Problem 3: Kod konwersji matryc OpenCV
PaddleOCR: Niektóre bazy kodu zawierają metody pomocnicze, które ładują obrazy ze strumieni lub tablic bajtów, najpierw zapisując do pliku tymczasowego, a następnie wywołując Cv2.ImRead(). Te wzory istnieją, ponieważ Cv2.ImRead() akceptuje tylko ścieżki plików.
Rozwiązanie: OcrInputIronOCR akceptuje strumienie i tablice bajtów bezpośrednio. Usuń plik tymczasowy pośredniczący:
// PaddleOCR: stream → temp file → Mat → OCR
string tempPath = Path.GetTempFileName() + ".png";
using (var fs = File.Create(tempPath))
await imageStream.CopyToAsync(fs);
using Mat mat = Cv2.ImRead(tempPath);
PaddleOcrResult result = ocr.Run(mat);
File.Delete(tempPath);
// IronOCR: stream → OCR (no temp file)
using var input = new OcrInput();
input.LoadImage(imageStream);
var result = ocr.Read(input);
// PaddleOCR: stream → temp file → Mat → OCR
string tempPath = Path.GetTempFileName() + ".png";
using (var fs = File.Create(tempPath))
await imageStream.CopyToAsync(fs);
using Mat mat = Cv2.ImRead(tempPath);
PaddleOcrResult result = ocr.Run(mat);
File.Delete(tempPath);
// IronOCR: stream → OCR (no temp file)
using var input = new OcrInput();
input.LoadImage(imageStream);
var result = ocr.Read(input);
Imports System.IO
Imports OpenCvSharp
Imports IronOcr
' PaddleOCR: stream → temp file → Mat → OCR
Dim tempPath As String = Path.GetTempFileName() & ".png"
Using fs = File.Create(tempPath)
Await imageStream.CopyToAsync(fs)
End Using
Using mat As Mat = Cv2.ImRead(tempPath)
Dim result As PaddleOcrResult = ocr.Run(mat)
End Using
File.Delete(tempPath)
' IronOCR: stream → OCR (no temp file)
Using input As New OcrInput()
input.LoadImage(imageStream)
Dim result = ocr.Read(input)
End Using
Przewodnik po danych wejściowych strumieniowych obejmuje ładowanie strumieni z odpowiedzi HTTP, obiektów blob w bazach danych oraz strumieni pamięci.
Problem 4: Usunięcie wzorca inicjalizacji asynchronicznej
PaddleOCR: Inicjalizacja silnika jest asynchroniczna, ponieważ pobieranie modelu wymaga operacji wejścia/wyjścia sieciowego. Wymusza to asynchroniczność w całym łańcuchu wywołań, co może stanowić problem w kontekstach synchronicznych, takich jak konstruktory lub nieasynchroniczne procedury obsługi zdarzeń.
Rozwiązanie: Inicjalizacja IronOCR jest synchroniczna. new IronTesseract() nie wykonuje operacji I/O. Usuń await i modyfikator async z dowolnej metody, której jedyną operacją asynchroniczną było pobieranie modelu:
// PaddleOCR: async forced by model download
public async Task<string> ExtractTextAsync(string imagePath)
{
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead(imagePath);
return ocr.Run(mat).Text;
}
// IronOCR: synchronous — no async required unless the caller needs it
public string ExtractText(string imagePath)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage(imagePath);
return ocr.Read(input).Text;
}
// PaddleOCR: async forced by model download
public async Task<string> ExtractTextAsync(string imagePath)
{
FullOcrModel models = await OnlineFullModels.EnglishV4.DownloadAsync();
using PaddleOcrAll ocr = new PaddleOcrAll(models);
using Mat mat = Cv2.ImRead(imagePath);
return ocr.Run(mat).Text;
}
// IronOCR: synchronous — no async required unless the caller needs it
public string ExtractText(string imagePath)
{
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage(imagePath);
return ocr.Read(input).Text;
}
Imports System.Threading.Tasks
' PaddleOCR: async forced by model download
Public Async Function ExtractTextAsync(imagePath As String) As Task(Of String)
Dim models As FullOcrModel = Await OnlineFullModels.EnglishV4.DownloadAsync()
Using ocr As New PaddleOcrAll(models)
Using mat As Mat = Cv2.ImRead(imagePath)
Return ocr.Run(mat).Text
End Using
End Using
End Function
' IronOCR: synchronous — no async required unless the caller needs it
Public Function ExtractText(imagePath As String) As String
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage(imagePath)
Return ocr.Read(input).Text
End Using
End Function
IronOCR zapewnia również natywną obsługę asynchroniczną za pośrednictwem ocr.ReadAsync(input), gdy rzeczywiście potrzebne jest wykonanie nieblokujące w kontekście asynchronicznym.
Problem 5: Czyszczenie etapów kompilacji Docker
PaddleOCR: Plik Dockerfile zawiera apt-get install libopencv-dev, instrukcję COPY models/ /app/models/ i często krok RUN wstępnego pobierania modeli. Obraz bazowy to często obraz NVIDIA CUDA dla wdrożeń GPU.
Rozwiązanie: Usuń wszystkie instrukcje Dockerfile specyficzne dla PaddleOCR. Obraz Docker IronOCR nie wymaga żadnego specjalnego obrazu bazowego ani etapu kopiowania modelu:
# PaddleOCR Dockerfile (remove all of this)
FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04
RUN apt-get update && apt-get install -y libopencv-dev libgdiplus
COPY models/ /app/models/
COPY . /app
#IronOCR Dockerfile (clean)
FROM mcr.microsoft.com/dotnet/aspnet:8.0
COPY . /app
WORKDIR /app
ENTRYPOINT ["dotnet", "YourApp.dll"]
Wynikowy obraz zmniejsza się z około 1,5 GB do około 400 MB. Przewodnik wdrażania Docker obejmuje wymagania dotyczące bibliotek systemu Linux oraz kompilacje wieloarchitektoniczne.
Problem 6: Unieważnianie pamięci podręcznej modelu CI/CD
PaddleOCR: Potoki CI/CD, które buforują etap przywracania NuGet, muszą oddzielnie zarządzać buforowaniem plików modeli. Powszechnym wzorem jest buforowanie folderu models/ między uruchomieniami. Gdy wersja opakowania ulega aktualizacji, zmienia się klucz pamięci podręcznej i modele muszą zostać ponownie pobrane z serwerów Baidu, co wydłuża proces o 30–60 sekund.
Rozwiązanie:IronOCR nie posiada katalogu pamięci podręcznej modeli. Jedyna wymagana pamięć podręczna to standardowa pamięć podręczna pakietów NuGet. Brak oddzielnego etapu buforowania, brak unieważniania pamięci podręcznej przy aktualizacjach opakowania, brak pobierania z serwerów stron trzecich podczas CI:
# Remove from CI/CD pipeline:
# - name: Cache PaddleOCR models
# uses: actions/cache@v3
# with:
# path: models/
# key: paddleocr-models-${{env.PADDLEOCR_VERSION}}
#IronOCR only needs standard NuGet caching:
- name: Cache NuGet packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: nuget-${{hashFiles('**/*.csproj')}}
# Remove from CI/CD pipeline:
# - name: Cache PaddleOCR models
# uses: actions/cache@v3
# with:
# path: models/
# key: paddleocr-models-${{env.PADDLEOCR_VERSION}}
#IronOCR only needs standard NuGet caching:
- name: Cache NuGet packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
key: nuget-${{hashFiles('**/*.csproj')}}
Lista kontrolna migracji PaddleOCR (.NET)
Przed migracją
Przed wprowadzeniem jakichkolwiek zmian należy przeprowadzić audyt kodu źródłowego w celu zidentyfikowania wszystkich miejsc użycia PaddleOCR:
# Find all PaddleOCR namespace imports
grep -rn "using Sdcb.PaddleOCR" --include="*.cs" .
# Find all OpenCvSharp imports (added as PaddleOCR dependency)
grep -rn "using OpenCvSharp" --include="*.cs" .
# Find all Mat usage patterns
grep -rn "Cv2\.ImRead\|new Mat\|Mat mat" --include="*.cs" .
# Find all async model download calls
grep -rn "DownloadAsync\|OnlineFullModels\|LocalDetectionModel" --include="*.cs" .
# Find all GPU device configuration
grep -rn "PaddleDevice\|EnableUseGpu\|cuda" --include="*.cs" .
# Find all result region access patterns
grep -rn "result\.Regions\|region\.Score\|region\.Rect" --include="*.cs" .
# Locate model directory references in configuration files
grep -rn "PP-OCRv4\|cls_infer\|det_infer\|rec_infer" --include="*.cs" --include="*.json" --include="*.yaml" .
# Find all PaddleOCR namespace imports
grep -rn "using Sdcb.PaddleOCR" --include="*.cs" .
# Find all OpenCvSharp imports (added as PaddleOCR dependency)
grep -rn "using OpenCvSharp" --include="*.cs" .
# Find all Mat usage patterns
grep -rn "Cv2\.ImRead\|new Mat\|Mat mat" --include="*.cs" .
# Find all async model download calls
grep -rn "DownloadAsync\|OnlineFullModels\|LocalDetectionModel" --include="*.cs" .
# Find all GPU device configuration
grep -rn "PaddleDevice\|EnableUseGpu\|cuda" --include="*.cs" .
# Find all result region access patterns
grep -rn "result\.Regions\|region\.Score\|region\.Rect" --include="*.cs" .
# Locate model directory references in configuration files
grep -rn "PP-OCRv4\|cls_infer\|det_infer\|rec_infer" --include="*.cs" --include="*.json" --include="*.yaml" .
Zinwentaryzuj katalogi modeli i zanotuj całkowity rozmiar. Zidentyfikuj, które modele językowe są używane (chiński, angielski, japoński itd.), aby określić, które pakiety IronOcr.Languages.* dodać. Zwróć uwagę, czy występuje konfiguracja GPU — te pliki wymagają najwięcej pracy przy czyszczeniu.
Migracja kodu
- Usuń
Sdcb.PaddleOCR,Sdcb.PaddleOCR.Models.Online,Sdcb.PaddleInference.runtime.*,OpenCvSharp4iOpenCvSharp4.runtime.*z pliku.csproj - Dodaj
IronOcrdo pliku.csproj - Dodaj pakiety
IronOcr.Languages.*dla każdego języka nieanglojęzycznego, wcześniej pobranego jako model PaddleOCR - Zamień wszystkie dyrektywy
using Sdcb.PaddleOCR*iusing OpenCvSharpnausing IronOcr - Dodaj
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";przy starcie aplikacji - Zamień
FullOcrModel models = await OnlineFullModels.*.DownloadAsync()na nic — usuń całkowicie linię - Zamień
new PaddleOcrAll(models)nanew IronTesseract() - Zamień
new PaddleOcrAll(models, PaddleDevice.Gpu(deviceId: 0))nanew IronTesseract() - Zamień
Mat mat = Cv2.ImRead(path)navar input = new OcrInput(); input.LoadImage(path); - Zamień
ocr.Run(mat)naocr.Read(input) - Zamień dostęp do
result.Regionsnaresult.Pages[0].Lineslubresult.Pages[0].Words - Zamień
region.Score >= thresholdnaword.Confidence >= threshold * 100 - Zamień
region.Rect.Center.X / .Center.Ynaword.X / word.Y - Usuń logikę ręcznego sortowania — dane wyjściowe IronOCRsą już w kolejności odczytu
- Usuń katalog
models/i wszystkie pliki modelu z repozytorium i skryptów wdrożeniowych
Po migracji
- Zweryfikuj, czy
dotnet buildkończy się sukcesem z zerową liczbą odniesień doSdcb.*,OpenCvSharplubPaddleInferencew wyniku kompilacji - Uruchom OCR na tym samym reprezentatywnym zestawie dokumentów, który został użyty do walidacji wyników PaddleOCR, i porównaj dokładność tekstu
- Sprawdź, czy wartości pewności są odczytywane jako liczby całkowite z zakresu 0–100 (a nie liczby zmiennoprzecinkowe z zakresu 0–1) we wszystkich punktach filtrowania
- Sprawdź, czy kolejność czytania jest poprawna bez ręcznego sortowania — zwróć szczególną uwagę na układy wielokolumnowe i faktury
- Przetestuj, czy kompilacja obrazu Docker kończy się bez obrazu bazowego CUDA lub
apt-get install libopencv-dev - Sprawdź, czy rozmiar obrazu Docker nie przekracza 500 MB
- Uruchom potok CI/CD od początku do końca i sprawdź, czy podczas kompilacji nie dochodzi do żadnych zewnętrznych pobrań
- Przetestuj wdrożenie w izolacji sieciowej: sprawdź, czy aplikacja uruchamia się i przetwarza dokumenty bez połączeń wychodzących z sieci
- W przypadku plików wejściowych TIFF zawierających wiele klatek należy sprawdzić, czy wszystkie klatki zostały przetworzone, a liczba klatek odpowiada plikówi źródłowemu
- W przypadku dowolnych wejść PDF zweryfikuj, czy
input.LoadPdf()produkuje tę samą liczbę stron i treść tekstu, co poprzednia konwersja oparta na PdfiumViewer
Kluczowe korzyści z migracji do IronOCR
Artefakty wdrożenia kurczą się o 80 procent. Powierzchnia wdrożenia PaddleOCR — paddle_inference.dll, biblioteki DLL OpenCV i trzy katalogi modeli — dodaje 300–500 MB do każdego celu wdrożenia. Po migracji rozmiar wdrożenia IronOCR wynosi około 80 MB. Rozmiar obrazów Docker zmniejsza się z ~1,5 GB do ~400 MB. Uruchamianie kontenerów jest szybsze, koszty przechowywania są niższe, a potoki wdrażania, które wcześniej przesyłały 500 MB artefaktów, teraz przesyłają 80 MB.
Czas uruchamiania z zimnego startu skraca się z sekund do milisekund. PaddleOCR ładuje trzy pliki modeli sieci neuronowych z dysku podczas pierwszej inferencji, co powoduje 3–5-sekundową przerwę przed zwrotem pierwszego wywołania. W funkcjach bezserwerowych, scenariuszach automatycznego skalowania lub w każdym kontekście, w którym nowe instancje są uruchamiane na żądanie, za ten zimny start płaci się wielokrotnie. Silnik IronOCR jest dołączony do pakietu i uruchamia się w mniej niż sekundę. Podstawowy przykład OCR ilustruje wzorzec inicjalizacji.
Zakres językowy rozszerza się z 14 do 125 bez konieczności prac infrastrukturalnych. PaddleOCR obsługuje 14 języków. Dodanie dowolnego z 111 języków obsługiwanych przez IronOCR, wykraczających poza limit PaddleOCR, wymaga jedynie dodania jednego pakietu NuGet dla każdego języka — bez pobierania modeli, zarządzania katalogami ani synchronizacji wersji. Zespoły, których liczba dokumentów rozszerza się na nowe rynki, nie muszą zajmować się przepisywaniem ani nowym projektem infrastrukturalnym, aby dodać obsługę OCR w języku polskim, wietnamskim, greckim lub hebrajskim. Pełny katalog języków zawiera wszystkie ponad 125 dostępnych pakietów.
Wynik w formacie PDF z możliwością wyszukiwania wymaga jednej linii. PaddleOCR zwraca regiony tekstowe. Przekształcenie tych obszarów w warstwę PDF z możliwością wyszukiwania wymaga oddzielnej biblioteki PDF, konwersji współrzędnych piksel-punkt oraz kodu do wstawiania niewidocznego tekstu, co staje się stałym elementem konserwacji. Po migracji result.SaveAsSearchablePdf("output.pdf") zastępuje cały ten podsystem. Bezpośrednie korzyści odnoszą procesy archiwizacji zeskanowanych dokumentów, potoki faks-do-PDF oraz integracje z systemami zarządzania dokumentami. Poradnik w formacie PDF z funkcją wyszukiwania oraz wpis na blogu dotyczący ekstrakcji danych z plików PDF obejmują wszystkie dostępne opcje wyjściowe.
Brak zewnętrznych połączeń sieciowych na żadnym etapie. PaddleOCR łączy się z magazynem bj.bcebos.com firmy Baidu w celu pobierania modeli. W środowiskach, w których połączenia wychodzące są ograniczone — sieciach rządowych, systemach typu air-gapped, infrastrukturze usług finansowych — połączenie to wymaga albo wyjątku w zaporze sieciowej, albo procesu pobierania z wyprzedzeniem, co zwiększa złożoność CI/CD.IronOCR nie nawiązuje żadnych połączeń zewnętrznych podczas działania. Modele przywracają się jako część dotnet restore z NuGet i są obecne w wyniku wdrożenia. Przewodnik wdrażania AWS i przewodnik wdrażania Azure obejmują konfigurację specyficzną dla chmury w środowiskach z ograniczeniami sieciowymi.
Jeden kontakt komercyjny dla całego stosu OCR. Problemy PaddleOCR obejmują powłokę Sdcb.PaddleOCR (GitHub społecznościowy), framework PaddlePaddle (Baidu), OpenCvSharp (społeczność) i CUDA/cuDNN (NVIDIA). Każda warstwa ma inny kanał wsparcia, bez gwarancji czasu odpowiedzi.IronOCR to pojedynczy produkt firmy Iron Software z komercyjnym wsparciem e-mailowym i poziomami priorytetowej odpowiedzi. Centrum dokumentacji IronOCR gromadzi w jednym miejscu całą dokumentację API, poradniki i zasoby dotyczące rozwiązywania problemów.
Często Zadawane Pytania
Dlaczego warto przejść z PaddleOCR na IronOCR?
Typowe czynniki motywujące to eliminacja złożoności interoperacyjności COM, zastąpienie zarządzania licencjami opartego na plikach, uniknięcie rozliczeń za stronę, umożliwienie wdrażania w Dockerze/kontenerach oraz przyjęcie natywnego dla NuGet przepływu pracy, który integruje się ze standardowymi narzędziami .NET.
Jakie są główne zmiany w kodzie podczas migracji z PaddleOCR do IronOCR?
Zastąp sekwencje inicjalizacji PaddleOCR instancjonowaniem IronTesseract, usuń zarządzanie cyklem życia COM (jawne wzorce Create/Load/Close) i zaktualizuj nazwy właściwości wyników. W rezultacie znacznie zmniejsza się liczba powtarzających się linii kodu.
Jak zainstalować IronOCR, aby rozpocząć migrację?
Uruchom polecenie „Install-Package IronOcr” w konsoli menedżera pakietów lub „dotnet add package IronOcr” w interfejsie CLI. Pakiety językowe są oddzielnymi pakietami: na przykład „dotnet add package IronOcr.Languages.French” dla języka francuskiego.
Czy IronOCR dorównuje dokładnością OCR PaddleOCR w przypadku standardowych dokumentów biznesowych?
IronOCR zapewnia wysoką dokładność w przypadku standardowych treści biznesowych, w tym faktur, umów, paragonów i formularzy wypełnionych na komputerze. Filtry przetwarzania wstępnego obrazu (prostowanie, usuwanie szumów, wzmacnianie kontrastu) dodatkowo poprawiają rozpoznawanie w przypadku pogorszonej jakości danych wejściowych.
W jaki sposób IronOCR obsługuje dane językowe, które PaddleOCR instaluje oddzielnie?
Dane językowe w IronOCR są dystrybuowane jako pakiety NuGet. Polecenie „dotnet add package IronOcr.Languages.German” instaluje obsługę języka niemiećkiego. Nie wymaga to ręcznego umieszczania plików ani podawania ścieżek katalogów.
Czy migracja z PaddleOCR do IronOCR wymaga zmian w infrastrukturze wdrożeniowej?
IronOCR wymaga mniej zmian w infrastrukturze niż PaddleOCR. Nie ma ścieżek binarnych SDK, lokalizacji plików licencyjnych ani konfiguracji serwerów licencyjnych. Pakiet NuGet zawiera kompletny silnik OCR, a klucz licencyjny jest ciągiem znaków ustawionym w kodzie aplikacji.
Jak skonfigurować licencjonowanie IronOCR po migracji?
W kodzie uruchamiającym aplikację przypisz IronOcr.License.LicenseKey = „YOUR-KEY”. W Dockerze lub Kubernetesie zapisz klucz jako zmienną środowiskową i odczytaj go podczas uruchamiania. Użyj License.IsValidLicense do sprawdzenia ważności przed przyjęciem ruchu.
Czy IronOCR może przetwarzać pliki PDF w taki sam sposób jak PaddleOCR?
Tak. IronOCR odczytuje zarówno natywne, jak i zeskanowane pliki PDF. Należy utworzyć instancję IronTesseract, wywołać ocr.Read(input), gdzie input jest ścieżką do pliku PDF lub obiektem OcrPdfInput, a następnie iterować strony OcrResult. Nie jest wymagany oddzielny proces renderowania plików PDF.
W jaki sposób IronOCR radzi sobie z wątkami podczas przetwarzania dużych ilości danych?
IronTesseract można bezpiecznie instancjonować dla każdego wątku. Uruchom jedną instancję na wątek w Parallel.ForEach lub puli zadań, uruchom OCR równolegle i usuń każdą instancję po zakończeniu. Nie jest wymagany żaden stan globalny ani blokowanie.
Jakie formaty wyjściowe obsługuje IronOCR po wyodrębnieniu tekstu?
IronOCR zwraca ustrukturyzowane wyniki, w tym tekst, współrzędne słów, wyniki pewności i strukturę strony. Opcje eksportu obejmują zwykły tekst, PDF z możliwością wyszukiwania oraz obiekty wyników ustrukturyzowanych do dalszego przetwarzania.
Czy ceny IronOCR są bardziej przewidywalne niż PaddleOCR w przypadku skalowania obciążenia?
IronOCR stosuje licencję wieczystą z opłatą ryczałtową, bez opłat za stronę lub wolumen. Niezależnie od tego, czy przetwarzasz 10 000, czy 10 milionów stron, koszt licencji pozostaje stały. Opcje licencji wolumenowych i zespołowych znajdują się na stronie z cennikiem IronOCR.
Co stanie się z moimi istniejącymi testami po migracji z PaddleOCR do IronOCR?
Testy sprawdzające wyodrębnioną treść tekstową powinny nadal przechodzić pomyślnie po migracji. Testy weryfikujące wzorce wywołań API lub cykl życia obiektów COM będą wymagały aktualizacji, aby odzwierciedlały prostszy model inicjalizacji i wyników IronOCR.

