NET Maui'de OCR Nasıl Yapılır?
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
// IronOCR: One namespace, one package, one line
using IronOcr;
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var text = new IronTesseract().Read("document.jpg").Text;
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.
| Özellik | LEADTOOLS OCR | IronOCR |
|---|---|---|
| Gerekli NuGet paketleri | Minimum 4 (daha fazlası PDF için) | 1 (IronOcr) |
| Lisans mekanizması | .LIC + .LIC.KEY dosya çifti | Dize anahtarı |
| Lisans dağıtımı | Her üretim makinesinde dosyalar | Ortam 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 gereklidir | Gerekli değil |
| PDF girişi | Sayfa bazında rasterleştirme döngüsü | Yerel LoadPdf() |
| Şifre korumalı PDF | Ayrı Leadtools.Pdf modülü gerektirir | Yerleşik Password parametresi |
| Aranabilir PDF çıktısı | DocumentWriter + PdfDocumentOptions + document.Save() | result.SaveAsSearchablePdf() |
| Ön işlem | Ayrı komut sınıfları (DeskewCommand, DespeckleCommand, vb.) | OcrInput üzerinde yerleşik filtre yöntemleri |
| Çok sayfalı TIFF | CodecsLoadByteOrder ile manuel çerçeve yinelemesi | input.LoadImageFrames() |
| Yapısal çıktı | Sayfa ve bölge seviyesi | Koordinatlı sayfa, paragraf, satır, kelime, karakter |
| Güvenlik puanlaması | OcrPageRecognizeStatus enum | Yüzde olarak result.Confidence |
| Barkod okuma | Ayrıca LEADTOOLS Barkod modülü | Yerleşik (ReadBarCodes = true) |
| Thread güvenliği | Dikkatli yönetim gerektirir | Tam (her iş parçacığına bir IronTesseract) |
| Desteklenen diller | 60–120 (motor bağımlı) | 125'ten fazla NuGet dil paketleri üzerinden |
| Dil dağıtımı | tessdata files or engine-bundled files | Her dil için NuGet paketi |
| Çapraz platform | Her platform için çalışma zamanı yapılandırması ile desteklenir | Windows, Linux, macOS, Docker, Azure, AWS |
| Docker dağıtımı | .KEY dosyaları monte edilmeli veya gömülmelidir | Standart dotnet publish |
| Ticari destek | Evet | Evet |
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
NuGet kullanarak IronOCR'u yükleyin:
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;
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");
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();
}
}
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
}
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;
}
}
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);
}
}
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);
}
}
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();
}
}
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; }
}
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);
}
}
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; }
}
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}");
}
}
}
}
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 OCR | IronOCR |
|---|---|
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.IsStarted | Gerekli 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).TotalPages | Gerekli 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.RecognizeStatus | result.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.Bounds | result.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 = password | input.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");
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);
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
}
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);
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.
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);
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" .
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
- Tüm LEADTOOLS NuGet paketlerini kaldırın:
Leadtools,Leadtools.Ocr,Leadtools.Codecs,Leadtools.Forms.DocumentWriters,Leadtools.Pdf IronOcrNuGet paketini yükleyin- Tüm LEADTOOLS
usingdirektifleriniusing IronOcr;ile değiştirin .LICve.LIC.KEYdosyalarını projeden ve dağıtım ürünlerinden kaldırın- Uygulama başlatıldığında
RasterSupport.SetLicense(licPath, keyContent)'üIronOcr.License.LicenseKey = "key"ile değiştirin - Sadece
IOcrEngineveRasterCodecsyaşam döngüsünü yönetmek için var olan tümIDisposableservis sınıflarını silin OcrEngineManager.CreateEngine()+engine.Startup()yerinenew IronTesseract()kullanın_codecs.Load(imagePath)'ı, birusing var input = new OcrInput()bloğu içindeinput.LoadImage(imagePath)ile değiştirin- Çok çerçeveli TIFF sayfa döngülerini
input.LoadImageFrames(tiffPath)ile değiştirin - PDF sayfa döngüsü yinelemesini
input.LoadPdf(pdfPath)ile değiştirin document.Pages.AddPage()+page.Recognize(null)+page.GetText(-1)yerineocr.Read(input).TextkullanınOcrZone+page.Zones.Add()kalıplarınıinput.LoadImage(path, new CropRectangle(x, y, w, h))ile değiştirinPdfDocumentOptions+DocumentWriterInstance.SetOptions()+document.Save()yerineresult.SaveAsSearchablePdf(path)kullanın- Ön işlem komut sınıflarını (
DeskewCommand,DespeckleCommand,AutoBinarizeCommand)input.Deskew(),input.DeNoise(),input.Binarize()ileOcrInputörneğinde değiştirin - 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.Confidencekullanarak 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.Pdfmodü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.ForEachile 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.

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.