Altbilgi içeriğine atla
VIDEOLAR

AWS Textract'dan IronOCR'a Geçiş

Bu kılavuz, bulut bağımlılıkları olmadan yerel belge işlemi gereken .NET geliştiricileri için AWS Textract'ten IronOCR'a tam bir geçişi ele alır. Genel bilgilerden, asenkron boru hattının kaldırılması, S3'ün ortadan kaldırılması ve her Textract işleminin IronOCR eşdeğerine taşınması için gereken özel kod değiştirmelerini kapsar.

AWS Textract'den Neden Göç Edilmeli

AWS Textract yetenekli bir yönetilen hizmettir, ancak mimarisi - mali ve operasyonel - belge yükü arttıkça artan maliyetler getirir. Ciddi belge işleme hatları inşa eden ekipler sonunda tüm bu sürtünme noktalarına ulaşırlar.

AWS Kimlik Bilgisi Altyapısı Her Dağıtımı Bileştirir. Textract kodunu çalıştıran her ortamın AWS kimlik bilgilerine ihtiyacı vardır: IAM kullanıcı veya rol, erişim anahtarı ve gizli, bölge yapılandırması ve — PDF işlemesi için — S3 kovası izinleri dahil olmak üzere. İşlemin başladığı ilk sayfadan önce beş farklı yapılandırma adımı vardır. Üretim dağıtımları, kimlik bilgisi döngü politikaları, Docker konteynerlarına veya Kubernetes podlarına güvenli enjeksiyon ve IAM politika kaymaları sessiz hatalara neden olduğunda AccessDeniedException için izleme gerektirir. IronOCR, başlatıldığında bir kez ayarlanan bir dize gerektirir: bir lisans anahtarı.

Sayfa Başına Fiyatlandırma Üst Sınır Yoktur. DetectDocumentText için sayfa başı taban fiyatı $0,0015'tir, bu maliyet değil tabandır. Tablo içeren herhangi bir belge, sayfa başına $0,015'te AnalyzeDocument tetikler — taban fiyatın on katı. Formlar, sayfa başına başka bir $0.05 ekler. Tablo çıkarımı ile ayda 100.000 sayfa karışık bir belge iş akışı yıllık $18.000 çalıştırır ve bu rakam her Ocak'ta sıfırlanır.IronOCR Professional lisansı bir kez $2,999 maliyetindedir. Bu noktadan sonra, hacimden bağımsız olarak sayfa başına maliyet sıfırdır.

Asenkron PDF Hattı Bir Bakım Sorumluluğudur. Textract ile herhangi bir çok sayfalı PDF işlemi beş farklı aşama gerektirir: S3 yüklemesi, StartDocumentTextDetection, polling döngüsü, sayfalı sonuç alma ve S3 temizliği. Her aşama, kendi hata işleme, tekrar stratejisi ve zaman aşımı yönetimine gerek duyan bağımsız bir hata modu oluşturur. Bu hattı üretim ortamına yollayan ekipler, bunu kurmaya harcadıklarından daha fazla zaman harcadıklarını sürekli bildirirler. IronOCR, iki satır kod ile PDF okur.

İnternet Erişimi Olmadan Textract Çalışmaz. İzole ağ segmentlerinde Docker konteynerleri, yerinde sunucular, izole araştırma ortamları ve giden trafiği sınırlamaları olan endüstriyel sistemler hepsi bir ortak özellik paylaşır: Textract kullanılamaz. IronOCR, bir NuGet paketi olarak kurulur ve ilk paket indirme sonrasında herhangi bir ağ çağrısı yapmaksızın çalışır.

Veriler Her Çağrıda Altyapınızdan Ayrılır. Textract ile yapılan her OCR işlemi, belge içeriğini Amazon'un sunucularına iletir. PHI işleyen sağlık kuruluşları, CUI işleyen savunma yüklenicileri, ayrıcalıklı iletişimleri işleyen yasal ekipler ve ödeme kartı görüntüleri işleyen finansal kuruluşlar için bu bir yapılandırma seçeneği değil — bu tamamen düzenlenmiş ortamlarda Textract'in kullanılmasını yasaklayan bir mimari kısıtlamadır. IronOCR, donanımınızda işler. Devre dışı bırakılacak bir bulut modu yok; yerel işleme, tek moddur.

Hız Limitleri Yığın İletimi Kısıtlar. Varsayılan StartDocumentTextDetection TPS limiti saniyede 5 istektir. Yüzlerce belge işleyen yığın işler, SemaphoreSlim kısıtlama, ProvisionedThroughputExceededException üzerine üstel gecikme ve hız yenileme zamanlayıcıları gerektirir. TPS artışı talep etmek, garanti edilmeyen bir sonuçla formal AWS destek davası gerektirir. IronOCR, yerel CPU'nun izin verdiği hızda işlem yapar — 16 çekirdekli bir sunucu, düz bir Parallel.ForEach ile 16 belgeyi eşzamanlı olarak işler, hizmet katmanı müzakeresi gerekmez.

Temel Sorun

Her Textract dağıtımı bu tören ile başlar — tek bir sayfa işlenmeden önce:

// Textract: five environment variables, an IAM role, and an S3 bucket
// — all required before the first OCR call

// Environment must have:
//   AWS_ACCESS_KEY_ID=AKIA...
//   AWS_SECRET_ACCESS_KEY=...
//   AWS_DEFAULT_REGION=us-east-1
//   IAM role: textract:DetectDocumentText, textract:AnalyzeDocument
//   IAM role: s3:PutObject, s3:DeleteObject (for any PDF processing)
//   S3 bucket: my-textract-staging-bucket (with lifecycle policy to prevent cost accumulation)

public class TextractOcrService
{
    private readonly AmazonTextractClient _textractClient;
    private readonly AmazonS3Client _s3Client; // required for PDFs

    public TextractOcrService()
    {
        // Fails with AmazonClientException if credentials not found in chain
        _textractClient = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
        _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
    }
}
// Textract: five environment variables, an IAM role, and an S3 bucket
// — all required before the first OCR call

// Environment must have:
//   AWS_ACCESS_KEY_ID=AKIA...
//   AWS_SECRET_ACCESS_KEY=...
//   AWS_DEFAULT_REGION=us-east-1
//   IAM role: textract:DetectDocumentText, textract:AnalyzeDocument
//   IAM role: s3:PutObject, s3:DeleteObject (for any PDF processing)
//   S3 bucket: my-textract-staging-bucket (with lifecycle policy to prevent cost accumulation)

public class TextractOcrService
{
    private readonly AmazonTextractClient _textractClient;
    private readonly AmazonS3Client _s3Client; // required for PDFs

    public TextractOcrService()
    {
        // Fails with AmazonClientException if credentials not found in chain
        _textractClient = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
        _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
    }
}
Imports Amazon
Imports Amazon.Textract
Imports Amazon.S3

' Textract: five environment variables, an IAM role, and an S3 bucket
' — all required before the first OCR call

' Environment must have:
'   AWS_ACCESS_KEY_ID=AKIA...
'   AWS_SECRET_ACCESS_KEY=...
'   AWS_DEFAULT_REGION=us-east-1
'   IAM role: textract:DetectDocumentText, textract:AnalyzeDocument
'   IAM role: s3:PutObject, s3:DeleteObject (for any PDF processing)
'   S3 bucket: my-textract-staging-bucket (with lifecycle policy to prevent cost accumulation)

Public Class TextractOcrService
    Private ReadOnly _textractClient As AmazonTextractClient
    Private ReadOnly _s3Client As AmazonS3Client ' required for PDFs

    Public Sub New()
        ' Fails with AmazonClientException if credentials not found in chain
        _textractClient = New AmazonTextractClient(Amazon.RegionEndpoint.USEast1)
        _s3Client = New AmazonS3Client(Amazon.RegionEndpoint.USEast1)
    End Sub
End Class
$vbLabelText   $csharpLabel

IronOCR, tüm kimlik bilgisi zincirini basit bir atama ile değiştirir:

// IronOCR: one line, one string, done
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Or from environment (no IAM, no rotation, no S3)
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// IronOCR: one line, one string, done
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// Or from environment (no IAM, no rotation, no S3)
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
Imports System

' IronOCR: one line, one string, done
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' Or from environment (no IAM, no rotation, no S3)
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
$vbLabelText   $csharpLabel

IronOCR ve AWS Textract: Özellik Karşılaştırması

Aşağıdaki tablo, her iki kütüphane'nin göç kararları için en önemli olan boyutlardaki yeteneklerini eşleştirir.

