Przejdź do treści stopki
PORóWNAJ Z INNYMI KOMPONENTAMI

MODI OCR C# vs. IronOCR: Wybór odpowiedniej biblioteki optycznego rozpoznawania znaków w C#

TesseractOCR (fork Sicos1977) to naprawdę aktywna, nowoczesna nakładka .NET — i właśnie dlatego warto dokładnie przyjrzeć się jej ograniczeniom. W przeciwieństwie do zarchiwizowanego projektu charlesw/tesseract, ten fork jest przeznaczony dla .NET 6+ i wykorzystuje Tesseract 5.4.1. Jednak nowsza wersja nie naprawia silnika Tesseract, na którym jest oparta. Zespoły przechodzące z charlesw naTesseractOCRze względu na kompatybilność frameworków odkrywają, że wszystkie trudne problemy pozostają: zarządzanie folderem tessdata, brak wbudowanego przetwarzania wstępnego, brak natywnej obsługi PDF oraz silnik niezabezpieczony przed wielowątkowością, który wymusza jedną instancję na wątek w scenariuszach współbieżnych.

Zrozumienie TesseractOCR

TesseractOCR to opakowanie .NET na licencji Apache 2.0, utrzymywane przez Keesa van Spelde (Sicos1977) jako społecznościowy fork oryginalnego projektu charlesw/tesseract. Głównym powodem utworzenia forka były względy praktyczne: aktywność charlesw'a spadła po 2023 roku, pozostawiając programistów .NET Framework 6/7/8 bez aktualnego powiązania Tesseract z frameworkiem.TesseractOCRwypełnia tę lukę, obsługując platformy .NET 6.0, 7.0 i 8.0 oraz dołączając biblioteki natywne Tesseract 5.x dla systemów Windows x64, Linux x64 i macOS.

Architektura opiera się na opakowaniu P/Invoke: zarządzany kod .NET wywołuje natywny interfejs API Tesseract C poprzez interop. Pakiet NuGet zawiera natywne pliki binarne dla popularnych platform, co eliminuje niektóre problemy związane z wdrażaniem bibliotek natywnych, występujące w starszych opakowaniach. Jednak podstawowa konstrukcja pozostaje wąskim powiązaniem z silnikiem Tesseract — bez logiki przetwarzania wstępnego, bez potoku PDF, bez abstrakcji wątków.

Kluczowe cechy architektury:

  • Aktywna konserwacja przez jednego programistę-wolontariusza — aktualizacje są dostarczane, ale nie ma umowy SLA, nie ma wsparcia komercyjnego, a współczynnik awaryjności wynosi jeden
  • Obejmuje Tesseract 5.5.0 — dostępne są najnowsze ulepszenia silnika LSTM, co stanowi przewagę nad wersją 5.2.0 autorstwa charlesw
  • Obsługuje .NET Framework 6.0+ — obsługa nowoczesnych frameworków jest głównym powodem istnienia tego forka
  • Wymaga ręcznego zarządzania tessdata — pliki językowe .traineddata muszą zostać pobrane oddzielnie i wdrożone wraz z aplikacją
  • Brak wbudowanego przetwarzania wstępnego — wrapper wywołuje engine.Process(image) bezpośrednio; Poprawa jakości obrazu leży całkowicie w gestii programisty
  • Silnik niewątkowy — instancje Engine nie mogą być współdzielone między wątkami; każdy równoległy proces potrzebuje własnej instancji, co zwiększa zużycie pamięci
  • Brak natywnej obsługi plików PDF — przetwarzanie plików PDF wymaga oddzielnej biblioteki (Docnet.Core, PdfiumViewer) do renderowania stron na obrazy, zanim Tesseract będzie mógł je przetworzyć
  • ~200 tys. pobrań z NuGet w porównaniu z ~8 mln charlesw — mniejsza społeczność oznacza mniej odpowiedzi na Stack Overflow, mniej samouczków i więcej pracy nad dostosowaniem istniejących zasobów Tesseract

Inicjalizacja silnika i zależność od tessdata

Każde działanieTesseractOCRzaczyna się od inicjalizacji Engine, która wymaga folderu tessdata zawierającego pliki językowe .traineddata pobrane ręcznie z zewnętrznych repozytoriów:

// tessdata/eng.traineddata must exist before this line runs
// Downloaded separately: curl -L -o tessdata/eng.traineddata
//   https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata
using var engine = new Engine(@"./tessdata", Language.English, EngineMode.Default);
using var image = TesseractOCR.Pix.Image.LoadFromFile("document.png");
using var page = engine.Process(image);

string text = page.Text;
float confidence = page.MeanConfidence; // Returns 0.0-1.0 float
// tessdata/eng.traineddata must exist before this line runs
// Downloaded separately: curl -L -o tessdata/eng.traineddata
//   https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata
using var engine = new Engine(@"./tessdata", Language.English, EngineMode.Default);
using var image = TesseractOCR.Pix.Image.LoadFromFile("document.png");
using var page = engine.Process(image);

string text = page.Text;
float confidence = page.MeanConfidence; // Returns 0.0-1.0 float
Imports TesseractOCR

' tessdata/eng.traineddata must exist before this line runs
' Downloaded separately: curl -L -o tessdata/eng.traineddata
'   https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata
Using engine As New Engine("./tessdata", Language.English, EngineMode.Default)
    Using image As Pix.Image = TesseractOCR.Pix.Image.LoadFromFile("document.png")
        Using page As Page = engine.Process(image)
            Dim text As String = page.Text
            Dim confidence As Single = page.MeanConfidence ' Returns 0.0-1.0 float
        End Using
    End Using
End Using
$vbLabelText   $csharpLabel

Konstruktor Engine akceptuje ścieżkę do katalogu tessdata i wartość enum Language. Jeśli katalog nie istnieje, brakuje pliku .traineddata lub wersja pliku nie pasuje do wersji silnika Tesseract, inicjalizacja zgłasza wyjątek. Są to trzy najczęstsze błędy produkcyjne występujące w każdej nakładce Tesseract, aTesseractOCRdziedziczy je wszystkie. W pliku README projektu znajduje się kod sprawdzający, czy folder tessdata i poszczególne pliki językowe są obecne przed próbą skompilowania silnika — co pokazuje, jak często programiści napotykają ten problem.

Zrozumienie IronOCR

IronOCR to komercyjna biblioteka OCR dla platformy .NET, która wykorzystuje zoptymalizowany silnik Tesseract 5 z automatycznym przetwarzaniem wstępnym, natywnym wejściem/wyjściem PDF oraz architekturą bezpieczną dla wątków. Cała biblioteka jest dostarczana jako pojedynczy pakiet NuGet bez zewnętrznych zależności, bez zarządzania folderem tessdata i bez konfiguracji biblioteki natywnej.

Kluczowe cechy:

  • Pojedyncza instalacja NuGetdotnet add package IronOcr tworzy działający pipeline OCR; brak tessdata, brak konfiguracji rodzimych plików binarnych, brak dodatkowych pakietów potrzebnych dla podstawowego przepływu pracy
  • Automatyczne przetwarzanie wstępne — silnik automatycznie stosuje korekcję przekrzywienia, usuwanie szumów, poprawę kontrastu, binarizację i skalowanie rozdzielczości; explicit filter methods are available when fine-grained control is needed
  • Rodzimy input i output PDF — pliki PDF są ładowane bezpośrednio przez OcrInput.LoadPdf(); skanowane pliki PDF produkują wyjście PDF z możliwością przeszukiwania za pomocą result.SaveAsSearchablePdf()
  • IronTesseract odporny na wielowątkowość — pojedyncza instancja przetwarza równoczesne żądania bez powielania na wątek
  • Ponad 125 języków w postaci pakietów NuGet — bez konieczności pobierania plików z zewnątrz; pakiety językowe instalowane za pomocą dotnet add package IronOcr.Languages.French i są odwoływane bez konfiguracji ścieżki
  • Licencja wieczysta — $999 Lite / $1,499 Plus / $2,999 Professional; brak kosztów za dokument, nie jest wymagana subskrypcja
  • Wielopłatformowość z zachowaniem spójnego działania — Windows, Linux, macOS, Docker, Azure i AWS działają z tego samego pakietu bez konfiguracji specyficznej dla platformy

