IRONSOFTWAREHOME
VIDEOLAR

NET Maui'de OCR Nasıl Yapılır?

Curtis Chau
Curtis Chau
Updated: 28 Haziran 2026

Bu kılavuz .NET geliştiricilerini LEADTOOLS OCR'dan IronOCR'a tam bir göç süreciyle yönlendirir. NuGet paketi değişiminden tam kod göçüne kadar her adımı kapsar ve LEADTOOLS'un başlangıç seremonisi, çoklu ad alanı yapısı ve dosya tabanlı lisans dağıtım modelinden en çok etkilenen desenler için öncesi ve sonrası örnekleri verir.

Neden LEADTOOLS OCR'dan Göç Etmeliyiz

LEADTOOLS OCR, kökeni 1990'a dayanan bir kurumsal görüntüleme platformunda bulunur ve API bu geçmişi yansıtır. Minimum çalışma yapılandırması dört NuGet paketi, dört ad alanı, bilinen bir yola dağıtılmış iki fiziksel lisans dosyası, motor öncesi başlatılan bir codec katmanı, üç seçenekten biri seçilen bir motor türü ve çalışma zamanında programın belleğe yüklenmesini sağlayan bir başlatma çağrısı gerektirir. Tüm bunlar, tek bir karakter tanınmadan önce çalışır. IronOCR'a geçiş yapan ekipler, o katmanların tamamını - bir paket, bir ad alanı, lisans anahtarı ayarlamak için bir satır - ortadan kaldırır.

Dosya Tabanlı Lisans Dağıtımı Kaplarda Bozulur. LEADTOOLS, uygulamayı çalıştıran her makinede belirli bir yolda okunabilen LEADTOOLS.LIC ve LEADTOOLS.LIC.KEY adlı iki fiziksel dosya gerektirir. Docker konteynerlerinde, bu dosyalar ya görüntüye yerleştirilmeli (katman geçmişinde onları açığa çıkararak) ya da çalıştırma sırasında monte edilmeli (her düzen ortamında hacim koordinasyonu gerektiren). Azure Functions ve AWS Lambda, iş çevresi olmadan lisans dosyası dağıtımı için mekanizma sunmaz. CI/CD hatları dosyaların başlangıç çağrısı tarafından kullanılan tam yolda bulunmasını gerektirir, aksi takdirde uygulama tek bir belge işlemeye başlamadan önce hata verir. IronOCR, her iki dosyayı bir ortam değişkenine, Kubernetes gizli bilgisine veya bir Azure Key Vault referansına uyacak bir dizeyle değiştirir.

Tek Bir Görev İçin Dört Paket. Çalışan bir LEADTOOLS OCR projesi, minimum olarak Leadtools, Leadtools.Ocr, Leadtools.Codecs ve Leadtools.Forms.DocumentWriters gerektirir. Şifre korumalı PDF desteği, satın alınan pakete dahil edilmeyebilecek ek bir Leadtools.Pdf modülü gerektirir. Her paketin mevcut, uyumlu ve aynı sürümde olması gerekir. IronOCR, tek bir NuGet paketi olarak gönderilir. Tüm yetenekler — yerel PDF girişi, aranabilir PDF çıktısı, önişleme, barkod okuma — dahildir.

Motor Yaşam Döngüsü Bir Bakım Alanı Oluşturur. LEADTOOLS, OCR motorunu IDisposable servis sınıfında kapsar, bu sadece idiomatik .NET nedenlerinden ötürü değil, Shutdown() çağrısının Dispose()'den önce yapılması gerektiğinden dolayıdır, aksi hâlde uygulama hataları oluşturur. LEADTOOLS toplu işlemcilerinin üretim uygulamalarında genellikle belge parçaları arasında GC.Collect() / GC.WaitForPendingFinalizers() çağrıları, biriken RasterImage örneklerini telafi etmek için bulunur.IronOCR standart using bloklarını kullanır. OcrInput, imha edilmesi gereken tek nesnedir.

Paket Karışıklığı Üretimde Yüzey Alır. LEADTOOLS fiyatlandırmasını açıkça yayınlamaz. Belge Görüntüleme SDK'sı — OCR'yi içeren sınıf — bir geliştirici başına yıllık 3.000–8.000 $ tahmini maliyetle çalışır. OCR modülünü PDF modülü olmadan satın alan ekipler, üretimde şifre korumalı belgeler üzerinde RasterSupport.IsLocked() doğru döndüğünde eksikliği keşfeder. OmniPage motoru doğruluk katmanı, LEADTOOLS satın alımının üzerine farklı bir Kofax lisans anlaşması gerektirir. IronOCR, her katmanda tüm özellikleri lisanslar. İkinci bir satıcı ilişkisi, şifrelenmiş belgeler için ayrı bir modül yoktur.

Başlangıç Maliyeti Soğuk Başlangıçları Etkiler. engine.Startup(), çalışma zamanı dosyalarını belleğe yükleyen engelleyici bir çağrıdır. Soğuk başlatma gecikmesinin önemli olduğu sunucusuz ortamlarda — Azure Functions, AWS Lambda — her türlü tanıma işi başlamadan önce 500–2000 ms'lik bir engelleyici başlangıç, bir yapısal sorun teşkil eder. IronOCR, tembel başlatma kullanır. IronTesseract örneği ilk kullanımda başlatılır ve aynı süreç içindeki sonraki çağrılar hiç başlangıç maliyeti ödemez.

Temel Sorun

LEADTOOLS dört ad alanı, dört NuGet paketi ve herhangi bir karakter tanınmadan önce bir başlangıç seremonisi gerektirir:

// LEADTOOLS: Four namespaces, four packages, six steps before recognition
using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;
using Leadtools.Forms.DocumentWriters;

RasterSupport.SetLicense(licPath, File.ReadAllText(keyPath)); // Step 1: two files on disk
var codecs = new RasterCodecs();                              // Step 2: codec layer
var engine = OcrEngineManager.CreateEngine(OcrEngineType.LEAD); // Step 3: engine factory
engine.Startup(codecs, null, null, runtimePath);              // Step 4: blocking startup
// ... still need to create document, add page, call Recognize(), extract text
C#
// IronOCR: One namespace, one package, one line
using IronOcr;

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
C#