Özellik AWS Textract IronOCR
İşleme Yeri Amazon bulutu (zorunlu) Yalnızca yerel / yerinde
İnternet Gerekli Her zaman Asla
Kimlik Bilgisi Kurulumu IAM kullanıcı/rol + isteğe bağlı S3 kovası Tek lisans anahtarı dizesi
Çok Sayfalı PDF S3 aşamalandırma + asenkron iş gerektirir Doğrudan eşzamanlı input.LoadPdf()
Şifre Korumalı PDF Desteklenmiyor input.LoadPdf(path, Password: "x")
Çok Çerçeveli TIFF Desteklenmiyor input.LoadImageFrames("multi.tiff")
Asenkron Anket Gerekir Evet (tüm PDF'ler için) Hayır — varsayılan olarak senkronize
Oran Sınırlamaları 5 TPS varsayılan (StartDocumentTextDetection) Yok — sadece CPU sınırlı
Sayfa Başına Maliyet Sayfa başına 0,0015–0,065 $ Lisans satın aldıktan sonra $0
Otomatik Ön İşleme Dahili, yapılandırılamaz Yeniden hizalama, Gürültü Giderme, Kontrast, İkiliye Çevirme, Keskinleştirme, Ölçekleme
Aranabilir PDF Çıktısı Mevcut değil result.SaveAsSearchablePdf()
hOCR Dışa Aktarma Mevcut değil result.SaveAsHocrFile()
Barkod Okuma Mevcut değil ocr.Configuration.ReadBarCodes = true
Bölge Tabanlı OCR AnalyzeDocument + blok ilişkileri aracılığıyla CropRectangle(x, y, width, height)
Yapılandırılmış Sonuçlar Düz List<Block>, BlockType ile filtrelenmiş Yazılı Pages, Paragraphs, Lines, Words
Desteklenen Diller İngilizce ağırlıklı (ek seç) 125+ dil paketi üzerinden NuGet
Çok Dilli Eşzamanlı Desteklenmiyor OcrLanguage.French + OcrLanguage.German
İzole Dağıtım Mümkün değil Tam destekli
BAA Olmadan HIPAA Mümkün değil Harici işlemci gerektirmez — sadece yerinde
Docker Dağıtımı Enjekte edilmiş AWS kimlik bilgileri gerektirir Kimlik bilgisi gerektirmez — düz NuGet paketi
Çapraz Platform AWS yönetimi (yalnızca Linux) Windows, Linux, macOS, Docker, Azure, AWS EC2
Lisanslama Modeli Sayfa başına ölçülmüş faturalama (sürekli harcama) Süresiz tek seferlik ($999 / $1.499 / $2.999)

Hızlı Başlangıç: AWS Textract'ten IronOCR'a Geçiş

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

AWS SDK paketlerini kaldırın:

dotnet remove package AWSSDK.Textract
dotnet remove package AWSSDK.S3
dotnet remove package AWSSDK.Core
dotnet remove package AWSSDK.Textract
dotnet remove package AWSSDK.S3
dotnet remove package AWSSDK.Core
SHELL

NuGet kullanarak IronOCR'u yükleyin:

dotnet add package IronOcr

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

Tüm AWS alan adı içe aktarma işlemlerini tek bir IronOCR alan adı ile değiştirin:

// Before (AWS Textract)
using Amazon.Textract;
using Amazon.Textract.Model;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Runtime;

// After (IronOCR)
using IronOcr;
// Before (AWS Textract)
using Amazon.Textract;
using Amazon.Textract.Model;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Runtime;

// After (IronOCR)
using IronOcr;
Imports Amazon.Textract
Imports Amazon.Textract.Model
Imports Amazon.S3
Imports Amazon.S3.Model
Imports Amazon.Runtime

Imports IronOcr
$vbLabelText   $csharpLabel

Adım 3: Lisansa İzin Verin

Uygulama başlatıldığında bir kez lisans başlatmayı ekleyin. Tüm AWS kimlik bilgisi çevresel değişken kurulumunu kaldırın:

// Remove from startup:
//   AWS_ACCESS_KEY_ID environment variable
//   AWS_SECRET_ACCESS_KEY environment variable
//   AWS_DEFAULT_REGION environment variable
//   ~/.aws/credentials file entries
//   IAM role bindings on the execution context

// Add instead:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Remove from startup:
//   AWS_ACCESS_KEY_ID environment variable
//   AWS_SECRET_ACCESS_KEY environment variable
//   AWS_DEFAULT_REGION environment variable
//   ~/.aws/credentials file entries
//   IAM role bindings on the execution context

// Add instead:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
' Remove from startup:
'   AWS_ACCESS_KEY_ID environment variable
'   AWS_SECRET_ACCESS_KEY environment variable
'   AWS_DEFAULT_REGION environment variable
'   ~/.aws/credentials file entries
'   IAM role bindings on the execution context

' Add instead:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Kod Göç Örnekleri

AmazonTextractClient Yapıcısını ve IAM Kurulumunu Değiştirme

En görünür göç değişikliği istemci başlatmasıdır. Textract, kimlik bilgisi çözümlemesi ile birlikte olan bir bağımlılık enjekte edilmiş istemci gerektirir — yani istemci ve tüm bağımlılıkları her dağıtım ortamında önceden yapılandırılmış olmalıdır. Herhangi bir yanlış yapılandırma, ilk OCR çağrısı AmazonClientException fırlatana kadar sessizce başarısız olur.

AWS Textract Yaklaşımı:

// Requires: NuGet AWSSDK.Textract, AWSSDK.S3
// Requires: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION in environment
// Requires: IAM policy with textract:* and s3:PutObject, s3:DeleteObject

using Amazon.S3;
using Amazon.Textract;

public class DocumentOcrService
{
    private readonly AmazonTextractClient _textractClient;
    private readonly AmazonS3Client _s3Client;
    private readonly string _stagingBucket;

    public DocumentOcrService(IConfiguration config)
    {
        // Credential chain: environment → ~/.aws/credentials → EC2 instance profile
        // Fails if none found — runtime exception, not compile-time
        _textractClient = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
        _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
        _stagingBucket = config["Textract:StagingBucket"]; // bucket must exist and have permissions
    }

    public async Task<string> ReadImageAsync(string imagePath)
    {
        var bytes = File.ReadAllBytes(imagePath);
        var response = await _textractClient.DetectDocumentTextAsync(
            new DetectDocumentTextRequest
            {
                Document = new Document { Bytes = new MemoryStream(bytes) }
            });

        return string.Join("\n", response.Blocks
            .Where(b => b.BlockType == BlockType.LINE)
            .Select(b => b.Text));
    }
}
// Requires: NuGet AWSSDK.Textract, AWSSDK.S3
// Requires: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION in environment
// Requires: IAM policy with textract:* and s3:PutObject, s3:DeleteObject

using Amazon.S3;
using Amazon.Textract;

public class DocumentOcrService
{
    private readonly AmazonTextractClient _textractClient;
    private readonly AmazonS3Client _s3Client;
    private readonly string _stagingBucket;

    public DocumentOcrService(IConfiguration config)
    {
        // Credential chain: environment → ~/.aws/credentials → EC2 instance profile
        // Fails if none found — runtime exception, not compile-time
        _textractClient = new AmazonTextractClient(Amazon.RegionEndpoint.USEast1);
        _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
        _stagingBucket = config["Textract:StagingBucket"]; // bucket must exist and have permissions
    }

    public async Task<string> ReadImageAsync(string imagePath)
    {
        var bytes = File.ReadAllBytes(imagePath);
        var response = await _textractClient.DetectDocumentTextAsync(
            new DetectDocumentTextRequest
            {
                Document = new Document { Bytes = new MemoryStream(bytes) }
            });

        return string.Join("\n", response.Blocks
            .Where(b => b.BlockType == BlockType.LINE)
            .Select(b => b.Text));
    }
}
Imports Amazon.S3
Imports Amazon.Textract
Imports System.IO
Imports System.Threading.Tasks
Imports Microsoft.Extensions.Configuration

Public Class DocumentOcrService
    Private ReadOnly _textractClient As AmazonTextractClient
    Private ReadOnly _s3Client As AmazonS3Client
    Private ReadOnly _stagingBucket As String

    Public Sub New(config As IConfiguration)
        ' Credential chain: environment → ~/.aws/credentials → EC2 instance profile
        ' Fails if none found — runtime exception, not compile-time
        _textractClient = New AmazonTextractClient(Amazon.RegionEndpoint.USEast1)
        _s3Client = New AmazonS3Client(Amazon.RegionEndpoint.USEast1)
        _stagingBucket = config("Textract:StagingBucket") ' bucket must exist and have permissions
    End Sub

    Public Async Function ReadImageAsync(imagePath As String) As Task(Of String)
        Dim bytes = File.ReadAllBytes(imagePath)
        Dim response = Await _textractClient.DetectDocumentTextAsync(
            New DetectDocumentTextRequest With {
                .Document = New Document With {.Bytes = New MemoryStream(bytes)}
            })

        Return String.Join(vbCrLf, response.Blocks _
            .Where(Function(b) b.BlockType = BlockType.LINE) _
            .Select(Function(b) b.Text))
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

// Requires: NuGet IronOcr
// Requires: one license key string — nothing else

using IronOcr;

public class DocumentOcrService
{
    private readonly IronTesseract _ocr;

    public DocumentOcrService()
    {
        IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; // or set at Program.cs startup
        _ocr = new IronTesseract();
    }

    public string ReadImage(string imagePath)
    {
        // No credential chain, no region, no bucket — just read
        return _ocr.Read(imagePath).Text;
    }
}
// Requires: NuGet IronOcr
// Requires: one license key string — nothing else

using IronOcr;

public class DocumentOcrService
{
    private readonly IronTesseract _ocr;

    public DocumentOcrService()
    {
        IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; // or set at Program.cs startup
        _ocr = new IronTesseract();
    }

    public string ReadImage(string imagePath)
    {
        // No credential chain, no region, no bucket — just read
        return _ocr.Read(imagePath).Text;
    }
}
Imports IronOcr

Public Class DocumentOcrService
    Private ReadOnly _ocr As IronTesseract

    Public Sub New()
        IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY" ' or set at Program.vb startup
        _ocr = New IronTesseract()
    End Sub

    Public Function ReadImage(imagePath As String) As String
        ' No credential chain, no region, no bucket — just read
        Return _ocr.Read(imagePath).Text
    End Function
End Class
$vbLabelText   $csharpLabel

Tüm AWS kimlik bilgileri altyapısı — IAM rolleri, ortam değişkenleri, ~/.aws/credentials dosyaları, S3 kovası yaşam döngüsü politikaları ve bölge yapılandırması — kaldırılır. DocumentOcrService yapıcısı, çalışma zamanı hata modlarına sahip 3 bağımlı enjeksiyon sitesinden tek bir lisans atamasına geçer. Dağıtım desenleri hakkında ayrıntılar için IronTesseract kurulum kılavuzuna bakın.

StartDocumentTextDetection'i Çok Çerçeveli TIFF İşleme ile Değiştirme

Textract'ın asenkron iş API'si (StartDocumentTextDetection) çok sayfalı herhangi bir belge için gereklidir. Belge dijitalleştirme hatlarında yaygın bir desen, her bir taranmış sayfa için bir çerçeve olan çok çerçeveli TIFF'ler olarak taranan belgeleri almak Textract, doğrudan TIFF girişi kabul edemez; iş bir job başlatana/yüklenene kadar belge PDF'ye dönüştürülmeli ve S3'e yüklenmelidir. IronOCR, çok çerçeveli TIFF'leri yerel olarak okur.

AWS Textract Yaklaşımı:

// Textract cannot accept TIFF directly — requires PDF conversion + S3 + async job
// This shows the conversion overhead plus the minimum async pipeline

using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<string> ProcessScannedTiffAsync(string tiffPath, string s3Bucket)
{
    // Step 0: Convert TIFF to PDF first (Textract does not accept TIFF for async jobs)
    // Requires a separate PDF conversion library — not shown here
    var pdfPath = Path.ChangeExtension(tiffPath, ".pdf");
    ConvertTiffToPdf(tiffPath, pdfPath); // external dependency required

    // Step 1: Upload converted PDF to S3
    var s3Key = $"staging/{Guid.NewGuid()}.pdf";
    using (var stream = File.OpenRead(pdfPath))
    {
        await _s3Client.PutObjectAsync(new PutObjectRequest
        {
            BucketName = s3Bucket,
            Key = s3Key,
            InputStream = stream
        });
    }

    try
    {
        // Step 2: Start async detection job
        var startResp = await _textractClient.StartDocumentTextDetectionAsync(
            new StartDocumentTextDetectionRequest
            {
                DocumentLocation = new DocumentLocation
                {
                    S3Object = new S3Object { Bucket = s3Bucket, Name = s3Key }
                }
            });

        // Step 3: Poll every 5 seconds — can block for 30–120 seconds on large files
        GetDocumentTextDetectionResponse pollResp;
        do
        {
            await Task.Delay(5000);
            pollResp = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest { JobId = startResp.JobId });
        } while (pollResp.JobStatus == JobStatus.IN_PROGRESS);

        if (pollResp.JobStatus != JobStatus.SUCCEEDED)
            throw new Exception($"Job failed: {pollResp.StatusMessage}");

        // Step 4: Collect paginated results
        var text = new StringBuilder();
        string token = null;
        do
        {
            var page = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest
                {
                    JobId = startResp.JobId,
                    NextToken = token
                });
            foreach (var block in page.Blocks.Where(b => b.BlockType == BlockType.LINE))
                text.AppendLine(block.Text);
            token = page.NextToken;
        } while (token != null);

        return text.ToString();
    }
    finally
    {
        // Step 5: Clean up S3 — orphaned objects accumulate storage costs
        await _s3Client.DeleteObjectAsync(s3Bucket, s3Key);
        File.Delete(pdfPath); // clean up intermediate PDF
    }
}
// Textract cannot accept TIFF directly — requires PDF conversion + S3 + async job
// This shows the conversion overhead plus the minimum async pipeline

using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<string> ProcessScannedTiffAsync(string tiffPath, string s3Bucket)
{
    // Step 0: Convert TIFF to PDF first (Textract does not accept TIFF for async jobs)
    // Requires a separate PDF conversion library — not shown here
    var pdfPath = Path.ChangeExtension(tiffPath, ".pdf");
    ConvertTiffToPdf(tiffPath, pdfPath); // external dependency required

    // Step 1: Upload converted PDF to S3
    var s3Key = $"staging/{Guid.NewGuid()}.pdf";
    using (var stream = File.OpenRead(pdfPath))
    {
        await _s3Client.PutObjectAsync(new PutObjectRequest
        {
            BucketName = s3Bucket,
            Key = s3Key,
            InputStream = stream
        });
    }

    try
    {
        // Step 2: Start async detection job
        var startResp = await _textractClient.StartDocumentTextDetectionAsync(
            new StartDocumentTextDetectionRequest
            {
                DocumentLocation = new DocumentLocation
                {
                    S3Object = new S3Object { Bucket = s3Bucket, Name = s3Key }
                }
            });

        // Step 3: Poll every 5 seconds — can block for 30–120 seconds on large files
        GetDocumentTextDetectionResponse pollResp;
        do
        {
            await Task.Delay(5000);
            pollResp = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest { JobId = startResp.JobId });
        } while (pollResp.JobStatus == JobStatus.IN_PROGRESS);

        if (pollResp.JobStatus != JobStatus.SUCCEEDED)
            throw new Exception($"Job failed: {pollResp.StatusMessage}");

        // Step 4: Collect paginated results
        var text = new StringBuilder();
        string token = null;
        do
        {
            var page = await _textractClient.GetDocumentTextDetectionAsync(
                new GetDocumentTextDetectionRequest
                {
                    JobId = startResp.JobId,
                    NextToken = token
                });
            foreach (var block in page.Blocks.Where(b => b.BlockType == BlockType.LINE))
                text.AppendLine(block.Text);
            token = page.NextToken;
        } while (token != null);

        return text.ToString();
    }
    finally
    {
        // Step 5: Clean up S3 — orphaned objects accumulate storage costs
        await _s3Client.DeleteObjectAsync(s3Bucket, s3Key);
        File.Delete(pdfPath); // clean up intermediate PDF
    }
}
Imports Amazon.S3
Imports Amazon.S3.Model
Imports Amazon.Textract
Imports Amazon.Textract.Model
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks

Public Async Function ProcessScannedTiffAsync(tiffPath As String, s3Bucket As String) As Task(Of String)
    ' Step 0: Convert TIFF to PDF first (Textract does not accept TIFF for async jobs)
    ' Requires a separate PDF conversion library — not shown here
    Dim pdfPath = Path.ChangeExtension(tiffPath, ".pdf")
    ConvertTiffToPdf(tiffPath, pdfPath) ' external dependency required

    ' Step 1: Upload converted PDF to S3
    Dim s3Key = $"staging/{Guid.NewGuid()}.pdf"
    Using stream = File.OpenRead(pdfPath)
        Await _s3Client.PutObjectAsync(New PutObjectRequest With {
            .BucketName = s3Bucket,
            .Key = s3Key,
            .InputStream = stream
        })
    End Using

    Try
        ' Step 2: Start async detection job
        Dim startResp = Await _textractClient.StartDocumentTextDetectionAsync(
            New StartDocumentTextDetectionRequest With {
                .DocumentLocation = New DocumentLocation With {
                    .S3Object = New S3Object With {.Bucket = s3Bucket, .Name = s3Key}
                }
            })

        ' Step 3: Poll every 5 seconds — can block for 30–120 seconds on large files
        Dim pollResp As GetDocumentTextDetectionResponse
        Do
            Await Task.Delay(5000)
            pollResp = Await _textractClient.GetDocumentTextDetectionAsync(
                New GetDocumentTextDetectionRequest With {.JobId = startResp.JobId})
        Loop While pollResp.JobStatus = JobStatus.IN_PROGRESS

        If pollResp.JobStatus <> JobStatus.SUCCEEDED Then
            Throw New Exception($"Job failed: {pollResp.StatusMessage}")
        End If

        ' Step 4: Collect paginated results
        Dim text = New StringBuilder()
        Dim token As String = Nothing
        Do
            Dim page = Await _textractClient.GetDocumentTextDetectionAsync(
                New GetDocumentTextDetectionRequest With {
                    .JobId = startResp.JobId,
                    .NextToken = token
                })
            For Each block In page.Blocks.Where(Function(b) b.BlockType = BlockType.LINE)
                text.AppendLine(block.Text)
            Next
            token = page.NextToken
        Loop While token IsNot Nothing

        Return text.ToString()
    Finally
        ' Step 5: Clean up S3 — orphaned objects accumulate storage costs
        Await _s3Client.DeleteObjectAsync(s3Bucket, s3Key)
        File.Delete(pdfPath) ' clean up intermediate PDF
    End Try
End Function
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

//IronOCR reads multi-frame TIFF directly — no conversion, no S3, no polling

using IronOcr;

public string ProcessScannedTiff(string tiffPath)
{
    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath); // reads all frames natively

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

    // Access per-page results if needed
    foreach (var page in result.Pages)
        Console.WriteLine($"Page {page.PageNumber}: {page.Words.Length} words detected");

    return result.Text;
}
//IronOCR reads multi-frame TIFF directly — no conversion, no S3, no polling

using IronOcr;

public string ProcessScannedTiff(string tiffPath)
{
    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath); // reads all frames natively

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

    // Access per-page results if needed
    foreach (var page in result.Pages)
        Console.WriteLine($"Page {page.PageNumber}: {page.Words.Length} words detected");

    return result.Text;
}
Imports IronOcr

Public Function ProcessScannedTiff(tiffPath As String) As String
    Using input As New OcrInput()
        input.LoadImageFrames(tiffPath) ' reads all frames natively

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

        ' Access per-page results if needed
        For Each page In result.Pages
            Console.WriteLine($"Page {page.PageNumber}: {page.Words.Length} words detected")
        Next

        Return result.Text
    End Using
End Function
$vbLabelText   $csharpLabel

Belgeyi PDF'ye dönüştürme adımı, S3 yüklemesi, asenkron anket döngüsü, sayfalı sonuç birikimi ve S3 temizleme işlemi ortadan kalkar.IronOCR uygulaması, çerçeveleri doğrudan okur ve hiçbir ara format dönüşümü olmadan result.Pages aracılığıyla sayfa başına erişim sağlar. TIFF ve GIF giriş kılavuzu, yalnızca çerçevelerin bir alt kümesinin gerektiği durumlar için çerçeve seçimini kapsar.

S3 Aşamalandırmayı Aranabilir PDF Çıktısı ile Değiştirme

Yaygın bir Textract kullanım durumu, taranmış PDF arşivlerini aranabilir forma dönüştürmektir. Textract yaklaşımı, her PDF'yi S3'e yüklemeyi, asenkron işi çalıştırmayı, çıkarılan metni toplamayı, ardından bu metni aranabilir katman olarak gömmek için ayrı bir PDF kütüphanesi kullanmayı gerektirir. IronOCR, taramayı gerçekleştirir ve tek bir çağrıda aranabilir bir PDF üretir.

AWS Textract Yaklaşımı:

// Textract extracts text but cannot produce searchable PDFs
// Requires: S3 upload + async job + separate PDF library to embed the text layer

using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<string> ExtractTextForSearchableLayerAsync(
    string scannedPdfPath,
    string s3Bucket)
{
    // Must upload to S3 — cannot pass PDF bytes directly for async jobs
    var key = $"ocr-input/{Guid.NewGuid()}.pdf";

    await using (var fs = File.OpenRead(scannedPdfPath))
    {
        await _s3Client.PutObjectAsync(new PutObjectRequest
        {
            BucketName = s3Bucket,
            Key = key,
            InputStream = fs,
            ContentType = "application/pdf"
        });
    }

    string jobId;
    try
    {
        var startResp = await _textractClient.StartDocumentTextDetectionAsync(
            new StartDocumentTextDetectionRequest
            {
                DocumentLocation = new DocumentLocation
                {
                    S3Object = new S3Object { Bucket = s3Bucket, Name = key }
                }
            });
        jobId = startResp.JobId;
    }
    catch
    {
        await _s3Client.DeleteObjectAsync(s3Bucket, key);
        throw;
    }

    // Poll — minimum 5s wait; typical 15–60s for a 10-page PDF
    GetDocumentTextDetectionResponse pollResp;
    int pollAttempts = 0;
    const int maxAttempts = 120; // 10 minute timeout

    do
    {
        await Task.Delay(5000);
        pollResp = await _textractClient.GetDocumentTextDetectionAsync(
            new GetDocumentTextDetectionRequest { JobId = jobId });

        if (++pollAttempts >= maxAttempts)
            throw new TimeoutException("Textract job timed out after 10 minutes");

    } while (pollResp.JobStatus == JobStatus.IN_PROGRESS);

    await _s3Client.DeleteObjectAsync(s3Bucket, key); // cleanup regardless of outcome

    if (pollResp.JobStatus != JobStatus.SUCCEEDED)
        throw new Exception($"Textract job status: {pollResp.JobStatus} — {pollResp.StatusMessage}");

    // Return extracted text — caller must use a separate library to produce searchable PDF
    return string.Join("\n", pollResp.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .Select(b => b.Text));

    // Caller still needs: iTextSharp, PdfSharp, or similar to embed text layer
}
// Textract extracts text but cannot produce searchable PDFs
// Requires: S3 upload + async job + separate PDF library to embed the text layer

using Amazon.S3;
using Amazon.S3.Model;
using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<string> ExtractTextForSearchableLayerAsync(
    string scannedPdfPath,
    string s3Bucket)
{
    // Must upload to S3 — cannot pass PDF bytes directly for async jobs
    var key = $"ocr-input/{Guid.NewGuid()}.pdf";

    await using (var fs = File.OpenRead(scannedPdfPath))
    {
        await _s3Client.PutObjectAsync(new PutObjectRequest
        {
            BucketName = s3Bucket,
            Key = key,
            InputStream = fs,
            ContentType = "application/pdf"
        });
    }

    string jobId;
    try
    {
        var startResp = await _textractClient.StartDocumentTextDetectionAsync(
            new StartDocumentTextDetectionRequest
            {
                DocumentLocation = new DocumentLocation
                {
                    S3Object = new S3Object { Bucket = s3Bucket, Name = key }
                }
            });
        jobId = startResp.JobId;
    }
    catch
    {
        await _s3Client.DeleteObjectAsync(s3Bucket, key);
        throw;
    }

    // Poll — minimum 5s wait; typical 15–60s for a 10-page PDF
    GetDocumentTextDetectionResponse pollResp;
    int pollAttempts = 0;
    const int maxAttempts = 120; // 10 minute timeout

    do
    {
        await Task.Delay(5000);
        pollResp = await _textractClient.GetDocumentTextDetectionAsync(
            new GetDocumentTextDetectionRequest { JobId = jobId });

        if (++pollAttempts >= maxAttempts)
            throw new TimeoutException("Textract job timed out after 10 minutes");

    } while (pollResp.JobStatus == JobStatus.IN_PROGRESS);

    await _s3Client.DeleteObjectAsync(s3Bucket, key); // cleanup regardless of outcome

    if (pollResp.JobStatus != JobStatus.SUCCEEDED)
        throw new Exception($"Textract job status: {pollResp.JobStatus} — {pollResp.StatusMessage}");

    // Return extracted text — caller must use a separate library to produce searchable PDF
    return string.Join("\n", pollResp.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .Select(b => b.Text));

    // Caller still needs: iTextSharp, PdfSharp, or similar to embed text layer
}
Imports Amazon.S3
Imports Amazon.S3.Model
Imports Amazon.Textract
Imports Amazon.Textract.Model

Public Async Function ExtractTextForSearchableLayerAsync(
    scannedPdfPath As String,
    s3Bucket As String) As Task(Of String)

    ' Must upload to S3 — cannot pass PDF bytes directly for async jobs
    Dim key = $"ocr-input/{Guid.NewGuid()}.pdf"

    Await Using fs = File.OpenRead(scannedPdfPath)
        Await _s3Client.PutObjectAsync(New PutObjectRequest With {
            .BucketName = s3Bucket,
            .Key = key,
            .InputStream = fs,
            .ContentType = "application/pdf"
        })
    End Using

    Dim jobId As String
    Try
        Dim startResp = Await _textractClient.StartDocumentTextDetectionAsync(
            New StartDocumentTextDetectionRequest With {
                .DocumentLocation = New DocumentLocation With {
                    .S3Object = New S3Object With {.Bucket = s3Bucket, .Name = key}
                }
            })
        jobId = startResp.JobId
    Catch
        Await _s3Client.DeleteObjectAsync(s3Bucket, key)
        Throw
    End Try

    ' Poll — minimum 5s wait; typical 15–60s for a 10-page PDF
    Dim pollResp As GetDocumentTextDetectionResponse
    Dim pollAttempts As Integer = 0
    Const maxAttempts As Integer = 120 ' 10 minute timeout

    Do
        Await Task.Delay(5000)
        pollResp = Await _textractClient.GetDocumentTextDetectionAsync(
            New GetDocumentTextDetectionRequest With {.JobId = jobId})

        If System.Threading.Interlocked.Increment(pollAttempts) >= maxAttempts Then
            Throw New TimeoutException("Textract job timed out after 10 minutes")
        End If

    Loop While pollResp.JobStatus = JobStatus.IN_PROGRESS

    Await _s3Client.DeleteObjectAsync(s3Bucket, key) ' cleanup regardless of outcome

    If pollResp.JobStatus <> JobStatus.SUCCEEDED Then
        Throw New Exception($"Textract job status: {pollResp.JobStatus} — {pollResp.StatusMessage}")
    End If

    ' Return extracted text — caller must use a separate library to produce searchable PDF
    Return String.Join(vbLf, pollResp.Blocks _
        .Where(Function(b) b.BlockType = BlockType.LINE) _
        .Select(Function(b) b.Text))

    ' Caller still needs: iTextSharp, PdfSharp, or similar to embed text layer
