Altbilgi içeriğine atla
VIDEOLAR

ABBYY FineReader'dan IronOCR'a Geçiş

Bu kılavuz .NET geliştiricileriniABBYY FineReader EngineSDK'yı IronOCR ile değiştirmek üzere adım adım yönlendirir. COM bağımlılıklarını ve SDK yükleyici kalıntılarını kaldırma mekanik adımlarını kapsar, ABBYY'nin API'sini IronOCR eşdeğerleriyle eşleştirir ve üretim ABBYY entegrasyonlarında en sık rastlanılan desenler için öncesi/sonrası kod örnekleri sağlar. Geçiş, projeleri için ABBYY'nin kurumsal maliyet ve dağıtım karmaşıklığının artık uygun olmadığını belirleyen ekipleri hedefler.

Neden ABBYY FineReader'dan Geçiş Yapılmalı

ABBYY FineReader Engine, yetenekli bir OCR platformu, ancak mimarisi, özel altyapı ekiplerine sahip kurumsal Windows mağazaları için tasarlanmıştı. Bir .NET ekibinin gerçek iş yükü fatura işleme, sözleşme dijitalleştirme veya taranmış form çıkarımı olduğunda, bu mimari bir varlık değil, bir yük haline gelir.

COM Interop Borcu Zamanla Artar. .NET'teki her ABBYY entegrasyonu, bir COM birlikte çalışabilirlik katmanı üzerinden çalışır. COM nesneleri açık bir yaşam döngüsü yönetimi gerektirir: oluşturma, başlatma, işleme, ardından bir finally bloğunda kapama veya süreç hafıza kaçağı yapar. ABBYY'ye dokunan her kod yolu bu deseni taşır. İki veya üç yıldır özellik eklemeleri ile, yaşam döngüsü ritüeli hizmet sınıflarına, arka plan çalışanlarına ve istek işleyicilere yayılır. Sonuç, her OCR ile ilgili sınıfta %30-50 oranında standard kod öbeği olacaktır ki IronTesseract'e geçtiğinizde tamamen ortadan kalkar.

SDK Yükleyicisi Modern Dağıtım Desenlerini Engeller. ABBYY, ikili dosyalarını, dil verilerini, çalışma zamanı dosyalarını ve lisans dosyalarını kodlanmış yollara yerleştiren bir Windows SDK yükleyicisi aracılığıyla dağıtılır. ABBYY kullanan bir hizmeti kapsülleştirmek ya o kurulum çıktısından 300+ MB özel bir temel imaj oluşturmayı ya da başlatma sırasında lisans dosyalarıyla hacimleri bağlamayı gerektirir. Hiçbiri standart bir Kubernetes veya bulut-yerel hattına uymaz.IronOCR bir NuGet paketidir: diğer tüm bağımlılıkları çeken aynı dotnet restore, OCR motorunun tamamını da çeker.

Sayfa Başı Lisanslama, Hacmi Bir Maliyet Merkezi Haline Getirir. ABBYY'nin hacme dayalı lisanslama modelleri, belirli eşikleri aşan işleme başına sayfa başına ücret alır. Başlangıçta ayda 50.000 belge işleyen ve iki yıl sonra 500.000'e ulaşan bir uygulama, başarısına doğrudan orantılı olarak artan OCR maliyetlerine sahiptir. IronOCR, lisans için sabit bir ücret alır — ayda iki milyon sayfa işleyen bir ekip, iki bin sayfa işleyen bir ekiple aynı lisans maliyetini öder.

Dil Verileri Manuel Dağıtım Koordinasyonu Gerektirir. ABBYY dil paketleri, SDK çalışma zamanı dizininde dosyalar olarak bulunur. Bir dil eklemek, doğru veri dosyalarını belirlemeyi, bunları her dağıtım hedefinde doğru yola kopyalamayı ve CI/CD komut dosyalarını onları içermesi için güncellemeyi gerektirir. IronOCR'de Fransızca eklemek dotnet add package IronOcr.Languages.French gibidir — paket yöneticisi geri kalanını halleder.

Lisans Dosyası Hataları Uyarısız Üretime Vurur. ABBYY lisansları .lic ve .key dosyaları olarak belirli disk yollarında bulunmalı ve loader.GetEngineObject() çalıştığında mevcut olmalıdır. Bu dosyalar, yeni bir üretim sunucusunda eksikse — yanlış dağıtım komut dosyası, başarısız dosya kopyası, izin sorunu — çağrı başlangıçta atılır. Süresi dolmuş bir lisans da aynı şekilde başarısız olur. IronOCR'nin lisanslaması, başlatıcı kodda atanan, herhangi bir gizli yöneticiye kaydedilebilen bir string anahtardır, uygulama trafik kabul etmeden önce IronOcr.License.IsValidLicense tarafından doğrulama kontrolü yapılır.

Thread Güvenliği, Tek Bir Paylaşılmış Motor Örneği Gerektirir. ABBYY'nin motoru birden fazla thread'den eşzamanlı CreateFRDocument çağrıları için kolayca thread güvenli değildir. Üretim uygulamaları, kilit stratejileri veya işlemci havuzları kullanır. IronOCR'nin IronTesseract durumsuzdur: her thread başına bir örnek açın, kilitleme olmadan eşzamanlı olarak tanıma işlemi gerçekleştirin ve tamamlandığında kapatın.

Temel Sorun

// ABBYY: COM loader + license path validation + profile load — before a single pixel of OCR runs
var loader = new EngineLoader();
var engine = loader.GetEngineObject(
    @"C:\Program Files\ABBYY SDK\FineReader Engine\Bin",  // Breaks on every new machine
    @"C:\Program Files\ABBYY SDK\License"                 // Fails if .lic file is missing
);
engine.LoadPredefinedProfile("DocumentConversion_Accuracy");
var langParams = engine.CreateLanguageParams();
langParams.Languages.Add("English");
// ABBYY: COM loader + license path validation + profile load — before a single pixel of OCR runs
var loader = new EngineLoader();
var engine = loader.GetEngineObject(
    @"C:\Program Files\ABBYY SDK\FineReader Engine\Bin",  // Breaks on every new machine
    @"C:\Program Files\ABBYY SDK\License"                 // Fails if .lic file is missing
);
engine.LoadPredefinedProfile("DocumentConversion_Accuracy");
var langParams = engine.CreateLanguageParams();
langParams.Languages.Add("English");
' ABBYY: COM loader + license path validation + profile load — before a single pixel of OCR runs
Dim loader As New EngineLoader()
Dim engine = loader.GetEngineObject(
    "C:\Program Files\ABBYY SDK\FineReader Engine\Bin",  ' Breaks on every new machine
    "C:\Program Files\ABBYY SDK\License"                 ' Fails if .lic file is missing
)
engine.LoadPredefinedProfile("DocumentConversion_Accuracy")
Dim langParams = engine.CreateLanguageParams()
langParams.Languages.Add("English")
$vbLabelText   $csharpLabel
// IronOCR: the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
// IronOCR: the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
Imports IronOcr

' IronOCR: the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim ocr As New IronTesseract()
$vbLabelText   $csharpLabel

IronOCR ve ABBYY FineReader: Özellik Karşılaştırması

Aşağıdaki tablo, bu geçişi değerlendiren ekipler için ilgili yetenekleri kapsar.

Özellik ABBYY FineReader Engine IronOCR
Kurulum SDK yükleyicisi (Windows) dotnet add package IronOcr
Edinim Satış ile iletişim (4-12 hafta) Kendi kendine hizmet NuGet
Lisanslama Modeli Enterprise, sunucu başına veya sayfa başına Sürekli, $999-$2,999 tek seferlik
Lisans Yönetimi .lic + .key diskteki dosyalar Kodu veya ortam değişkenindeki dize anahtarı
.NET Entegrasyonu COM interop Yerel .NET
COM Bağımlılığı Evet Hayır
İş Parçacığı Güvenliği Kilitleme stratejisi gerektirir Tam (thread başına bir IronTesseract)
Desteklenen Diller 190+ 125+
Dil Kurulumu Çalışma zamanı veri dosyaları SDK yolunda NuGet dil paketleri
PDF Girişi Evet (CreatePDFFile aracılığıyla) Evet (yerel, input.LoadPdf())
Aranabilir PDF Çıktısı Evet (ihracat hattı) Evet (result.SaveAsSearchablePdf() ile)
Otomatik Ön İşleme Profil tabanlı Dahili (Deskew, DeNoise, Contrast, Binarize, Sharpen)
Bölge Tabanlı OCR Bölge nesneleri (CreateZone, SetBounds) CropRectangle parametresi
Barkod Okuma Evet Evet (ocr.Configuration.ReadBarCodes = true ile)
Çapraz Platform Windows, Linux, macOS Windows, Linux, macOS, Docker, Azure, AWS
Docker Dağıtımı Özel temel resim gereklidir Standart .NET temel imajı + libgdiplus
Güven Skoru Evet Evet (result.Confidence ile)
İlk OCR Sonuç Süresi 4-12 hafta (tedarik) Aynı gün