Porównanie funkcji

Funkcja TesseractOCR IronOCR
.NET jako grupa docelowa .NET 6.0, 7.0, 8.0 .NET 6.0, 7.0, 8.0, .NET Framework 4.6.2+
Licencja Apache 2.0 (bezpłatna) Komercyjna ($999+ wieczysta)
tessdata management Wymagane (pobieranie ręczne) Nie jest wymagane (w pakiecie)
Wbudowane przetwarzanie wstępne None Filtry automatyczne + jawne
Natywne wprowadzanie plików PDF Nie Tak
Wynik w formacie PDF z możliwością wyszukiwania Nie Tak
Bezpieczeństwo wątków Nie (silniki na wątek) Tak (pojedyncza wspólna instancja)

Szczegółowe porównanie funkcji

Funkcja TesseractOCR IronOCR
Konfiguracja i wdrożenie
Instalacja NuGet TesseractOCR IronOcr
wymagana teczka tessdata Tak Nie
Pobierz plik językowy Podręcznik (GitHub) Pakiet NuGet
Natywne pakiety binarne Częściowe (popularne platformy) Pełna
Wdrożenie w jednym pakiecie Nie (tessdata oddzielnie) Tak
Środowisko odizolowane Wymagane są wstępnie przygotowane dane tessdata Pakiety NuGet działają w trybie offline
Możliwości OCR
Wersja silnika Tesseract 5.5.0 5.x (zoptymalizowane)
Automatyczne prostowanie Nie Tak
Automatyczne usuwanie szumów Nie Tak
Automatyczny kontrast Nie Tak
Poprawa rozdzielczości Nie Tak (EnhanceResolution(300))
Binaryzacja Nie Tak
Obsługa plików PDF
Plik wejściowy PDF Nie (wymagana biblioteka zewnętrzna) Tak (język ojczysty)
Plik PDF chroniony hasłem Nie (wymaga odszyfrowania + ponownego przetworzenia) Tak (pojedynczy parametr)
Wynik w formacie PDF z możliwością wyszukiwania Nie Tak
Konkretne zakresy stron Podręcznik (pętla renderowania na stronę) Tak (LoadPdfPages)
Obsługa języków
Obsługiwane języki Dowolny plik tessdata Ponad 125 za pośrednictwem NuGet
Składnia wielojęzyczna Language.English | Language.French OcrLanguage.English + OcrLanguage.French
Dane językowe dostosowane do potrzeb klienta Tak (skopiuj plik do tessdata) Tak (niestandardowe pakiety językowe)
Wątkowanie i przetwarzanie wsadowe
Silnik bezpieczny dla wątków Nie Tak
Wzorzec przetwarzania równoległego Silnik wielowątkowy (wymagający dużej ilości pamięci) Pojedynczy egzemplarz, równoległe dane wejściowe
Pamięć na wątek ~40–100 MB na instancję silnika Współdzielona instancja
Wynik i rezultaty
Wskaźnik pewności page.MeanConfidence (0.0-1.0) result.Confidence (0-100%)
Pozycjonowanie na poziomie słów Ograniczone Tak (X, Y, szerokość, wysokość na WORD)
Strukturalna hierarchia wyników Nie Strony, akapity, wiersze, słowa
Odczytywanie BarCode podczas OCR Nie Tak
eksport hOCR Nie Tak
Wsparcie i konserwacja
Model utrzymania Pojedynczy programista-wolontariusz Zespół handlowy
Wsparcie komercyjne Nie Tak (e-mail, opcje umowy SLA)
Odpowiedź na zgłoszenia na GitHubie Harmonogram pracy wolontariuszy Harmonogram komercyjny

Zarządzanie danymi: problem wdrożeniowy, który nie znika

Wersja Sicos1977 zaktualizowała silnik Tesseract i unowocześniła framework docelowy. Nie zmieniło to sposobu działania danych językowych. Każde środowisko, które uruchamia TesseractOCR, potrzebuje folderu tessdata wypełnionego plikami .traineddata przed pierwszym wywołaniem konstruktora Engine.

Podejście TesseractOCR

Plik basic-ocr.cs w tym repozytorium zawiera metodę ValidateTessData(), którą projekt zaleca uruchomić przed jakąkolwiek operacją OCR. Ten wzorzec obronny istnieje, ponieważ tryb awarii — wyjątek TesseractException rzucony w połowie procesu — jest na tyle powszechny, że przykłady biblioteki się przed tym zabezpieczają:

// From BasicOcrService in tesseractocr-basic-ocr.cs
private void ValidateTessData()
{
    if (!Directory.Exists(_tessDataPath))
    {
        throw new DirectoryNotFoundException(
            $"tessdata folder not found at: {_tessDataPath}\n" +
            "Download traineddata files from: https://github.com/tesseract-ocr/tessdata_best");
    }

    string engTrainedData = Path.Combine(_tessDataPath, "eng.traineddata");
    if (!File.Exists(engTrainedData))
    {
        throw new FileNotFoundException(
            $"eng.traineddata not found in {_tessDataPath}\n" +
            "Download from: https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata");
    }
}
// From BasicOcrService in tesseractocr-basic-ocr.cs
private void ValidateTessData()
{
    if (!Directory.Exists(_tessDataPath))
    {
        throw new DirectoryNotFoundException(
            $"tessdata folder not found at: {_tessDataPath}\n" +
            "Download traineddata files from: https://github.com/tesseract-ocr/tessdata_best");
    }

    string engTrainedData = Path.Combine(_tessDataPath, "eng.traineddata");
    if (!File.Exists(engTrainedData))
    {
        throw new FileNotFoundException(
            $"eng.traineddata not found in {_tessDataPath}\n" +
            "Download from: https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata");
    }
}
Private Sub ValidateTessData()
    If Not Directory.Exists(_tessDataPath) Then
        Throw New DirectoryNotFoundException(
            $"tessdata folder not found at: {_tessDataPath}" & vbCrLf &
            "Download traineddata files from: https://github.com/tesseract-ocr/tessdata_best")
    End If

    Dim engTrainedData As String = Path.Combine(_tessDataPath, "eng.traineddata")
    If Not File.Exists(engTrainedData) Then
        Throw New FileNotFoundException(
            $"eng.traineddata not found in {_tessDataPath}" & vbCrLf &
            "Download from: https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata")
    End If
End Sub
$vbLabelText   $csharpLabel

Problem pogłębia wielojęzyczne OCR. Każdy język wymaga własnego pliku .traineddata — 15 do 50 MB na język — a pliki muszą pochodzić z poprawnej wersji repozytorium. Repozytorium tessdata_best zapewnia wyższą dokładność, ale wolniejsze przetwarzanie; tessdata_fast stawia szybkość ponad dokładnością. Mieszanie wersji lub używanie plików tessdata stworzonych dla Tesseract 4.x z silnikiem Tesseract 5.x powoduje ciche pogorszenie dokładności bez żadnego sygnału o błędzie.

W przypadku wdrożeń Docker pliki tessdata muszą być wbudowane w obraz lub zamontowane w znanej ścieżce. W przypadku potoków CI/CD etap pobierania musi być zautomatyzowany i buforowany. W przypadku środowisk odizolowanych pliki muszą zostać wcześniej przygotowane. Każda konfiguracja wdrożenia to kolejne miejsce, w którym może dojść do niepowodzenia.

// Multi-language requires each .traineddata file pre-downloaded
// eng.traineddata + fra.traineddata + deu.traineddata all required
using var engine = new Engine(@"./tessdata",
    Language.English | Language.French | Language.German,
    EngineMode.Default);