End Function
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

//IronOCR reads the PDF and produces a searchable PDF output directly
// No S3, no polling, no external PDF library needed

using IronOcr;

public void ConvertToSearchablePdf(string scannedPdfPath, string outputPath)
{
    var ocr = new IronTesseract();

    using var input = new OcrInput();
    input.LoadPdf(scannedPdfPath);

    var result = ocr.Read(input);

    // Embed extracted text as searchable layer in one call
    result.SaveAsSearchablePdf(outputPath);

    Console.WriteLine($"Pages processed: {result.Pages.Length}");
    Console.WriteLine($"Overall confidence: {result.Confidence:F1}%");
}
//IronOCR reads the PDF and produces a searchable PDF output directly
// No S3, no polling, no external PDF library needed

using IronOcr;

public void ConvertToSearchablePdf(string scannedPdfPath, string outputPath)
{
    var ocr = new IronTesseract();

    using var input = new OcrInput();
    input.LoadPdf(scannedPdfPath);

    var result = ocr.Read(input);

    // Embed extracted text as searchable layer in one call
    result.SaveAsSearchablePdf(outputPath);

    Console.WriteLine($"Pages processed: {result.Pages.Length}");
    Console.WriteLine($"Overall confidence: {result.Confidence:F1}%");
}
Imports IronOcr

Public Sub ConvertToSearchablePdf(scannedPdfPath As String, outputPath As String)
    Dim ocr As New IronTesseract()

    Using input As New OcrInput()
        input.LoadPdf(scannedPdfPath)

        Dim result = ocr.Read(input)

        ' Embed extracted text as searchable layer in one call
        result.SaveAsSearchablePdf(outputPath)

        Console.WriteLine($"Pages processed: {result.Pages.Length}")
        Console.WriteLine($"Overall confidence: {result.Confidence:F1}%")
    End Using
End Sub
$vbLabelText   $csharpLabel

Anket zaman aşımı mantığı, S3 yükleme ve temizleme deseni ve dış PDF kütüphane bağımlılığı ortadan kalkar. SaveAsSearchablePdf, tanınan metni doğrudan çıktı dosyasına gömerek, her taranan sayfayı ikinci bir kütüphane olmadan tamamen metin arama yapılabilir hale getirir. aranabilir PDF kılavuzu, sayfa seçimini, sıkıştırma seçeneklerini ve meta veri gömmeyi kapsar. PDF OCR boru hatlarının daha geniş bağlamı için PDF giriş kılavuzuna bakın.

AnalyzeDocument Blok Graf Geçişini Yapılandırılmış Sayfa Sonuçları ile Değiştirme

Textract'ın AnalyzeDocument ile TABLES ve FORMS, her bir eleman — satırlar, kelimeler, hücreler, tablo başlıkları, form tuşları, form değerleri — aynı Block türünde olan ama sadece BlockType ile ayırt edilen ve RelationshipType.CHILD ID dizileri ile bağlantılı olan düz bir List<Block> döndürür. Bir belgenin mantıksal yapısını yeniden oluşturmak için bu ilişki grafı üzerinde gezinmek gerekir. IronOCR, türlendirilmiş bir hiyerarşi döndürür: sayfalar, paragraflar, satırlar, kelimeler, her biri koordinat erişimi ile.

AWS Textract Yaklaşımı:

// AnalyzeDocument with TABLES returns blocks that must be graph-traversed
// to determine which words belong to which paragraphs

using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<List<DocumentSection>> ExtractDocumentStructureAsync(string imagePath)
{
    var bytes = File.ReadAllBytes(imagePath);

    var response = await _textractClient.AnalyzeDocumentAsync(
        new AnalyzeDocumentRequest
        {
            Document = new Document { Bytes = new MemoryStream(bytes) },
            FeatureTypes = new List<string> { "TABLES", "FORMS" }
            // Note: AnalyzeDocument (TABLES) costs $0.015/page — 10x DetectDocumentText
        });

    var sections = new List<DocumentSection>();

    // Filter LINE blocks for paragraph reconstruction
    // LINE blocks are not grouped into paragraphs — must infer from Y proximity
    var lineBlocks = response.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .OrderBy(b => b.Geometry?.BoundingBox?.Top ?? 0)
        .ToList();

    // Group lines into pseudo-paragraphs by vertical gap heuristic
    var currentParagraph = new List<Block>();
    float? lastBottom = null;
    const float paragraphGapThreshold = 0.02f; // 2% of page height

    foreach (var line in lineBlocks)
    {
        var top = line.Geometry?.BoundingBox?.Top ?? 0;
        var height = line.Geometry?.BoundingBox?.Height ?? 0;

        if (lastBottom.HasValue && (top - lastBottom.Value) > paragraphGapThreshold)
        {
            if (currentParagraph.Any())
            {
                sections.Add(new DocumentSection
                {
                    Text = string.Join(" ", currentParagraph.Select(b => b.Text)),
                    LineCount = currentParagraph.Count,
                    // Confidence: average of all LINE block confidence values
                    Confidence = (float)currentParagraph.Average(b => b.Confidence ?? 0)
                });
                currentParagraph.Clear();
            }
        }

        currentParagraph.Add(line);
        lastBottom = top + height;
    }

    if (currentParagraph.Any())
        sections.Add(new DocumentSection
        {
            Text = string.Join(" ", currentParagraph.Select(b => b.Text)),
            LineCount = currentParagraph.Count,
            Confidence = (float)currentParagraph.Average(b => b.Confidence ?? 0)
        });

    return sections;
}

public class DocumentSection
{
    public string Text { get; set; }
    public int LineCount { get; set; }
    public float Confidence { get; set; }
}
// AnalyzeDocument with TABLES returns blocks that must be graph-traversed
// to determine which words belong to which paragraphs

using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<List<DocumentSection>> ExtractDocumentStructureAsync(string imagePath)
{
    var bytes = File.ReadAllBytes(imagePath);

    var response = await _textractClient.AnalyzeDocumentAsync(
        new AnalyzeDocumentRequest
        {
            Document = new Document { Bytes = new MemoryStream(bytes) },
            FeatureTypes = new List<string> { "TABLES", "FORMS" }
            // Note: AnalyzeDocument (TABLES) costs $0.015/page — 10x DetectDocumentText
        });

    var sections = new List<DocumentSection>();

    // Filter LINE blocks for paragraph reconstruction
    // LINE blocks are not grouped into paragraphs — must infer from Y proximity
    var lineBlocks = response.Blocks
        .Where(b => b.BlockType == BlockType.LINE)
        .OrderBy(b => b.Geometry?.BoundingBox?.Top ?? 0)
        .ToList();

    // Group lines into pseudo-paragraphs by vertical gap heuristic
    var currentParagraph = new List<Block>();
    float? lastBottom = null;
    const float paragraphGapThreshold = 0.02f; // 2% of page height

    foreach (var line in lineBlocks)
    {
        var top = line.Geometry?.BoundingBox?.Top ?? 0;
        var height = line.Geometry?.BoundingBox?.Height ?? 0;

        if (lastBottom.HasValue && (top - lastBottom.Value) > paragraphGapThreshold)
        {
            if (currentParagraph.Any())
            {
                sections.Add(new DocumentSection
                {
                    Text = string.Join(" ", currentParagraph.Select(b => b.Text)),
                    LineCount = currentParagraph.Count,
                    // Confidence: average of all LINE block confidence values
                    Confidence = (float)currentParagraph.Average(b => b.Confidence ?? 0)
                });
                currentParagraph.Clear();
            }
        }

        currentParagraph.Add(line);
        lastBottom = top + height;
    }

    if (currentParagraph.Any())
        sections.Add(new DocumentSection
        {
            Text = string.Join(" ", currentParagraph.Select(b => b.Text)),
            LineCount = currentParagraph.Count,
            Confidence = (float)currentParagraph.Average(b => b.Confidence ?? 0)
        });

    return sections;
}

public class DocumentSection
{
    public string Text { get; set; }
    public int LineCount { get; set; }
    public float Confidence { get; set; }
}
Imports Amazon.Textract
Imports Amazon.Textract.Model
Imports System.IO
Imports System.Linq
Imports System.Threading.Tasks

Public Class DocumentProcessor
    Private _textractClient As IAmazonTextract

    Public Sub New(textractClient As IAmazonTextract)
        _textractClient = textractClient
    End Sub

    Public Async Function ExtractDocumentStructureAsync(imagePath As String) As Task(Of List(Of DocumentSection))
        Dim bytes = File.ReadAllBytes(imagePath)

        Dim response = Await _textractClient.AnalyzeDocumentAsync(
            New AnalyzeDocumentRequest With {
                .Document = New Document With {.Bytes = New MemoryStream(bytes)},
                .FeatureTypes = New List(Of String) From {"TABLES", "FORMS"}
            })

        Dim sections = New List(Of DocumentSection)()

        Dim lineBlocks = response.Blocks _
            .Where(Function(b) b.BlockType = BlockType.LINE) _
            .OrderBy(Function(b) If(b.Geometry?.BoundingBox?.Top, 0)) _
            .ToList()

        Dim currentParagraph = New List(Of Block)()
        Dim lastBottom As Single? = Nothing
        Const paragraphGapThreshold As Single = 0.02F

        For Each line In lineBlocks
            Dim top = If(line.Geometry?.BoundingBox?.Top, 0)
            Dim height = If(line.Geometry?.BoundingBox?.Height, 0)

            If lastBottom.HasValue AndAlso (top - lastBottom.Value) > paragraphGapThreshold Then
                If currentParagraph.Any() Then
                    sections.Add(New DocumentSection With {
                        .Text = String.Join(" ", currentParagraph.Select(Function(b) b.Text)),
                        .LineCount = currentParagraph.Count,
                        .Confidence = CSng(currentParagraph.Average(Function(b) If(b.Confidence, 0)))
                    })
                    currentParagraph.Clear()
                End If
            End If

            currentParagraph.Add(line)
            lastBottom = top + height
        Next

        If currentParagraph.Any() Then
            sections.Add(New DocumentSection With {
                .Text = String.Join(" ", currentParagraph.Select(Function(b) b.Text)),
                .LineCount = currentParagraph.Count,
                .Confidence = CSng(currentParagraph.Average(Function(b) If(b.Confidence, 0)))
            })
        End If

        Return sections
    End Function
End Class

Public Class DocumentSection
    Public Property Text As String
    Public Property LineCount As Integer
    Public Property Confidence As Single
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

//IronOCR returns a typed hierarchy — paragraphs are first-class objects
// No block graph, no heuristic gap detection, no confidence averaging

using IronOcr;

public List<DocumentSection> ExtractDocumentStructure(string imagePath)
{
    var ocr = new IronTesseract();
    var result = ocr.Read(imagePath);

    var sections = new List<DocumentSection>();

    foreach (var page in result.Pages)
    {
        foreach (var paragraph in page.Paragraphs)
        {
            sections.Add(new DocumentSection
            {
                Text = paragraph.Text,
                LineCount = paragraph.Lines.Length,
                // Coordinate access: exact pixel position on the page
                LocationX = paragraph.X,
                LocationY = paragraph.Y,
                Width = paragraph.Width,
                Height = paragraph.Height,
                Confidence = paragraph.Confidence
            });
        }
    }

    return sections;
}