Hızlı Başlangıç: ABBYY FineReader'dan IronOCR'a Geçiş

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

ABBYY FineReader Engine, herhangi bir NuGet paketine sahip değil. SDK'yı kaldırarak ve proje dosyanızdan manuel montaj referansını kaldırarak bunu kaldırın:


<Reference Include="FREngine">
  <HintPath>C:\Program Files\ABBYY SDK\FineReader Engine\Bin\FREngine.dll</HintPath>
</Reference>

<Reference Include="FREngine">
  <HintPath>C:\Program Files\ABBYY SDK\FineReader Engine\Bin\FREngine.dll</HintPath>
</Reference>
XML

Ardından Visual Studio'nun Referanslar düğümünden FREngine.dll COM birlikte çalışma referansını kaldırın veya proje dosyanızdaki karşılık gelen girdiyi doğrudan silin. NuGet kullanarak IronOCR'u yükleyin:

dotnet add package IronOcr

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

// Before (ABBYY)
using FREngine;
using ABBYY.FineReader;

// After (IronOCR)
using IronOcr;
// Before (ABBYY)
using FREngine;
using ABBYY.FineReader;

// After (IronOCR)
using IronOcr;
Imports IronOcr
$vbLabelText   $csharpLabel

Adım 3: Lisansa İzin Verin

OCR çağrılarından önce, uygulama başlangıcında bunu bir kez ekleyin:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Anahtarı, üretim dağıtımları için bir ortam değişkeninde veya gizli yöneticide saklayın:

IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY");
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY");
Imports System

IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
$vbLabelText   $csharpLabel

Kod Göç Örnekleri

Bir Windows Hizmetindeki Motor Ömrü vs Stateless IronTesseract

ABBYY'nin motor başlatma töreni, EngineLoader ve IEngine nesneleri oluşturulması maliyetli olduğundan bir hizmet sargısında yer almalıdır. Çoğu üretim entegrasyonu, motoru tek bir hizmette belirgin başlangıç ve yıkım metotları ile sarar.

ABBYY FineReader Yaklaşımı:

using FREngine;

public class DocumentOcrService : IHostedService, IDisposable
{
    private IEngine _engine;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        // Step 1: Create loader — requiresCOM interopregistration
        var loader = new EngineLoader();

        // Step 2: Load engine from SDK path — throws if license files are missing
        _engine = loader.GetEngineObject(
            @"C:\Program Files\ABBYY SDK\FineReader Engine\Bin",
            @"C:\Program Files\ABBYY SDK\License"
        );

        // Step 3: Load profile before any recognition work
        _engine.LoadPredefinedProfile("DocumentConversion_Accuracy");

        return Task.CompletedTask;
    }

    public string ProcessDocument(string imagePath)
    {
        // Document must be created and destroyed per call
        var document = _engine.CreateFRDocument();
        try
        {
            document.AddImageFile(imagePath, null, null);
            document.Process(null);
            return document.PlainText.Text;
        }
        finally
        {
            document.Close(); // Memory leaks if omitted
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _engine = null; // COM cleanup
        return Task.CompletedTask;
    }

    public void Dispose() => _engine = null;
}
using FREngine;

public class DocumentOcrService : IHostedService, IDisposable
{
    private IEngine _engine;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        // Step 1: Create loader — requiresCOM interopregistration
        var loader = new EngineLoader();

        // Step 2: Load engine from SDK path — throws if license files are missing
        _engine = loader.GetEngineObject(
            @"C:\Program Files\ABBYY SDK\FineReader Engine\Bin",
            @"C:\Program Files\ABBYY SDK\License"
        );

        // Step 3: Load profile before any recognition work
        _engine.LoadPredefinedProfile("DocumentConversion_Accuracy");

        return Task.CompletedTask;
    }

    public string ProcessDocument(string imagePath)
    {
        // Document must be created and destroyed per call
        var document = _engine.CreateFRDocument();
        try
        {
            document.AddImageFile(imagePath, null, null);
            document.Process(null);
            return document.PlainText.Text;
        }
        finally
        {
            document.Close(); // Memory leaks if omitted
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _engine = null; // COM cleanup
        return Task.CompletedTask;
    }

    public void Dispose() => _engine = null;
}
Imports FREngine
Imports System.Threading
Imports System.Threading.Tasks

Public Class DocumentOcrService
    Implements IHostedService, IDisposable

    Private _engine As IEngine

    Public Function StartAsync(cancellationToken As CancellationToken) As Task Implements IHostedService.StartAsync
        ' Step 1: Create loader — requires COM interop registration
        Dim loader As New EngineLoader()

        ' Step 2: Load engine from SDK path — throws if license files are missing
        _engine = loader.GetEngineObject(
            "C:\Program Files\ABBYY SDK\FineReader Engine\Bin",
            "C:\Program Files\ABBYY SDK\License"
        )

        ' Step 3: Load profile before any recognition work
        _engine.LoadPredefinedProfile("DocumentConversion_Accuracy")

        Return Task.CompletedTask
    End Function

    Public Function ProcessDocument(imagePath As String) As String
        ' Document must be created and destroyed per call
        Dim document = _engine.CreateFRDocument()
        Try
            document.AddImageFile(imagePath, Nothing, Nothing)
            document.Process(Nothing)
            Return document.PlainText.Text
        Finally
            document.Close() ' Memory leaks if omitted
        End Try
    End Function

    Public Function StopAsync(cancellationToken As CancellationToken) As Task Implements IHostedService.StopAsync
        _engine = Nothing ' COM cleanup
        Return Task.CompletedTask
    End Function

    Public Sub Dispose() Implements IDisposable.Dispose
        _engine = Nothing
    End Sub
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;

public class DocumentOcrService
{
    //Hayırstartup, no shutdown, no COM lifecycle
    // IronTesseract is stateless — create per call or reuse per thread

    public string ProcessDocument(string imagePath)
    {
        return new IronTesseract().Read(imagePath).Text;
    }
}
using IronOcr;

public class DocumentOcrService
{
    //Hayırstartup, no shutdown, no COM lifecycle
    // IronTesseract is stateless — create per call or reuse per thread

    public string ProcessDocument(string imagePath)
    {
        return new IronTesseract().Read(imagePath).Text;
    }
}
Imports IronOcr

Public Class DocumentOcrService
    'Hayırstartup, no shutdown, no COM lifecycle
    ' IronTesseract is stateless — create per call or reuse per thread

    Public Function ProcessDocument(imagePath As String) As String
        Return New IronTesseract().Read(imagePath).Text
    End Function
End Class
$vbLabelText   $csharpLabel

IronTesseract bir motor yaşam döngüsüne sahip değildir. İlk kullanımda dahili olarak başlatılır ve açık bir kapatma gerektirmez. Barındırılan hizmet sargısı, IEngine alanı ve tüm StopAsync yöntemleri ortadan kalkıyor. Uygulama belgeleri eşzamanlı olarak işliyorsa, her thread kendi IronTesseract örneğini oluşturur — kilitleme gerekmez. IronTesseract kurulum kılavuzu, TesseractVersion ve Configuration özellikleri dahil olmak üzere yapılandırma seçeneklerini kapsar.

Tanıma Dili Kurulumu

ABBYY dil yapılandırması bir LanguageParams nesnesi oluşturmayı, yüklü veri dosyalarıyla eşleşmesi gereken dil adı dizgileri eklemeyi ve bu parametreleri herhangi bir belge işlenmeden önce motora bağlamayı içerir. Her ek dil, çalışma zamanı yolunda konuşlandırılmış karşılık gelen veri dosyalarını gerektirir.