// If any traineddata file is missing, this throws at construction time
using var image = TesseractOCR.Pix.Image.LoadFromFile(imagePath);
using var page = engine.Process(image);

return page.Text;
// Multi-language requires each .traineddata file pre-downloaded
// eng.traineddata + fra.traineddata + deu.traineddata all required
using var engine = new Engine(@"./tessdata",
    Language.English | Language.French | Language.German,
    EngineMode.Default);

// If any traineddata file is missing, this throws at construction time
using var image = TesseractOCR.Pix.Image.LoadFromFile(imagePath);
using var page = engine.Process(image);

return page.Text;
Imports TesseractOCR

' Multi-language requires each .traineddata file pre-downloaded
' eng.traineddata + fra.traineddata + deu.traineddata all required
Using engine As New Engine("./tessdata", Language.English Or Language.French Or Language.German, EngineMode.Default)

    ' If any traineddata file is missing, this throws at construction time
    Using image As TesseractOCR.Pix.Image = TesseractOCR.Pix.Image.LoadFromFile(imagePath)
        Using page As Page = engine.Process(image)
            Return page.Text
        End Using
    End Using
End Using
$vbLabelText   $csharpLabel

Podejście IronOCR

IronOCR udostępnia obsługę języków w postaci pakietów NuGet. Wersja angielska jest dołączona do pakietu podstawowego. Dodatkowe języki instaluje się za pomocą jednego polecenia i nie wymagają one konfiguracji ścieżki:

// dotnet add package IronOcr.Languages.French
// dotnet add package IronOcr.Languages.German
// Nie tessdata folder, no download scripts, no path validation

var ocr = new IronTesseract();
ocr.Language = OcrLanguage.French;
ocr.AddSecondaryLanguage(OcrLanguage.German);

using var input = new OcrInput();
input.LoadImage(imagePath);
var result = ocr.Read(input);

return result.Text;
// dotnet add package IronOcr.Languages.French
// dotnet add package IronOcr.Languages.German
// Nie tessdata folder, no download scripts, no path validation

var ocr = new IronTesseract();
ocr.Language = OcrLanguage.French;
ocr.AddSecondaryLanguage(OcrLanguage.German);

using var input = new OcrInput();
input.LoadImage(imagePath);
var result = ocr.Read(input);

return result.Text;
Imports IronOcr

Dim ocr As New IronTesseract()
ocr.Language = OcrLanguage.French
ocr.AddSecondaryLanguage(OcrLanguage.German)

Using input As New OcrInput()
    input.LoadImage(imagePath)
    Dim result = ocr.Read(input)
    Return result.Text
End Using
$vbLabelText   $csharpLabel

Pakiet językowy jest zależnością NuGet, posiada wersję, jest przywracany automatycznie i wdrażany wraz z plikiem binarnym aplikacji. Brak zewnętrznych repozytoriów GitHub, brak skryptów curl, brak konfiguracji systemu kompilacji do kopiowania plików do katalogu wyjściowego. W przypadku wdrożeń typu air-gapped pakiet NuGet można przywrócić w trybie offline z prywatnego źródła w taki sam sposób, jak każdy inny pakiet. Przewodnik po wielu językach obejmuje konfigurację dla wszystkich ponad 125 obsługiwanych języków.

Przetwarzanie wstępne: czego nowoczesny fork wciąż nie potrafi

Fork Sicos1977 projektuTesseractOCRjest nowszy niż fork charlesw, jest przeznaczony dla aktualnej wersji .NET i zawiera zaktualizowane pliki binarne Tesseract. Żadne z tego nie zmienia tego, co się dzieje, gdy programista przekazuje wypaczone, niskokontrastowe lub jakości fotograficznej obrazy z kamery telefonu do engine.Process(image). Silnik pobiera surowe piksele. Tesseract generuje wyniki o obniżonej jakości. Następnie programista dodaje zewnętrzną bibliotekę obrazów do wykresu zależności i pisze kod przetwarzania wstępnego.

Podejście TesseractOCR

Plik migration-comparison.cs w tym repozytorium przedstawia wzorzec przetwarzania wstępnego wymagany przez TesseractOCR. Zewnętrzna biblioteka obrazowania (w tym przypadku SixLabors.ImageSharp) musi zostać dodana, parametry filtrów muszą być dostosowane ręcznie, a wstępnie przetworzony obraz musi zostać zapisany do pliku tymczasowego zanimTesseractOCRbędzie mógł go odczytać — ponieważ API TesseractOCR.Pix.Image oczekuje ścieżki pliku:

// Requires: dotnet add package SixLabors.ImageSharp
// Manual preprocessing — each parameter requires tuning per document type

using var image = Image.Load(imagePath);

image.Mutate(x => x.Grayscale());
image.Mutate(x => x.Contrast(1.5f));         // 1.5 is a guess; tune per use case
image.Mutate(x => x.GaussianBlur(0.5f));     // Denoise with blur
image.Mutate(x => x.BinaryThreshold(0.5f)); // Threshold requires manual tuning

// Deskew is NOT in ImageSharp — requires separate Hough transform implementation
// (~50-100 additional lines)

string tempPath = Path.GetTempFileName() + ".png";
try
{
    image.Save(tempPath);

    using var engine = new Engine(@"./tessdata", Language.English);
    using var pixImage = TesseractOCR.Pix.Image.LoadFromFile(tempPath);
    using var page = engine.Process(pixImage);

    return page.Text;
}
finally
{
    File.Delete(tempPath); // Clean up temp file
}
// Requires: dotnet add package SixLabors.ImageSharp
// Manual preprocessing — each parameter requires tuning per document type

using var image = Image.Load(imagePath);

image.Mutate(x => x.Grayscale());
image.Mutate(x => x.Contrast(1.5f));         // 1.5 is a guess; tune per use case
image.Mutate(x => x.GaussianBlur(0.5f));     // Denoise with blur
image.Mutate(x => x.BinaryThreshold(0.5f)); // Threshold requires manual tuning

// Deskew is NOT in ImageSharp — requires separate Hough transform implementation
// (~50-100 additional lines)

string tempPath = Path.GetTempFileName() + ".png";
try
{
    image.Save(tempPath);

    using var engine = new Engine(@"./tessdata", Language.English);
    using var pixImage = TesseractOCR.Pix.Image.LoadFromFile(tempPath);
    using var page = engine.Process(pixImage);

    return page.Text;
}
finally
{
    File.Delete(tempPath); // Clean up temp file
}
Imports SixLabors.ImageSharp
Imports SixLabors.ImageSharp.Processing
Imports TesseractOCR
Imports System.IO

' Requires: dotnet add package SixLabors.ImageSharp
' Manual preprocessing — each parameter requires tuning per document type

Dim image As Image = Image.Load(imagePath)

image.Mutate(Sub(x) x.Grayscale())
image.Mutate(Sub(x) x.Contrast(1.5F))         ' 1.5 is a guess; tune per use case
image.Mutate(Sub(x) x.GaussianBlur(0.5F))     ' Denoise with blur
image.Mutate(Sub(x) x.BinaryThreshold(0.5F))  ' Threshold requires manual tuning

' Deskew is NOT in ImageSharp — requires separate Hough transform implementation
' (~50-100 additional lines)

Dim tempPath As String = Path.GetTempFileName() & ".png"
Try
    image.Save(tempPath)

    Using engine As New Engine("./tessdata", Language.English)
        Using pixImage As TesseractOCR.Pix.Image = TesseractOCR.Pix.Image.LoadFromFile(tempPath)
            Using page As Page = engine.Process(pixImage)
                Return page.Text
            End Using
        End Using
    End Using
Finally
    File.Delete(tempPath) ' Clean up temp file
End Try
$vbLabelText   $csharpLabel