IronOCR vs LEADTOOLS OCR: Özellik Karşılaştırması

Aşağıdaki tablo, yetenekleri iki kütüphane arasında doğrudan eşleştirir.

ÖzellikLEADTOOLS OCRIronOCR
Gerekli NuGet paketleriMinimum 4 (daha fazlası PDF için)1 (IronOcr)
Lisans mekanizması.LIC + .LIC.KEY dosya çiftiDize anahtarı
Lisans dağıtımıHer üretim makinesinde dosyalarOrtam değişkeni veya yapılandırma
Fiyatlandırma modeli$3,000–$15,000+/geliştirici/yıl (tahmini)$999–$2.999 tek seferlik süresiz
Motor başlangıcıÇalışma zamanı yoluyla manuel Startup()Otomatik, tembel
Motor kapanışıShutdown() öncesinde manuel Dispose()Gerekli değil
Codec katmanıTüm görüntü yüklemeleri için RasterCodecs gereklidirGerekli değil
PDF girişiSayfa bazında rasterleştirme döngüsüYerel LoadPdf()
Şifre korumalı PDFAyrı Leadtools.Pdf modülü gerektirirYerleşik Password parametresi
Aranabilir PDF çıktısıDocumentWriter + PdfDocumentOptions + document.Save()result.SaveAsSearchablePdf()
Ön işlemAyrı komut sınıfları (DeskewCommand, DespeckleCommand, vb.)OcrInput üzerinde yerleşik filtre yöntemleri
Çok sayfalı TIFFCodecsLoadByteOrder ile manuel çerçeve yinelemesiinput.LoadImageFrames()
Yapısal çıktıSayfa ve bölge seviyesiKoordinatlı sayfa, paragraf, satır, kelime, karakter
Güvenlik puanlamasıOcrPageRecognizeStatus enumYüzde olarak result.Confidence
Barkod okumaAyrıca LEADTOOLS Barkod modülüYerleşik (ReadBarCodes = true)
Thread güvenliğiDikkatli yönetim gerektirirTam (her iş parçacığına bir IronTesseract)
Desteklenen diller60–120 (motor bağımlı)125'ten fazla NuGet dil paketleri üzerinden
Dil dağıtımıtessdata files or engine-bundled filesHer dil için NuGet paketi
Çapraz platformHer platform için çalışma zamanı yapılandırması ile desteklenirWindows, Linux, macOS, Docker, Azure, AWS
Docker dağıtımı.KEY dosyaları monte edilmeli veya gömülmelidirStandart dotnet publish
Ticari destekEvetEvet

Hızlı Başlangıç: LEADTOOLS OCR'dan IronOCR'a Geçiş

Adım 1: NuGet Paketini Değiştirin

Tüm LEADTOOLS paketlerini kaldırın:

dotnet remove package Leadtools
dotnet remove package Leadtools.Ocr
dotnet remove package Leadtools.Codecs
dotnet remove package Leadtools.Forms.DocumentWriters
dotnet remove package Leadtools.Pdf
SHELL

NuGet kullanarak IronOCR'u yükleyin:

dotnet add package IronOcr

Adım 2: Ad Alanlarını Güncelleyin

Tüm LEADTOOLS using direktiflerini tek bir IronOCR içe aktarması ile değiştirin:

// Before (LEADTOOLS)
using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;
using Leadtools.Forms.DocumentWriters;

// After (IronOCR)
using IronOcr;
C#

Adım 3: Lisansa İzin Verin

Tüm RasterSupport.SetLicense() çağrılarını ve .LIC / .LIC.KEY dosya referanslarını kaldırın. Uygulama başlangıcında IronOCR lisans anahtarını ekleyin:

// Single line replaces the entire file-based license setup
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Production pattern: pull from environment variable or secrets manager
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
C#

Lisans anahtarı, herhangi bir standart .NET sır yönetim deseni — appsettings.json, Azure Key Vault, AWS Secrets Manager veya bir Kubernetes sırrı içinde depolanabilir. Uygulama ikili dosyasıyla birlikte hiçbir dosya dağıtılmasına gerek yoktur.

Kod Göç Örnekleri

Motor Başlatma ve Kapatma Yaşam Döngüsü Kaldırma

LEADTOOLS, motor yaşam döngüsünün açıkça yönetilmesi gerektiğinden katı bir hizmet sınıfı örüntüsü zorunlu kılar. Yapıcı motoru başlatır, Dispose() onu doğru sırayla kapatır ve Shutdown()'yi Dispose()'den önce atlayan herhangi bir kod yolu bir çalışma zamanı hatası üretir.

LEADTOOLS OCR Yaklaşımı:

using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;

// Service class required purely to manage engine lifecycle
public class LeadtoolsOcrService : IDisposable
{
    private IOcrEngine _engine;
    private RasterCodecs _codecs;
    private readonly string _runtimePath;

    public LeadtoolsOcrService(string licPath, string keyPath, string runtimePath)
    {
        _runtimePath = runtimePath;

        // License setup — two files, both must be present
        RasterSupport.SetLicense(licPath, File.ReadAllText(keyPath));

        // Codec layer — required before engine creation
        _codecs = new RasterCodecs();

        // Engine factory — engine type determines capability and cost
        _engine = OcrEngineManager.CreateEngine(OcrEngineType.LEAD);

        // Blocking startup — loads runtime into memory (500–2000ms)
        _engine.Startup(_codecs, null, null, _runtimePath);
    }

    public bool IsReady => _engine?.IsStarted ?? false;

    public string Process(string imagePath)
    {
        if (!IsReady)
            throw new InvalidOperationException("Engine not started");

        using var image = _codecs.Load(imagePath);
        using var doc = _engine.DocumentManager.CreateDocument();
        var page = doc.Pages.AddPage(image, null);
        page.Recognize(null);
        return page.GetText(-1);
    }

    public void Dispose()
    {
        // Order is mandatory: Shutdown before Dispose
        if (_engine?.IsStarted == true)
            _engine.Shutdown();

        _engine?.Dispose();
        _codecs?.Dispose();
    }
}
C#