ABBYY FineReader Yaklaşımı:

using FREngine;

// Engine must already be initialized with sdkPath and licensePath
private void ConfigureLanguages(IEngine engine, string[] languageCodes)
{
    // Create language parameters object
    var langParams = engine.CreateLanguageParams();

    // Add each language — string names must match installed data file names
    // Missing data file causes runtime failure
    foreach (var lang in languageCodes)
    {
        langParams.Languages.Add(lang);  // e.g., "English", "French", "German"
    }

    // Language params are associated at the profile level, not per-document
    // Changing languages requires reloading profile or reinitializing engine
    engine.LoadPredefinedProfile("DocumentConversion_Accuracy");
}

public string RecognizeFrenchDocument(IEngine engine, string imagePath)
{
    var langParams = engine.CreateLanguageParams();
    langParams.Languages.Add("French");  // Requires FrenchLanguage data files at runtime path

    var document = engine.CreateFRDocument();
    try
    {
        document.AddImageFile(imagePath, null, null);
        document.Process(null);
        return document.PlainText.Text;
    }
    finally
    {
        document.Close();
    }
}
using FREngine;

// Engine must already be initialized with sdkPath and licensePath
private void ConfigureLanguages(IEngine engine, string[] languageCodes)
{
    // Create language parameters object
    var langParams = engine.CreateLanguageParams();

    // Add each language — string names must match installed data file names
    // Missing data file causes runtime failure
    foreach (var lang in languageCodes)
    {
        langParams.Languages.Add(lang);  // e.g., "English", "French", "German"
    }

    // Language params are associated at the profile level, not per-document
    // Changing languages requires reloading profile or reinitializing engine
    engine.LoadPredefinedProfile("DocumentConversion_Accuracy");
}

public string RecognizeFrenchDocument(IEngine engine, string imagePath)
{
    var langParams = engine.CreateLanguageParams();
    langParams.Languages.Add("French");  // Requires FrenchLanguage data files at runtime path

    var document = engine.CreateFRDocument();
    try
    {
        document.AddImageFile(imagePath, null, null);
        document.Process(null);
        return document.PlainText.Text;
    }
    finally
    {
        document.Close();
    }
}
Imports FREngine

' Engine must already be initialized with sdkPath and licensePath
Private Sub ConfigureLanguages(engine As IEngine, languageCodes As String())
    ' Create language parameters object
    Dim langParams = engine.CreateLanguageParams()

    ' Add each language — string names must match installed data file names
    ' Missing data file causes runtime failure
    For Each lang In languageCodes
        langParams.Languages.Add(lang)  ' e.g., "English", "French", "German"
    Next

    ' Language params are associated at the profile level, not per-document
    ' Changing languages requires reloading profile or reinitializing engine
    engine.LoadPredefinedProfile("DocumentConversion_Accuracy")
End Sub

Public Function RecognizeFrenchDocument(engine As IEngine, imagePath As String) As String
    Dim langParams = engine.CreateLanguageParams()
    langParams.Languages.Add("French")  ' Requires FrenchLanguage data files at runtime path

    Dim document = engine.CreateFRDocument()
    Try
        document.AddImageFile(imagePath, Nothing, Nothing)
        document.Process(Nothing)
        Return document.PlainText.Text
    Finally
        document.Close()
    End Try
End Function
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;

// Single language — install IronOcr.Languages.French via NuGet first
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.French;
var result = ocr.Read("french-document.jpg");
Console.WriteLine(result.Text);

// Multiple simultaneous languages — operator overload, no data file management
var multiOcr = new IronTesseract();
multiOcr.Language = OcrLanguage.French + OcrLanguage.German + OcrLanguage.English;
var multiResult = multiOcr.Read("multilingual-contract.jpg");
Console.WriteLine(multiResult.Text);
using IronOcr;

// Single language — install IronOcr.Languages.French via NuGet first
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.French;
var result = ocr.Read("french-document.jpg");
Console.WriteLine(result.Text);

// Multiple simultaneous languages — operator overload, no data file management
var multiOcr = new IronTesseract();
multiOcr.Language = OcrLanguage.French + OcrLanguage.German + OcrLanguage.English;
var multiResult = multiOcr.Read("multilingual-contract.jpg");
Console.WriteLine(multiResult.Text);
Imports IronOcr

' Single language — install IronOcr.Languages.French via NuGet first
Dim ocr As New IronTesseract()
ocr.Language = OcrLanguage.French
Dim result = ocr.Read("french-document.jpg")
Console.WriteLine(result.Text)

' Multiple simultaneous languages — operator overload, no data file management
Dim multiOcr As New IronTesseract()
multiOcr.Language = OcrLanguage.French + OcrLanguage.German + OcrLanguage.English
Dim multiResult = multiOcr.Read("multilingual-contract.jpg")
Console.WriteLine(multiResult.Text)
$vbLabelText   $csharpLabel

Dil paketleri, standart NuGet paketleri olarak yüklenir (dotnet add package IronOcr.Languages.French). Manuel olarak konuşlandırılacak veri dosyaları yok, yol yapılandırması yok, diller değiştirildiğinde motor yeniden başlatılması yok. çoklu diller kılavuzu, dilleri birleştirmeyi kapsar ve diller indeksi 125+'ten fazla mevcut paketleri listeler.

Çoklu Çerçeve TIFF İşleme

ABBYY, çok sayfalı TIFF dosyalarını çerçeveleri yineleyerek ve her çerçeveyi ayrı bir belge sayfası olarak ekleyerek işler. Çerçeve sayısı, TIFF nesnesinden alınmalı, ardından her çerçeve belge konteynerine ayrı olarak eklenmelidir.

ABBYY FineReader Yaklaşımı:

using FREngine;

public string ProcessMultiFrameTiff(IEngine engine, string tiffPath)
{
    var document = engine.CreateFRDocument();

    try
    {
        // Must add each frame individually — no automatic multi-frame handling
        // Page count requires reading the TIFF metadata before processing
        var imageInfo = engine.CreateImageInfo();
        imageInfo.LoadImageFile(tiffPath);
        int frameCount = imageInfo.FrameCount;

        for (int i = 0; i < frameCount; i++)
        {
            // Each frame added with its frame index via image processing params
            var imgParams = engine.CreateImageProcessingParams();
            imgParams.FrameIndex = i;
            document.AddImageFile(tiffPath, imgParams, null);
        }

        document.Process(null);
        return document.PlainText.Text;
    }
    finally
    {
        document.Close();
    }
}
using FREngine;

public string ProcessMultiFrameTiff(IEngine engine, string tiffPath)
{
    var document = engine.CreateFRDocument();

    try
    {
        // Must add each frame individually — no automatic multi-frame handling
        // Page count requires reading the TIFF metadata before processing
        var imageInfo = engine.CreateImageInfo();
        imageInfo.LoadImageFile(tiffPath);
        int frameCount = imageInfo.FrameCount;

        for (int i = 0; i < frameCount; i++)
        {
            // Each frame added with its frame index via image processing params
            var imgParams = engine.CreateImageProcessingParams();
            imgParams.FrameIndex = i;
            document.AddImageFile(tiffPath, imgParams, null);
        }

        document.Process(null);
        return document.PlainText.Text;
    }
    finally
    {
        document.Close();
    }
}
Imports FREngine

Public Function ProcessMultiFrameTiff(engine As IEngine, tiffPath As String) As String
    Dim document = engine.CreateFRDocument()

    Try
        ' Must add each frame individually — no automatic multi-frame handling
        ' Page count requires reading the TIFF metadata before processing
        Dim imageInfo = engine.CreateImageInfo()
        imageInfo.LoadImageFile(tiffPath)
        Dim frameCount As Integer = imageInfo.FrameCount

        For i As Integer = 0 To frameCount - 1
            ' Each frame added with its frame index via image processing params
            Dim imgParams = engine.CreateImageProcessingParams()
            imgParams.FrameIndex = i
            document.AddImageFile(tiffPath, imgParams, Nothing)
        Next

        document.Process(Nothing)
        Return document.PlainText.Text
    Finally
        document.Close()
    End Try
End Function
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;

// LoadImageFrames handles multi-frame TIFF automatically
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");

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

// Per-page results accessible directly
foreach (var page in result.Pages)
{
    Console.WriteLine($"Frame {page.PageNumber}: {page.Text.Length} characters");
    Console.WriteLine(page.Text);
}
using IronOcr;