Plik README dlaTesseractOCRwymienia spadki dokładności w przypadku niedoskonałych danych wejściowych: 5-stopniowe przekrzywienie powoduje spadek dokładności z 97% do 65–75%; jakość zdjęć zrobionych aparatem w telefonie spada do 30–50%. Nie są to skrajne przypadki w produkcji — jest to domyślny stan skanowanych dokumentów, zdjęć tablic i faksów. Odzyskanie tej dokładności wymaga korekcji zniekształceń, redukcji szumów i normalizacji kontrastu. Sama funkcja Deskew nie jest dostępna w popularnych bibliotekach obrazówania .NET i wymaga wdrożenia algorytmu wykrywania kąta transformacji Hougha.

Podejście IronOCR

Pipeline przetwarzania wstępnego IronOCR jest wbudowany w OcrInput. Wywołanie Deskew(), DeNoise(), Contrast() i EnhanceResolution() stosuje odpowiednie algorytmy bez zewnętrznych bibliotek, bez plików tymczasowych i bez dostrajania parametrów dla typowych rodzajów dokumentów:

// Nie external imaging library needed
// Nie temp files, no manual parameter tuning

using var input = new OcrInput();
input.LoadImage(imagePath);
input.Deskew();           // Automatic angle detection and correction
input.DeNoise();          // Intelligent noise removal
input.Contrast();         // Automatyczny kontrast enhancement
input.EnhanceResolution(300); // Upscale if below 300 DPI

var result = new IronTesseract().Read(input);

return result.Text;
// Nie external imaging library needed
// Nie temp files, no manual parameter tuning

using var input = new OcrInput();
input.LoadImage(imagePath);
input.Deskew();           // Automatic angle detection and correction
input.DeNoise();          // Intelligent noise removal
input.Contrast();         // Automatyczny kontrast enhancement
input.EnhanceResolution(300); // Upscale if below 300 DPI

var result = new IronTesseract().Read(input);

return result.Text;
Imports IronOcr

Using input As New OcrInput()
    input.LoadImage(imagePath)
    input.Deskew()           ' Automatic angle detection and correction
    input.DeNoise()          ' Intelligent noise removal
    input.Contrast()         ' Automatyczny kontrast enhancement
    input.EnhanceResolution(300) ' Upscale if below 300 DPI

    Dim result = New IronTesseract().Read(input)

    Return result.Text
End Using
$vbLabelText   $csharpLabel

W przypadku dokumentów, w których problemy z jakością nie są znane z góry, silnik automatycznie stosuje poprawki bazowe bez wyraźnych wywołań filtrów. Przewodnik po korekcji jakości obrazu obejmuje każdy filtr wraz z opcjami parametrów dla przypadków, w których zachowanie automatyczne wymaga dostosowania. Przewodnik dotyczący korekcji orientacji obrazu obejmuje w szczególności wykrywanie przekrzywienia i obrotu — operacje, które wymagałyby niestandardowej implementacji przy użyciu TesseractOCR. Przykład skanu o niskiej jakości pokazuje różnicę w dokładności w przypadku trudnych dokumentów.

Przetwarzanie plików PDF: biblioteka zewnętrzna

TesseractOCR przetwarza obrazy. Nie obsługuje plików PDF. Każdy proces przetwarzania plików PDF z wykorzystaniemTesseractOCRwymaga drugiej biblioteki do renderowania stron PDF do plików graficznych, a każdy proces renderowania obrazów z plików PDF wymaga zarządzania plikami tymczasowymi, konwersji formatu bajtowego oraz logiki czyszczenia.

Podejście TesseractOCR

Plik tesseractocr-pdf-processing.cs w tym repozytorium implementuje kompletną usługę OCR dla plików PDF. Wymaga on Docnet.Core jako dodatkowej zależności oraz około 100 linii kodu, aby wykonać to, co IronOCR osiąga w trzech. Podstawowa pętla ekstrakcji obejmuje ładowanie PDF za pomocą Docnet, renderowanie każdej strony do tablic bajtów BGRA, zapisywanie każdej strony do pliku tymczasowego (ponieważ TesseractOCR.Pix.Image.LoadFromFile wymaga ścieżki pliku, a nie tablicy bajtów), przetwarzanie OCR pliku tymczasowego, dodawanie do StringBuilder i usuwanie plików tymczasowych w bloku finally.

// Requires: dotnet add package TesseractOCR
//           dotnet add package Docnet.Core
// Note: Docnet is MIT-licensed; iTextSharp would be AGPL

using var library = DocLib.Instance;
using var docReader = library.GetDocReader(pdfPath, new PageDimensions(dpi, dpi));

int pageCount = docReader.GetPageCount();
var allText = new StringBuilder();
var tempFiles = new List<string>();

try
{
    using var engine = new Engine(_tessDataPath, Language.English, EngineMode.Default);

    for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
    {
        using var pageReader = docReader.GetPageReader(pageIndex);
        var width = pageReader.GetPageWidth();
        var height = pageReader.GetPageHeight();
        var imageBytes = pageReader.GetImage(); // BGRA bytes

        // TesseractOCR.Pix.Image requires a file path — write to temp
        string tempPath = Path.Combine(_tempDirectory, $"page_{pageIndex}_{Guid.NewGuid()}.png");
        tempFiles.Add(tempPath);
        SaveBgraAsPng(imageBytes, width, height, tempPath); // ~30 lines

        using var image = TesseractOCR.Pix.Image.LoadFromFile(tempPath);
        using var page = engine.Process(image);

        allText.AppendLine($"--- Page {pageIndex + 1} ---");
        allText.AppendLine(page.Text);
    }
}
finally
{
    foreach (var tempFile in tempFiles)
    {
        try { File.Delete(tempFile); } catch { }
    }
}
// Requires: dotnet add package TesseractOCR
//           dotnet add package Docnet.Core
// Note: Docnet is MIT-licensed; iTextSharp would be AGPL

using var library = DocLib.Instance;
using var docReader = library.GetDocReader(pdfPath, new PageDimensions(dpi, dpi));

int pageCount = docReader.GetPageCount();
var allText = new StringBuilder();
var tempFiles = new List<string>();

try
{
    using var engine = new Engine(_tessDataPath, Language.English, EngineMode.Default);

    for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
    {
        using var pageReader = docReader.GetPageReader(pageIndex);
        var width = pageReader.GetPageWidth();
        var height = pageReader.GetPageHeight();
        var imageBytes = pageReader.GetImage(); // BGRA bytes

        // TesseractOCR.Pix.Image requires a file path — write to temp
        string tempPath = Path.Combine(_tempDirectory, $"page_{pageIndex}_{Guid.NewGuid()}.png");
        tempFiles.Add(tempPath);
        SaveBgraAsPng(imageBytes, width, height, tempPath); // ~30 lines

        using var image = TesseractOCR.Pix.Image.LoadFromFile(tempPath);
        using var page = engine.Process(image);

        allText.AppendLine($"--- Page {pageIndex + 1} ---");
        allText.AppendLine(page.Text);
    }
}
finally
{
    foreach (var tempFile in tempFiles)
    {
        try { File.Delete(tempFile); } catch { }
    }
}
Imports Docnet.Core
Imports TesseractOCR
Imports System.IO
Imports System.Text

' Requires: dotnet add package TesseractOCR
'           dotnet add package Docnet.Core
' Note: Docnet is MIT-licensed; iTextSharp would be AGPL

Dim library = DocLib.Instance
Dim docReader = library.GetDocReader(pdfPath, New PageDimensions(dpi, dpi))

Dim pageCount As Integer = docReader.GetPageCount()
Dim allText As New StringBuilder()
Dim tempFiles As New List(Of String)()