IronOCR Yaklaşımı:

using IronOcr;

// No lifecycle management needed — the service class becomes trivial
public class OcrService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    // Always ready — no IsStarted check needed
    public string Process(string imagePath) => _ocr.Read(imagePath).Text;

    // No Dispose() needed for the engine
    // No Startup(), no Shutdown(), no codec layer
}
C#

IronTesseract örneği ilk kullanımda başlatılır. Yapıcı argümanlar yok, çalışma zamanı yolu yok, Startup() çağrısı yok. Yukarıdaki servis sınıfının IDisposable'yı uygulaması gerekmiyor — motor durumsuzdur ve her Read() çağrısında kullanılan OcrInput nesneleri, standart using deseni ile kendi temizliğini gerçekleştirir. IronTesseract kurulum kılavuzu, üretim senaryoları için dil seçimi ve performans ayarlamalarını da içeren yapılandırma seçeneklerini kapsar.

Çok Kareli TIFF Yığın İşleme

LEADTOOLS, toplam çerçeve sayısını öğrenmek için kodeği sorgulayarak çok çerçeveli TIFF dosyalarını işler ve ardından her _codecs.Load() çağrısında belirgin lastPage parametreleri ile yineleme yapar. Her çerçeve resmi manuel olarak atılmalıdır aksi takdirde bellek birikir.

LEADTOOLS OCR Yaklaşımı:

using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;

public class LeadtoolsTiffBatchService
{
    private readonly IOcrEngine _engine;
    private readonly RasterCodecs _codecs;

    public List<string> ProcessMultiFrameTiff(string tiffPath)
    {
        var pageTexts = new List<string>();

        // Must query page count before iterating
        var info = _codecs.GetInformation(tiffPath, true);
        int frameCount = info.TotalPages;

        using var document = _engine.DocumentManager.CreateDocument();

        for (int frameNum = 1; frameNum <= frameCount; frameNum++)
        {
            // Load one frame at a time — must specify firstPage/lastPage
            using var frameImage = _codecs.Load(
                tiffPath,
                0,                            // bitsPerPixel
                CodecsLoadByteOrder.BgrOrGray,
                frameNum,                     // firstPage
                frameNum);                    // lastPage

            var page = document.Pages.AddPage(frameImage, null);
            page.Recognize(null);
            pageTexts.Add(page.GetText(-1));

            // GC pressure accumulates if disposal is missed on any frame
        }

        return pageTexts;
    }

    public Dictionary<string, List<string>> ProcessTiffDirectory(string directoryPath)
    {
        var results = new Dictionary<string, List<string>>();

        foreach (var tiffFile in Directory.GetFiles(directoryPath, "*.tiff"))
        {
            results[tiffFile] = ProcessMultiFrameTiff(tiffFile);

            // Manual GC between files to prevent memory growth
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        return results;
    }
}
C#

IronOCR Yaklaşımı:

using IronOcr;

public class TiffBatchService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public List<string> ProcessMultiFrameTiff(string tiffPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);  // All frames loaded automatically

        var result = _ocr.Read(input);

        // Per-frame text available through result.Pages
        return result.Pages.Select(p => p.Text).ToList();
    }

    public Dictionary<string, List<string>> ProcessTiffDirectory(string directoryPath)
    {
        var results = new Dictionary<string, List<string>>();

        foreach (var tiffFile in Directory.GetFiles(directoryPath, "*.tiff"))
        {
            results[tiffFile] = ProcessMultiFrameTiff(tiffFile);
        }

        return results;
    }

    // Parallel processing across files — thread-safe out of the box
    public Dictionary<string, List<string>> ProcessTiffDirectoryParallel(string directoryPath)
    {
        var concurrentResults = new System.Collections.Concurrent.ConcurrentDictionary<string, List<string>>();
        var tiffFiles = Directory.GetFiles(directoryPath, "*.tiff");

        Parallel.ForEach(tiffFiles, tiffFile =>
        {
            using var input = new OcrInput();
            input.LoadImageFrames(tiffFile);
            var result = new IronTesseract().Read(input);
            concurrentResults[tiffFile] = result.Pages.Select(p => p.Text).ToList();
        });

        return new Dictionary<string, List<string>>(concurrentResults);
    }
}
C#

LoadImageFrames(), tek bir çağrıda TIFF'ten tüm çerçeveleri okur. Çerçeve sayısı sorgusu, döngü, açıkça çerçeve başına atama yok. Paralel sürüm, iş parçacığı başına bir IronTesseract örneği oluşturur, bu doğru bir desendir — tam iş parçacığı modeli için çok iş parçacığı kullanımı örneğine bakın. TIFF'ye özel giriş seçenekleri için TIFF ve GIF giriş kılavuzu, çerçeve seçimini ve çoklu format işleme koşullarını kapsar.

Belge Yazar Hat İş Simplifikasyonu

LEADTOOLS aranabilir PDF oluşturma, motor üzerinde bir DocumentWriter örneğini yapılandırmayı, çıktı türü ve örtüşme ayarları ile bir PdfDocumentOptions nesnesi oluşturmayı, seçenekleri SetOptions() aracılığıyla uygulamayı ve ardından document.Save() ile format enum'u çağırmayı gerektirir. Bu adımların her biri ayrı bir nesne ve ayrı bir API çağrısıdır.

LEADTOOLS OCR Yaklaşımı:

using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;
using Leadtools.Forms.DocumentWriters;

public class LeadtoolsDocumentWriterService
{
    private readonly IOcrEngine _engine;
    private readonly RasterCodecs _codecs;

    public void CreateSearchablePdfFromImages(string[] imagePaths, string outputPath)
    {
        using var document = _engine.DocumentManager.CreateDocument();

        foreach (var imagePath in imagePaths)
        {
            using var image = _codecs.Load(imagePath);
            var page = document.Pages.AddPage(image, null);
            page.Recognize(null);
        }

        // DocumentWriter configuration — four properties to set before save
        var pdfOptions = new PdfDocumentOptions
        {
            DocumentType = PdfDocumentType.Pdf,
            ImageOverText = true,     // Image layer visible, text layer searchable
            Linearized = false,
            Title = "Searchable Output"
        };

        // Apply options to the engine's writer instance
        _engine.DocumentWriterInstance.SetOptions(DocumentFormat.Pdf, pdfOptions);

        // Save with format enum — the format must match the options set above
        document.Save(outputPath, DocumentFormat.Pdf, null);
    }