// LoadImageFrames handles multi-frame TIFF automatically
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");

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

// Per-page results accessible directly
foreach (var page in result.Pages)
{
    Console.WriteLine($"Frame {page.PageNumber}: {page.Text.Length} characters");
    Console.WriteLine(page.Text);
}
Imports IronOcr

' LoadImageFrames handles multi-frame TIFF automatically
Using input As New OcrInput()
    input.LoadImageFrames("scanned-batch.tiff")

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

    ' Per-page results accessible directly
    For Each page In result.Pages
        Console.WriteLine($"Frame {page.PageNumber}: {page.Text.Length} characters")
        Console.WriteLine(page.Text)
    Next
End Using
$vbLabelText   $csharpLabel

OcrInput.LoadImageFrames, manuel yineleme olmadan çok sayfalı bir TIFF'teki her kareyi okur. Sonuç, her kare için metin, koordinat verileri ve güvenilirlik dahil result.Pages aracılığıyla sayfa başına erişim sağlar. TIFF giriş kılavuzu, hem çoklu çerçeve TIFF hem de animasyonlu GIF işleme konularını kapsar.

Paralel Toplu İşleme

ABBYY'nin COM tabanlı motoru, bir eşzamanlama stratejisi olmadan birkaç thread'den eşzamanlı CreateFRDocument çağrısı yapmak için güvenli değildir. Üretim toplu işlemcileri genellikle motor örneklerinin bir havuzunu tutar veya kilitleme yoluyla erişimi seri hale getirir. Her iki yaklaşım da IronOCR'nin ortadan kaldırdığı altyapı ekler.

ABBYY FineReader Yaklaşımı:

using FREngine;
using System.Collections.Concurrent;
using System.Threading;

public class AbbyyBatchProcessor
{
    // Pool required because engine is not safely concurrent
    private readonly SemaphoreSlim _engineLock = new SemaphoreSlim(1, 1);
    private IEngine _engine;

    public async Task<Dictionary<string, string>> ProcessBatchAsync(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // Must serialize — one document at a time through single engine
        foreach (var imagePath in imagePaths)
        {
            await _engineLock.WaitAsync();
            try
            {
                var document = _engine.CreateFRDocument();
                try
                {
                    document.AddImageFile(imagePath, null, null);
                    document.Process(null);
                    results[imagePath] = document.PlainText.Text;
                }
                finally
                {
                    document.Close();
                }
            }
            finally
            {
                _engineLock.Release();
            }
        }

        return new Dictionary<string, string>(results);
    }
}
using FREngine;
using System.Collections.Concurrent;
using System.Threading;

public class AbbyyBatchProcessor
{
    // Pool required because engine is not safely concurrent
    private readonly SemaphoreSlim _engineLock = new SemaphoreSlim(1, 1);
    private IEngine _engine;

    public async Task<Dictionary<string, string>> ProcessBatchAsync(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // Must serialize — one document at a time through single engine
        foreach (var imagePath in imagePaths)
        {
            await _engineLock.WaitAsync();
            try
            {
                var document = _engine.CreateFRDocument();
                try
                {
                    document.AddImageFile(imagePath, null, null);
                    document.Process(null);
                    results[imagePath] = document.PlainText.Text;
                }
                finally
                {
                    document.Close();
                }
            }
            finally
            {
                _engineLock.Release();
            }
        }

        return new Dictionary<string, string>(results);
    }
}
Imports FREngine
Imports System.Collections.Concurrent
Imports System.Threading

Public Class AbbyyBatchProcessor
    ' Pool required because engine is not safely concurrent
    Private ReadOnly _engineLock As New SemaphoreSlim(1, 1)
    Private _engine As IEngine

    Public Async Function ProcessBatchAsync(imagePaths As String()) As Task(Of Dictionary(Of String, String))
        Dim results As New ConcurrentDictionary(Of String, String)()

        ' Must serialize — one document at a time through single engine
        For Each imagePath In imagePaths
            Await _engineLock.WaitAsync()
            Try
                Dim document = _engine.CreateFRDocument()
                Try
                    document.AddImageFile(imagePath, Nothing, Nothing)
                    document.Process(Nothing)
                    results(imagePath) = document.PlainText.Text
                Finally
                    document.Close()
                End Try
            Finally
                _engineLock.Release()
            End Try
        Next

        Return New Dictionary(Of String, String)(results)
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public class OcrBatchProcessor
{
    public Dictionary<string, string> ProcessBatch(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // IronTesseract is thread-safe — one instance per thread, fully parallel
        Parallel.ForEach(imagePaths, imagePath =>
        {
            var ocr = new IronTesseract();  // Each thread owns its instance
            var result = ocr.Read(imagePath);
            results[imagePath] = result.Text;
        });

        return new Dictionary<string, string>(results);
    }
}
using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public class OcrBatchProcessor
{
    public Dictionary<string, string> ProcessBatch(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // IronTesseract is thread-safe — one instance per thread, fully parallel
        Parallel.ForEach(imagePaths, imagePath =>
        {
            var ocr = new IronTesseract();  // Each thread owns its instance
            var result = ocr.Read(imagePath);
            results[imagePath] = result.Text;
        });

        return new Dictionary<string, string>(results);
    }
}
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

Public Class OcrBatchProcessor
    Public Function ProcessBatch(imagePaths As String()) As Dictionary(Of String, String)
        Dim results = New ConcurrentDictionary(Of String, String)()

        ' IronTesseract is thread-safe — one instance per thread, fully parallel
        Parallel.ForEach(imagePaths, Sub(imagePath)
                                         Dim ocr = New IronTesseract() ' Each thread owns its instance
                                         Dim result = ocr.Read(imagePath)
                                         results(imagePath) = result.Text
                                     End Sub)

        Return New Dictionary(Of String, String)(results)
    End Function
End Class
$vbLabelText   $csharpLabel

Her IronTesseract örneği bağımsızdır. Parallel.ForEach hiçbir paylaşılan durum, kilit ya da serileştirme olmadan mevcut CPU çekirdeklerini doyurur. ABBYY versiyonu, eşzamanlı sarmalayıcıya rağmen belgeleri sırasıyla işler;IronOCR versiyonu onları gerçekten paralel olarak işler. çok iş parçacığı örneği bu deseni zamanlama karşılaştırmaları ile gösterir. Daha üst düzey throughput kontrolü için hız optimizasyon kılavuzuna bakın.

Belge İhracat Yolu

ABBYY, Export yöntemiyle FileExportFormatEnum değerlerini kullanarak birçok dışa aktarma formatını destekler. DOCX, RTF veya düz metin olarak dışa aktarma, format spesifik dışa aktarma parametre nesneleri oluşturmayı ve ardından uygun enum değeri ve parametre nesnesiyle document.Export çağrısı yapmayı gerektirir.

ABBYY FineReader Yaklaşımı:

using FREngine;

public class AbbyyExporter
{
    private IEngine _engine;

    public void ExportToMultipleFormats(string imagePath, string outputDir)
    {
        var document = _engine.CreateFRDocument();

        try
        {
            document.AddImageFile(imagePath, null, null);
            document.Process(null);

            string baseName = Path.GetFileNameWithoutExtension(imagePath);

            // Export as plain text
            document.Export(
                Path.Combine(outputDir, baseName + ".txt"),
                FileExportFormatEnum.FEF_TextUnicodeDefaults,
                null
            );

            // Export as searchable PDF (requires PDF export params)
            var pdfParams = _engine.CreatePDFExportParams();
            pdfParams.Scenario = PDFExportScenarioEnum.PDES_Balanced;
            pdfParams.UseOriginalPaperSize = true;
            document.Export(
                Path.Combine(outputDir, baseName + ".pdf"),
                FileExportFormatEnum.FEF_PDF,
                pdfParams
            );

            // Export as DOCX
            var docxParams = _engine.CreateDOCXExportParams();
            document.Export(
                Path.Combine(outputDir, baseName + ".docx"),
                FileExportFormatEnum.FEF_DOCX,
                docxParams
            );
        }
        finally
        {
            document.Close();
        }
    }
}
using FREngine;

public class AbbyyExporter
{
    private IEngine _engine;