Try
    Using engine As New Engine(_tessDataPath, Language.English, EngineMode.Default)
        For pageIndex As Integer = 0 To pageCount - 1
            Using pageReader = docReader.GetPageReader(pageIndex)
                Dim width = pageReader.GetPageWidth()
                Dim height = pageReader.GetPageHeight()
                Dim imageBytes = pageReader.GetImage() ' BGRA bytes

                ' TesseractOCR.Pix.Image requires a file path — write to temp
                Dim tempPath As String = Path.Combine(_tempDirectory, $"page_{pageIndex}_{Guid.NewGuid()}.png")
                tempFiles.Add(tempPath)
                SaveBgraAsPng(imageBytes, width, height, tempPath) ' ~30 lines

                Using image = TesseractOCR.Pix.Image.LoadFromFile(tempPath)
                    Using page = engine.Process(image)
                        allText.AppendLine($"--- Page {pageIndex + 1} ---")
                        allText.AppendLine(page.Text)
                    End Using
                End Using
            End Using
        Next
    End Using
Finally
    For Each tempFile In tempFiles
        Try
            File.Delete(tempFile)
        Catch
        End Try
    Next
End Try
$vbLabelText   $csharpLabel

PDFy chronione haslem wymagaja trzeciej biblioteki (iText z licencjonowaniem AGPL lub PDFSharp) do odszyfrowania dokumentu wczesniej, co dodaje kolejne zaleznosc i kolejny problem z licencjonowaniem do przeanalizowania. Komentarz w pliku tesseractocr-pdf-processing.cs na ten temat jest bezpośredni: "TesseractOCR + Docnet nie obsługują bezpośrednio plików PDF chronionych hasłem". Musisz: 1. Użyć biblioteki PDF obsługującej deszyfrowanie... 2. Najpierw odszyfruj/usuń hasło... 3. Zapisz odszyfrowany plik PDF... 4. Następnie przetwórz za pomocą powyższego kodu.

Podejście IronOCR

Obsługa plików PDF w IronOCR jest natywna. Bez zewnętrznych bibliotek, bez plików tymczasowych, bez konwersji formatów bajtowych. Przewodnik dotyczący plików PDF obejmuje wszystkie scenariusze związane z plikami PDF — pełne dokumenty, zakresy stron oraz pliki chronione hasłem:

// Pełna PDF — native, no external library
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(pdfPath);
var result = ocr.Read(input);
string text = result.Text;

// Plik PDF chroniony hasłem — built-in, one parameter
using var encryptedInput = new OcrInput();
encryptedInput.LoadPdf("encrypted.pdf", Password: "secret");
var encryptedResult = ocr.Read(encryptedInput);

// Specific page range — no manual loop required
using var pageInput = new OcrInput();
pageInput.LoadPdfPages(pdfPath, startPage: 1, endPage: 5);
var pageResult = ocr.Read(pageInput);
// Pełna PDF — native, no external library
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf(pdfPath);
var result = ocr.Read(input);
string text = result.Text;

// Plik PDF chroniony hasłem — built-in, one parameter
using var encryptedInput = new OcrInput();
encryptedInput.LoadPdf("encrypted.pdf", Password: "secret");
var encryptedResult = ocr.Read(encryptedInput);

// Specific page range — no manual loop required
using var pageInput = new OcrInput();
pageInput.LoadPdfPages(pdfPath, startPage: 1, endPage: 5);
var pageResult = ocr.Read(pageInput);
Imports IronTesseract

' Pełna PDF — native, no external library
Dim ocr As New IronTesseract()
Using input As New OcrInput()
    input.LoadPdf(pdfPath)
    Dim result = ocr.Read(input)
    Dim text As String = result.Text
End Using

' Plik PDF chroniony hasłem — built-in, one parameter
Using encryptedInput As New OcrInput()
    encryptedInput.LoadPdf("encrypted.pdf", Password:="secret")
    Dim encryptedResult = ocr.Read(encryptedInput)
End Using

' Specific page range — no manual loop required
Using pageInput As New OcrInput()
    pageInput.LoadPdfPages(pdfPath, startPage:=1, endPage:=5)
    Dim pageResult = ocr.Read(pageInput)
End Using
$vbLabelText   $csharpLabel

Skanowane pliki PDF — scenariusz, w którym połączenie Docnet + przetwarzanie wstępne + OCR wTesseractOCRjest najbardziej uciążliwe — to także scenariusz, w którym pipeline przetwarzania wstępnego IronOCR ma największe znaczenie. Skanowany PDF przechodzi przez LoadPdf(), automatyczne przetwarzanie wstępne, OCR i opcjonalne wyjście PDF z możliwością przeszukiwania w łańcuchu liniowym bez zarządzania plikami tymczasowymi. Przykład PDF OCR i przewodnik po PDF z możliwością przeszukiwania obejmują cały przepływ pracy zawierający result.SaveAsSearchablePdf(), na który nie ma odpowiednika w TesseractOCR.

Wielowątkowość: Koszt pamięci silników niezabezpieczonych przed wielowątkowością

Silnik Engine wTesseractOCRnie jest odporny na wielowątkowość. Plik basic-ocr.cs zawiera klasę ThreadSafeOcrService z wyraźnym ostrzeżeniem: "Obciążenie pamięci: 4 wątki x 50MB = 200MB+ tylko dla silników." Koszt równoczesnego używaniaTesseractOCRto jedna instancja silnika na wątek, każda o średniej wielkości 40-100MB rodzimych zasobów Tesseract, każda wymagająca około 500ms czasu inicjalizacji.

Podejście TesseractOCR

Przetwarzanie równoległe zTesseractOCRwymaga utworzenia nowego Engine wewnątrz każdej lambdy pracownika:

// WARNING: Engine is NOT thread-safe — must create per thread
// Memory: _maxDegreeOfParallelism * engine footprint (~40-100MB each)

var results = new ConcurrentDictionary<string, string>();

Parallel.ForEach(
    imagePaths,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    imagePath =>
    {
        // Per-thread engine — required, expensive (~500ms init, ~50MB memory)
        using var engine = new Engine(@"./tessdata", Language.English, EngineMode.Default);
        using var image = TesseractOCR.Pix.Image.LoadFromFile(imagePath);
        using var page = engine.Process(image);

        results[imagePath] = page.Text;
    });
// WARNING: Engine is NOT thread-safe — must create per thread
// Memory: _maxDegreeOfParallelism * engine footprint (~40-100MB each)

var results = new ConcurrentDictionary<string, string>();

Parallel.ForEach(
    imagePaths,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    imagePath =>
    {
        // Per-thread engine — required, expensive (~500ms init, ~50MB memory)
        using var engine = new Engine(@"./tessdata", Language.English, EngineMode.Default);
        using var image = TesseractOCR.Pix.Image.LoadFromFile(imagePath);
        using var page = engine.Process(image);

        results[imagePath] = page.Text;
    });
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

' WARNING: Engine is NOT thread-safe — must create per thread
' Memory: _maxDegreeOfParallelism * engine footprint (~40-100MB each)

Dim results As New ConcurrentDictionary(Of String, String)()

Parallel.ForEach(
    imagePaths,
    New ParallelOptions With {.MaxDegreeOfParallelism = 4},
    Sub(imagePath)
        ' Per-thread engine — required, expensive (~500ms init, ~50MB memory)
        Using engine As New Engine("./tessdata", Language.English, EngineMode.Default)
            Using image As TesseractOCR.Pix.Image = TesseractOCR.Pix.Image.LoadFromFile(imagePath)
                Using page As Page = engine.Process(image)
                    results(imagePath) = page.Text
                End Using
            End Using
        End Using
    End Sub)
$vbLabelText   $csharpLabel

Wzorzec ponownego wykorzystania pojedynczego silnika (tworzenie jednego silnika poza pętlą i ponowne wykorzystywanie go sekwencyjnie) działa w przypadku przetwarzania szeregowego, ale zawodzi, jeśli jakikolwiek inny wątek dotknie instancji. Przetwarzanie wsadowe pod obciążeniem wymaga zatem albo zaakceptowania kosztu pamięci silników na wątek, albo wdrożenia puli silników lokalnych dla wątków z ostrożnym zarządzaniem cyklem życia.

Podejście IronOCR