    public void CreateSearchablePdfFromPdf(string inputPdfPath, string outputPath)
    {
        var pdfInfo = _codecs.GetInformation(inputPdfPath, true);
        using var document = _engine.DocumentManager.CreateDocument();

        for (int i = 1; i <= pdfInfo.TotalPages; i++)
        {
            using var pageImage = _codecs.Load(inputPdfPath, 0,
                CodecsLoadByteOrder.BgrOrGray, i, i);

            var page = document.Pages.AddPage(pageImage, null);
            page.Recognize(null);
        }

        var pdfOptions = new PdfDocumentOptions
        {
            DocumentType = PdfDocumentType.Pdf,
            ImageOverText = true,
            Title = Path.GetFileNameWithoutExtension(inputPdfPath)
        };

        _engine.DocumentWriterInstance.SetOptions(DocumentFormat.Pdf, pdfOptions);
        document.Save(outputPath, DocumentFormat.Pdf, null);
    }
}
C#

IronOCR Yaklaşımı:

using IronOcr;

public class SearchablePdfService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public void CreateSearchablePdfFromImages(string[] imagePaths, string outputPath)
    {
        using var input = new OcrInput();
        foreach (var imagePath in imagePaths)
            input.LoadImage(imagePath);

        var result = _ocr.Read(input);
        result.SaveAsSearchablePdf(outputPath);  // DocumentWriter pipeline: gone
    }

    public void CreateSearchablePdfFromPdf(string inputPdfPath, string outputPath)
    {
        using var input = new OcrInput();
        input.LoadPdf(inputPdfPath);

        var result = _ocr.Read(input);
        result.SaveAsSearchablePdf(outputPath);
    }

    // Get bytes directly — useful for streaming responses in ASP.NET
    public byte[] CreateSearchablePdfBytes(string inputPdfPath)
    {
        using var input = new OcrInput();
        input.LoadPdf(inputPdfPath);
        return _ocr.Read(input).SaveAsSearchablePdfBytes();
    }
}
C#

SaveAsSearchablePdf(), tüm PdfDocumentOptions + SetOptions() + document.Save() zincirini değiştirir. Resim üstü metin katmanı davranışı otomatik olarak yapılır. Tam aranabilir PDF çıktı dokümantasyonu için aranabilir PDF nasıl yapılır kılavuzu çıktı seçeneklerini kapsar ve aranabilir PDF örneği ASP.NET yanıt akışlarına entegrasyonu gösterir.

Çok Bölgeli Alan Çıkarma Göçü

LEADTOOLS bölge tabanlı OCR, OcrZone nesneleri ile LeadRect sınırları, OcrZoneType ve OcrZoneCharacterFilters özelliklerini kullanır. Birden fazla bölge tek bir sayfaya eklenir ve bir page.Recognize() çağrısında tanınır, ardından bölge indeksi ile çıkarılır. Bölge dizini ekleme sırasını eşleştirir, bu da çıkarma döngüsünün bu sıralamayı koruması gerektiği anlamına gelir.

LEADTOOLS OCR Yaklaşımı:

using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;

public class LeadtoolsFormFieldExtractor
{
    private readonly IOcrEngine _engine;
    private readonly RasterCodecs _codecs;

    // Invoice field extraction using named zones
    public InvoiceFields ExtractInvoiceFields(string invoicePath)
    {
        using var image = _codecs.Load(invoicePath);
        using var document = _engine.DocumentManager.CreateDocument();
        var page = document.Pages.AddPage(image, null);

        // Must clear auto-detected zones before adding custom ones
        page.Zones.Clear();

        // Zone definitions — index order matters for extraction
        var zoneDefinitions = new[]
        {
            new { Name = "InvoiceNumber", X = 450, Y = 80,  W = 200, H = 30 },
            new { Name = "InvoiceDate",   X = 450, Y = 115, W = 200, H = 30 },
            new { Name = "VendorName",    X = 50,  Y = 150, W = 300, H = 40 },
            new { Name = "TotalAmount",   X = 450, Y = 600, W = 200, H = 30 }
        };

        foreach (var def in zoneDefinitions)
        {
            var zone = new OcrZone
            {
                Bounds = new LeadRect(def.X, def.Y, def.W, def.H),
                ZoneType = OcrZoneType.Text,
                CharacterFilters = OcrZoneCharacterFilters.None,
                RecognitionModule = OcrZoneRecognitionModule.Auto
            };
            page.Zones.Add(zone);
        }

        page.Recognize(null);

        // Extract by index — must match insertion order exactly
        return new InvoiceFields
        {
            InvoiceNumber = page.Zones[0].Text?.Trim(),
            InvoiceDate   = page.Zones[1].Text?.Trim(),
            VendorName    = page.Zones[2].Text?.Trim(),
            TotalAmount   = page.Zones[3].Text?.Trim()
        };
    }
}

public class InvoiceFields
{
    public string InvoiceNumber { get; set; }
    public string InvoiceDate   { get; set; }
    public string VendorName    { get; set; }
    public string TotalAmount   { get; set; }
}
C#

IronOCR Yaklaşımı:

using IronOcr;

public class FormFieldExtractor
{
    private readonly IronTesseract _ocr = new IronTesseract();

    // Each field gets its own CropRectangle-scoped Read() call
    // No zone index management, no zone ordering dependency
    public InvoiceFields ExtractInvoiceFields(string invoicePath)
    {
        return new InvoiceFields
        {
            InvoiceNumber = ReadRegion(invoicePath, 450, 80,  200, 30),
            InvoiceDate   = ReadRegion(invoicePath, 450, 115, 200, 30),
            VendorName    = ReadRegion(invoicePath, 50,  150, 300, 40),
            TotalAmount   = ReadRegion(invoicePath, 450, 600, 200, 30)
        };
    }

