Przejdź do treści stopki
FILMY

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
SHELL

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
SHELL

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
$vbLabelText   $csharpLabel

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"
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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)
$vbLabelText   $csharpLabel

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)
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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')}}
YAML

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" .
SHELL

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

  1. Usuń Sdcb.PaddleOCR, Sdcb.PaddleOCR.Models.Online, Sdcb.PaddleInference.runtime.*, OpenCvSharp4 i OpenCvSharp4.runtime.* z pliku .csproj
  2. Dodaj IronOcr do pliku .csproj
  3. Dodaj pakiety IronOcr.Languages.* dla każdego języka nieanglojęzycznego, wcześniej pobranego jako model PaddleOCR
  4. Zamień wszystkie dyrektywy using Sdcb.PaddleOCR* i using OpenCvSharp na using IronOcr
  5. Dodaj IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; przy starcie aplikacji
  6. Zamień FullOcrModel models = await OnlineFullModels.*.DownloadAsync() na nic — usuń całkowicie linię
  7. Zamień new PaddleOcrAll(models) na new IronTesseract()
  8. Zamień new PaddleOcrAll(models, PaddleDevice.Gpu(deviceId: 0)) na new IronTesseract()
  9. Zamień Mat mat = Cv2.ImRead(path) na var input = new OcrInput(); input.LoadImage(path);
  10. Zamień ocr.Run(mat) na ocr.Read(input)
  11. Zamień dostęp do result.Regions na result.Pages[0].Lines lub result.Pages[0].Words
  12. Zamień region.Score >= threshold na word.Confidence >= threshold * 100
  13. Zamień region.Rect.Center.X / .Center.Y na word.X / word.Y
  14. Usuń logikę ręcznego sortowania — dane wyjściowe IronOCRsą już w kolejności odczytu
  15. Usuń katalog models/ i wszystkie pliki modelu z repozytorium i skryptów wdrożeniowych

Po migracji

  • Zweryfikuj, czy dotnet build kończy się sukcesem z zerową liczbą odniesień do Sdcb.*, OpenCvSharp lub PaddleInference w 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.

Zwróć uwagęPDFium, PaddleOCR, PDFSharp, Tesseract, iText są zarejestrowanymi znakami towarowymi ich właścicieli. Ta strona nie jest powiązana z Baidu, Chromium Project, Google, PaddlePaddle, empira Software GmbH lub iText Group. Wszystkie nazwy produktów, loga i marki są własnością ich właścicieli. Porównania mają charakter wyłącznie informacyjny i odzwierciedlają informacje dostępne publicznie w momencie pisania.

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.

Kannaopat Udonpant
Inżynier oprogramowania
Zanim stał się inżynierem oprogramowania, Kannapat ukończył doktorat z zasobów środowiskowych na Uniwersytecie Hokkaido w Japonii. W czasie studiowania, Kannapat również został członkiem Laboratorium Robotyki Pojazdów, które jest częścią Wydziału Inżynierii Bioprodukcji. W 2022 roku wykorzystał swoje umiejętności w ...
Czytaj więcej

Zespół wsparcia Iron

Jesteśmy online 24 godziny, 5 dni w tygodniu.
Czat
E-mail
Zadzwoń do mnie