    public void ExportToMultipleFormats(string imagePath, string outputDir)
    {
        var document = _engine.CreateFRDocument();

        try
        {
            document.AddImageFile(imagePath, null, null);
            document.Process(null);

            string baseName = Path.GetFileNameWithoutExtension(imagePath);

            // Export as plain text
            document.Export(
                Path.Combine(outputDir, baseName + ".txt"),
                FileExportFormatEnum.FEF_TextUnicodeDefaults,
                null
            );

            // Export as searchable PDF (requires PDF export params)
            var pdfParams = _engine.CreatePDFExportParams();
            pdfParams.Scenario = PDFExportScenarioEnum.PDES_Balanced;
            pdfParams.UseOriginalPaperSize = true;
            document.Export(
                Path.Combine(outputDir, baseName + ".pdf"),
                FileExportFormatEnum.FEF_PDF,
                pdfParams
            );

            // Export as DOCX
            var docxParams = _engine.CreateDOCXExportParams();
            document.Export(
                Path.Combine(outputDir, baseName + ".docx"),
                FileExportFormatEnum.FEF_DOCX,
                docxParams
            );
        }
        finally
        {
            document.Close();
        }
    }
}
Imports FREngine

Public Class AbbyyExporter
    Private _engine As IEngine

    Public Sub ExportToMultipleFormats(imagePath As String, outputDir As String)
        Dim document = _engine.CreateFRDocument()

        Try
            document.AddImageFile(imagePath, Nothing, Nothing)
            document.Process(Nothing)

            Dim baseName As String = Path.GetFileNameWithoutExtension(imagePath)

            ' Export as plain text
            document.Export(
                Path.Combine(outputDir, baseName & ".txt"),
                FileExportFormatEnum.FEF_TextUnicodeDefaults,
                Nothing
            )

            ' Export as searchable PDF (requires PDF export params)
            Dim pdfParams = _engine.CreatePDFExportParams()
            pdfParams.Scenario = PDFExportScenarioEnum.PDES_Balanced
            pdfParams.UseOriginalPaperSize = True
            document.Export(
                Path.Combine(outputDir, baseName & ".pdf"),
                FileExportFormatEnum.FEF_PDF,
                pdfParams
            )

            ' Export as DOCX
            Dim docxParams = _engine.CreateDOCXExportParams()
            document.Export(
                Path.Combine(outputDir, baseName & ".docx"),
                FileExportFormatEnum.FEF_DOCX,
                docxParams
            )
        Finally
            document.Close()
        End Try
    End Sub
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;

public class OcrExporter
{
    public void ExportToMultipleFormats(string imagePath, string outputDir)
    {
        var ocr = new IronTesseract();
        var result = ocr.Read(imagePath);
        string baseName = Path.GetFileNameWithoutExtension(imagePath);

        // Plain text — direct property access
        File.WriteAllText(
            Path.Combine(outputDir, baseName + ".txt"),
            result.Text
        );

        // Searchable PDF — one method call, no parameter objects
        result.SaveAsSearchablePdf(
            Path.Combine(outputDir, baseName + ".pdf")
        );

        // hOCR format — for document management systems
        result.SaveAsHocrFile(
            Path.Combine(outputDir, baseName + ".hocr")
        );
    }
}
using IronOcr;

public class OcrExporter
{
    public void ExportToMultipleFormats(string imagePath, string outputDir)
    {
        var ocr = new IronTesseract();
        var result = ocr.Read(imagePath);
        string baseName = Path.GetFileNameWithoutExtension(imagePath);

        // Plain text — direct property access
        File.WriteAllText(
            Path.Combine(outputDir, baseName + ".txt"),
            result.Text
        );

        // Searchable PDF — one method call, no parameter objects
        result.SaveAsSearchablePdf(
            Path.Combine(outputDir, baseName + ".pdf")
        );

        // hOCR format — for document management systems
        result.SaveAsHocrFile(
            Path.Combine(outputDir, baseName + ".hocr")
        );
    }
}
Imports IronOcr
Imports System.IO

Public Class OcrExporter
    Public Sub ExportToMultipleFormats(imagePath As String, outputDir As String)
        Dim ocr As New IronTesseract()
        Dim result = ocr.Read(imagePath)
        Dim baseName As String = Path.GetFileNameWithoutExtension(imagePath)

        ' Plain text — direct property access
        File.WriteAllText(
            Path.Combine(outputDir, baseName & ".txt"),
            result.Text
        )

        ' Searchable PDF — one method call, no parameter objects
        result.SaveAsSearchablePdf(
            Path.Combine(outputDir, baseName & ".pdf")
        )

        ' hOCR format — for document management systems
        result.SaveAsHocrFile(
            Path.Combine(outputDir, baseName & ".hocr")
        )
    End Sub
End Class
$vbLabelText   $csharpLabel

IronOCR'nin OcrResult, .Text öğelerini doğrudan açığa çıkarır ve parametre nesneleri veya format enumları olmadan çıktı yöntemleri sağlar. ABBYY'nin üç adımlı parametre/dışa aktarma dizisine karşılık olarak, PDF dışa aktarmayı tek satırda yönetir SaveAsSearchablePdf. arama yapılabilir PDF kılavuzu, sayfa aralığı seçeneklerini ve sıkıştırma ayarlarını kapsar. hOCR ihracat kılavuzu, konum-bilinçli OCR çıktısını tüketen sistemler için HOCR formatını kapsar.

ABBYY FineReader API,IronOCR Eşlem Referansı

ABBYY FineReader Engine IronOCR Karşılığı
new EngineLoader() Gerekli değil
loader.GetEngineObject(sdkPath, licensePath) new IronTesseract()
engine.LoadPredefinedProfile("...") Gerekli değil (dahili olarak ele alınır)
engine.CreateLanguageParams() Gerekli değil
langParams.Languages.Add("French") ocr.Language = OcrLanguage.French
langParams.Languages.Add("English") + langParams.Languages.Add("German") ocr.Language = OcrLanguage.English + OcrLanguage.German
engine.CreateFRDocument() new OcrInput()
engine.CreateFRDocumentFromImage(path, null) ocr.Read(path)
document.AddImageFile(path, null, null) input.LoadImage(path)
imageInfo.LoadImageFile(tiff) + frameCount döngüsü input.LoadImageFrames(tiff)
engine.CreatePDFFile() sonra pdfFile.Open(path, null, null) input.LoadPdf(path)
document.Process(null) ocr.Read(input)
document.PlainText.Text result.Text
frDocument.Pages[i].PlainText.Text result.Pages[i].Text
page.Layout.Blocks + BlockTypeEnum.BT_Table kontrolü result.Pages + kelime koordinat verileri
block.GetAsTableBlock() result.Pages[i].Lines (koordinatlarla birlikte)
engine.CreatePDFExportParams() Gerekli değil
document.Export(path, FEF_PDF, params) result.SaveAsSearchablePdf(path)
document.Export(path, FEF_TextUnicodeDefaults, null) File.WriteAllText(path, result.Text)
engine.CreateDOCXExportParams() + Dışa Aktarma Doğrudan desteklenmez
document.Close() using tarafından OcrInput üzerinde yönetilir
_engine.GetLicenseInfo().ExpirationDate IronOcr.License.IsValidLicense
Lisans dosyaları (ABBYY.lic, ABBYY.key) IronOcr.License.LicenseKey = "key"
engine.CreateZone() + zone.SetBounds(x, y, w, h) new CropRectangle(x, y, width, height)

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

Sorun 1: SDK'yı Kaldırdıktan Sonra COM Kayıt Hataları

ABBYY: Proje referanslarından FREngine.dll kaldırıldıktan sonra bile, sınıfların eski ad alanını koruduğu için Could not load type 'FREngine.EngineLoader' veya COM birlikte çalışma hatalarıyla yapının başarısız olabileceğini unutmayın.

Çözüm: Referansı kaldırmadan önce tüm FREngine ve ABBYY.FineReader kullanımlarını arayın. Özellikle bir IEngine alanını iptal etmek için uygulanan her sınıfın boşaltma mantığı using bloklarıyla OcrInput üzerine değiştirilmelidir:

// Before: explicit Close in finally
var document = _engine.CreateFRDocument();
try { document.Process(null); }
finally { document.Close(); }

// After: using pattern on OcrInput
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = new IronTesseract().Read(input);
// Before: explicit Close in finally
var document = _engine.CreateFRDocument();
try { document.Process(null); }
finally { document.Close(); }