    private string ReadRegion(string imagePath, int x, int y, int width, int height)
    {
        using var input = new OcrInput();
        input.LoadImage(imagePath, new CropRectangle(x, y, width, height));
        return _ocr.Read(input).Text.Trim();
    }

    // Batch: extract the same field from many invoices in parallel
    public Dictionary<string, string> ExtractInvoiceNumbersBatch(string[] invoicePaths)
    {
        var results = new System.Collections.Concurrent.ConcurrentDictionary<string, string>();

        Parallel.ForEach(invoicePaths, invoicePath =>
        {
            using var input = new OcrInput();
            input.LoadImage(invoicePath, new CropRectangle(450, 80, 200, 30));
            results[invoicePath] = new IronTesseract().Read(input).Text.Trim();
        });

        return new Dictionary<string, string>(results);
    }
}
C#

CropRectangle doğrudan LoadImage()'ya geçirildiğinde, tüm OcrZone kurulumunu değiştirir. İzlenecek bir bölge indeksi, gerekli page.Zones.Clear() çağrısı veya tanıma durumu kontrolü yoktur. bölge tabanlı OCR kılavuzu tekli ve çoklu bölge ayıklama örneklerini kapsar. Tam bir fatura alan çıkarma öğreticisi için fatura OCR öğreticisine bakın.

Sözel Koordinatlarla Yapılandırılmış Veri Çıkarma

LEADTOOLS yapılandırılmış çıktı, sayfa ve bölge seviyesinde çalışır. Bağımsız kelime düzeyinde veri elde etmek için geliştirici, tanınmış bir bölgeden OcrWord nesnelerine erişir. API tanıma sonrası bölge koleksiyonu üzerinde çalışmayı ve her bir bölge için kelime listesi yinelemeyi gerektirir.

LEADTOOLS OCR Yaklaşımı:

using Leadtools;
using Leadtools.Ocr;
using Leadtools.Codecs;

public class LeadtoolsStructuredExtractor
{
    private readonly IOcrEngine _engine;
    private readonly RasterCodecs _codecs;

    public List<WordLocation> ExtractWordsWithLocations(string imagePath)
    {
        var wordLocations = new List<WordLocation>();

        using var image = _codecs.Load(imagePath);
        using var document = _engine.DocumentManager.CreateDocument();
        var page = document.Pages.AddPage(image, null);
        page.Recognize(null);

        // Access words through the zone collection
        foreach (OcrZone zone in page.Zones)
        {
            foreach (OcrWord word in zone.Words)
            {
                wordLocations.Add(new WordLocation
                {
                    Text       = word.Value,
                    X          = word.Bounds.X,
                    Y          = word.Bounds.Y,
                    Width      = word.Bounds.Width,
                    Height     = word.Bounds.Height,
                    Confidence = word.Confidence
                });
            }
        }

        return wordLocations;
    }
}

public class WordLocation
{
    public string Text       { get; set; }
    public int    X          { get; set; }
    public int    Y          { get; set; }
    public int    Width      { get; set; }
    public int    Height     { get; set; }
    public int    Confidence { get; set; }
}
C#

IronOCR Yaklaşımı:

using IronOcr;

public class StructuredExtractor
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public List<WordLocation> ExtractWordsWithLocations(string imagePath)
    {
        var result = _ocr.Read(imagePath);

        // Five-level hierarchy: Pages > Paragraphs > Lines > Words > Characters
        return result.Pages
            .SelectMany(page => page.Paragraphs)
            .SelectMany(para => para.Lines)
            .SelectMany(line => line.Words)
            .Select(word => new WordLocation
            {
                Text       = word.Text,
                X          = word.X,
                Y          = word.Y,
                Width      = word.Width,
                Height     = word.Height,
                Confidence = (int)word.Confidence
            })
            .ToList();
    }

    // Paragraph-level extraction with position data
    public void PrintDocumentStructure(string imagePath)
    {
        var result = _ocr.Read(imagePath);
        Console.WriteLine($"Document confidence: {result.Confidence}%");

        foreach (var page in result.Pages)
        {
            Console.WriteLine($"Page {page.PageNumber}:");
            foreach (var paragraph in page.Paragraphs)
            {
                Console.WriteLine($"  Paragraph at ({paragraph.X}, {paragraph.Y}):");
                Console.WriteLine($"  {paragraph.Text}");
            }
        }
    }
}
C#

IronOCR'un sonuç hiyerarşisi, Pages'den Paragraphs, Lines, Words ve Characters aracılığıyla aşağı iner. Her seviye, X, Y, Width, Height, Text ve Confidence'yi ortaya çıkarır. LEADTOOLS bölge tabanlı erişim örüntüsü yok olur — kelime verisine ulaşmak için bölge yinelemeye gerek yoktur. sonuçları okuma nasıl yapılır kılavuzu, koordinat erişim örüntüleriyle birlikte tam çıktı modelini kapsar. OcrResult API referansı, sonuç hiyerarşisindeki her özelliği belgeler.

LEADTOOLS OCRAPI'sinden IronOCR Haritalama Referansı