IronTesseract jest odporny na wielowątkowość. Jeden egzemplarz przetwarza żądania z dowolnej liczby współbieżnych wątków:

// Single instance — thread-safe, no per-thread duplication
var ocr = new IronTesseract();

var results = new ConcurrentDictionary<string, string>();

Parallel.ForEach(imagePaths, imagePath =>
{
    using var input = new OcrInput(imagePath);
    results[imagePath] = ocr.Read(input).Text;
});
// Single instance — thread-safe, no per-thread duplication
var ocr = new IronTesseract();

var results = new ConcurrentDictionary<string, string>();

Parallel.ForEach(imagePaths, imagePath =>
{
    using var input = new OcrInput(imagePath);
    results[imagePath] = ocr.Read(input).Text;
});
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

' Single instance — thread-safe, no per-thread duplication
Dim ocr As New IronTesseract()

Dim results As New ConcurrentDictionary(Of String, String)()

Parallel.ForEach(imagePaths, Sub(imagePath)
    Using input As New OcrInput(imagePath)
        results(imagePath) = ocr.Read(input).Text
    End Using
End Sub)
$vbLabelText   $csharpLabel

Przykład wielowątkowości ilustruje ten wzorzec. Zajmowana pamięć dla 4 równoległych procesów to jedna instancja silnika zamiast czterech. W przypadku potoków przetwarzania dokumentów w partiach, gdzie liczy się przepustowość, jest to istotna różnica.

Przewodnik po mapowaniu API

TesseractOCR Odpowiednik IronOCR Uwagi
Engine(tessDataPath, Language.English, EngineMode.Default) new IronTesseract() Nie jest wymagana ścieżka do plików tessdata
TesseractOCR.Pix.Image.LoadFromFile(path) new OcrInput(path) Obsługuje więcej formatów
engine.Process(image) ocr.Read(input) Podstawowe wywołanie OCR
page.Text result.Text Pełny tekst wyodrębniony
page.MeanConfidence (0.0-1.0) result.Confidence (0-100) Skala się różni
Language.English | Language.French OcrLanguage.English + OcrLanguage.French Operator różni się
EngineMode.Default Nie dotyczy Automatyczny wybór
TesseractOCR.Exceptions.TesseractException IronOcr.Exceptions.OcrException Mniej typów wyjątków do obsługi
Ręczne przetwarzanie wstępne (ImageSharp) input.Deskew(), input.DeNoise(), input.Contrast() Wbudowane, bez zewnętrznej biblioteki
Docnet GetPageReader().GetImage() + plik tymczasowy input.LoadPdf(path) Natywny plik PDF, bez plików tymczasowych
Nie dotyczy input.LoadPdf(path, Password: "secret") Brak odpowiednika bez dodatkowej biblioteki
Nie dotyczy result.SaveAsSearchablePdf(path) Brak odpowiednika wTesseractOCR
Nie dotyczy result.Pages, result.Lines, result.Words Strukturalny wynik
Nie dotyczy ocr.Configuration.ReadBarCodes = true Współodczyt BarCode
Instancje Engine na wątek Pojedyncza instancja IronTesseract Wbudowana bezpieczeństwo wątków

Kiedy zespoły rozważają przejście zTesseractOCRna IronOCR

Jakość dokumentów jest zróżnicowana

Integracja zTesseractOCRdziała bez zarzutu na skanach o wysokiej jakości 300 DPI. W momencie, gdy jakość dokumentów spada — przekrzywione strony ze skanera płaskiego, faksy o niskim kontraście, zdjęcia paragonów zrobione telefonem — pojawia się luka w dokładności. Własny test porównawczy README pokazuje, że bez wstępnego przetwarzania dokładność zdjęć zrobionych aparatem w telefonie spada do 30–50%. Zbudowanie i dostrojenie potoku przetwarzania wstępnego w ImageSharp lub SkiaSharp w celu odzyskania tej dokładności zajmuje 8–20 godzin pracy programistycznej i wprowadza dodatkową zależność. Zespoły, które sześć miesięcy po początkowej integracji odkrywają, że ich założenie dotyczące "wysokiej jakości skanowania" było błędne, stanowią typowy przypadek migracji z TesseractOCR. Luka w przetwarzaniu wstępnym nie jest problemem konfiguracyjnym, który można rozwiązać raz na zawsze — pojawia się za każdym razem, gdy do procesu trafia nowy typ dokumentu lub metoda przechwytywania.

Dokumenty PDF są częścią procesu wprowadzania danych

Połączenie Docnet.Core +TesseractOCRdo OCR plików PDF działa, ale zastąpienie 3 linii kodu wymaga napisania około 100 linii. Z praktycznego punktu widzenia wymaga to oceny licencji Docnet (MIT), jego działania na różnych platformach, obsługi nieprawidłowo sformatowanych plików PDF oraz interakcji z istniejącym kodem tessdata i kodem przetwarzania wstępnego. Zespoły tworzące systemy zarządzania dokumentami, programy do przetwarzania faktur lub dowolne procesy, w których pliki PDF stanowią główny wkład, zauważają, że podejście oparte na zewnętrznej bibliotece PDF z czasem powoduje coraz więcej utrudnień: obsługa wymiarów stron, wybór DPI do renderowania, logika czyszczenia plików tymczasowych oraz całkowity brak możliwości wyszukiwania w plikach PDF. Zespół, który musi tworzyć pliki PDF z możliwością wyszukiwania na podstawie zeskanowanych danych, nie ma szans na osiągnięcie tego celu, korzystając wyłącznie z TesseractOCR.

Architektura wątków osiąga limity pamięci

Cztery równoległe procesy OCR wTesseractOCRzużywają 200–400 MB pamięci silnika, zanim przetworzony zostanie choćby jeden obraz. Nie stanowi to problemu dla zadania działającego w tle o niskiej przepustowości. Stanowi to problem dla punktu końcowego .NET Core obsługującego wiele jednoczesnych przesyłek dokumentów lub procesora wsadowego zwiększającego przepustowość. Wzorzec silnika oparty na wątkach oznacza również, że każdy nowy wątek ponosi koszt inicjalizacji wynoszący około 500 ms przed przetworzeniem pierwszego dokumentu. Zespoły, które wybrałyTesseractOCRjako usługę działającą w tle, a następnie musiały zwiększyć przepustowość, napotykają ten limit. Przejście na silnik bezpieczny dla wątków całkowicie eliminuje obciążenie związane z każdym wątkiem.

Zmiany w środowisku wdrożeniowym po zakończeniu wstępnego etapu rozwoju

TesseractOCR wymaga plików tessdata wdrożonych razem z aplikacją. W lokalnym środowisku programisty jest to wykonalne. W kontenerze Docker oznacza to albo wbudowanie plików tessdata w obraz (co zwiększa rozmiar obrazu o 15–50 MB na język), albo zamontowanie woluminu w znanej ścieżce (co zwiększa złożoność operacyjną). W potoku CI/CD oznacza to tworzenie skryptów i buforowanie pobranych plików. W usłudze Azure App Service lub AWS Lambda konfiguracja ścieżki tessdata jest kolejnym ustawieniem specyficznym dla środowiska, które może różnić się od konfiguracji używanej podczas programowania. Zespoły, które zaczynają od lokalnej weryfikacji koncepcji, a następnie przechodzą do wdrożenia w kontenerach lub w chmurze, odkrywają, że wymagania dotyczące danych tessdata zachowują się inaczej w każdym środowisku. Pakiety językowe IronOCR oparte na NuGet są wdrażane identycznie wszędzie tam, gdzie pakiet jest przywracany.

Wsparcie społeczności osiąga granicę rozgałęzienia