public class DocumentSection
{
    public string Text { get; set; }
    public int LineCount { get; set; }
    public int LocationX { get; set; }
    public int LocationY { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public double Confidence { get; set; }
}
//IronOCR returns a typed hierarchy — paragraphs are first-class objects
// No block graph, no heuristic gap detection, no confidence averaging

using IronOcr;

public List<DocumentSection> ExtractDocumentStructure(string imagePath)
{
    var ocr = new IronTesseract();
    var result = ocr.Read(imagePath);

    var sections = new List<DocumentSection>();

    foreach (var page in result.Pages)
    {
        foreach (var paragraph in page.Paragraphs)
        {
            sections.Add(new DocumentSection
            {
                Text = paragraph.Text,
                LineCount = paragraph.Lines.Length,
                // Coordinate access: exact pixel position on the page
                LocationX = paragraph.X,
                LocationY = paragraph.Y,
                Width = paragraph.Width,
                Height = paragraph.Height,
                Confidence = paragraph.Confidence
            });
        }
    }

    return sections;
}

public class DocumentSection
{
    public string Text { get; set; }
    public int LineCount { get; set; }
    public int LocationX { get; set; }
    public int LocationY { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public double Confidence { get; set; }
}
Imports IronOcr

Public Function ExtractDocumentStructure(imagePath As String) As List(Of DocumentSection)
    Dim ocr As New IronTesseract()
    Dim result = ocr.Read(imagePath)

    Dim sections As New List(Of DocumentSection)()

    For Each page In result.Pages
        For Each paragraph In page.Paragraphs
            sections.Add(New DocumentSection With {
                .Text = paragraph.Text,
                .LineCount = paragraph.Lines.Length,
                .LocationX = paragraph.X,
                .LocationY = paragraph.Y,
                .Width = paragraph.Width,
                .Height = paragraph.Height,
                .Confidence = paragraph.Confidence
            })
        Next
    Next

    Return sections
End Function

Public Class DocumentSection
    Public Property Text As String
    Public Property LineCount As Integer
    Public Property LocationX As Integer
    Public Property LocationY As Integer
    Public Property Width As Integer
    Public Property Height As Integer
    Public Property Confidence As Double
End Class
$vbLabelText   $csharpLabel

Paragraflar, satırlar ve kelimeler, .X, .Y, .Width, .Height ve .Confidence özellikleri ile yazılı koleksiyonlar olarak doğrudan erişilebilir. BoundingBox normalizasyonu, boşluk eşiği sezgisel kararları, blok türü filtreleme yok. okuma sonuçları kılavuzu, karakter seviyesinde koordinat erişimi de dahil olmak üzere tam OcrResult hiyerarşisini belgelendirir. Bu yapıya bağlı fatura ve makbuz iş akışları için fatura OCR öğreticisine bakın.

Oran Sınırlı Toplu İşleme Yerine Sınırsız Paralel Yürütme ile Değiştirme

Yığın görüntü işleme, Textract'ın TPS limitlerinin en görünür operasyonel maliyeti ürettiği yerdir. DetectDocumentText eşzamanlı API'si hız sınırlıdır; Saniyede 5'ten fazla istek göndermek ProvisionedThroughputExceededException üretir. Doğru yığın işleme, SemaphoreSlim kısıtlama, geri çekilme ile tekrar mantığı ve uçuşta istekler için dikkatli muhasebe gerektirir. IronOCR'un oran sınırı yoktur — üretim hızı yalnızca mevcut CPU çekirdekleriyle sınırlıdır.

AWS Textract Yaklaşımı:

// Batch processing requires SemaphoreSlim throttle + retry on rate limit exceeded

using Amazon.Textract;
using Amazon.Textract.Model;
using System.Collections.Concurrent;

public async Task<Dictionary<string, string>> ProcessImageBatchAsync(
    IReadOnlyList<string> imagePaths,
    IProgress<(int Completed, int Total)> progress = null)
{
    var results = new ConcurrentDictionary<string, string>();
    var semaphore = new SemaphoreSlim(5); // 5 concurrent — Textract default TPS limit
    var tasks = new List<Task>();
    int completed = 0;

    foreach (var path in imagePaths)
    {
        await semaphore.WaitAsync();

        tasks.Add(Task.Run(async () =>
        {
            try
            {
                string text = null;
                int retryCount = 0;

                while (text == null && retryCount < 3)
                {
                    try
                    {
                        var bytes = await File.ReadAllBytesAsync(path);
                        var response = await _textractClient.DetectDocumentTextAsync(
                            new DetectDocumentTextRequest
                            {
                                Document = new Document { Bytes = new MemoryStream(bytes) }
                            });

                        text = string.Join("\n", response.Blocks
                            .Where(b => b.BlockType == BlockType.LINE)
                            .Select(b => b.Text));
                    }
                    catch (AmazonTextractException ex)
                        when (ex.ErrorCode == "ProvisionedThroughputExceededException")
                    {
                        // Exponential backoff on rate limit — blocks the entire thread
                        await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, retryCount)));
                        retryCount++;
                    }
                }

                results[path] = text ?? string.Empty;
                var done = Interlocked.Increment(ref completed);
                progress?.Report((done, imagePaths.Count));
            }
            finally
            {
                semaphore.Release();
            }
        }));
    }

    await Task.WhenAll(tasks);
    return results.ToDictionary(x => x.Key, x => x.Value);
}
// Batch processing requires SemaphoreSlim throttle + retry on rate limit exceeded

using Amazon.Textract;
using Amazon.Textract.Model;
using System.Collections.Concurrent;

public async Task<Dictionary<string, string>> ProcessImageBatchAsync(
    IReadOnlyList<string> imagePaths,
    IProgress<(int Completed, int Total)> progress = null)
{
    var results = new ConcurrentDictionary<string, string>();
    var semaphore = new SemaphoreSlim(5); // 5 concurrent — Textract default TPS limit
    var tasks = new List<Task>();
    int completed = 0;

    foreach (var path in imagePaths)
    {
        await semaphore.WaitAsync();

        tasks.Add(Task.Run(async () =>
        {
            try
            {
                string text = null;
                int retryCount = 0;

                while (text == null && retryCount < 3)
                {
                    try
                    {
                        var bytes = await File.ReadAllBytesAsync(path);
                        var response = await _textractClient.DetectDocumentTextAsync(
                            new DetectDocumentTextRequest
                            {
                                Document = new Document { Bytes = new MemoryStream(bytes) }
                            });

                        text = string.Join("\n", response.Blocks
                            .Where(b => b.BlockType == BlockType.LINE)
                            .Select(b => b.Text));
                    }
                    catch (AmazonTextractException ex)
                        when (ex.ErrorCode == "ProvisionedThroughputExceededException")
                    {
                        // Exponential backoff on rate limit — blocks the entire thread
                        await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, retryCount)));
                        retryCount++;
                    }
                }

                results[path] = text ?? string.Empty;
                var done = Interlocked.Increment(ref completed);
                progress?.Report((done, imagePaths.Count));
            }
            finally
            {
                semaphore.Release();
            }
        }));
    }

    await Task.WhenAll(tasks);
    return results.ToDictionary(x => x.Key, x => x.Value);
}
Imports Amazon.Textract
Imports Amazon.Textract.Model
Imports System.Collections.Concurrent
Imports System.IO
Imports System.Threading

Public Async Function ProcessImageBatchAsync(
    imagePaths As IReadOnlyList(Of String),
    Optional progress As IProgress(Of (Completed As Integer, Total As Integer)) = Nothing) As Task(Of Dictionary(Of String, String))

    Dim results As New ConcurrentDictionary(Of String, String)()
    Dim semaphore As New SemaphoreSlim(5) ' 5 concurrent — Textract default TPS limit
    Dim tasks As New List(Of Task)()
    Dim completed As Integer = 0

    For Each path In imagePaths
        Await semaphore.WaitAsync()

        tasks.Add(Task.Run(Async Function()
            Try
                Dim text As String = Nothing
                Dim retryCount As Integer = 0

                While text Is Nothing AndAlso retryCount < 3
                    Try
                        Dim bytes = Await File.ReadAllBytesAsync(path)
                        Dim response = Await _textractClient.DetectDocumentTextAsync(
                            New DetectDocumentTextRequest With {
                                .Document = New Document With {.Bytes = New MemoryStream(bytes)}
                            })

                        text = String.Join(vbLf, response.Blocks _
                            .Where(Function(b) b.BlockType = BlockType.LINE) _
                            .Select(Function(b) b.Text))
                    Catch ex As AmazonTextractException When ex.ErrorCode = "ProvisionedThroughputExceededException"
                        ' Exponential backoff on rate limit — blocks the entire thread
                        Await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, retryCount)))
                        retryCount += 1
                    End Try
                End While

                results(path) = If(text, String.Empty)
                Dim done = Interlocked.Increment(completed)
                If progress IsNot Nothing Then
                    progress.Report((done, imagePaths.Count))
                End If
            Finally
                semaphore.Release()
            End Try
        End Function))
    Next

    Await Task.WhenAll(tasks)
    Return results.ToDictionary(Function(x) x.Key, Function(x) x.Value)
End Function
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

// No rate limits, no semaphore, no retry logic — Parallel.ForEach saturates all cores

using IronOcr;
using System.Collections.Concurrent;

public Dictionary<string, string> ProcessImageBatch(
    IReadOnlyList<string> imagePaths,
    IProgress<(int Completed, int Total)> progress = null)
{
    var ocr = new IronTesseract();
    var results = new ConcurrentDictionary<string, string>();
    int completed = 0;

    Parallel.ForEach(imagePaths, path =>
    {
        var result = ocr.Read(path);
        results[path] = result.Text;

        var done = Interlocked.Increment(ref completed);
        progress?.Report((done, imagePaths.Count));
    });

    return results.ToDictionary(x => x.Key, x => x.Value);
}
// No rate limits, no semaphore, no retry logic — Parallel.ForEach saturates all cores

using IronOcr;
using System.Collections.Concurrent;

public Dictionary<string, string> ProcessImageBatch(
    IReadOnlyList<string> imagePaths,
    IProgress<(int Completed, int Total)> progress = null)
{
    var ocr = new IronTesseract();
    var results = new ConcurrentDictionary<string, string>();
    int completed = 0;

    Parallel.ForEach(imagePaths, path =>
    {
        var result = ocr.Read(path);
        results[path] = result.Text;

        var done = Interlocked.Increment(ref completed);
        progress?.Report((done, imagePaths.Count));
    });

    return results.ToDictionary(x => x.Key, x => x.Value);
}
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Threading

Public Function ProcessImageBatch(
    imagePaths As IReadOnlyList(Of String),
    Optional progress As IProgress(Of (Completed As Integer, Total As Integer)) = Nothing) As Dictionary(Of String, String)

    Dim ocr As New IronTesseract()
    Dim results As New ConcurrentDictionary(Of String, String)()
    Dim completed As Integer = 0

    Parallel.ForEach(imagePaths, Sub(path)
                                     Dim result = ocr.Read(path)
                                     results(path) = result.Text

                                     Dim done = Interlocked.Increment(completed)
                                     If progress IsNot Nothing Then
                                         progress.Report((done, imagePaths.Count))
                                     End If
                                 End Sub)

    Return results.ToDictionary(Function(x) x.Key, Function(x) x.Value)
End Function
$vbLabelText   $csharpLabel

SemaphoreSlim, tekrar döngüsü, üstel geri çekilme ve ProvisionedThroughputExceededException catch blokları kaldırılır. IronTesseract, iş parçacığı güvenlidir ve kilitler olmadan tam paralel yükü yöneten iş parçacıkları arasında paylaşılır tek bir örnektir. 8 çekirdekli bir makinede bu, 8 belgeyi yapılandırma gerektirmeksizin eşzamanlı işler; 32 çekirdekte, aynı anda 32. çok iş parçacıklı örnek tam deseni gösterir ve hız optimizasyonu kılavuzu, üretim hızına odaklanan dağıtımlar için motor yapılandırma ayarlarını kapsar.