// After: using pattern on OcrInput
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = new IronTesseract().Read(input);
Option Strict On



' Before: explicit Close in finally
Dim document = _engine.CreateFRDocument()
Try
    document.Process(Nothing)
Finally
    document.Close()
End Try

' After: using pattern on OcrInput
Using input As New OcrInput()
    input.LoadImage(imagePath)
    Dim result = New IronTesseract().Read(input)
End Using
$vbLabelText   $csharpLabel

Sorun 2: Tanıma Profili Karşılığı Yok

ABBYY: engine.LoadPredefinedProfile("DocumentConversion_Speed") veya engine.LoadPredefinedProfile("FieldLevelRecognition") çağrıları yapan kod, doğruluk ve hız arasında denge kurmak için ABBYY'e özgü profiller kullanır. Profile adında bir IronOCR eşdeğer özelliği yoktur.

Çözüm: IronOCR, IronTesseract.Configuration aracılığıyla aynı değiş-tokuşları yapar. Hız optimizasyonu için, ocr.Configuration.TesseractVersion = TesseractVersion.Tesseract5 ayarlayın (varsayılan) ve ön işleme filtrelerini azaltın. Maksimum doğruluk için tam ön işlem hattını ekleyin:

// Speed-optimized
var ocr = new IronTesseract();
//Hayırpreprocessing — fastest path
var result = ocr.Read("clean-document.jpg");

// Accuracy-optimized for difficult inputs
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("degraded-scan.jpg");
input.Deskew();
input.DeNoise();
input.Contrast();
input.Binarize();
var result = ocr.Read(input);
// Speed-optimized
var ocr = new IronTesseract();
//Hayırpreprocessing — fastest path
var result = ocr.Read("clean-document.jpg");

// Accuracy-optimized for difficult inputs
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("degraded-scan.jpg");
input.Deskew();
input.DeNoise();
input.Contrast();
input.Binarize();
var result = ocr.Read(input);
Imports IronTesseract

' Speed-optimized
Dim ocr As New IronTesseract()
' Hayırpreprocessing — fastest path
Dim result = ocr.Read("clean-document.jpg")

' Accuracy-optimized for difficult inputs
Dim ocr As New IronTesseract()
Using input As New OcrInput()
    input.LoadImage("degraded-scan.jpg")
    input.Deskew()
    input.DeNoise()
    input.Contrast()
    input.Binarize()
    Dim result = ocr.Read(input)
End Using
$vbLabelText   $csharpLabel

görüntü kalitesi düzeltme kılavuzu, hangi filtrelerin hangi girdi kalitesi sorunlarını çözdüğünü açıklar. hız optimizasyon kılavuzu, temiz belgelerde işleme süresini azaltan konfigürasyon özelliklerini kapsar.

Sorun 3: Lisans Dosyası Dağıtım Adımı CI/CD'de Kalmaktadır

ABBYY: Yapı hatları genellikle bir ABBYY.lic ve ABBYY.key güvenli bir depodan dağıtım hedefine kopyalayan bir adım içerir. Geçişten sonra, ekipler bazen bu adımı kaldırmayı unutur ve artık mevcut olmayan yolları referans alan ölü dağıtım kodu bırakır.

Çözüm: Lisans dosyası kopyalama adımını tamamen kaldırın. Onun yerine bir ortam değişkeni enjeksiyon adımı ekleyin:

# Remove these CI/CD steps after migration:
# - name: Copy ABBYY license files
#   run: |
#     cp $SECRETS_PATH/ABBYY.lic $DEPLOY_PATH/License/
#     cp $SECRETS_PATH/ABBYY.key $DEPLOY_PATH/License/

# Add this instead (environment variable injection):
# - name: Set IronOCR license
#   env:
#     IRONOCR_LICENSE_KEY: ${{secrets.IRONOCR_LICENSE}}
# Remove these CI/CD steps after migration:
# - name: Copy ABBYY license files
#   run: |
#     cp $SECRETS_PATH/ABBYY.lic $DEPLOY_PATH/License/
#     cp $SECRETS_PATH/ABBYY.key $DEPLOY_PATH/License/

# Add this instead (environment variable injection):
# - name: Set IronOCR license
#   env:
#     IRONOCR_LICENSE_KEY: ${{secrets.IRONOCR_LICENSE}}
YAML

Ve uygulama başlangıcında:

IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
    ?? throw new InvalidOperationException("IRONOCR_LICENSE_KEY not set");
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
    ?? throw new InvalidOperationException("IRONOCR_LICENSE_KEY not set");
Imports System