TesseractOCR ma około 200 tys. pobrań z NuGet. charlesw/tesseract ma około 8 mln. Pytania na Stack Overflow, posty na blogach i problemy na GitHub dotyczące wrapperów Tesseract .NET przytłaczająco odwołują się do API charlesw — TesseractEngine, a nie Engine; Pix.LoadFromFile, a nie TesseractOCR.Pix.Image.LoadFromFile. Rozwiązania, które sprawdzają się w przypadku charlesw, wymagają dostosowania do różnic w API TesseractOCR. Dla zespołów, których głównym modelem wsparcia są zasoby społecznościowe, jest to prawdziwy czynnik zwiększający tarcie.

Typowe kwestie związane z migracją

Zastąpienie przestrzeni nazw i klas

Podstawowa substytucja to Engine do IronTesseract i TesseractOCR.Pix.Image.LoadFromFile() do OcrInput. Zamiana przestrzeni nazw (using TesseractOCR do using IronOcr) obejmuje większość odniesień. GdzieTesseractOCRużywa Language.English |Language.French (bitwise OR on a flags enum),IronOCR uses OcrLanguage.English + OcrLanguage.French (operacja dodawania). Skala zaufania różni się również:TesseractOCRzwraca page.MeanConfidence jako float od 0.0 do 1.0;IronOCR zwraca result.Confidence jako double od 0 do 100. Wszelkie logiki progowe porównujące wartości pewności wymagają aktualizacji.

// Before (TesseractOCR)
using var engine = new Engine(@"./tessdata", Language.English, EngineMode.Default);
using var image = TesseractOCR.Pix.Image.LoadFromFile("document.png");
using var page = engine.Process(image);
float confidence = page.MeanConfidence; // 0.0 to 1.0

// After (IronOCR)
var ocr = new IronTesseract();
using var input = new OcrInput("document.png");
var result = ocr.Read(input);
double confidence = result.Confidence; // 0 to 100
// Before (TesseractOCR)
using var engine = new Engine(@"./tessdata", Language.English, EngineMode.Default);
using var image = TesseractOCR.Pix.Image.LoadFromFile("document.png");
using var page = engine.Process(image);
float confidence = page.MeanConfidence; // 0.0 to 1.0

// After (IronOCR)
var ocr = new IronTesseract();
using var input = new OcrInput("document.png");
var result = ocr.Read(input);
double confidence = result.Confidence; // 0 to 100
Imports TesseractOCR
Imports IronOcr

' Before (TesseractOCR)
Using engine As New Engine("./tessdata", Language.English, EngineMode.Default)
    Using image As TesseractOCR.Pix.Image = TesseractOCR.Pix.Image.LoadFromFile("document.png")
        Using page As Page = engine.Process(image)
            Dim confidence As Single = page.MeanConfidence ' 0.0 to 1.0
        End Using
    End Using
End Using

' After (IronOCR)
Dim ocr As New IronTesseract()
Using input As New OcrInput("document.png")
    Dim result As OcrResult = ocr.Read(input)
    Dim confidence As Double = result.Confidence ' 0 to 100
End Using
$vbLabelText   $csharpLabel

Usuń zależności związane z przetwarzaniem wstępnym

Jeśli istniejąca integracjaTesseractOCRposiada już potok przetwarzania wstępnego ImageSharp lub SkiaSharp, kod ten można usunąć po migracji. Wbudowane metody IronOCRDeskew(), DeNoise(), Contrast() i EnhanceResolution() zastępują zewnętrzny łańcuch filtrów. Kod tworzenia i czyszczenia plików tymczasowych wokół wstępnie przetworzonego obrazu również zanika — OcrInput akceptuje ścieżkę pliku, tablicę bajtów, strumień lub Bitmap bezpośrednio bez pisania do pliku pośredniego. Przykład filtrów obrazów obejmuje dostępne filtry i ich odpowiedniki.

Usuń bibliotekę zewnętrzną PDF

Zespoły korzystające z Docnet.Core lub PdfiumViewer do renderowania plików PDF mogą całkowicie usunąć te pakiety. Zastąp całą pętlę renderowania PDF — DocLib.Instance, GetDocReader, GetPageReader, GetImage, SaveBgraAsPng, tworzenie pliku tymczasowego, Pix.Image.LoadFromFile, engine.Process — przez input.LoadPdf(pdfPath). Przewodnik po formatach wejściowych PDF oraz strona poświęcona zastosowaniom OCR w plikach PDF obejmują pełny zakres interfejsu API IronOCR PDF. Usuń folder tessdata z projektu, usuń konfigurację build <CopyToOutputDirectory> dla plików tessdata i aktualizuj obrazy Docker, aby usunąć wszelkie kroki apt-get install tesseract-ocr.

Obszar obsługi błędów ulega zmniejszeniu

TesseractOCR wymaga łapania TesseractOCR.Exceptions.TesseractException dla awarii inicjalizacji silnika, DllNotFoundException dla brakujących bibliotek natywnych i BadImageFormatException dla niezgodności architektury.IronOCRłączy swoje natywne zależności i zarządza inicjalizacją wewnętrznie, więc te typy wyjątków nie mają zastosowania. Pozostała powierzchnia błędów to standard IOException dla problemów z dostępem do plików i IronOcr.Exceptions.OcrException dla specyficznych awarii OCR.

Dodatkowe możliwości IronOCR

Oprócz obszarów objętych tym porównaniem,IronOCR zawiera funkcje, które nie mają odpowiedników w TesseractOCR:

  • PDF z możliwością przeszukiwaniaresult.SaveAsSearchablePdf() konwertuje zeskanowany dokument do PDF z osadzonym, wybieralnym tekstem;TesseractOCRnie generuje żadnych plików PDF
  • OCR oparte na regionieinput.LoadImage("invoice.jpg", new CropRectangle(0, 0, 600, 100)) ogranicza przetwarzanie do określonego obszaru; przydatne do ekstrakcji pol formularzy i parsowania dokumentow strukturalnych
  • Odczyt kodów kreskowych podczas OCRocr.Configuration.ReadBarCodes = true odczytuje kody kreskowe i kody QR osadzone w dokumentach w tym samym przebiegu, co ekstrakcja tekstu
  • Strukturalne dane wynikoweresult.Pages, result.Paragraphs, result.Lines i result.Words ujawniają strukturę dokumentu z danymi współrzędnych na słowo;TesseractOCRzwraca płaski ciąg tekstowy z pojedynczą wartością pewności
  • Eksport hOCRresult.SaveAsHocrFile() tworzy wyjście w formacie hOCR dla dalszych procesów przetwarzania dokumentów
  • Asynchroniczny OCR — wbudowana obsługa async/await dla integracji ASP.NET Core bez ręcznych wrapperów Task.Run
  • Wyniki pewności dla poszczególnych słów — pewność na poziomie słów pozwala na odfiltrowanie niepewnych wyników;TesseractOCRzapewnia jedynie średni poziom pewności na poziomie dokumentu
  • Specjalistyczne odczytywanie dokumentów — odczytywanie paszportów, czeków MICR i tablic rejestracyjnych z optymalizacjami specyficznymi dla danej dziedziny, wykraczającymi poza ogólne OCR

Zgodność z platformą .NET i gotowość na przyszłość

TesseractOCR jest przeznaczony dla platform .NET 6.0, 7.0 i 8.0, co obejmuje aktualne wersje LTS i STS.IronOCR obsługuje te same nowoczesne wersje .NET i zapewnia kompatybilność wsteczną z .NET Framework 4.6.2+ dla zespołów, które nie zakończyły jeszcze migracji frameworku. Obie biblioteki działają w systemach Windows, Linux i macOS.IronOCR dostarcza optymalizacje specyficzne dla platformy w pakiecie NuGet dla wszystkich obsługiwanych platform bez konieczności konfiguracji specyficznej dla platformy;TesseractOCRzawiera natywne pliki binarne dla popularnych platform, ale wymaga dodatkowej konfiguracji bibliotek natywnych dla rzadkich dystrybucji Linuksa i niestandardowych obrazów bazowych Docker.IronOCR publikuje przewodniki wdrożeniowe dla Docker, Linux, Azure i AWS zawierające sprawdzone konfiguracje dla środowisk produkcyjnych.