AnalyzeDocument Form Çıkarımını Bölge Tabanlı CropRectangle OCR ile Değiştirme

Textract'ın AnalyzeDocument ile FORMS, KEY_VALUE_SET bloklarını RelationshipType.VALUE ilişkileri ile bağlanmış şekilde döndürür. Form alanı anahtar-değer çiftlerini yeniden oluşturmak için EntityTypes.Contains("KEY") ile filtreleme yapmanız, ardından VALUE ilişki kimliklerini takip etmeniz ve metni birleştirmek için alt WORD bloklarını getirmeniz gerekir. Alan konumlarının bilindiği sabit format formlar için IronOCR'ın CropRectangle, ilişki grafiği geçişi olmadan her alanı doğrudan çıkarır — ve sayfa başı maliyeti sıfırdır.

AWS Textract Yaklaşımı:

// FORMS mode costs $0.05/page — the most expensive Textract tier
// Relationship graph traversal required to reconstruct key-value pairs

using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<Dictionary<string, string>> ExtractInvoiceFieldsAsync(string imagePath)
{
    var bytes = File.ReadAllBytes(imagePath);

    // $0.05/page for FORMS analysis
    var response = await _textractClient.AnalyzeDocumentAsync(
        new AnalyzeDocumentRequest
        {
            Document = new Document { Bytes = new MemoryStream(bytes) },
            FeatureTypes = new List<string> { "FORMS" }
        });

    var allBlocks = response.Blocks;
    var fields = new Dictionary<string, string>();

    // Find KEY blocks only
    var keyBlocks = allBlocks.Where(b =>
        b.BlockType == BlockType.KEY_VALUE_SET &&
        b.EntityTypes?.Contains("KEY") == true);

    foreach (var keyBlock in keyBlocks)
    {
        // Assemble key text from CHILD WORD blocks
        var keyText = GetTextFromBlock(allBlocks, keyBlock);

        // Find associated VALUE block via VALUE relationship
        var valueBlockId = keyBlock.Relationships?
            .FirstOrDefault(r => r.Type == RelationshipType.VALUE)?
            .Ids.FirstOrDefault();

        if (valueBlockId == null) continue;

        var valueBlock = allBlocks.FirstOrDefault(b => b.Id == valueBlockId);
        if (valueBlock == null) continue;

        var valueText = GetTextFromBlock(allBlocks, valueBlock);
        fields[keyText.TrimEnd(':')] = valueText;
    }

    return fields;
}

private string GetTextFromBlock(IList<Block> allBlocks, Block block)
{
    if (block.Relationships == null) return string.Empty;

    var childWordIds = block.Relationships
        .Where(r => r.Type == RelationshipType.CHILD)
        .SelectMany(r => r.Ids);

    return string.Join(" ", allBlocks
        .Where(b => b.BlockType == BlockType.WORD && childWordIds.Contains(b.Id))
        .Select(b => b.Text));
}
// FORMS mode costs $0.05/page — the most expensive Textract tier
// Relationship graph traversal required to reconstruct key-value pairs

using Amazon.Textract;
using Amazon.Textract.Model;

public async Task<Dictionary<string, string>> ExtractInvoiceFieldsAsync(string imagePath)
{
    var bytes = File.ReadAllBytes(imagePath);

    // $0.05/page for FORMS analysis
    var response = await _textractClient.AnalyzeDocumentAsync(
        new AnalyzeDocumentRequest
        {
            Document = new Document { Bytes = new MemoryStream(bytes) },
            FeatureTypes = new List<string> { "FORMS" }
        });

    var allBlocks = response.Blocks;
    var fields = new Dictionary<string, string>();

    // Find KEY blocks only
    var keyBlocks = allBlocks.Where(b =>
        b.BlockType == BlockType.KEY_VALUE_SET &&
        b.EntityTypes?.Contains("KEY") == true);

    foreach (var keyBlock in keyBlocks)
    {
        // Assemble key text from CHILD WORD blocks
        var keyText = GetTextFromBlock(allBlocks, keyBlock);

        // Find associated VALUE block via VALUE relationship
        var valueBlockId = keyBlock.Relationships?
            .FirstOrDefault(r => r.Type == RelationshipType.VALUE)?
            .Ids.FirstOrDefault();

        if (valueBlockId == null) continue;

        var valueBlock = allBlocks.FirstOrDefault(b => b.Id == valueBlockId);
        if (valueBlock == null) continue;

        var valueText = GetTextFromBlock(allBlocks, valueBlock);
        fields[keyText.TrimEnd(':')] = valueText;
    }

    return fields;
}

private string GetTextFromBlock(IList<Block> allBlocks, Block block)
{
    if (block.Relationships == null) return string.Empty;

    var childWordIds = block.Relationships
        .Where(r => r.Type == RelationshipType.CHILD)
        .SelectMany(r => r.Ids);

    return string.Join(" ", allBlocks
        .Where(b => b.BlockType == BlockType.WORD && childWordIds.Contains(b.Id))
        .Select(b => b.Text));
}
Imports Amazon.Textract
Imports Amazon.Textract.Model
Imports System.IO
Imports System.Threading.Tasks

Public Class InvoiceFieldExtractor
    Private _textractClient As AmazonTextractClient

    Public Async Function ExtractInvoiceFieldsAsync(imagePath As String) As Task(Of Dictionary(Of String, String))
        Dim bytes = File.ReadAllBytes(imagePath)

        ' $0.05/page for FORMS analysis
        Dim response = Await _textractClient.AnalyzeDocumentAsync(
            New AnalyzeDocumentRequest With {
                .Document = New Document With {.Bytes = New MemoryStream(bytes)},
                .FeatureTypes = New List(Of String) From {"FORMS"}
            })

        Dim allBlocks = response.Blocks
        Dim fields As New Dictionary(Of String, String)()

        ' Find KEY blocks only
        Dim keyBlocks = allBlocks.Where(Function(b) 
                                            Return b.BlockType = BlockType.KEY_VALUE_SET AndAlso
                                                   b.EntityTypes?.Contains("KEY") = True
                                        End Function)

        For Each keyBlock In keyBlocks
            ' Assemble key text from CHILD WORD blocks
            Dim keyText = GetTextFromBlock(allBlocks, keyBlock)

            ' Find associated VALUE block via VALUE relationship
            Dim valueBlockId = keyBlock.Relationships?.
                FirstOrDefault(Function(r) r.Type = RelationshipType.VALUE)?.
                Ids.FirstOrDefault()

            If valueBlockId Is Nothing Then Continue For

            Dim valueBlock = allBlocks.FirstOrDefault(Function(b) b.Id = valueBlockId)
            If valueBlock Is Nothing Then Continue For

            Dim valueText = GetTextFromBlock(allBlocks, valueBlock)
            fields(keyText.TrimEnd(":"c)) = valueText
        Next

        Return fields
    End Function

    Private Function GetTextFromBlock(allBlocks As IList(Of Block), block As Block) As String
        If block.Relationships Is Nothing Then Return String.Empty

        Dim childWordIds = block.Relationships.
            Where(Function(r) r.Type = RelationshipType.CHILD).
            SelectMany(Function(r) r.Ids)

        Return String.Join(" ", allBlocks.
            Where(Function(b) b.BlockType = BlockType.WORD AndAlso childWordIds.Contains(b.Id)).
            Select(Function(b) b.Text))
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

// CropRectangle extracts each field zone directly — no relationship graph
// Works for any fixed-format form where field positions are known

using IronOcr;

// Define the field zones for your form template once
private static readonly Dictionary<string, CropRectangle> InvoiceFieldZones =
    new Dictionary<string, CropRectangle>
    {
        { "InvoiceNumber", new CropRectangle(450, 80,  300, 35) },
        { "InvoiceDate",   new CropRectangle(450, 120, 300, 35) },
        { "VendorName",    new CropRectangle(50,  160, 400, 35) },
        { "TotalAmount",   new CropRectangle(450, 680, 200, 35) },
        { "DueDate",       new CropRectangle(450, 720, 200, 35) }
    };

public Dictionary<string, string> ExtractInvoiceFields(string imagePath)
{
    var ocr = new IronTesseract();
    var fields = new Dictionary<string, string>();

    foreach (var zone in InvoiceFieldZones)
    {
        using var input = new OcrInput();
        input.LoadImage(imagePath, zone.Value); // load only the defined region

        var result = ocr.Read(input);
        fields[zone.Key] = result.Text.Trim();
    }

    return fields;
}
// CropRectangle extracts each field zone directly — no relationship graph
// Works for any fixed-format form where field positions are known

using IronOcr;

// Define the field zones for your form template once
private static readonly Dictionary<string, CropRectangle> InvoiceFieldZones =
    new Dictionary<string, CropRectangle>
    {
        { "InvoiceNumber", new CropRectangle(450, 80,  300, 35) },
        { "InvoiceDate",   new CropRectangle(450, 120, 300, 35) },
        { "VendorName",    new CropRectangle(50,  160, 400, 35) },
        { "TotalAmount",   new CropRectangle(450, 680, 200, 35) },
        { "DueDate",       new CropRectangle(450, 720, 200, 35) }
    };

public Dictionary<string, string> ExtractInvoiceFields(string imagePath)
{
    var ocr = new IronTesseract();
    var fields = new Dictionary<string, string>();

    foreach (var zone in InvoiceFieldZones)
    {
        using var input = new OcrInput();
        input.LoadImage(imagePath, zone.Value); // load only the defined region

        var result = ocr.Read(input);
        fields[zone.Key] = result.Text.Trim();
    }

    return fields;
}
Imports IronOcr

' CropRectangle extracts each field zone directly — no relationship graph
' Works for any fixed-format form where field positions are known

' Define the field zones for your form template once
Private Shared ReadOnly InvoiceFieldZones As New Dictionary(Of String, CropRectangle) From {
    {"InvoiceNumber", New CropRectangle(450, 80, 300, 35)},
    {"InvoiceDate", New CropRectangle(450, 120, 300, 35)},
    {"VendorName", New CropRectangle(50, 160, 400, 35)},
    {"TotalAmount", New CropRectangle(450, 680, 200, 35)},
    {"DueDate", New CropRectangle(450, 720, 200, 35)}
}

Public Function ExtractInvoiceFields(imagePath As String) As Dictionary(Of String, String)
    Dim ocr As New IronTesseract()
    Dim fields As New Dictionary(Of String, String)()

    For Each zone In InvoiceFieldZones
        Using input As New OcrInput()
            input.LoadImage(imagePath, zone.Value) ' load only the defined region

            Dim result = ocr.Read(input)
            fields(zone.Key) = result.Text.Trim()
        End Using
    Next

    Return fields
End Function
$vbLabelText   $csharpLabel

KEY_VALUE_SET blok filtreleme, RelationshipType.VALUE geçişi ve GetTextFromBlock yardımcı kaldırılır. Her alan, yalnızca onu içeren piksel bölgesini okur — ne eksik ne fazla. bölge tabanlı OCR kılavuzu CropRectangle koordinatları ve şablon ölçümlerinden nasıl bölgeler tanımlanacağını kapsar. Fatura özgü iş akışları için fatura OCR blog yazısı ve makbuz tarama öğretici, tam alan çıkarma hatlarını gösterir.

AWS Textract API'den IronOCR Eşleştirme Referansı