IronOcr.License.LicenseKey = If(Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY"), Throw New InvalidOperationException("IRONOCR_LICENSE_KEY not set"))
$vbLabelText   $csharpLabel

Sorun 4: Motorun İş Parçacığına Güvenirli Olmaması — Mevcut Kilitleme Kodu

ABBYY: Birden fazla thread'den ABBYY'yi çağıran uygulamalar tipik olarak SemaphoreSlim, lock ifadeleri veya COM birlikte çalışma sorunlarından kaçınmak için thread yerel motor örnekleri içerir. Bu senkronizasyon kodu ABBYY'nin iş parçacığı modeli için uygundur.

Çözüm: ABBYY çağrılarını saran tüm senkronizasyon kodunu silin. IronOCR'nin IronTesseract, thread başına örneklemek için güvenlidir:

// Remove all of this:
// private readonly SemaphoreSlim _engineLock = new SemaphoreSlim(1, 1);
// await _engineLock.WaitAsync();
// try { ... } finally { _engineLock.Release(); }

// Replace with:
Parallel.ForEach(documents, doc =>
{
    var ocr = new IronTesseract(); // One per thread — no lock needed
    results[doc.Id] = ocr.Read(doc.Path).Text;
});
// Remove all of this:
// private readonly SemaphoreSlim _engineLock = new SemaphoreSlim(1, 1);
// await _engineLock.WaitAsync();
// try { ... } finally { _engineLock.Release(); }

// Replace with:
Parallel.ForEach(documents, doc =>
{
    var ocr = new IronTesseract(); // One per thread — no lock needed
    results[doc.Id] = ocr.Read(doc.Path).Text;
});
Imports System.Threading.Tasks

Parallel.ForEach(documents, Sub(doc)
    Dim ocr = New IronTesseract() ' One per thread — no lock needed
    results(doc.Id) = ocr.Read(doc.Path).Text
End Sub)
$vbLabelText   $csharpLabel

Sorun 5: CreateImageInfo / FrameCount TIFF Deseni için

ABBYY: Sustalı bir TIFF dosyasından engine.CreateImageInfo() ve imageInfo.LoadImageFile() kullanarak çerçeve sayısını okuyan ve çerçeveler arasında yineleme yapan kod, IronOCR'de doğrudan bir eşdeğerine sahip değildir çünkü OcrInput.LoadImageFrames çerçeve numaralandırmayı dahili olarak halleder.

Çözüm: Çerçeve sayımı döngüsünü tamamen silin:

// Remove:
// var imageInfo = engine.CreateImageInfo();
// imageInfo.LoadImageFile(tiffPath);
// for (int i = 0; i < imageInfo.FrameCount; i++) { document.AddImageFile(...) }

// Replace with:
using var input = new OcrInput();
input.LoadImageFrames("multi-page-scan.tiff");
var result = new IronTesseract().Read(input);
// result.Pages contains one entry per TIFF frame
// Remove:
// var imageInfo = engine.CreateImageInfo();
// imageInfo.LoadImageFile(tiffPath);
// for (int i = 0; i < imageInfo.FrameCount; i++) { document.AddImageFile(...) }

// Replace with:
using var input = new OcrInput();
input.LoadImageFrames("multi-page-scan.tiff");
var result = new IronTesseract().Read(input);
// result.Pages contains one entry per TIFF frame
Imports IronOcr

' Remove:
' Dim imageInfo = engine.CreateImageInfo()
' imageInfo.LoadImageFile(tiffPath)
' For i As Integer = 0 To imageInfo.FrameCount - 1
'     document.AddImageFile(...)
' Next

' Replace with:
Using input As New OcrInput()
    input.LoadImageFrames("multi-page-scan.tiff")
    Dim result = New IronTesseract().Read(input)
    ' result.Pages contains one entry per TIFF frame
End Using
$vbLabelText   $csharpLabel

Sorun 6: DOCX İhracatı İçin Doğrudan Karşılık Yok

ABBYY: document.Export(path, FileExportFormatEnum.FEF_DOCX, docxParams) bir Word belgesi üretir. IronOCR, DOCX çıktısını doğrudan üretmez.

Çözüm:IronOCR aranabilir PDF'ler ve yapılandırılmış veri üretir. DOCX çıktısı gerektiren iş akışları için pratik geçiş yolu, aranabilir bir PDF üretmek ve sonuç olarak dönüştürmek veya yapılandırılmış metni çıkarıp bir Dokümanı DOCX'e yazmak için Open XML SDK gibi bir kütüphane kullanmaktır:

//IronOCR to searchable PDF (closest equivalent)
var result = new IronTesseract().Read(inputPath);
result.SaveAsSearchablePdf(outputPath.Replace(".docx", ".pdf"));

// Or extract structured text for downstream DOCX generation
foreach (var paragraph in result.Paragraphs)
{
    Console.WriteLine(paragraph.Text);
    // Write to DOCX via Open XML SDK or similar
}
//IronOCR to searchable PDF (closest equivalent)
var result = new IronTesseract().Read(inputPath);
result.SaveAsSearchablePdf(outputPath.Replace(".docx", ".pdf"));

// Or extract structured text for downstream DOCX generation
foreach (var paragraph in result.Paragraphs)
{
    Console.WriteLine(paragraph.Text);
    // Write to DOCX via Open XML SDK or similar
}
Imports IronOcr

' IronOCR to searchable PDF (closest equivalent)
Dim result = New IronTesseract().Read(inputPath)
result.SaveAsSearchablePdf(outputPath.Replace(".docx", ".pdf"))

' Or extract structured text for downstream DOCX generation
For Each paragraph In result.Paragraphs
    Console.WriteLine(paragraph.Text)
    ' Write to DOCX via Open XML SDK or similar
Next
$vbLabelText   $csharpLabel

sonuçları okuma kılavuzu, paragraf, satır, kelime ve karakter seviyesinde koordinat verilerine erişimi kapsar.

ABBYY FineReader Geçiş Kontrol Listesi

Geçiş Öncesi Görevler

Herhangi bir değişiklik yapmadan önce kod tabanını denetleyin:

# Find all files using ABBYY namespaces
grep -r "using FREngine" --include="*.cs" .
grep -r "using ABBYY" --include="*.cs" .

# Find engine lifecycle patterns
grep -r "EngineLoader\|GetEngineObject\|LoadPredefinedProfile" --include="*.cs" .

# Find document lifecycle patterns
grep -r "CreateFRDocument\|document\.Close\|AddImageFile\|document\.Process" --include="*.cs" .

# Find language configuration
grep -r "CreateLanguageParams\|langParams\.Languages" --include="*.cs" .

# Find export calls
grep -r "FileExportFormatEnum\|CreatePDFExportParams\|document\.Export" --include="*.cs" .

# Find license file references in CI/CD and deployment scripts
grep -r "ABBYY\.lic\|ABBYY\.key" .
# Find all files using ABBYY namespaces
grep -r "using FREngine" --include="*.cs" .
grep -r "using ABBYY" --include="*.cs" .

# Find engine lifecycle patterns
grep -r "EngineLoader\|GetEngineObject\|LoadPredefinedProfile" --include="*.cs" .

# Find document lifecycle patterns
grep -r "CreateFRDocument\|document\.Close\|AddImageFile\|document\.Process" --include="*.cs" .

# Find language configuration
grep -r "CreateLanguageParams\|langParams\.Languages" --include="*.cs" .

# Find export calls
grep -r "FileExportFormatEnum\|CreatePDFExportParams\|document\.Export" --include="*.cs" .

# Find license file references in CI/CD and deployment scripts
grep -r "ABBYY\.lic\|ABBYY\.key" .
SHELL

Her IEngine veya IFRDocument alanı tutan sınıfı belgeleyin. Hangi ihracat biçimlerinin kullanıldığına dikkat edin — DOCX çıktısı alternatif bir yaklaşım gerektirir (Yukarıdaki Sorun 6'ya bakın).

Kod Güncelleme Görevleri

  1. Tüm .csproj dosyalarından FREngine.dll referansını kaldırın
  2. ABBYY kullanan her projede dotnet add package IronOcr çalıştırın
  3. Uygulama başlangıcında IronOcr.License.LicenseKey = ... ekleyin (Program.cs veya başlatıcı sınıf)
  4. İngilizce olmayan her dil için dil NuGet paketlerini yükleyin (dotnet add package IronOcr.Languages.French vs.)
  5. Tüm EngineLoader, GetEngineObject ve LoadPredefinedProfile çağrılarını silin
  6. Tüm CreateLanguageParams ve langParams.Languages.Add çağrılarını silin
  7. engine.CreateFRDocument() + document.AddImageFile() + document.Process() yerine new IronTesseract().Read(path) kullanın
  8. Çok çerçeveli TIFF döngülerini input.LoadImageFrames(tiffPath) ile değiştirin
  9. document.PlainText.Text yerine result.Text kullanın
  10. frDocument.Pages[i].PlainText.Text yerine result.Pages[i].Text kullanın
  11. document.Export(..., FEF_PDF, pdfParams) yerine result.SaveAsSearchablePdf(path) kullanın
  12. Tüm document.Close() çağrılarını OcrInput üzerindeki using bloklarıyla değiştirin
  13. SemaphoreSlim ve ABBYY motor erişimini seri hale getiren kilitleme kodunu silin
  14. engine.CreateZone() / zone.SetBounds() / page.Zones.Add() yerine input.LoadImage()'a iletilen new CropRectangle(x, y, width, height) kullanın
  15. CI/CD boru hatlarından lisans dosyası kopyalama adımlarını kaldırın
  16. Docker görüntülerini güncelleyin — SDK yükleme katmanını kaldırın, Linux hedefleri için libgdiplus ekleyin

Geçiş Sonrası Testler

  • Her belge türünün (faturalar, sözleşmeler, taranmış formlar) temsilci bir örneğinde metin çıkarma çıktısını doğrulayın
  • Çoklu sayfalı TIFF işleminin ABBYY'nin ürettiği çerçeve sayısıyla aynı sayıda sayfa döndüğünü doğrulayın
  • ABBYY temel karşılaştırması için kullanılan aynı girdilere karşı çok dilli belgeleri test edin
  • Adobe Reader ve tarayıcı PDF görüntüleyicilerinde aranabilir PDF çıktısının metin aranabilir olduğunu doğrulayın
  • Üretim eşzamanlılık seviyesiyle paralel toplu işlemciyi çalıştırın ve hata olmadığını doğrulayın
  • Kalite kapıları için bir temel eşik oluşturmak adına bilinen iyi belgeler üzerinde result.Confidence kontrolü yapın
  • Aşama dağıtım ortamında ortam değişkeninden lisans anahtarı başlatmasını test edin
  • ABBYY SDK hacim yüklemesi olmadan Docker görüntüsünün OCR yapıp yapmadığını doğrulayın
  • Lisans dosyası kopyalama adımı olmadan CI/CD boru hattının tamamlandığını doğrulayın
  • Toplu işlemci üzerinde bir bellek profilini çalıştırarak hiçbir OcrInput nesnesinin sızmadığını onaylayın (using yerleşimini doğrulayın)

IronOCR'a Geçişin Ana Faydaları

Karmaşıklık Bir Büyüklük Sırasına Göre Düşer. Her ABBYY dağıtımı SDK kurulumu, lisans dosyası yerleştirme, çalışma zamanı yolu konfigürasyonu ve dosyaların doğru yollarında olduğunu doğrulama gerektiriyordu. IronOCR, bir NuGet bağımlılığı olarak dağıtılır. dotnet publish, OCR motorunu içeren bağımsız bir eser üretir. Docker dağıtım kılavuzu ve Azure kurulum kılavuzu, tam yapıyı gösterir — her ikisi de tek sayfaya sığar.

COM Birlikte Çalışma Gitti. COM katmanının kaldırılması, yeni makinelerdeki COM kayıt hataları, katman iş parçacığı uyumsuzlukları, RCW yaşam döngüsü hataları ve her ABBYY belge işleme çağrısının gerektirdiği 15-25 satırlık try/finally kod öbeği de dahil olmak üzere bir çalışma zamanı hataları kategorisinin tümünü ortadan kaldırır. Kod tabanı küçülür. Hata yüzeyi de küçülür.

Hacim Büyümesi Artık Bütçe Gözden Geçirmelerini Tetiklemez. IronOCR'nin süresiz lisansı, sınırsız belge hacmini kapsar. İlk yıl ayda 10.000 belge işleyen ve üçüncü yılda ayda 2.000.000 belge işleyen bir uygulama, aynı OCR lisanslama maliyetini taşır. Sayfa başına sayaç yok, aşım faturaları yok, hacim kademi yeniden müzakereleri yok. lisanslama sayfası tüm seviyeleri gösterir — 2.999 dolarlık Professional lisansı, çalışan her hacimi işleyen on geliştiriciyi kapsar.

Çapraz Platform Dağıtımı Yeni Altyapı Seçeneklerini Açıyor. ABBYY COM katmanı Windows gerektirir. Belge işleme maliyeti veya yoğunluk nedenleriyle Linux konteynerlerine taşıyan ekipler engellendi. IronOCR, aynı NuGet paketinden Windows, Linux ve macOS üzerinde aynı şekilde çalışır. ABBYY'den geçiş, uygulama yığınının OCR katmanından Windows kısıtlamasını kaldırır. Linux dağıtım kılavuzu ve AWS dağıtım kılavuzu her ortam için tam ayarı kapsar.

Paralel Throughput Ekstra Altyapı Çalışması Olmadan Kullanılabilir. ABBYY motor erişimi seri hale getiren kilit stratejileri yok oldu. IronTesseract örnekleri bağımsızdır: her thread için bir tane oluşturun, bir belge yığını boyunca Parallel.ForEach çalıştırın, sonuçları alın. Throughput, ekstra kod gerekmeksizin mevcut CPU çekirdekleriyle ölçeklenir. çoklu iş parçacığı örneği, çok çekirdekli donanımda duvar saati iyileştirmelerini gösterir.

Dil Konfigürasyonu Bir Paket Referansıdır. Almanca veya Japonca OCR işlevselliğini ABBYY entegrasyonuna eklemek, veri dosyalarını tanımlamayı, her hedef makinedeki çalışma zamanı yollarına dağıtmayı ve dosyaların eksik olması durumunda arıza yönetimini gerektiriyordu.IronOCR ile dotnet add package IronOcr.Languages.German dil paketini sürümlü, tekrarlanabilir bir NuGet bağımlılığı olarak ekler. Paket yöneticisi, her derlemede verinin mevcut olduğunu sağlar. özel dil paketi kılavuzu, uzman alanlar için özel dil modellerinin eğitimini ve konuşlandırmasını kapsar.

Lütfen dikkate alınABBYY FineReader ve Tesseract, ilgili sahiplerinin tescilli markalarıdır. Bu site ABBYY veya Google ile ilişkilendirilmemiş, onaylanmamış veya desteklenmemiştir. 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.

Sıkça Sorulan Sorular

Neden ABBYY FineReader Engine'den IronOCR'a geçmeliyim?

Yaygın geçiş nedenleri arasında COM ara bağlamının karmaşıklığını ortadan kaldırmak, dosya tabanlı lisans yönetimini değiştirmek, sayfa başına fatura düzenlemekten kaçınmak, Docker/kapsayıcı dağıtımını etkinleştirmek ve standart .NET araçlarıyla entegre olan bir NuGet doğal iş akışı benimsemek yer almaktadır.

ABBYY FineReader Engine'den IronOCR'a geçişteki ana kod değişiklikleri nelerdir?

ABBYY FineReader başlatma dizilerini IronTesseract oluşturma ile değiştirin, COM yaşam döngüsü yönetimini (açık Oluştur/Yükle/Kapat desenleri) kaldırın ve sonuç özellik adlarını güncelleyin. Sonuç, önemli ölçüde daha az sablon satırıdır.

Geçişi başlatmak için IronOCR'u nasıl kurarım?

Paket Yöneticisi Konsolunda 'Install-Package IronOcr' veya CLI'da 'dotnet add package IronOcr' çalıştırın. Dil paketleri ayrı paketlerdir: Örneğin, Fransızca için 'dotnet add package IronOcr.Languages.French'.

IronOCR, ABBYY FineReader Engine'in standart iş belgeleri için OCR doğruluğuna eşit midir?

IronOCR, faturalar, sözleşmeler, makbuzlar ve yazılı formlar dahil olmak üzere standart işletme içerikleri için yüksek doğruluğa ulaşır. Görüntü ön işleme filtreleri (dengelemeyi düzeltme, gürültü kaldırma, kontrast artırma) bozulmuş girdiler üzerindeki tanımayı daha da iyileştirir.

IronOCR, ABBYY FineReader Engine'in ayrı olarak yüklediği dil verilerini nasıl ele alır?

IronOCR'daki dil verileri, NuGet paketleri olarak dağıtılır. 'dotnet add package IronOcr.Languages.German' komutuyla Almanca desteği yüklenir. Herhangi bir manuel dosya yerleştirme veya dizin yolu gerekmez.

ABBYY FineReader Engine'den IronOCR'a geçiş, dağıtım altyapısında değişiklikler gerektirir mi?

IronOCR, ABBYY FineReader Engine'den daha az altyapı değişikliği gerektirir. SDK ikili yolları, lisans dosyası yerleştirmeleri veya lisans sunucu yapılandırmaları yoktur. NuGet paketi, tamamıyla OCR motorunu içerir ve lisans anahtarı uygulama kodunda bir dize olarak ayarlanır.

Geçişten sonra IronOCR lisanslamasını nasıl yapılandırırım?

Uygulama başlangıç ​​kodunda IronOcr.License.LicenseKey = "SİZİN-ANAHTARINIZ" atayın. Docker veya Kubernetes'te, anahtarı bir ortam değişkeni olarak saklayın ve başlangıçta okuyun. Trafiği kabul etmeden önce doğrulamak için License.IsValidLicense kullanın.

IronOCR, PDF'leri ABBYY FineReader gibi işleyebilir mi?

Evet. IronOCR hem yerel hem de taranmış PDF'leri okur. Bir PDF yolu veya OcrPdfInput olan girdiye ocr.Read(input) çağrısı yapmak için IronTesseract örneği çağırın ve OcrResult sayfalarını yineleyin. Ayrı bir PDF işleme hattı gerekmez.

IronOCR, yüksek hacim işleme sırasında iş parçacığı nasıl ele alır?

IronTesseract, iş parçacığı başına örnek olacak şekilde güvenlidir. Paralel.ForEach veya Görev havuzunda her iş parçacığı için bir örnek oluşturun, OCR'u eşzamanlı olarak çalıştırın ve her örneği iş tamamlandığında bırakın. Küresel durum veya kilitleme gerekmez.

IronOCR metin çıktıktan sonra hangi çıktıları destekler?

IronOCR, metin, kelime koordinatları, güven skorları ve sayfa yapısını içeren yapılandırılmış sonuçlar döndürür. Dışa aktarma seçenekleri düz metin, aranabilir PDF ve aşağı akış işlemesi için yapılandırılmış sonuç nesneleri içerir.

IronOCR'un fiyatlandırması, ABBYY FineReader Engine'den daha öngörülebilir mi? İş yüklerini artırırken?

IronOCR, sayfa başına veya hacim ücretlendirmesi olmadan düz oranlı sürekli lisanslama kullanır. 10.000 veya 10 milyon sayfa işleseniz de lisans maliyeti sabit kalır. Hacim ve ekip lisanslama seçenekleri IronOCR fiyatlandırma sayfasındadır.

ABBYY FineReader Engine'den IronOCR'a geçişten sonra mevcut testlerime ne olur?

Çıkarılmış metin içeriğini doğrulayan testler, geçişten sonra çalışmaya devam etmelidir. API çağrı şablonlarını veya COM nesne yaşam döngüsünü doğrulayan testler, IronOCR'un daha basit başlatma ve sonuç modelini yansıtacak şekilde güncellenmelidir.

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

Daha Fazla Oku

Iron Destek Ekibi

Haftada 5 gün, 24 saat çevrimiçiyiz.
Sohbet
E-posta
Beni Ara