Wnioski

TesseractOCR zajmuje prawdziwą niszę: jest to właściwy wybór, gdy potrzebujesz aktywnie utrzymywanego, opartego na nowoczesnym frameworku powiązania z Tesseractem do projektu, który wymaga licencji Apache 2.0, przetwarza czyste obrazy wysokiej jakości i dysponuje wewnętrznym doświadczeniem w zakresie przetwarzania obrazów, aby zbudować dowolne przetwarzanie wstępne wymagane przez potok. Fork Sicos1977 jest znacznie lepszy niż korzystanie z archiwalnego projektu charlesw do nowych zadań związanych z .NET 6+ — nowszy silnik, aktywne poprawki błędów, prawdziwe natywne pakiety międzyplatformowe. W przypadku projektów, które spełniają profil "clean-input" i ograniczają się wyłącznie do oprogramowania open source, jest to wystarczające.

Argument tego porównania jest bardziej konkretny: aktualizacja opakowania nie naprawia tego, czego sam Tesseract nie zapewnia. Wymagania dotyczące tessdata pozostają niezmienione. Silnik niezabezpieczony przed wielowątkowością pozostaje bez zmian. Brak przetwarzania wstępnego pozostaje bez zmian. Brak natywnej obsługi plików PDF pozostaje bez zmian. Zespół, który wybieraTesseractOCRze względu na jego nowoczesną obsługę platformy .NET, nadal musi przeznaczyć 26–56 godzin na wstępną konfigurację, wdrożenie przetwarzania wstępnego i integrację z formatem PDF — tyle samo czasu, ile potrzebowałby w przypadku charlesw. Nowoczesny fork zmniejsza tarcia związane z wersjami; nie zmniejsza nakładu pracy związanego z integracją.

IronOCR odpowiada bezpośrednio na wszystkie cztery luki: języki instalują się jako pakiety NuGet, IronTesseract jest odporny na wielowątkowość, przetwarzanie wstępne jest automatyczne, a PDF jest rodzimy. Kompromis to $999 dla licencji Lite. W przypadku większości aplikacji produkcyjnych ten kompromis szybko się opłaca: czas pracy programisty, nawet przy konkurencyjnej stawce, przewyższa koszt licencji już w pierwszym tygodniu prac konfiguracyjnych, nie licząc bieżącej konserwacji.

Otwartym pytaniem dla każdego zespołu oceniającegoTesseractOCRnie jest to, czy fork jest aktywny i dobrze utrzymywany — bo jest. Pytanie brzmi, czy podstawowa architektura Tesseract spełnia wymagania produkcyjne. Jeśli odpowiedź dotyczy dokumentów o zmiennej jakości, danych wejściowych w formacie PDF, skalowalnej przepustowości lub modelu wdrożenia, w którym zarządzanie danymi jest utrudnione, podejście IronOCR eliminuje te problemy za cenę jednorazowej opłaty licencyjnej.

Zwróć uwagęPDFium, PDFSharp, Tesseract, i iText sa zarejestrowanymi znakami towarowymi ich odpowiednich wlascicieli. Ta strona nie jest powiązana, popierana ani sponsorowana przez Chromium Project, Google, 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

Czym jest TesseractOCR.Net?

TesseractOCR.Net to rozwiązanie OCR używane przez programistów i przedsiębiorstwa do wyodrębniania tekstu z obrazów i dokumentów. Jest to jedna z kilku opcji OCR ocenianych obok IronOCR do tworzenia aplikacji .NET.

Jak IronOCR porównuje się do TesseractOCR.Net dla programistów .NET?

IronOCR to natywna dla NuGet biblioteka OCR dla .NET używająca IronTesseract jako swojego głównego silnika. W porównaniu do TesseractOCR.Net oferuje prostszą wdrożenie (bez instalatorów SDK), jednolitą stawkę cenową oraz czysty interfejs API C# bez potrzeby współpracy z COM lub zależności od chmury.

Czy IronOCR jest łatwiejszy do skonfigurowania niż TesseractOCR.Net?

IronOCR instaluje się za pomocą jednego pakietu NuGet. Nie ma żadnych instalatorów SDK, plików licencyjnych do skopiowania, komponentów COM do zarejestrowania ani oddzielnych plików binarnych środowiska uruchomieniowego, którymi trzeba by zarządzać. Cały silnik OCR jest zawarty w pakiecie.

Jakie różnice w dokładności istnieją między TesseractOCR.Net a IronOCR?

IronOCR osiąga wysoką dokładność rozpoznawania standardowych dokumentów biznesowych, faktur, paragonów i zeskanowanych formularzy. W przypadku dokumentów o bardzo niskiej jakości lub rzadkich skryptów dokładność zależy od jakości źródła. IronOCR zawiera filtry wstępnego przetwarzania obrazu, które poprawiają rozpoznawanie danych wejściowych o niskiej jakości.

Czy IronOCR obsługuje wyodrębnianie tekstu z plików PDF?

Tak. IronOCR wyodrębnia tekst zarówno z natywnych plików PDF, jak i ze skanowanych obrazów PDF za pomocą jednego wywołania. Obsługuje również wielostronicowe pliki TIFF, obrazy i strumienie. W przypadku skanowanych plików PDF OCR jest stosowany strona po stronie, z obiektami wynikowymi dla każdej strony.

Jak licencjonowanie TesseractOCR.Net porównuje się do IronOCR?

IronOCR korzysta z licencji wieczystej o stałej stawce, bez opłat za stronę lub skan. Organizacje przetwarzające duże ilości dokumentów płacą ten sam koszt licencji niezależnie od ilości. Szczegóły i ceny hurtowe znajdują się na stronie licencji IronOCR.

Jakie języki obsługuje IronOCR?

IronOCR obsługuje 127 języków za pośrednictwem oddzielnych pakietów językowych NuGet. Dodanie języka wymaga wykonania pojedynczego polecenia „dotnet add package IronOcr.Languages.{Language}”. Nie jest wymagane ręczne umieszczanie plików ani konfiguracja ścieżek.

Jak zainstalować IronOCR w projekcie .NET?

Instalacja przez NuGet: „Install-Package IronOcr” w konsoli menedżera pakietów lub „dotnet add package IronOcr” w CLI. Dodatkowe pakiety językowe instaluje się w ten sam sposób. Nie jest wymagany natywny instalator SDK.

Czy IronOCR nadaje się do wdrożeń Docker i kontenerowych, w przeciwieństwie do TesseractOCR.Net?

Tak. IronOCR działa w kontenerach Docker za pośrednictwem pakietu NuGet. Klucz licencyjny jest ustawiany za pomocą zmiennej środowiskowej. Silnik OCR nie wymaga żadnych plików licencyjnych, ścieżek SDK ani montowania woluminów.

Czy mogę wypróbować IronOCR przed zakupem, w porównaniu do TesseractOCR.Net?

Tak. Tryb próbny IronOCR przetwarza dokumenty i zwraca wyniki OCR z nakładką znaku wodnego na wyjściu. Przed zakupem licencji można sprawdzić dokładność na własnych dokumentach.

Czy IronOCR obsługuje odczytywanie kodów kreskowych oprócz wyodrębniania tekstu?

IronOCR koncentruje się na wyodrębnianiu tekstu i OCR. Do odczytu kodów kreskowych firma Iron Software udostępnia bibliotekę IronBarcode jako dodatek. Obie biblioteki są dostępne osobno lub w ramach pakietu Iron Suite.

Czy łatwo jest przenieść się z TesseractOCR.Net do IronOCR?

Migracja z TesseractOCR.Net do IronOCR zazwyczaj polega na zastąpieniu sekwencji inicjalizacyjnych instancjowaniem IronTesseract, usunięciu zarządzania cyklem życia COM i aktualizacji wywołań API. Większość migracji znacznie zmniejsza złożoność kodu.

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