AWS Textract IronOCR Karşılığı
AmazonTextractClient IronTesseract
AmazonS3Client Gerekli değil
DetectDocumentTextRequest OcrInput ile input.LoadImage()
DetectDocumentTextResponse OcrResult
AnalyzeDocumentRequest (TABLOLAR/FORMLAR) OcrInput isteğe bağlı CropRectangle
StartDocumentTextDetectionRequest OcrInput ile input.LoadPdf() — eş zamanlı, iş başlatması yok
GetDocumentTextDetectionRequest Uygulanamaz — sonuçlar anında
Document.Bytes input.LoadImage(byteArray) veya input.LoadImage(stream)
S3Object (belge hazırlama) Dosya yolu veya akış — aşamalandırma gerektirmez
Block (BlockType.LINE) result.Lines (yazılı koleksiyon)
Block (BlockType.WORD) result.Words (yazılı koleksiyon)
Block (BlockType.TABLE) result.Words koordinat yakınlığına göre gruplandırılmış
Block (BlockType.KEY_VALUE_SET) CropRectangle alan başına bölge çıkarması
Block.Confidence word.Confidence / result.Confidence
Block.Geometry.BoundingBox word.X, word.Y, word.Width, word.Height
RelationshipType.CHILD geçişi Türlenmiş sonuç nesnelerinde doğrudan özelliğe erişim
JobStatus.IN_PROGRESS Uygulanamaz — eşzamansız durum yok
JobStatus.SUCCEEDED Uygulanamaz — eşzamanlı dönüş
response.NextToken (sayfalama) Uygulanamaz — sonuçlar sayfalandırılmamış
ProvisionedThroughputExceededException Uygulanamaz — TPS sınırları yok
AccessDeniedException Uygun değil — kimlik zinciri yok
input.LoadImageFrames() Çok çerçeveli TIFF doğrudan destek( Textract'a eşdeğer yok)
result.SaveAsSearchablePdf() Aranabilir PDF çıktısı (Textract'a eşdeğer yok)

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

Problem 1: Yeni Dağıtım Ortamlarında Kimlik Bilgileri Yanlış Yapılandırılmış

AWS Textract: AmazonTextractClient yapıcısı kimlik bilgilerini bir zincirden çözümler: ortam değişkenleri, ~/.aws/credentials, EC2 örnek profili, ECS görev rolü. Yeni bir Docker konteynerında veya CI ortamında, eğer bunlardan hiçbiri yapılandırılmamışsa, istemci hata vermeden oluşturulur ama her API çağrısı AmazonClientException: No credentials specified fırlatır. Başarısızlık, çalışma zamanına kadar görünmez.

Çözüm: Kimlik bilgisi zincirini tamamen kaldırın. Yapılandırılması daha basit ve yönetilecek IAM izinleri olmayan bir çevresel değişkenden IronOCR lisans anahtarını ayarlayın:

// Single environment variable — no IAM, no rotation, no chain resolution
var key = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
if (string.IsNullOrEmpty(key))
    throw new InvalidOperationException("IRONOCR_LICENSE environment variable is not set");

IronOcr.License.LicenseKey = key;
// Single environment variable — no IAM, no rotation, no chain resolution
var key = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
if (string.IsNullOrEmpty(key))
    throw new InvalidOperationException("IRONOCR_LICENSE environment variable is not set");

IronOcr.License.LicenseKey = key;
Imports System

' Single environment variable — no IAM, no rotation, no chain resolution
Dim key As String = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
If String.IsNullOrEmpty(key) Then
    Throw New InvalidOperationException("IRONOCR_LICENSE environment variable is not set")
End If

IronOcr.License.LicenseKey = key
$vbLabelText   $csharpLabel

Problem 2: Tüm Kod Tabanında Asenkron Çağrı Yerleri

AWS Textract: Tüm SDK asenkron olduğu için (DetectDocumentTextAsync, StartDocumentTextDetectionAsync, GetDocumentTextDetectionAsync), tüm Textract çağrı yerleri async Task<t> çağrı yığınına yayar. IronOCR'un eşzamanlı API'sine geçiş, her yerde bir karar gerektirir.

Çözüm: Arka plan işleme servisleri ve denetleyici eylemleri için, IronOCR'un eşzamanlı çağrıları, arka plan iş parçacıklarında güvenlidir. Mevcut çağrı zincirinin asenkron kalması gerektiğinde sadece Task.Run ile sarın:

// If the call site must remain async (e.g., an ASP.NET controller action):
public async Task<IActionResult> ProcessUpload(IFormFile file)
{
    using var ms = new MemoryStream();
    await file.CopyToAsync(ms);

    // Offload synchronous OCR to thread pool — keeps controller non-blocking
    var text = await Task.Run(() =>
    {
        var ocr = new IronTesseract();
        using var input = new OcrInput();
        input.LoadImage(ms.ToArray());
        return ocr.Read(input).Text;
    });

    return Ok(text);
}
// If the call site must remain async (e.g., an ASP.NET controller action):
public async Task<IActionResult> ProcessUpload(IFormFile file)
{
    using var ms = new MemoryStream();
    await file.CopyToAsync(ms);

    // Offload synchronous OCR to thread pool — keeps controller non-blocking
    var text = await Task.Run(() =>
    {
        var ocr = new IronTesseract();
        using var input = new OcrInput();
        input.LoadImage(ms.ToArray());
        return ocr.Read(input).Text;
    });

    return Ok(text);
}
Imports System.IO
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc

Public Class YourController
    Inherits Controller

    ' If the call site must remain async (e.g., an ASP.NET controller action):
    Public Async Function ProcessUpload(file As IFormFile) As Task(Of IActionResult)
        Using ms As New MemoryStream()
            Await file.CopyToAsync(ms)

            ' Offload synchronous OCR to thread pool — keeps controller non-blocking
            Dim text = Await Task.Run(Function()
                                          Dim ocr = New IronTesseract()
                                          Using input As New OcrInput()
                                              input.LoadImage(ms.ToArray())
                                              Return ocr.Read(input).Text
                                          End Using
                                      End Function)

            Return Ok(text)
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Zaten arka plan iş parçacıklarında çalışan yığın işlemcileri ve arka plan hizmetleri için ocr.Read()'yi eşzamanlı olarak çağırın — Task.Run, bu bağlamlarda yarar sağlamadan ek yük ekler. asenkron OCR kılavuzu, önerilen desenleri kapsar.

Problem 3: Kod İsrafı Aracılığıyla Dağıtılan S3 Kova Temizleme Mantığı

AWS Textract: Textract işlemesi için S3'e yükleme yapan herhangi bir kod, iş tamamlandıktan sonra S3'den silmelidir. Bu temizlik sık sık finally bloklarında yaşar ve bazen hata yollarında atlanır, depolama maliyetlerini biriktiren yetim nesneler oluşturur. Göç sırasında, S3 temizleme kodu, OCR ile kavramsal olarak ilişkili olmadığı için göz ardı etmek kolaydır.

Çözüm:IronOCR için eşdeğer yoktur, tüm S3 yükleme ve temizleme desenleri. Tüm PutObjectAsync, DeleteObjectAsync ve S3 ile ilgili try/finally bloklarını tamamen silin.IronOCR yerel yollardan veya akışlardan doğrudan okur:

// Before: upload → job → poll → extract → cleanup (50+ lines)
// After: two lines, no cleanup required

using var input = new OcrInput();
input.LoadPdf(localPdfPath);
var text = new IronTesseract().Read(input).Text;
// Before: upload → job → poll → extract → cleanup (50+ lines)
// After: two lines, no cleanup required

using var input = new OcrInput();
input.LoadPdf(localPdfPath);
var text = new IronTesseract().Read(input).Text;
Imports IronOcr

Using input As New OcrInput()
    input.LoadPdf(localPdfPath)
    Dim text As String = New IronTesseract().Read(input).Text
End Using
$vbLabelText   $csharpLabel

Göç sonrası S3 aşamalama kovasını devre dışı bırakın. PDF giriş kılavuzu ve akış girdi kılavuzu, S3 aşamalandırılmış belge erişiminin yerine geçen her girdi desenini kapsar.

Problem 4: Blok Graf Geçiş Kodu için Doğrudan Eşdeğer Yok

AWS Textract: Block.Relationships üzerinden tablo hücrelerini, form alanlarını veya paragraf gruplamalarını yeniden oluşturmak için kod geçiş yapmak üzere en çok zaman alan koddur. Bire bir değiştirme yoktur, çünkü IronOCR bir ilişki grafı yerine türlendirilmiş koleksiyonlar döndürür.

Çözüm: Her geçiş desenini uygun türlendirilmiş özellik ile değiştirin. İlişki ID aramaları doğrudan özellik erişimine dönüşür:

// Before: filter by BlockType + traverse relationship IDs
var paragraphText = string.Join(" ", allBlocks
    .Where(b => b.BlockType == BlockType.WORD &&
                childIds.Contains(b.Id))
    .Select(b => b.Text));

// After: direct paragraph text (no filtering, no relationship lookup)
foreach (var page in result.Pages)
    foreach (var para in page.Paragraphs)
        Console.WriteLine(para.Text); // already assembled
// Before: filter by BlockType + traverse relationship IDs
var paragraphText = string.Join(" ", allBlocks
    .Where(b => b.BlockType == BlockType.WORD &&
                childIds.Contains(b.Id))
    .Select(b => b.Text));

// After: direct paragraph text (no filtering, no relationship lookup)
foreach (var page in result.Pages)
    foreach (var para in page.Paragraphs)
        Console.WriteLine(para.Text); // already assembled
' Before: filter by BlockType + traverse relationship IDs
Dim paragraphText As String = String.Join(" ", allBlocks _
    .Where(Function(b) b.BlockType = BlockType.WORD AndAlso _
                childIds.Contains(b.Id)) _
    .Select(Function(b) b.Text))

' After: direct paragraph text (no filtering, no relationship lookup)
For Each page In result.Pages
    For Each para In page.Paragraphs
        Console.WriteLine(para.Text) ' already assembled
    Next
Next
$vbLabelText   $csharpLabel

BlockType.CELL ve ColumnIndex özelliklerine bağlı tablo yeniden yapılandırması için, result.Words üzerine kelime koordinat gruplamaları kullanın. tablo okuma kılavuzu, koordinat bazlı yaklaşımı kapsar.

Problem 5: ProvisionedThroughputExceededException Yakalama Blokları

AWS Textract: Sağlam yığın işleme kodu AmazonTextractException ile ErrorCode == "ProvisionedThroughputExceededException" yakalar ve geri çekilme ile tekrar uygular. Bu hata kodu,IronOCR eşdeğeri olmayan Textract özel bir kavramıdır.

Çözüm: Tüm ProvisionedThroughputExceededException catch bloklarını silin. IronOCR'un TPS sınırı yoktur. Tamamen Parallel.ForEach ile kısıtlanmış yığın modelini değiştirin:

// Delete: SemaphoreSlim, retry loops, ProvisionedThroughputExceededException handlers
// Replace with:
Parallel.ForEach(imagePaths, path =>
{
    var result = new IronTesseract().Read(path);
    results[path] = result.Text;
});
// Delete: SemaphoreSlim, retry loops, ProvisionedThroughputExceededException handlers
// Replace with:
Parallel.ForEach(imagePaths, path =>
{
    var result = new IronTesseract().Read(path);
    results[path] = result.Text;
});
Imports System.Threading.Tasks

Parallel.ForEach(imagePaths, Sub(path)
    Dim result = New IronTesseract().Read(path)
    results(path) = result.Text
End Sub)
$vbLabelText   $csharpLabel

Problem 6: Yapıcı İle İç İçe Geçirilmiş Bölge Kapsamı Ayarı

AWS Textract: new AmazonTextractClient(Amazon.RegionEndpoint.USEast1) bir bölgeyi sabitler. Çoklu bölge dağıtımları, birden fazla istemci örneği veya dinamik bölge seçimi gerektirir. Textract, yeni bölgelerde destek eklediğinde kodun güncellenmesi gerekir.

Çözüm: IronOCR'un bölge kavramı yok. Tüm Amazon.RegionEndpoint referanslarını kaldırın. IronTesseract yapıcısı ağ yapılandırması almaz — işleme yereldir. Her bölge kendi hesabının içinde çalıştığı AWS altyapısındaki çoklu bölge dağıtımları için,IronOCR örnekleri hiçbir çapraz bölge çağrısı olmaksızın belgeleri kendi hesap sınırları dâhilinde işler.

AWS Textract Göç Kontrol Listesi

Öncesi-Geçiş

Kod tabanındaki tüm Textract ve S3 SDK kullanımını denetleyin:

grep -rn "Amazon.Textract\|AmazonTextractClient\|DetectDocumentText" --include="*.cs" .
grep -rn "StartDocumentTextDetection\|GetDocumentTextDetection\|JobStatus" --include="*.cs" .
grep -rn "AmazonS3Client\|PutObjectRequest\|DeleteObjectAsync" --include="*.cs" .
grep -rn "BlockType\|RelationshipType\|KEY_VALUE_SET" --include="*.cs" .
grep -rn "ProvisionedThroughputExceededException\|AmazonTextractException" --include="*.cs" .
grep -rn "AWSSDK\|Amazon.RegionEndpoint" --include="*.csproj" .
grep -rn "Amazon.Textract\|AmazonTextractClient\|DetectDocumentText" --include="*.cs" .
grep -rn "StartDocumentTextDetection\|GetDocumentTextDetection\|JobStatus" --include="*.cs" .
grep -rn "AmazonS3Client\|PutObjectRequest\|DeleteObjectAsync" --include="*.cs" .
grep -rn "BlockType\|RelationshipType\|KEY_VALUE_SET" --include="*.cs" .
grep -rn "ProvisionedThroughputExceededException\|AmazonTextractException" --include="*.cs" .
grep -rn "AWSSDK\|Amazon.RegionEndpoint" --include="*.csproj" .
SHELL

Aşağıdakilerini yazmadan önce envanterini yapın:

  • AmazonTextractClient içeren tüm dosyaları sayın — her biri bir değiştirme hedefidir
  • Tüm AnalyzeDocument çağrı yerlerini listeleyin — TABLES, FORMS veya her ikisinin de kullanılıp kullanılmadığını not edin
  • Tüm asenkron polling döngülerini (do { await Task.Delay } while JobStatus == IN_PROGRESS) belirleyin
  • Tüm S3 temizleme finally bloklarını bulun — bunlar tümden silinir, yerine konulmaz
  • Tüm ProvisionedThroughputExceededException catch bloklarını sayın — silinir, yerine konulmaz
  • Tüm BlockType.TABLE, BlockType.CELL, BlockType.KEY_VALUE_SET geçiş mantığını not edin — her biri yapılandırılmış çıktı değişimi gerektirir

Kod Geçişi

  1. Tüm .csproj dosyalarından AWSSDK.Textract, AWSSDK.S3 ve AWSSDK.Core'yi kaldırın
  2. OCR gerçekleştiren her projede dotnet add package IronOcr çalıştırın
  3. Uygulama başlangıcında bir kez IronOcr.License.LicenseKey = ... ekleyin (Program.cs veya eşdeğeri)
  4. Tüm using Amazon.Textract;, using Amazon.Textract.Model;, using Amazon.S3;, using Amazon.Runtime; ifadelerini kaldırın
  5. Daha önce Textract ad alanlarını içe aktaran her dosyaya using IronOcr; ekleyin
  6. Tüm AmazonTextractClient yapıcı çağrılarını new IronTesseract() ile değiştirin
  7. Tüm AmazonS3Client örneklenmesini ve tüm PutObjectAsync / DeleteObjectAsync çağrılarını doğrudan dosya yolu veya akış okumaları ile değiştirin
  8. Tüm DetectDocumentTextAsync çağrılarını değiştirin: var text = ocr.Read(path).Text
  9. Tüm StartDocumentTextDetectionAsync ve polling döngülerini input.LoadPdf(path) ve ocr.Read(input) ile değiştirin
  10. Tüm çok çerçeveli TIFF hatlarını (TIFF → PDF → S3 → asenkron) input.LoadImageFrames(tiffPath) ile değiştirin
  11. BlockType.LINE / BlockType.WORD filtre zincirlerini result.Lines / result.Words ile değiştirin
  12. BlockType.KEY_VALUE_SET ilişki geçişlerini CropRectangle bölge çıkarmaları ile değiştirin
  13. Tüm ProvisionedThroughputExceededException catch bloklarını ve SemaphoreSlim kısıtlamalarını silin
  14. Paylaşılan bir IronTesseract örneği kullanarak kısıtlanmış yığın desenlerini Parallel.ForEach ile değiştirin
  15. Tüm AWS kimlik bilgisi ortam değişkeni yapılandırmalarını dağıtım manifestolarından ve CI hatlarından kaldırın
  16. Tüm işleme kodu taşındı ve doğrulandıktan sonra S3 evreleme kovalıklarını devre dışı bırakın

Geçiş Sonrası

  • Uygulamanın yalnızca IRONOCR_LICENSE ayarlı olarak temiz bir şekilde başlatıldığından ve tüm AWS ortam değişkenlerinin kaldırıldığından emin olun
  • Textract tarafından önceden işlenmiş aynı örnek resimlerde OCR çalıştırın ve çıkarılan metni doğruluk açısından karşılaştırın
  • Çok sayfalı bir PDF'yi doğrudan işleyin ve tüm sayfaların S3 veya async anket olmadan çıkarıldığını doğrulayın
  • Çok çerçeveli bir TIFF'i işleyin ve sayfa sayısının aynı belge için Textract'ın çıktısıyla eşleştiğini doğrulayın
  • 50'den fazla resim seti ile yığın işlemesini test edin ve hiçbir ProvisionedThroughputExceededException eşdeğerinin oluşmadığını doğrulayın
  • İnternet çıkışı olmayan bir Docker konteynerında uygulamayı çalıştırın ve OCR'nin başarıyla tamamlandığını doğrulayın
  • Aranabilir PDF çıktısının Adobe Reader'da doğru açıldığını ve tam metin aranabilir olduğunu doğrulayın
  • Dağıtım ortamından AWS_ACCESS_KEY_ID ve AWS_SECRET_ACCESS_KEY 'i kaldırmanın hiçbir şeyi bozmadığını doğrulayın
  • Bilinen Textract çıktılarına karşı form veya fatura çıkarma iş akışlarını test ederek alan doğruluğunu doğrulayın
  • Temsilci bir belge seti için işleme gecikmesini ölçün ve en az 5 saniyelik anket bekleme süresinin ortadan kalktığını doğrulayın

IronOCR'a Geçişin Ana Faydaları

Tek Bir NuGet Paketi için Altyapı Konsolidasyonu. Üç AWS SDK paketi, yaşam döngüsü politikalarına sahip bir S3 kovalığı, her bir dağıtım ortamında IAM rolleri ve AWS kimlik bilgileri rotasyon prosedürleri bir NuGet paketiyle değiştirilmiştir. .csproj değişikliği dotnet remove package AWSSDK.Textract tarafından dotnet add package IronOcr takip edilir. AWS kimlik bilgisi yönetiminin tüm aşağı akış sonuçları — güvenlik denetimleri, rotasyon programları, ortam değişken hijyeni, Docker sırları yapılandırması — onunla ortadan kaybolur.

Öngörülebilir Toplam Sahip Olma Maliyeti. Sayfa başına faturalandırma modeli, belge hacmiyle orantılı olarak değişen maliyetler üretir. IronOCR'ye geçtikten sonra, işlenen ek sayfa başına maliyet, hacimden bağımsız olarak sıfırdır. Bir ekip, Textract AnalyzeDocument oranında ayda 200.000 sayfa işlem yaparken, yalnızca OCR için yılda 36.000 dolar harcar. $2,999 olan IronOCR Enterprise lisansı, faturalandırmadan kaçınmanın ilk 31 gününde bu maliyeti karşılar. Tam kademeli detaylar ve SaaS yeniden dağıtım şartları için IronOCR lisans sayfasını inceleyin.

Eşzamanlı İşleme, Beş Aşamalı Async Karmaşıklığını Ortadan Kaldırır. S3 yükleme, iş başlatma, anket döngüleri, sayfalı sonuç toplama ve temizleme sona erdirme bloku Textract PDF hattında beş bağımsız hata modu temsil eder. Göçten sonra, bir PDF iki satırda okunur. Hata işleme, ocr.Read() çağrısı etrafında tek bir try/catch'e indirgenir. Polling zaman aşımı mantığı, do/while JobStatus == IN_PROGRESS döngüsü, nextToken sayfalama akümülatörü — bu kavramların hiçbiri IronOCR kod tabanında mevcut değil. Bakım yükü, kaldırılan kodla orantılı olarak düşer.

Tam Dağıtım Esnekliği. Textract her OCR çağrısında internet erişimi gerektirir. IronOCR, sadece kurulum sırasında NuGet paketini indirmek için internet erişimi gerektirir. Bundan sonra, izole ağlarda, dışa yönelik kurallar olmayan Docker konteynerlerinde, yerel sunucularda ve Textract erişimi olmayan AWS EC2 örneklerinde çalışır. Windows Server'da üretimde çalışan aynı ikili, Linux konteynerında da çalışır. Önceden Textract kullanımı engellenmiş konteynerize ortamlar için belirli yapılandırmayı Docker dağıtım kılavuzu ve Linux dağıtım kılavuzu kapsar.

Veri Egemenliği Mimarisi, Yapılandırma Değil. IronOCR'nin devre dışı bırakılacak ağ iletim modu yoktur — yerel işleme tek moddur.IronOCR üzerinden işlenen belgeler asla ana bilgisayarı terk etmez. PHI işleyen sağlık uygulamaları, CUI işleyen savunma uygulamaları ve ödeme kartı görüntüleri işleyen finansal uygulamalar için bu, BAA pazarlığı gerektirmeyen, bölgesel veri ikametgahı yapılandırması gerekmeyen ve Amazon'un veri işleme politikalarının incelenmesini gerektirmeyen bir uyum duruşudur. Uyum kapsamı kendi altyapınızın sınırıdır; zaten kontrol ettiğiniz sınır. Bir uyum incelemesini tamamlayan ekipler için tam özellik özeti ve dağıtım belgeleri IronOCR ürün sayfasında bulunmaktadır.

Belge Kalite Kontrolü İçin Yapılandırılabilir Ön İşleme. Textract'ın dahili ön işlemesi erişilemez veya yapılandırılamaz. Tarama sonucunun kötü olduğu durumda, tek çare çıktıyı kabul etmek veya yeniden taramak. IronOCR, tam ön işleme hattını ortaya çıkarır: Deskew(), DeNoise(), Contrast(), Binarize(), Sharpen(), Scale(), Dilate(), Erode() ve DeepCleanBackgroundNoise(). Zor taramalarda düşük güven sonuçları nedeniyle Textract'tan belgeleri taşıyan ekipler, döndürme, gürültü, düşük kontrast veya yetersiz çözünürlük gibi belirli kusura uyarlanmış filtrelerle kök nedeni doğrudan ele alabilirler. Mevcut filtreleri ve uygun kullanım durumlarını belgeleyen ön işleme özellikleri sayfasını ve görüntü kalitesi düzeltme kılavuzunu inceleyin.

Lütfen dikkate alınAWS Textract, PDFSharp, Tesseract ve iText ilgili sahiplerinin tescilli markalarıdır. Bu site, Amazon Web Services, Google, empira Software GmbH veya iText Group ile ilişkili değildir, onaylanmış veya desteklenmemektedir. Tüm ürün adları, logolar ve markalar, ilgili sahiplerinin mülküdür. 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

Amazon Textract'tan neden 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.

Amazon Textract'tan IronOCR'a geçişteki ana kod değişiklikleri nelerdir?

Amazon Textract 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, Amazon Textract'ın 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, Amazon Textract'ın 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.

Amazon Textract'tan IronOCR'a geçiş, dağıtım altyapısında değişiklikler gerektirir mi?

IronOCR, Amazon Textract'tan 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 Amazon Textract 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ı, Amazon Textract'tan 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.

Amazon Textract'tan 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