IRONSOFTWAREHOME
FILMY

Jak poprawić jakość obrazu, aby uzyskać lepsze wyniki OCR przy użyciu języka C#

Kannaopat Udonpant
Kannapat Udonpant
Updated: 1 sierpnia 2026

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);
C#

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);
C#

IronOCR vs PaddleOCR (.NET): Porównanie funkcji

Poniższa tabela przedstawia aspekty, które mają największe znaczenie podczas planowania migracji.

FunkcjaPaddleOCR (Sdcb)IronOCR
Wymagane pakiety NuGet4-51
Wymagane pliki wzorcoweTak (3 katalogi, ~21 MB)Nie (w pakiecie)
Źródło pobierania modeluSerwery Baidu (bj.bcebos.com)Przywracanie NuGet (Iron Software)
Zależność od OpenCVWymagane (OpenCvSharp4)None
Obraz wejściowyPoprzez Mat mat = Cv2.ImRead()Bezpośrednia ścieżka do pliku, strumień, tablica bajtów
Natywne wprowadzanie plików PDFNieTak (input.LoadPdf())
Wynik w formacie PDF z możliwością wyszukiwaniaNieTak (result.SaveAsSearchablePdf())
Wprowadzanie plików TIFF z wieloma ramkamiRęczna pętla dla poszczególnych klatekinput.LoadImageFrames()
Obsługa GPUTak (wymagane CUDA 11.8 + cuDNN)Zoptymalizowane pod kątem procesora (nie wymaga karty graficznej)
Wbudowane przetwarzanie wstępneNie (sieć neuronowa radzi sobie z odchyleniami/szumami)Tak (Deskew, DeNoise, Contrast, Binarize, Sharpen)
Obsługiwane języki14125+
Metoda instalacji językaDownloadAsync() na model językowydotnet add package IronOcr.Languages.*
Wielojęzyczne tłumaczenie symultaniczneNie (oddzielny model dla każdego języka)Tak (OcrLanguage.English + OcrLanguage.French)
Strukturalny wynikresult.Regions (przestrzenny, nieposortowany)Strony, akapity, wiersze, słowa, znaki
Ocena pewnościWartość zmiennoprzecinkowa dla regionu (0-1)Procentowy wynik za WORD (0–100)
Odczytywanie BarCodeNieTak (ocr.Configuration.ReadBarCodes = true)
eksport hOCRNieTak
Rozmiar wdrożenia300–500 MB~80 MB
Rozmiar obrazu Docker~1,5 GB (z bazą CUDA)~400 MB
Czas rozruchu3–5 sekund (ładowanie modelu)Mniej niż 1 sekunda
WielopłatformoweWindows, 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 komercyjneSprawy społeczności / GitHubTak (Iron Software, z umową SLA)
LicencjaApache 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
SHELL

Jeśli zainstalowano środowisko uruchomieniowe GPU, należy je również usunąć:

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;
C#

Krok 3: Inicjalizacja licencji

Dodaj inicjalizację licencji raz na początek aplikacji, zanim utworzona zostanie jakakolwiek instancja IronTesseract:

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);
C#

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);
C#

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})");
}
C#

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}%)");
    }
}
C#

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);
C#

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);
}
C#

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}");
    }
}
C#

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.");
C#

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}%");
C#

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());
C#

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");
C#

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)IronOCRUwagi
Sdcb.PaddleOCRIronOcrPrzestrzeń nazw
Sdcb.PaddleOCR.Models.OnlineNie dotyczyNie jest wymagana przestrzeń nazw do pozyskiwania modeli
Sdcb.PaddleInferenceNie dotyczyNie jest wymagana przestrzeń nazw backendowa
FullOcrModelNie dotyczyBrak odpowiednika — modele są w pakiecie
OnlineFullModels.ChineseV4.DownloadAsync()dotnet add package IronOcr.Languages.ChineseSimplifiedPozyskiwanie modeli zastąpione przez NuGet
LocalDetectionModel.FromDirectory(path)Nie dotyczyBrak zarządzania ścieżkami modeli
LocalClassificationModel.FromDirectory(path)Nie dotyczyBrak zarządzania ścieżkami modeli
LocalRecognitionModel.FromDirectory(path)Nie dotyczyBrak zarządzania ścieżkami modeli
new PaddleOcrAll(models)new IronTesseract()Instancjonowanie silnika
new PaddleOcrAll(models, PaddleDevice.Gpu(0))Nie dotyczyCałkowicie usunięto wybór urządzeń GPU
PaddleDevice.Cpu()Nie dotyczyCPU jest jedynym trybem; nie jest potrzebny wybór
ocr.AllowRotateDetection = trueinput.Deskew()Korekta rotacji
ocr.Enable180Classification = trueAutomatyczneWbudowana 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.Textresult.TextPełny tekst dokumentu
result.Regionsresult.Pages[0].Lines lub .WordsObszary tekstu ustrukturyzowanego
region.Textword.Text / line.TextTreść tekstowa regionu
region.Score (float 0-1)word.Confidence (int 0-100)Wartość pewności — skala się różni
region.Rect.Center.Xword.XPozycja pozioma
region.Rect.Center.Yword.YPozycja pionowa
region.Rect.Size.Widthword.WidthSzerokość ramki ograniczającej
region.Rect.Size.Heightword.HeightWysokość ramki ograniczającej
Nie dotyczyinput.LoadPdf(path)Natywne wprowadzanie plików PDF (bez odpowiednika PaddleOCR)
Nie dotyczyinput.LoadImageFrames(path)Wielokadrowy plik TIFF (brak odpowiednika w PaddleOCR)
Nie dotyczyresult.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);
C#

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);
C#

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);
C#

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;
}
C#

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"]
Text

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

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

Powiązane artykuły

Key in blue circle

Uzyskaj natychmiast swój darmowy 30-dniowy Klucz Testowy.

Your trial license will be sent to your email address

Brak ograniczeń. 100% dostępności. Bez karty kredytowej.

bullet_checkedNie wymaga karty kredytowej ani tworzenia kontaBrak ograniczeń. 100% dostępności. Bez karty kredytowej.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Otrzymaj swoją Konsultację Bez Zobowiązań
Wypełnij poniższy formularz lub wyślij e-mail na sales@ironsoftware.com
Twoje dane zawsze będą utrzymywane w tajemnicy.
Zaufane przez miliony inżynierów na całym świecie
Logotypy klientów Iron Software
Otrzymaj swój darmowy Klucz Próbny na 30 dni natychmiast.
Nie wymaga karty kredytowej ani tworzenia konta