LEADTOOLS OCRIronOCR
RasterSupport.SetLicense(licPath, keyContent)IronOcr.License.LicenseKey = "key"
new RasterCodecs()Gerekli değil
OcrEngineManager.CreateEngine(OcrEngineType.LEAD)new IronTesseract()
engine.Startup(codecs, null, null, runtimePath)Gerekli değil
engine.IsStartedGerekli değil (her zaman hazır)
engine.Shutdown()Gerekli değil
engine.Dispose()Gerekli değil
_codecs.Load(imagePath)input.LoadImage(imagePath)
_codecs.Load(path, 0, BgrOrGray, page, page)input.LoadPdf(path) veya input.LoadImageFrames(path)
_codecs.GetInformation(path, true).TotalPagesGerekli değil — otomatik
engine.DocumentManager.CreateDocument()Gerekli değil
document.Pages.AddPage(image, null)input.LoadImage(imagePath)
page.Recognize(null)ocr.Read(input) (tanıma kısmı Read())
page.GetText(-1)result.Text
page.RecognizeStatusresult.Confidence (yüzde)
OcrZone { Bounds = new LeadRect(x, y, w, h) }new CropRectangle(x, y, w, h)
page.Zones.Clear()Gerekli değil
page.Zones.Add(zone)input.LoadImage(path, cropRect)
zone.Words / word.Boundsresult.Pages[n].Words / word.X, word.Y
DeskewCommand().Run(image)input.Deskew()
DespeckleCommand().Run(image)input.DeNoise()
AutoBinarizeCommand().Run(image)input.Binarize()
ContrastBrightnessCommand().Run(image)input.Contrast()
new PdfDocumentOptions { ImageOverText = true }SaveAsSearchablePdf() tarafından otomatik olarak ele alınır
engine.DocumentWriterInstance.SetOptions(format, opts)Gerekli değil
document.Save(path, DocumentFormat.Pdf, null)result.SaveAsSearchablePdf(path)
_codecs.Options.Pdf.Load.Password = passwordinput.LoadPdf(path, Password: password)
RasterSupport.IsLocked(RasterSupportType.Document)IronOcr.License.IsLicensed

Yaygın Göç Sorunları ve Çözümleri

Sorun 1: Lisans Dosya Yolu Çözümleme Hataları

LEADTOOLS: RasterSupport.SetLicense(), .LIC ve .LIC.KEY dosya yollarını çalışma dizinine göre çözer, bu da bin/Debug, bin/Release, Docker konteynerleri ve IIS uygulama havuzları arasında farklılık gösterir. Yaygın bir başarısızlık modu, geliştirme sırasında çalışan ancak üretimde "License file not found" fırlatan bir yoldur, çünkü çalışma dizini değişmiştir.

Çözüm: Her iki lisans dosyasını ve SetLicense() çağrısını tamamen silin. Bir ortam değişkeninden okunan tek bir dize ataması ile değiştirin:

// Remove this:
// RasterSupport.SetLicense(licPath, File.ReadAllText(keyPath));

// Replace with this:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
    ?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable not set");
C#

Dize anahtarı, her ortamda aynı şekilde davranır. Bunu, veritabanı bağlantı dizgeleri için zaten kullanılan aynı gizli yöneticiye depolayın.

Sorun 2: Motor Başlatılmadı İstisnası

LEADTOOLS: engine.Startup() tamamlanmadan önce veya engine.Shutdown() çağrıldıktan sonra (örneğin, kapatma sırasında kullanımdan önce yok etmek yarışı durumu), bir InvalidOperationException "Motor başlatılmadı." ile fırlatır. Uzun ömürlü servis sınıfları, IsStarted kontrolleri ile buna karşı koruma sağlamalıdır.

Çözüm: IronTesseract, başlangıç çağrısı gerektirmez ve başlatılmış/durdurulmuş bir durumu yoktur. IsStarted koruması ve tüm yaşam döngüsü servis sınıfı silinebilir:

// Remove the guard:
// if (!_engine.IsStarted)
//     throw new InvalidOperationException("Engine not started");

// IronTesseract is always ready — just call Read()
var result = _ocr.Read(imagePath);
C#

Sorun 3: Batch İşlemde RasterImage Bellek Birikimi

LEADTOOLS: PDF sayfaları veya görüntü dosyaları üzerinde yineleyerek gerçekleştirilen toplu işlem, bir döngü içinde RasterImage örnekleri oluşturur. Herhangi bir kod yolu, using bloğundan çıkmadan önce atılan bir istisna nedeniyle veya eksik bir çağrı ile manuel bir imha deseni nedeniyle bir RasterImage'yi imha etmezse, serbest bırakılmamış görüntüler bellekte birikir. LEADTOOLS üretim kodu, toplu işlemeler arasında GC.Collect() / GC.WaitForPendingFinalizers() çağrılarını telafi edici bir mekanizma olarak yaygın bir şekilde içerir.

Çözüm: Tüm GC.Collect() çağrılarını kaldırın. OcrInput,IronOCR işlem hattında tek IDisposable'dir ve standart using bloğu ile her toplu işlem için kapsamlanmıştır.

// Remove this pattern:
// GC.Collect();
// GC.WaitForPendingFinalizers();

// Replace with standard using scope:
foreach (var filePath in filePaths)
{
    using var input = new OcrInput();
    input.LoadImage(filePath);
    var text = _ocr.Read(input).Text;
    // input disposed here — no accumulation
}
C#

Ek bellek optimizasyonu kılavuzu için müşteri bellek tahsisi azaltımı blog yazısına başvurun.

Sorun 4: DocumentWriterInstance Seçenekleri Çağrılar Arasında Kalıcı

LEADTOOLS: engine.DocumentWriterInstance.SetOptions(), paylaşılan motor yazar örneğinde durumu değiştirir. Bir kod yolu PdfDocumentOptions'yı DocumentType = PdfDocumentType.PdfA ile ayarlarsa ve müteakip çağrı bu seçenekleri document.Save()'dan önce sıfırlamazsa, önceki çağrının çıktı formatı kalır. Bu, paylaşılan motor örneğinde duruma dayalı yan etkidir.

Çözüm: IronOCR, paylaşılan yazıcı durumu yoktur. Her SaveAsSearchablePdf() çağrısı bağımsızdır:

// Remove the options setup:
// var pdfOptions = new PdfDocumentOptions { ... };
// _engine.DocumentWriterInstance.SetOptions(DocumentFormat.Pdf, pdfOptions);
// document.Save(outputPath, DocumentFormat.Pdf, null);

// Replace with:
result.SaveAsSearchablePdf(outputPath);
C#

Her çağrı, bir görüntü kaplaması ve aranabilir bir metin katmanı ile standart PDF çıktısı üretir. Çağrılar arasında sıfırlanması gereken paylaşılan seçenek durumu yoktur.

Sorun 5: Yanlış Paket — Çalışma Zamanında Eksik Modül

LEADTOOLS: Document Imaging SDK'sını satın alan ekipler, Leadtools.Pdf türlerinin kullanılamayabileceğini veya şifreli PDF sayfalarının RasterException ile RasterExceptionCode.FeatureNotSupported fırlatabileceğini görebilir. Bu, satın alınan paketin PDF modülünü içermediğinde olur ve hata yalnızca üretimde çalışma zamanında ortaya çıkar.

Çözüm: IronOCR, her lisans katmanında tüm özellikleri içerir. Ayrı bir PDF modülü, şifreli belgeler için bir eklenti veya daha yüksek doğruluklu bir motor için ikinci bir satıcı bulunmamaktadır. Tek IronOcr paketi yüklendikten sonra, tam özellik seti herhangi bir ek satın alma gerektirmeden kullanılabilir durumdadır.

dotnet add package IronOcr

Sorun 6: Boylam İndeksi Yeniden Sıralama Sonrası Uyumsuzluk

LEADTOOLS: Bölge çıkarımı, çıkarım mantığını page.Zones.Add()'deki yerleştirme sırasına bağlayan pozisyonel indeksleme — page.Zones[0].Text, page.Zones[1].Text — kullanır. Bölge tanımlarını otomatik güncellemeyi ifade eden ya da yeniden sıralamak, ardından gelen tüm indeksleri yerleştirerek sessizce kırar.

Çözüm: IronOCR, alan başına CropRectangle ile adlandırılmış değişkenler kullanır. Alan tanımlarının yeniden sıralanması, çıkarma sırasında hiçbir etkiye sahip değildir çünkü her alan bağımsız olarak kapsamlanmıştır:

// Each field is independent — reorder freely without breaking extraction
var invoiceNumber = ReadRegion(imagePath, 450, 80,  200, 30);
var invoiceDate   = ReadRegion(imagePath, 450, 115, 200, 30);
var vendorName    = ReadRegion(imagePath, 50,  150, 300, 40);
var totalAmount   = ReadRegion(imagePath, 450, 600, 200, 30);
C#

LEADTOOLS OCRGöç Kontrol Listesi

Öncesi-Geçiş

Değişiklik yapmadan önce tüm LEADTOOLS kullanımını belirlemek için kod tabanını denetleyin:

# Find all LEADTOOLS namespace imports
grep -rn "using Leadtools" --include="*.cs" .

# Find engine lifecycle calls
grep -rn "OcrEngineManager\|\.Startup(\|\.Shutdown()" --include="*.cs" .

# Find license file references
grep -rn "SetLicense\|LEADTOOLS\.LIC\|\.LIC\.KEY" --include="*.cs" .

# Find RasterCodecs usage
grep -rn "RasterCodecs\|_codecs\.Load\|GetInformation" --include="*.cs" .

# Find DocumentWriter usage
grep -rn "DocumentWriterInstance\|PdfDocumentOptions\|DocumentFormat\." --include="*.cs" .

# Find zone-based OCR
grep -rn "OcrZone\|page\.Zones\|LeadRect\|ZoneType" --include="*.cs" .

# Find GC workarounds to remove
grep -rn "GC\.Collect\|WaitForPendingFinalizers" --include="*.cs" .
SHELL

Satın alınan LEADTOOLS paketinin — OCR modülü, PDF modülü ve motor türü (LEAD vs Tesseract vs OmniPage) — hangi olduğunu not edin, böylece eşdeğer IronOCR özellikleri göç sonrası doğrulama sırasında test edilir.

Kod Geçişi

  1. Tüm LEADTOOLS NuGet paketlerini kaldırın: Leadtools, Leadtools.Ocr, Leadtools.Codecs, Leadtools.Forms.DocumentWriters, Leadtools.Pdf
  2. IronOcr NuGet paketini yükleyin
  3. Tüm LEADTOOLS using direktiflerini using IronOcr; ile değiştirin
  4. .LIC ve .LIC.KEY dosyalarını projeden ve dağıtım ürünlerinden kaldırın
  5. Uygulama başlatıldığında RasterSupport.SetLicense(licPath, keyContent)IronOcr.License.LicenseKey = "key" ile değiştirin
  6. Sadece IOcrEngine ve RasterCodecs yaşam döngüsünü yönetmek için var olan tüm IDisposable servis sınıflarını silin
  7. OcrEngineManager.CreateEngine() + engine.Startup() yerine new IronTesseract() kullanın
  8. _codecs.Load(imagePath)'ı, bir using var input = new OcrInput() bloğu içinde input.LoadImage(imagePath) ile değiştirin
  9. Çok çerçeveli TIFF sayfa döngülerini input.LoadImageFrames(tiffPath) ile değiştirin
  10. PDF sayfa döngüsü yinelemesini input.LoadPdf(pdfPath) ile değiştirin
  11. document.Pages.AddPage() + page.Recognize(null) + page.GetText(-1) yerine ocr.Read(input).Text kullanın
  12. OcrZone + page.Zones.Add() kalıplarını input.LoadImage(path, new CropRectangle(x, y, w, h)) ile değiştirin
  13. PdfDocumentOptions + DocumentWriterInstance.SetOptions() + document.Save() yerine result.SaveAsSearchablePdf(path) kullanın
  14. Ön işlem komut sınıflarını (DeskewCommand, DespeckleCommand, AutoBinarizeCommand) input.Deskew(), input.DeNoise(), input.Binarize() ile OcrInput örneğinde değiştirin
  15. LEADTOOLS bellek yönetimini telafi etmek için eklenen tüm GC.Collect() / GC.WaitForPendingFinalizers() çağrılarını kaldırın

Geçiş Sonrası

  • Tanınan metin çıktısının, temsilci bir görüntü ve PDF örneği üzerinde LEADTOOLS çıktısıyla eşleştiğini doğrulayın
  • result.Confidence kullanarak güven puanlarının beklenen aralıklarda olduğundan emin olun
  • Çok kareli TIFF işleme, LEADTOOLS çerçeve yineleme döngüsü ile aynı sayıda sayfa ürettiğini test edin
  • Aranabilir PDF çıktısının, bir PDF okuyucusunda (Adobe Acrobat veya dengi) metin aranabilir olduğunu onaylayın
  • Üretim faturalarından veya formlarından bilinen iyi alan değerlerine karşı alan tabanlı çıkarımı test edin
  • Ayrı Leadtools.Pdf modülü olmadan şifre korumalı PDF şifresinin çözüldüğünü doğrulayın
  • Yük altında toplu işlemeyi çalıştırın ve bellek artışı olmadığını doğrulayın (önce tüm GC.Collect() kaldırın)
  • Lisans dosyası olmadan Docker ve CI/CD dağıtımını test edin — lisans anahtarının ortam değişkeninden doğru şekilde çözümlendiğini doğrulayın
  • İş parçacığı güvenliğini doğrulamak için Parallel.ForEach ile paralel işlemeyi test edin
  • Yapılandırılmış veri çıkarımının (result.Pages, page.Paragraphs, page.Words) doğru koordinatları döndürdüğünü doğrulayın

IronOCR'a Geçişin Ana Faydaları

Dağıtım Durumsuz Hale Gelir. LEADTOOLS .LIC ve .LIC.KEY dosyaları, her dağıtım ortamının taşıması gereken artefaktlardır. Onları içeren kapsayıcılar lisans verilerini imaj geçmişinde açığa çıkarır. Onları monte eden kapsayıcılar, hacim koordinasyonu gerektirir. IronOCR'ye göçten sonra, lisans bir ortam değişkeninde bir dizgedir. Dağıtım eseri, bir standart NuGet referansıdır. Dosya yoktur, yol yoktur, montaj stratejisi yoktur. Docker dağıtım kılavuzu ve Azure dağıtım kılavuzu, kapsayıcılaştırılmış ortamlar için tamamlanmış ayarı gösterir.

Dört Paket Bir Olur. Geçiş Leadtools, Leadtools.Ocr, Leadtools.Codecs, Leadtools.Forms.DocumentWriters ve isteğe bağlı olarak Leadtools.Pdf'yı tek bir IronOcr referansına indirir. Tüm yetenekler — işlem öncesi, yerel PDF girişi, aranabilir PDF çıktısı, barkod okuma, yapılandırılmış veri çıkarma, 125+ dil desteği — tek pakette yer alır. Özellik seti, hangi paketin satın alındığına bağlı değildir.

Toplu İşlem Elle Bellek Yönetimini Ortadan Kaldırır. LEADTOOLS toplu kodu, çok belgeli işlemler sırasında bellek birikimini önlemek için defansif GC.Collect() çağrılarını ve açık RasterImage imhasını taşır. IronOCR'un OcrInput'ü, bir using bloğu ile kapsamlanmış, temizlemeyi otomatik olarak gerçekleştirir. Paralel iş parçacığı güvenli işleme Parallel.ForEach ile — iş parçacığı başına bir IronTesseract örneği — senkronizasyon kodu olmadan çok çekirdekli verim sağlar. Üretim throughput ayarı için hız optimizasyonu kılavuzuna bakın.

Öngörülebilir Toplam Maliyet. LEADTOOLS'un beş geliştiricili bir ekip için tahmini maliyeti, ilk yılda 15.000–40.000 $ arasında koşar ve lisans maliyetinin %20-25'i oranında yıllık bakım gerektirir.IronOCR Professional $2,399'de on geliştirici ve on dağıtım konumunu kapsar ve bir kerelik süresiz bir satın almadır. Bir yıl güncellemeler dahildir. Güncelleme döneminden sonra devam eden kullanım için ek ödeme gerekmemektedir. IronOCR lisans sayfası, tüm katman fiyatlarını doğrudan yayınlar, satış danışmanlığı olmadan.

Bölge Kurulumu Olmadan Yapılandırılmış Veri. Geçişten sonra OcrResult üzerinde doğrudan sınırlayıcı kutu koordinatları ile kelime seviyesi, satır seviyesi ve paragraf seviyesi veri elde edilebilir duruma gelir — bölge tanımları gerekmez. Beş seviyeli hiyerarşi (Pages, Paragraphs, Lines, Words, Characters) her biri konum koordinatlarını ve eleman bazlı güven puanlarını sunar. Yapısal çıkarım elde etmek için LEADTOOLS bölge yapılandırmasına ihtiyaç duyan uygulamalar, daha basit bir API'den daha zengin veri elde ederler. OCR sonuçları özellik sayfası, tam çıktı modelini özetler.

Lütfen dikkate alın: Adobe Acrobat, Kofax OmniPage, LEADTOOLS ve Tesseract kendi sahiplerinin tescilli ticari markalarıdır. Bu site, Adobe Inc., Apryse, Google, Kofax veya LEAD Technologies tarafından bağlı, onaylanmış veya desteklenmemektedir. Tüm ürün adları, logolar ve markalar kendi sahiplerine aittir. Karşılaştırmalar, yalnızca bilgilendirme amaçlıdır ve yazı sırasında halka açık bilgilerle alakalı olarak yansıtılmaktadır.
Curtis Chau
Teknik Yazar

Curtis Chau, Bilgisayar Bilimleri alanında Lisans Derecesine (Carleton Üniversitesi) sahip ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirmeyle ilgileniyor. Sezgisel ve estetik açıdan hoş kullanıcı arayüzleri oluşturma tutkunu, Curtis modern çerçevelerle çalışmayı ve iyi yapılandırılmış, görsel olarak çekici kılavuzlar oluşturmayı seviyor.

...
Daha Fazla Oku

İlgili Makaleler

Key in blue circle

Ücretsiz 30 günlük Deneme Anahtarınızı anında edinin.

Your trial license will be sent to your email address

Herhangi bir sınırlama yoktur. %100 erişim. Kredi kartı gerekmez.

bullet_checkedKredi kartı veya hesap oluşturma gerektirmezHerhangi bir sınırlama yoktur. %100 erişim. Kredi kartı gerekmez.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Bağımsız Danışmanlık Alın
Aşağıdaki formu doldurun veya sales@ironsoftware.com adresine e-posta gönderin
Bilgileriniz daima gizli kalacaktır.
Dünya Çapında Milyonlarca Mühendisin Güvendiği
Iron Software müşteri logoları
Ücretsiz 30 Günlük Deneme Anahtarınızı anında alın.
Kredi kartı veya hesap oluşturma gerektirmez