Altbilgi içeriğine atla
VIDEOLAR

Windows'ta Tesseract OCR'ı C# ile Nasıl Yüklenir?

Bu kılavuz, .NET geliştiricilerini Google Cloud Vision'ı IronOCR ile değiştirmede birdenbire yerinde bir OCR motoru olarak geçirir. Yayınlanan dört yapısal değişimi kapsar: kimlik bilgisi kaldırma, Protobuf açıklama işleme yedeklemesi, toplu açıklama basitleştirme ve çok sayfalı belge işleme.

Google Cloud VisionOCR'den Neden Geçiş Yapılmalı

Taşınma kararı neredeyse her zaman iki farkındalıktan biriyle başlar: bir uyum denetimi bulut belge iletimini engeller ya da GCP kimlik bilgilerini, GCS kovalarını, asenkron anketleri ve görüntü başına ücretlendirmeyi yönetmenin operasyonel yüzeyi OCR'nin kendisinden daha pahalı hale gelir.

Servis Hesabı JSON Anahtar Yaşam Döngüsü. Uygulamanızın her dağıtımı — geliştirme makinesi, CI/CD hattı, hazırlık sunucusu, üretim sunucusu, Docker konteyneri, Kubernetes pod'u — aynı servis hesabı JSON anahtar dosyasını gerektirir. Dosya, bir RSA özel anahtarı içerir. Kaynak kontrole asla girmemeli, bir program çerçevesinde döndürülmeli, dosya sistemi izinleri ile korunmalı ve döndürülme gerçekleştiğinde tüm ortamlarda aynı anda güncellenmelidir. Bir tehlikeye atılmış anahtar, GCP Konsolunda manuel olarak iptal edilene kadar API erişimi verir. IronOCR, bu tüm operasyon yüzeyini uygulama başlangıcında bir kez ayarlanmış tek bir lisans anahtar dizisi ile değiştirir.

Ölçekli Hızlandırılmış Faturalandırma. 1.000 resim başına $1.50 ve PDF sayfası başına $0.0015 maliyetler, geliştirme sırasında görünmez, ancak üretimde can acıtıcıdır. Ayda 200.000 sayfa işleyeyen bir belge işleme hattı, yalnızca API ücretlerinde ayda $300 maliyete mal olur, GCS depolama maliyetlerinden ve çıkış maliyetlerinden önce. Bu $300 her ay süresiz yinelenir. IronOCR'nin süresiz lisansı, OCR'yi ölçüm bazlı işletim giderinden ikinci veya üçüncü yılda çalışması bedava olan sabit bir sermaye kalemi haline dönüştürür.

GCS Asenkron PDF Hattı. Google Cloud Vision, PDF'leri doğrudan API girdisi olarak kabul etmez. Tam boru hattı, ikinci bir NuGet paketini (Google.Cloud.Storage.V1), sağlanmış bir GCS bucket'ını, asenkron bir yüklemeyi, AsyncBatchAnnotateFilesAsync çağrısını, bir anket döngüsünü, GCS'den JSON çıktı analizini ve bir temizleme adımını gerektirir. Bu boru hattı, herhangi bir metin çıkarılmadan önce 50'den fazla kod satırını kapsar. IronOCR, dış bağımlılıklar olmadan senkron şekilde üç satırda bir PDF'yi okur.

Protobuf Sembol Birleştirme. DOCUMENT_TEXT_DETECTION yanıtı, Metin'leri bir Protobuf Sayfaları, Bloklar, Paragraflar, Kelimeler ve Semboller hiyerarşisi içerisinde sembol düzeyinde saklar. Paragraf metinlerini okumak, beş iç içe döngü boyunca yineleme yapılmasını ve .SelectMany(w => w.Symbols).Select(s => s.Text) çağrısının yapılmasını gerektirir.IronOCR paragraf metnini paragraph.Text olarak döndürür — türü belirli bir dizge özelliği.

Varsayılan Olarak Dakikada 1.800 İstek Limiti. Varsayılan kotanın üzerindeki toplu işler, boru hattını her aşım başına 60 saniye durduran StatusCode.ResourceExhausted yanıtlarını alır. Kota artırımı, bir GCP Konsolu isteği ve Google'ın onayını gerektirir. IronOCR, yerel olarak mevcut CPU çekirdekleri hızında işleme yapar — yönetilecek bir kota yok, onay alacak bir şey yok, ve oran sınırlama için herhangi bir tekrar mantığı gerekmiyor.

Çevrimdışı veya İzole Edilmiş Destek Yok. Google Cloud Vision, Google'ın uç noktalarına internet bağlantısı gerektirir. İzole edilmiş ağlar, sınıflandırılmış veri merkezleri ve endüstriyel kontrol sistemleri, herhangi bir mimari karmaşıklık seviyesinde kullanılamaz. IronOCR, başlangıç ​​lisans doğrulaması sonrasında sıfır dışa giden ağ bağlantısı ile çalışır.

Temel Sorun

Google Cloud Vision, OCR kodunun ilk satırı çalıştırılmadan önce disk üzerinde bir JSON anahtar dosyası gerektirir:

// Google Cloud Vision: JSON key file deployed to every server before this line works
// GOOGLE_APPLICATION_CREDENTIALS="/etc/secrets/service-account.json" must be set
// Key contains RSA private key — rotate manually, revoke if compromised
_client = ImageAnnotatorClient.Create();
var image = Image.FromFile("document.jpg");
var response = _client.DetectText(image);   // document leaves your infrastructure
string text = response[0].Description;
// Google Cloud Vision: JSON key file deployed to every server before this line works
// GOOGLE_APPLICATION_CREDENTIALS="/etc/secrets/service-account.json" must be set
// Key contains RSA private key — rotate manually, revoke if compromised
_client = ImageAnnotatorClient.Create();
var image = Image.FromFile("document.jpg");
var response = _client.DetectText(image);   // document leaves your infrastructure
string text = response[0].Description;
' Google Cloud Vision: JSON key file deployed to every server before this line works
' GOOGLE_APPLICATION_CREDENTIALS="/etc/secrets/service-account.json" must be set
' Key contains RSA private key — rotate manually, revoke if compromised
_client = ImageAnnotatorClient.Create()
Dim image = Image.FromFile("document.jpg")
Dim response = _client.DetectText(image)   ' document leaves your infrastructure
Dim text As String = response(0).Description
$vbLabelText   $csharpLabel

IronOCR, bir dize ile başlar ve tamamen yerel makinede çalışır:

// IronOCR: one string at startup, no key files, no environment variables
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read("document.jpg").Text;  // local, no cloud
// IronOCR: one string at startup, no key files, no environment variables
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read("document.jpg").Text;  // local, no cloud
Imports IronOcr

' IronOCR: one string at startup, no key files, no environment variables
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read("document.jpg").Text ' local, no cloud
$vbLabelText   $csharpLabel

IronOCR veGoogle Cloud VisionOCR: Özellik Karşılaştırması

Aşağıdaki tablo, geçiş için iş durumu oluşturan ekipler için özellikleri doğrudan eşler.

Özellik Google Cloud Vision OCR IronOCR
İşleme yeri Google Cloud (uzaktan) Yerinde (yerel)
Kimlik Doğrulama Servis hesabı JSON anahtarı + env değişken Lisans anahtarı dizesi
PDF girdisi GCS'ye Yükleme + asenkron API input.LoadPdf() doğrudan
Şifre korumalı PDF Desteklenmiyor LoadPdf(path, Password: "...")
Çok sayfalı TIFF girişi Sınırlı input.LoadImageFrames()
Aranabilir PDF çıktısı Mevcut değil result.SaveAsSearchablePdf()
Yapılandırılmış veri erişimi Protobuf: Sayfalar > Bloklar > Paragraflar > Kelimeler > Semboller result.Paragraphs, result.Lines, result.Words (türlenmiş .NET nesneleri)
Paragraf metin özelliği Hayır — sembol birleştirmesi gerekiyor paragraph.Text doğrudan özellik
Güven skoru Sembol başına (döngü gerekiyor) result.Confidence, word.Confidence
Otomatik görüntü ön işleme Hiçbiri (ML bunu ele alır) Deskew, DeNoise, Karşıtlık, İkili, Keskinleştir
Bölge bazlı OCR Yerel kırpma yok CropRectangle üzerinde OcrInput
Barkod okuma Ayrı API özelliği ocr.Configuration.ReadBarCodes = true
Oran sınırlamaları 1.800 istek/dakika varsayılan Yok (CPU'ya bağlı)
Çevrimdışı / izole Hayır Evet
Belge başına maliyet 1.000 resim başına $1.50; $0.0015/PDF sayfa Hiçbiri (süresiz lisans)
Desteklenen diller ~50 125+
FedRAMP yetkilendirmesi Yetkilendirilmemiş Uygulanmaz (yerinde)
HIPAA uyumluluk yolu İş Ortağı Sözleşmesi gerekli Üçüncü taraf veri işleme yok
.NET Framework desteği .NET Standard 2.0+ .NET Framework 4.6.2+ ve .NET 5/6/7/8/9
NuGet paketleri gerekli Google.Cloud.Vision.V1 + Google.Cloud.Storage.V1 IronOcr yalnızca
Fiyatlandırma modeli Başına istek ölçümlü faturalandırma Perpetual ($999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited)

Hızlı Başlangıç:Google Cloud VisionOCR'den IronOCR'ye Geçiş

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

Google Cloud paketlerini kaldırın:

dotnet remove package Google.Cloud.Vision.V1
dotnet remove package Google.Cloud.Storage.V1
dotnet remove package Google.Cloud.Vision.V1
dotnet remove package Google.Cloud.Storage.V1
SHELL

NuGet paketi sayfasından IronOCR yükleyin:

dotnet add package IronOcr

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

Google Cloud ad alanlarınıIronOCR ad alanı ile değiştirin:

// Before (Google Cloud Vision)
using Google.Cloud.Vision.V1;
using Google.Cloud.Storage.V1;
using Google.Protobuf;
using Grpc.Core;

// After (IronOCR)
using IronOcr;
// Before (Google Cloud Vision)
using Google.Cloud.Vision.V1;
using Google.Cloud.Storage.V1;
using Google.Protobuf;
using Grpc.Core;

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

Adım 3: Lisansa İzin Verin

Lisans başlatma işlemini uygulama başlangıcında, herhangi bir IronTesseract örneği oluşturulmadan önce bir kere ekleyin:

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

Üretimde, anahtarı bir ortam değişkeninden veya sır yöneticiden okuyun:

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

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

Kod Göç Örnekleri

Servis Hesabı Kimlik Bilgileri Yapılandırmasını Ortadan Kaldırma

Google Cloud Vision istemci başlatması tek bir satır gibi görünse de, kapsamlı ön gereklilik altyapısı gerektirir. Projeye katılan her geliştirici, her dağıtım ortamı ve her CI/CD hattının yapılandırıcı tamamlanmadan ve hata atmadan önce tam kimlik bilgisi yapılandırmasına sahip olması gerekir.

Google Cloud Vision Yaklaşımı:

using Google.Cloud.Vision.V1;

// Prerequisites before this class can be instantiated:
// 1. GCP project created and Vision API enabled in GCP Console
// 2. Service account created with roles/cloudvision.user IAM role
// 3. JSON key file downloaded to every server that runs this code
// 4. GOOGLE_APPLICATION_CREDENTIALS env var pointing to the JSON file
// 5. JSON file excluded from source control via .gitignore
// 6. Key rotation schedule established (recommended: 90 days)
// 7. Separate credentials per environment (dev/staging/prod)

public class DocumentOcrService
{
    private readonly ImageAnnotatorClient _client;
    private readonly string _projectId;

    public DocumentOcrService(string projectId)
    {
        _projectId = projectId;
        // Throws RpcException(StatusCode.PermissionDenied) if any prerequisite is missing
        _client = ImageAnnotatorClient.Create();
    }

    public string ReadDocument(string imagePath)
    {
        var image = Image.FromFile(imagePath);
        var response = _client.DetectText(image);
        return response.Count > 0 ? response[0].Description : string.Empty;
    }
}
using Google.Cloud.Vision.V1;

// Prerequisites before this class can be instantiated:
// 1. GCP project created and Vision API enabled in GCP Console
// 2. Service account created with roles/cloudvision.user IAM role
// 3. JSON key file downloaded to every server that runs this code
// 4. GOOGLE_APPLICATION_CREDENTIALS env var pointing to the JSON file
// 5. JSON file excluded from source control via .gitignore
// 6. Key rotation schedule established (recommended: 90 days)
// 7. Separate credentials per environment (dev/staging/prod)

public class DocumentOcrService
{
    private readonly ImageAnnotatorClient _client;
    private readonly string _projectId;

    public DocumentOcrService(string projectId)
    {
        _projectId = projectId;
        // Throws RpcException(StatusCode.PermissionDenied) if any prerequisite is missing
        _client = ImageAnnotatorClient.Create();
    }

    public string ReadDocument(string imagePath)
    {
        var image = Image.FromFile(imagePath);
        var response = _client.DetectText(image);
        return response.Count > 0 ? response[0].Description : string.Empty;
    }
}
Imports Google.Cloud.Vision.V1

' Prerequisites before this class can be instantiated:
' 1. GCP project created and Vision API enabled in GCP Console
' 2. Service account created with roles/cloudvision.user IAM role
' 3. JSON key file downloaded to every server that runs this code
' 4. GOOGLE_APPLICATION_CREDENTIALS env var pointing to the JSON file
' 5. JSON file excluded from source control via .gitignore
' 6. Key rotation schedule established (recommended: 90 days)
' 7. Separate credentials per environment (dev/staging/prod)

Public Class DocumentOcrService
    Private ReadOnly _client As ImageAnnotatorClient
    Private ReadOnly _projectId As String

    Public Sub New(projectId As String)
        _projectId = projectId
        ' Throws RpcException(StatusCode.PermissionDenied) if any prerequisite is missing
        _client = ImageAnnotatorClient.Create()
    End Sub

    Public Function ReadDocument(imagePath As String) As String
        Dim image = Image.FromFile(imagePath)
        Dim response = _client.DetectText(image)
        Return If(response.Count > 0, response(0).Description, String.Empty)
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;

// Prerequisites: set the license key once at app startup
//HayırJSON files, no environment variables beyond the key, no GCP Console configuration
//Hayırkey rotation, no IAM roles, no per-environment credential sets

public class DocumentOcrService
{
    private readonly IronTesseract _ocr;

    public DocumentOcrService()
    {
        // IronTesseract is ready immediately — no external validation required
        _ocr = new IronTesseract();
    }

    public string ReadDocument(string imagePath)
    {
        return _ocr.Read(imagePath).Text;
    }
}
using IronOcr;

// Prerequisites: set the license key once at app startup
//HayırJSON files, no environment variables beyond the key, no GCP Console configuration
//Hayırkey rotation, no IAM roles, no per-environment credential sets

public class DocumentOcrService
{
    private readonly IronTesseract _ocr;

    public DocumentOcrService()
    {
        // IronTesseract is ready immediately — no external validation required
        _ocr = new IronTesseract();
    }

    public string ReadDocument(string imagePath)
    {
        return _ocr.Read(imagePath).Text;
    }
}
Imports IronOcr

' Prerequisites: set the license key once at app startup
' HayırJSON files, no environment variables beyond the key, no GCP Console configuration
' Hayırkey rotation, no IAM roles, no per-environment credential sets

Public Class DocumentOcrService
    Private ReadOnly _ocr As IronTesseract

    Public Sub New()
        ' IronTesseract is ready immediately — no external validation required
        _ocr = New IronTesseract()
    End Sub

    Public Function ReadDocument(imagePath As String) As String
        Return _ocr.Read(imagePath).Text
    End Function
End Class
$vbLabelText   $csharpLabel

İşlevsel fark somuttur:Google Cloud Visionçalışma zamanında beş RpcException kategorisi oluşturur — PermissionDenied, ResourceExhausted, Unavailable, DeadlineExceeded ve Unauthenticated — her biri farklı bir altyapı arızası modunu temsil eder. IronOCR'nin hata modları IOException (dosya bulunamadı veya kilitli) ve OcrException (işleme hatası) 'dır. IronTesseract kurulum kılavuzu için yapılandırma seçenekleri ve IronOCR ürün sayfasına bakın.

Çoklu Özellik Türleriyle Toplu Açıklama İsteklerini Değiştirme

Google Cloud Vision, birden fazla görüntüyü tek bir BatchAnnotateImagesRequest içine toplu işlemeyi destekler, her görüntü Feature türleri listesiyle yapılandırılmıştır. Bu model, bir aramada hem TEXT_DETECTION hem de DOCUMENT_TEXT_DETECTION sonuçlarını toplamak gerektiğinde veya bir gezinmesiz yükleme overhead'ini en aza indirmek için birçok görüntü gönderildiğinde kullanılır. Protobuf yanıtı, her AnnotateImageResponse'i kendi orijinal isteğine indeksle eşleştirmesini gerektirir.

Google Cloud Vision Yaklaşımı:

using Google.Cloud.Vision.V1;
using System.Collections.Generic;

public class BatchAnnotationService
{
    private readonly ImageAnnotatorClient _client;

    public BatchAnnotationService()
    {
        _client = ImageAnnotatorClient.Create();
    }

    public List<string> BatchAnnotateImages(string[] imagePaths)
    {
        // Build one request per image with TEXT_DETECTION feature
        var requests = imagePaths.Select(path => new AnnotateImageRequest
        {
            Image = Image.FromFile(path),
            Features =
            {
                new Feature { Type = Feature.Types.Type.TextDetection },
                new Feature { Type = Feature.Types.Type.DocumentTextDetection }
            }
        }).ToList();

        // Single round-trip for all images in the batch
        var batchResponse = _client.BatchAnnotateImages(requests);

        // Match responses back to requests by index
        var results = new List<string>();
        for (int i = 0; i < batchResponse.Responses.Count; i++)
        {
            var response = batchResponse.Responses[i];
            if (response.Error != null)
            {
                // Per-item error in batch — must handle individually
                results.Add($"Error on {imagePaths[i]}: {response.Error.Message}");
                continue;
            }

            // Prefer DOCUMENT_TEXT_DETECTION full text if available
            var fullText = response.FullTextAnnotation?.Text
                ?? response.TextAnnotations.FirstOrDefault()?.Description
                ?? string.Empty;
            results.Add(fullText);
        }

        return results;
    }
}
using Google.Cloud.Vision.V1;
using System.Collections.Generic;

public class BatchAnnotationService
{
    private readonly ImageAnnotatorClient _client;

    public BatchAnnotationService()
    {
        _client = ImageAnnotatorClient.Create();
    }

    public List<string> BatchAnnotateImages(string[] imagePaths)
    {
        // Build one request per image with TEXT_DETECTION feature
        var requests = imagePaths.Select(path => new AnnotateImageRequest
        {
            Image = Image.FromFile(path),
            Features =
            {
                new Feature { Type = Feature.Types.Type.TextDetection },
                new Feature { Type = Feature.Types.Type.DocumentTextDetection }
            }
        }).ToList();

        // Single round-trip for all images in the batch
        var batchResponse = _client.BatchAnnotateImages(requests);

        // Match responses back to requests by index
        var results = new List<string>();
        for (int i = 0; i < batchResponse.Responses.Count; i++)
        {
            var response = batchResponse.Responses[i];
            if (response.Error != null)
            {
                // Per-item error in batch — must handle individually
                results.Add($"Error on {imagePaths[i]}: {response.Error.Message}");
                continue;
            }

            // Prefer DOCUMENT_TEXT_DETECTION full text if available
            var fullText = response.FullTextAnnotation?.Text
                ?? response.TextAnnotations.FirstOrDefault()?.Description
                ?? string.Empty;
            results.Add(fullText);
        }

        return results;
    }
}
Imports Google.Cloud.Vision.V1
Imports System.Collections.Generic
Imports System.Linq

Public Class BatchAnnotationService
    Private ReadOnly _client As ImageAnnotatorClient

    Public Sub New()
        _client = ImageAnnotatorClient.Create()
    End Sub

    Public Function BatchAnnotateImages(imagePaths As String()) As List(Of String)
        ' Build one request per image with TEXT_DETECTION feature
        Dim requests = imagePaths.Select(Function(path) New AnnotateImageRequest With {
            .Image = Image.FromFile(path),
            .Features = {
                New Feature With {.Type = Feature.Types.Type.TextDetection},
                New Feature With {.Type = Feature.Types.Type.DocumentTextDetection}
            }
        }).ToList()

        ' Single round-trip for all images in the batch
        Dim batchResponse = _client.BatchAnnotateImages(requests)

        ' Match responses back to requests by index
        Dim results = New List(Of String)()
        For i As Integer = 0 To batchResponse.Responses.Count - 1
            Dim response = batchResponse.Responses(i)
            If response.Error IsNot Nothing Then
                ' Per-item error in batch — must handle individually
                results.Add($"Error on {imagePaths(i)}: {response.Error.Message}")
                Continue For
            End If

            ' Prefer DOCUMENT_TEXT_DETECTION full text if available
            Dim fullText = If(response.FullTextAnnotation?.Text, response.TextAnnotations.FirstOrDefault()?.Description, String.Empty)
            results.Add(fullText)
        Next

        Return results
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

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

public class BatchAnnotationService
{
    public List<string> BatchAnnotateImages(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<int, string>();

        // Parallel processing — no batch size limit, no network round-trips
        Parallel.For(0, imagePaths.Length, i =>
        {
            var ocr = new IronTesseract();   // thread-safe: one instance per thread
            results[i] = ocr.Read(imagePaths[i]).Text;
        });

        // Reconstruct in original order
        return Enumerable.Range(0, imagePaths.Length)
            .Select(i => results[i])
            .ToList();
    }

    public OcrResult BatchAsDocument(string[] imagePaths)
    {
        // Load all images into a single OcrInput for combined document output
        using var input = new OcrInput();
        foreach (var path in imagePaths)
            input.LoadImage(path);

        return new IronTesseract().Read(input);
    }
}
using IronOcr;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;

public class BatchAnnotationService
{
    public List<string> BatchAnnotateImages(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<int, string>();

        // Parallel processing — no batch size limit, no network round-trips
        Parallel.For(0, imagePaths.Length, i =>
        {
            var ocr = new IronTesseract();   // thread-safe: one instance per thread
            results[i] = ocr.Read(imagePaths[i]).Text;
        });

        // Reconstruct in original order
        return Enumerable.Range(0, imagePaths.Length)
            .Select(i => results[i])
            .ToList();
    }

    public OcrResult BatchAsDocument(string[] imagePaths)
    {
        // Load all images into a single OcrInput for combined document output
        using var input = new OcrInput();
        foreach (var path in imagePaths)
            input.LoadImage(path);

        return new IronTesseract().Read(input);
    }
}
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Threading.Tasks

Public Class BatchAnnotationService
    Public Function BatchAnnotateImages(imagePaths As String()) As List(Of String)
        Dim results = New ConcurrentDictionary(Of Integer, String)()

        ' Parallel processing — no batch size limit, no network round-trips
        Parallel.For(0, imagePaths.Length, Sub(i)
                                               Dim ocr = New IronTesseract() ' thread-safe: one instance per thread
                                               results(i) = ocr.Read(imagePaths(i)).Text
                                           End Sub)

        ' Reconstruct in original order
        Return Enumerable.Range(0, imagePaths.Length) _
            .Select(Function(i) results(i)) _
            .ToList()
    End Function

    Public Function BatchAsDocument(imagePaths As String()) As OcrResult
        ' Load all images into a single OcrInput for combined document output
        Using input As New OcrInput()
            For Each path In imagePaths
                input.LoadImage(path)
            Next
            Return New IronTesseract().Read(input)
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR, toplu işlemi CPU çekirdekleri boyunca ağ yükü olmaksızın paralel hale getirir. Geri çekilme sınırı, yanıt-indeks eşleştirmesi ve ağ veya kimlik bilgisi hataları için madde başına hata işleme yok. Birden çok görüntüyü tek bir mantıksal belgede birleştiren işler için — bireysel JPEG'ler olarak gönderilen taranmış çok sayfalı formlar gibi — BatchAsDocument tüm görüntüleri bir OcrInput içerisine yükler ve OcrResult birleştirilmiş bir dönüş yapar, her bir giriş görüntüsüne indekslenmiş result.Pages ile. Çoklu iş parçacığı örneği, paralel işleme için performans ölçütlerini gösterir.

Protobuf Kelime Düzeyi Ek Açıklama Çıkarımı Geçişi

Google Cloud Vision'ın kelime düzeyi sınırlayıcı kutusu ve güven verileri, tam Protobuf hiyerarşisini dolaşmayı gerektirir: Sayfalar, ardından Bloklar, ardından Paragraflar, ardından Kelimeler, ardından Semboller. Kelime metnini çıkarmak, her Kelime'den Sembolleri birleştirmeyi gerektirir — Word nesnesi doğrudan .Text özelliğine sahip değildir. Sınır kutusu koordinatları, ayrı X, Y, Genislik, Yükseklik alanları yerine bir BoundingPoly ve Vertices listesinin bir bileşeni olarak saklanır.

Google Cloud Vision Yaklaşımı:

using Google.Cloud.Vision.V1;
using System.Collections.Generic;

public record WordAnnotation(string Text, int X, int Y, int Width, int Height, float Confidence);

public class WordLevelExtractor
{
    private readonly ImageAnnotatorClient _client;

    public WordLevelExtractor()
    {
        _client = ImageAnnotatorClient.Create();
    }

    public List<WordAnnotation> ExtractWordAnnotations(string imagePath)
    {
        var image = Image.FromFile(imagePath);
        var annotation = _client.DetectDocumentText(image);

        var words = new List<WordAnnotation>();

        // Navigate: Pages -> Blocks -> Paragraphs -> Words
        foreach (var page in annotation.Pages)
        {
            foreach (var block in page.Blocks)
            {
                foreach (var paragraph in block.Paragraphs)
                {
                    foreach (var word in paragraph.Words)
                    {
                        // Word.Text does not exist — must concatenate Symbols
                        var text = string.Concat(word.Symbols.Select(s => s.Text));

                        // BoundingPoly has Vertices, not X/Y/Width/Height
                        var vertices = word.BoundingBox.Vertices;
                        int x = vertices[0].X;
                        int y = vertices[0].Y;
                        int width = vertices.Count > 1 ? vertices[1].X - vertices[0].X : 0;
                        int height = vertices.Count > 2 ? vertices[2].Y - vertices[0].Y : 0;

                        words.Add(new WordAnnotation(text, x, y, width, height, word.Confidence));
                    }
                }
            }
        }

        return words;
    }
}
using Google.Cloud.Vision.V1;
using System.Collections.Generic;

public record WordAnnotation(string Text, int X, int Y, int Width, int Height, float Confidence);

public class WordLevelExtractor
{
    private readonly ImageAnnotatorClient _client;

    public WordLevelExtractor()
    {
        _client = ImageAnnotatorClient.Create();
    }

    public List<WordAnnotation> ExtractWordAnnotations(string imagePath)
    {
        var image = Image.FromFile(imagePath);
        var annotation = _client.DetectDocumentText(image);

        var words = new List<WordAnnotation>();

        // Navigate: Pages -> Blocks -> Paragraphs -> Words
        foreach (var page in annotation.Pages)
        {
            foreach (var block in page.Blocks)
            {
                foreach (var paragraph in block.Paragraphs)
                {
                    foreach (var word in paragraph.Words)
                    {
                        // Word.Text does not exist — must concatenate Symbols
                        var text = string.Concat(word.Symbols.Select(s => s.Text));

                        // BoundingPoly has Vertices, not X/Y/Width/Height
                        var vertices = word.BoundingBox.Vertices;
                        int x = vertices[0].X;
                        int y = vertices[0].Y;
                        int width = vertices.Count > 1 ? vertices[1].X - vertices[0].X : 0;
                        int height = vertices.Count > 2 ? vertices[2].Y - vertices[0].Y : 0;

                        words.Add(new WordAnnotation(text, x, y, width, height, word.Confidence));
                    }
                }
            }
        }

        return words;
    }
}
Imports Google.Cloud.Vision.V1
Imports System.Collections.Generic
Imports System.Linq

Public Class WordAnnotation
    Public Property Text As String
    Public Property X As Integer
    Public Property Y As Integer
    Public Property Width As Integer
    Public Property Height As Integer
    Public Property Confidence As Single

    Public Sub New(text As String, x As Integer, y As Integer, width As Integer, height As Integer, confidence As Single)
        Me.Text = text
        Me.X = x
        Me.Y = y
        Me.Width = width
        Me.Height = height
        Me.Confidence = confidence
    End Sub
End Class

Public Class WordLevelExtractor
    Private ReadOnly _client As ImageAnnotatorClient

    Public Sub New()
        _client = ImageAnnotatorClient.Create()
    End Sub

    Public Function ExtractWordAnnotations(imagePath As String) As List(Of WordAnnotation)
        Dim image = Image.FromFile(imagePath)
        Dim annotation = _client.DetectDocumentText(image)

        Dim words As New List(Of WordAnnotation)()

        ' Navigate: Pages -> Blocks -> Paragraphs -> Words
        For Each page In annotation.Pages
            For Each block In page.Blocks
                For Each paragraph In block.Paragraphs
                    For Each word In paragraph.Words
                        ' Word.Text does not exist — must concatenate Symbols
                        Dim text = String.Concat(word.Symbols.Select(Function(s) s.Text))

                        ' BoundingPoly has Vertices, not X/Y/Width/Height
                        Dim vertices = word.BoundingBox.Vertices
                        Dim x As Integer = vertices(0).X
                        Dim y As Integer = vertices(0).Y
                        Dim width As Integer = If(vertices.Count > 1, vertices(1).X - vertices(0).X, 0)
                        Dim height As Integer = If(vertices.Count > 2, vertices(2).Y - vertices(0).Y, 0)

                        words.Add(New WordAnnotation(text, x, y, width, height, word.Confidence))
                    Next
                Next
            Next
        Next

        Return words
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;
using System.Collections.Generic;

public record WordAnnotation(string Text, int X, int Y, int Width, int Height, double Confidence);

public class WordLevelExtractor
{
    private readonly IronTesseract _ocr;

    public WordLevelExtractor()
    {
        _ocr = new IronTesseract();
    }

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

        // Words are a flat collection — no hierarchy traversal, no symbol concatenation
        return result.Words.Select(w => new WordAnnotation(
            Text:       w.Text,         // direct string property
            X:          w.X,
            Y:          w.Y,
            Width:      w.Width,
            Height:     w.Height,
            Confidence: w.Confidence    // double, no conversion needed
        )).ToList();
    }
}
using IronOcr;
using System.Collections.Generic;

public record WordAnnotation(string Text, int X, int Y, int Width, int Height, double Confidence);

public class WordLevelExtractor
{
    private readonly IronTesseract _ocr;

    public WordLevelExtractor()
    {
        _ocr = new IronTesseract();
    }

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

        // Words are a flat collection — no hierarchy traversal, no symbol concatenation
        return result.Words.Select(w => new WordAnnotation(
            Text:       w.Text,         // direct string property
            X:          w.X,
            Y:          w.Y,
            Width:      w.Width,
            Height:     w.Height,
            Confidence: w.Confidence    // double, no conversion needed
        )).ToList();
    }
}
Imports IronOcr
Imports System.Collections.Generic

Public Class WordAnnotation
    Public Property Text As String
    Public Property X As Integer
    Public Property Y As Integer
    Public Property Width As Integer
    Public Property Height As Integer
    Public Property Confidence As Double

    Public Sub New(text As String, x As Integer, y As Integer, width As Integer, height As Integer, confidence As Double)
        Me.Text = text
        Me.X = x
        Me.Y = y
        Me.Width = width
        Me.Height = height
        Me.Confidence = confidence
    End Sub
End Class

Public Class WordLevelExtractor
    Private ReadOnly _ocr As IronTesseract

    Public Sub New()
        _ocr = New IronTesseract()
    End Sub

    Public Function ExtractWordAnnotations(imagePath As String) As List(Of WordAnnotation)
        Dim result = _ocr.Read(imagePath)

        ' Words are a flat collection — no hierarchy traversal, no symbol concatenation
        Return result.Words.Select(Function(w) New WordAnnotation(
            Text:=w.Text,         ' direct string property
            X:=w.X,
            Y:=w.Y,
            Width:=w.Width,
            Height:=w.Height,
            Confidence:=w.Confidence    ' double, no conversion needed
        )).ToList()
    End Function
End Class
$vbLabelText   $csharpLabel

Google Cloud Vision sürümündeki sembol birleştirme döngüsü bir tasarım seçimi değildir — Protobuf şemasının bir gereğidir. Word.Text, yanıt nesnesinde bir özellik değildir. Kelime düzeyindeki API'yi kullanan her ekip eşdeğer bir döngü yazar. IronOCR'nin OcrResult.Words koleksiyonu Text, X, Y, Width, Height ve Confidence'i birinci sınıf özellikler olarak ortaya çıkarır. Sonuçları okuma kılavuzu, her ayrıntı seviyesinde mevcut olan tam özellik setini belgeler.

Aynı anda birden fazla sayfalı TIFF İşleme işlemi ile Aranabilir PDF Çıkışı

Google Cloud Vision çok sayfalı TIFF dosyalarını, ayrı ayrı bir API çağrısı gerektiren bir dizi görüntü olarak ele alır. Tüm kareler için yapılandırılmış çıktı döndüren tek bir API çağrısı bulunmamaktadır.Google Cloud Visionsonuçlarından aranabilir bir PDF üretmek, ayrı bir PDF oluşturma kütüphanesi gerektirir - API yalnızca metin döndürür.

Google Cloud Vision Yaklaşımı:

using Google.Cloud.Vision.V1;
using System.Collections.Generic;
using System.Drawing;          // for TIFF frame extraction
using System.Drawing.Imaging;

public class TiffProcessingService
{
    private readonly ImageAnnotatorClient _client;

    public TiffProcessingService()
    {
        _client = ImageAnnotatorClient.Create();
    }

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

        // Load TIFF and extract frames manually using System.Drawing
        using var tiff = System.Drawing.Image.FromFile(tiffPath);
        var frameDimension = new FrameDimension(tiff.FrameDimensionsList[0]);
        int frameCount = tiff.GetFrameCount(frameDimension);

        for (int i = 0; i < frameCount; i++)
        {
            tiff.SelectActiveFrame(frameDimension, i);

            // Save each frame to a temp file — Vision API does not accept TIFF frames directly
            var tempPath = Path.Combine(Path.GetTempPath(), $"tiff-frame-{i}.jpg");
            tiff.Save(tempPath, ImageFormat.Jpeg);

            // One API call per frame — each call = one unit of quota
            var visionImage = Google.Cloud.Vision.V1.Image.FromFile(tempPath);
            var response = _client.DetectText(visionImage);
            pageTexts.Add(response.FirstOrDefault()?.Description ?? string.Empty);

            File.Delete(tempPath);
        }

        // Producing a searchable PDF requires a separate library (e.g., iTextSharp)
        //Google Cloud Visionhas no PDF output capability
        return pageTexts;
    }
}
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
using System.Drawing;          // for TIFF frame extraction
using System.Drawing.Imaging;

public class TiffProcessingService
{
    private readonly ImageAnnotatorClient _client;

    public TiffProcessingService()
    {
        _client = ImageAnnotatorClient.Create();
    }

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

        // Load TIFF and extract frames manually using System.Drawing
        using var tiff = System.Drawing.Image.FromFile(tiffPath);
        var frameDimension = new FrameDimension(tiff.FrameDimensionsList[0]);
        int frameCount = tiff.GetFrameCount(frameDimension);

        for (int i = 0; i < frameCount; i++)
        {
            tiff.SelectActiveFrame(frameDimension, i);

            // Save each frame to a temp file — Vision API does not accept TIFF frames directly
            var tempPath = Path.Combine(Path.GetTempPath(), $"tiff-frame-{i}.jpg");
            tiff.Save(tempPath, ImageFormat.Jpeg);

            // One API call per frame — each call = one unit of quota
            var visionImage = Google.Cloud.Vision.V1.Image.FromFile(tempPath);
            var response = _client.DetectText(visionImage);
            pageTexts.Add(response.FirstOrDefault()?.Description ?? string.Empty);

            File.Delete(tempPath);
        }

        // Producing a searchable PDF requires a separate library (e.g., iTextSharp)
        //Google Cloud Visionhas no PDF output capability
        return pageTexts;
    }
}
Imports Google.Cloud.Vision.V1
Imports System.Collections.Generic
Imports System.Drawing          ' for TIFF frame extraction
Imports System.Drawing.Imaging
Imports System.IO

Public Class TiffProcessingService
    Private ReadOnly _client As ImageAnnotatorClient

    Public Sub New()
        _client = ImageAnnotatorClient.Create()
    End Sub

    Public Function ProcessMultiPageTiff(tiffPath As String) As List(Of String)
        Dim pageTexts As New List(Of String)()

        ' Load TIFF and extract frames manually using System.Drawing
        Using tiff As System.Drawing.Image = System.Drawing.Image.FromFile(tiffPath)
            Dim frameDimension As New FrameDimension(tiff.FrameDimensionsList(0))
            Dim frameCount As Integer = tiff.GetFrameCount(frameDimension)

            For i As Integer = 0 To frameCount - 1
                tiff.SelectActiveFrame(frameDimension, i)

                ' Save each frame to a temp file — Vision API does not accept TIFF frames directly
                Dim tempPath As String = Path.Combine(Path.GetTempPath(), $"tiff-frame-{i}.jpg")
                tiff.Save(tempPath, ImageFormat.Jpeg)

                ' One API call per frame — each call = one unit of quota
                Dim visionImage As Google.Cloud.Vision.V1.Image = Google.Cloud.Vision.V1.Image.FromFile(tempPath)
                Dim response = _client.DetectText(visionImage)
                pageTexts.Add(If(response.FirstOrDefault()?.Description, String.Empty))

                File.Delete(tempPath)
            Next
        End Using

        ' Producing a searchable PDF requires a separate library (e.g., iTextSharp)
        ' Google Cloud Vision has no PDF output capability
        Return pageTexts
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

using IronOcr;

public class TiffProcessingService
{
    private readonly IronTesseract _ocr;

    public TiffProcessingService()
    {
        _ocr = new IronTesseract();
    }

    public string ProcessMultiPageTiff(string tiffPath)
    {
        using var input = new OcrInput();
        // LoadImageFrames handles all TIFF frames in one call — no temp files, no frame loop
        input.LoadImageFrames(tiffPath);

        var result = _ocr.Read(input);
        return result.Text;
    }

    public void ProcessMultiPageTiffToSearchablePdf(string tiffPath, string outputPdfPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);

        var result = _ocr.Read(input);

        //Google Cloud Visionhas no equivalent — this single call produces a searchable PDF
        result.SaveAsSearchablePdf(outputPdfPath);
    }

    public void ProcessLowQualityTiff(string tiffPath, string outputPdfPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);

        // Preprocessing before OCR improves accuracy on degraded scans
        input.Deskew();
        input.DeNoise();
        input.Contrast();

        var result = _ocr.Read(input);
        result.SaveAsSearchablePdf(outputPdfPath);
    }
}
using IronOcr;

public class TiffProcessingService
{
    private readonly IronTesseract _ocr;

    public TiffProcessingService()
    {
        _ocr = new IronTesseract();
    }

    public string ProcessMultiPageTiff(string tiffPath)
    {
        using var input = new OcrInput();
        // LoadImageFrames handles all TIFF frames in one call — no temp files, no frame loop
        input.LoadImageFrames(tiffPath);

        var result = _ocr.Read(input);
        return result.Text;
    }

    public void ProcessMultiPageTiffToSearchablePdf(string tiffPath, string outputPdfPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);

        var result = _ocr.Read(input);

        //Google Cloud Visionhas no equivalent — this single call produces a searchable PDF
        result.SaveAsSearchablePdf(outputPdfPath);
    }

    public void ProcessLowQualityTiff(string tiffPath, string outputPdfPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);

        // Preprocessing before OCR improves accuracy on degraded scans
        input.Deskew();
        input.DeNoise();
        input.Contrast();

        var result = _ocr.Read(input);
        result.SaveAsSearchablePdf(outputPdfPath);
    }
}
Imports IronOcr

Public Class TiffProcessingService
    Private ReadOnly _ocr As IronTesseract

    Public Sub New()
        _ocr = New IronTesseract()
    End Sub

    Public Function ProcessMultiPageTiff(tiffPath As String) As String
        Using input As New OcrInput()
            ' LoadImageFrames handles all TIFF frames in one call — no temp files, no frame loop
            input.LoadImageFrames(tiffPath)

            Dim result = _ocr.Read(input)
            Return result.Text
        End Using
    End Function

    Public Sub ProcessMultiPageTiffToSearchablePdf(tiffPath As String, outputPdfPath As String)
        Using input As New OcrInput()
            input.LoadImageFrames(tiffPath)

            Dim result = _ocr.Read(input)

            ' Google Cloud Vision has no equivalent — this single call produces a searchable PDF
            result.SaveAsSearchablePdf(outputPdfPath)
        End Using
    End Sub

    Public Sub ProcessLowQualityTiff(tiffPath As String, outputPdfPath As String)
        Using input As New OcrInput()
            input.LoadImageFrames(tiffPath)

            ' Preprocessing before OCR improves accuracy on degraded scans
            input.Deskew()
            input.DeNoise()
            input.Contrast()

            Dim result = _ocr.Read(input)
            result.SaveAsSearchablePdf(outputPdfPath)
        End Using
    End Sub
End Class
$vbLabelText   $csharpLabel

Google Cloud Vision sürümü, kare çıkarımı için System.Drawing gerektirir, geçici JPEG dosyaları diskte yazılır, her kare başına bir API çağrısı (kare sayısına orantılı kota tüketimi) ve düz metnin ötesinde herhangi bir çıktı üretmek için ayrı bir PDF kütüphanesi gerektirir. IronOCR, çok çerçeveli TIFF'leri LoadImageFrames aracılığıyla yerel olarak işler, tüm kareleri tek bir Read çağrısında işler ve SaveAsSearchablePdf aracılığıyla aranabilir PDF çıktısı üretir. Tarayıcıydan gelen arşivlenmiş TIFF belgeleri için, ProcessLowQualityTiff'ndeki ön işleme boru hattı, tek bir geçişte en yaygın kalite sorunlarını çözer. Tam API için TIFF ve GIF girdisi ve aranabilir PDF çıktısı sekmelerine bakın.

İlerlemenin Takip Edildiği Kota Sınırlamalı Toplu Geçiş

Üretim ölçeğinde, Google Cloud Vision'ın dakikada 1.800 istek için varsayılan kotası, ya sınırlamayı ya da katlanarak geri çekilmeyle yeniden deneme mantığını gerektirir. 5.000 belgeyi tek seferde işlemek, kotayı birden fazla kez aşacaktır. Her kota aşımı, hattı zorunlu 60 saniyelik bir bekleme süresi için engeller. IronOCR'nin hız sınırlandırması yoktur — boru hattı sadece CPU çekirdekleri ve mevcut iş parçacıkları ile sınırlıdır.

Google Cloud Vision Yaklaşımı:

using Google.Cloud.Vision.V1;
using Grpc.Core;
using System.Collections.Generic;

public class ThrottledBatchProcessor
{
    private readonly ImageAnnotatorClient _client;
    private const int MaxRequestsPerMinute = 1800;
    private const int RetryDelayMs = 60_000;

    public ThrottledBatchProcessor()
    {
        _client = ImageAnnotatorClient.Create();
    }

    public async Task<Dictionary<string, string>> ProcessWithThrottlingAsync(
        string[] imagePaths,
        IProgress<(int completed, int total)> progress)
    {
        var results = new Dictionary<string, string>();
        int completed = 0;

        foreach (var path in imagePaths)
        {
            bool succeeded = false;
            while (!succeeded)
            {
                try
                {
                    var image = Google.Cloud.Vision.V1.Image.FromFile(path);
                    var response = _client.DetectText(image);
                    results[path] = response.FirstOrDefault()?.Description ?? string.Empty;
                    succeeded = true;
                }
                catch (RpcException ex) when (ex.StatusCode == StatusCode.ResourceExhausted)
                {
                    // Rate limit exceeded — wait and retry
                    await Task.Delay(RetryDelayMs);
                }
            }

            progress.Report((++completed, imagePaths.Length));
        }

        return results;
    }
}
using Google.Cloud.Vision.V1;
using Grpc.Core;
using System.Collections.Generic;

public class ThrottledBatchProcessor
{
    private readonly ImageAnnotatorClient _client;
    private const int MaxRequestsPerMinute = 1800;
    private const int RetryDelayMs = 60_000;

    public ThrottledBatchProcessor()
    {
        _client = ImageAnnotatorClient.Create();
    }

    public async Task<Dictionary<string, string>> ProcessWithThrottlingAsync(
        string[] imagePaths,
        IProgress<(int completed, int total)> progress)
    {
        var results = new Dictionary<string, string>();
        int completed = 0;

        foreach (var path in imagePaths)
        {
            bool succeeded = false;
            while (!succeeded)
            {
                try
                {
                    var image = Google.Cloud.Vision.V1.Image.FromFile(path);
                    var response = _client.DetectText(image);
                    results[path] = response.FirstOrDefault()?.Description ?? string.Empty;
                    succeeded = true;
                }
                catch (RpcException ex) when (ex.StatusCode == StatusCode.ResourceExhausted)
                {
                    // Rate limit exceeded — wait and retry
                    await Task.Delay(RetryDelayMs);
                }
            }

            progress.Report((++completed, imagePaths.Length));
        }

        return results;
    }
}
Imports Google.Cloud.Vision.V1
Imports Grpc.Core
Imports System.Collections.Generic
Imports System.Threading.Tasks

Public Class ThrottledBatchProcessor
    Private ReadOnly _client As ImageAnnotatorClient
    Private Const MaxRequestsPerMinute As Integer = 1800
    Private Const RetryDelayMs As Integer = 60000

    Public Sub New()
        _client = ImageAnnotatorClient.Create()
    End Sub

    Public Async Function ProcessWithThrottlingAsync(
        imagePaths As String(),
        progress As IProgress(Of (completed As Integer, total As Integer))) As Task(Of Dictionary(Of String, String))

        Dim results As New Dictionary(Of String, String)()
        Dim completed As Integer = 0

        For Each path In imagePaths
            Dim succeeded As Boolean = False
            While Not succeeded
                Try
                    Dim image = Google.Cloud.Vision.V1.Image.FromFile(path)
                    Dim response = _client.DetectText(image)
                    results(path) = If(response.FirstOrDefault()?.Description, String.Empty)
                    succeeded = True
                Catch ex As RpcException When ex.StatusCode = StatusCode.ResourceExhausted
                    ' Rate limit exceeded — wait and retry
                    Await Task.Delay(RetryDelayMs)
                End Try
            End While

            progress.Report((Threading.Interlocked.Increment(completed), imagePaths.Length))
        Next

        Return results
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Yaklaşımı:

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

public class BatchProcessor
{
    public Dictionary<string, string> ProcessBatch(
        string[] imagePaths,
        IProgress<(int completed, int total)> progress)
    {
        var results = new ConcurrentDictionary<string, string>();
        int completed = 0;

        //Hız sınırı yok— full parallelism, no retry logic needed
        Parallel.ForEach(imagePaths, imagePath =>
        {
            var ocr = new IronTesseract();
            results[imagePath] = ocr.Read(imagePath).Text;
            progress.Report((Interlocked.Increment(ref completed), imagePaths.Length));
        });

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

    public void ProcessBatchToSearchablePdfs(
        string[] imagePaths,
        string outputDirectory)
    {
        Parallel.ForEach(imagePaths, imagePath =>
        {
            var ocr = new IronTesseract();
            var result = ocr.Read(imagePath);

            var outputPath = Path.Combine(
                outputDirectory,
                Path.GetFileNameWithoutExtension(imagePath) + "-searchable.pdf");

            result.SaveAsSearchablePdf(outputPath);
        });
    }
}
using IronOcr;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class BatchProcessor
{
    public Dictionary<string, string> ProcessBatch(
        string[] imagePaths,
        IProgress<(int completed, int total)> progress)
    {
        var results = new ConcurrentDictionary<string, string>();
        int completed = 0;

        //Hız sınırı yok— full parallelism, no retry logic needed
        Parallel.ForEach(imagePaths, imagePath =>
        {
            var ocr = new IronTesseract();
            results[imagePath] = ocr.Read(imagePath).Text;
            progress.Report((Interlocked.Increment(ref completed), imagePaths.Length));
        });

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

    public void ProcessBatchToSearchablePdfs(
        string[] imagePaths,
        string outputDirectory)
    {
        Parallel.ForEach(imagePaths, imagePath =>
        {
            var ocr = new IronTesseract();
            var result = ocr.Read(imagePath);

            var outputPath = Path.Combine(
                outputDirectory,
                Path.GetFileNameWithoutExtension(imagePath) + "-searchable.pdf");

            result.SaveAsSearchablePdf(outputPath);
        });
    }
}
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks

Public Class BatchProcessor
    Public Function ProcessBatch(imagePaths As String(), progress As IProgress(Of (completed As Integer, total As Integer))) As Dictionary(Of String, String)
        Dim results As New ConcurrentDictionary(Of String, String)()
        Dim completed As Integer = 0

        'Hız sınırı yok— full parallelism, no retry logic needed
        Parallel.ForEach(imagePaths, Sub(imagePath)
                                         Dim ocr As New IronTesseract()
                                         results(imagePath) = ocr.Read(imagePath).Text
                                         progress.Report((Interlocked.Increment(completed), imagePaths.Length))
                                     End Sub)

        Return New Dictionary(Of String, String)(results)
    End Function

    Public Sub ProcessBatchToSearchablePdfs(imagePaths As String(), outputDirectory As String)
        Parallel.ForEach(imagePaths, Sub(imagePath)
                                         Dim ocr As New IronTesseract()
                                         Dim result = ocr.Read(imagePath)

                                         Dim outputPath = Path.Combine(outputDirectory, Path.GetFileNameWithoutExtension(imagePath) & "-searchable.pdf")

                                         result.SaveAsSearchablePdf(outputPath)
                                     End Sub)
    End Sub
End Class
$vbLabelText   $csharpLabel

Google Cloud Vision sürümü sırasaldır çünkü paralel istekler hızı sınırını artıracaktır. Her ResourceExhausted istisnası, tam olarak 60 saniyelik bir durma sağlar. Kotaya 10 kez çarpan 5.000 belgeli bir parti, 10 dakika boş bekleme süresi ekler. IronOCR'nin versiyonu, kullanılabilir tüm çekirdekler arasında paralelleştirilerek beklemeden çalışır. Uzun süreli toplu işler için, ilerleme izleme API'si manuel Interlocked.Increment kurulum gerektirmeden yerleşik ilerleme geri çağrıları sağlar. Toplu taramalarda görüntü kalitesi sorunları için, görüntü kalitesi düzeltme kılavuzu, her Read çağrısından önce eklenebilecek ön işleme boru hattını kapsar.

Google Cloud Vision OCRAPI'sinden IronOCR'ye Haritalama Referansı

Google Cloud Vision IronOCR Notlar
ImageAnnotatorClient.Create() new IronTesseract() Müşteri başlatma; kimlik bilgisi dosyasına gerek yok
Image.FromFile(path) _ocr.Read(path) veya input.LoadImage(path) Doğrudan yol okuma, IronTesseract üzerinde kullanılabilir
_client.DetectText(image) _ocr.Read(path).Text TEXT_DETECTION eşdeğer
_client.DetectDocumentText(image) _ocr.Read(path) DOCUMENT_TEXT_DETECTION eşdeğer; mod otomatik
response[0].Description result.Text Tam belge metni
TextAnnotation OcrResult Üst düzey sonuç konteyneri
annotation.Text result.Text Tam metin dizisi
annotation.Pages[i] result.Pages[i] Sayfa başına erişim
page.Blocks[i].Paragraphs[j] result.Paragraphs[i] IronOCR paragrafları düz bir koleksiyon olarak sunar
paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text) paragraph.Text Doğrudan dize özelliği; sembol yinelemesi yok
word.BoundingBox.Vertices word.X, word.Y, word.Width, word.Height Köşe listesi yerine bağımsız int özellikleri
word.Confidence word.Confidence Kelime başına güven skoru
page.Confidence result.Confidence Genel sonuç güveni
Feature.Types.Type.DocumentTextDetection Otomatik IronOCR işlem modunu otomatik seçer
BatchAnnotateImagesRequest Parallel.ForEach + new IronTesseract() iş parçacığı başına Paralel yerel işleme; toplu boyut sınırlaması yok
_client.BatchAnnotateImages(requests) new IronTesseract().Read(input) ile çoklu-görüntü OcrInput Çoklu görüntü girdisi için tek çağrı
AsyncBatchAnnotateFilesAsync() input.LoadPdf(); _ocr.Read(input) PDF işleme senkronizasyondadır; GCS gerekli değil
StorageClient.Create() Gerekli değil GCS bağımlılığı yok
storageClient.UploadObjectAsync() Gerekli değil PDF'ler doğrudan yerel yoldan veya akıştan yüklenir
operation.PollUntilCompletedAsync() Gerekli değil İşleme senkronizedir
RpcException (StatusCode.ResourceExhausted) Uygulanamaz Hız sınırı yok
RpcException (StatusCode.PermissionDenied) Uygulanamaz Çalışma zamanı kimlik doğrulaması yok
GOOGLE_APPLICATION_CREDENTIALS ortam değişkeni IronOcr.License.LicenseKey Dosya yolu değil, dize ataması

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

Sorun 1: GOOGLE_APPLICATION_CREDENTIALS olmadan Yapıcı Atar

Google Cloud Vision: ImageAnnotatorClient.Create(), ortam değişkeni ayarlı değilse veya geçersiz bir dosyaya işaret ediyorsa, RpcException ile StatusCode.Unauthenticated veya StatusCode.PermissionDenied fırlatır. Bu hata başlangıçta meydana gelir, ilk API çağrısında değil, bu, herhangi bir ortamda kimlik bilgileri eksikse, tüm uygulamanın başlatılamayacağı anlamına gelir.

Çözüm:Google Cloud Visionpaketlerini kaldırdıktan sonra, ortam yapılandırmalarınızdan, CI/CD boru hattı gizli anahtarlarından, Kubernetes gizli anahtarlarından ve Docker Compose dosyalarından GOOGLE_APPLICATION_CREDENTIALS tüm referanslarını silin. Tek bir IRONOCR_LICENSE ortam değişkeni ile değiştirin:

// Remove this from every deployment environment:
// GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json

// Add this once at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
    ?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable is required.");
// Remove this from every deployment environment:
// GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json

// Add this once at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
    ?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable is required.");
' Remove this from every deployment environment:
' GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json

' Add this once at application startup:
IronOcr.License.LicenseKey = If(Environment.GetEnvironmentVariable("IRONOCR_LICENSE"), Throw New InvalidOperationException("IRONOCR_LICENSE environment variable is required."))
$vbLabelText   $csharpLabel

Sorun 2: Ad Alanı Kaldırıldıktan Sonra Protobuf Sembol Birleştirme Kodu Bozulur

Google Cloud Vision: .SelectMany(w => w.Symbols).Select(s => s.Text) kullanılarak paragraf veya kelime metni çıkarılan kod tabanınızdaki her konum, Google.Cloud.Vision.V1 ad alanı kaldırıldıktan sonra derleme hataları üretecektir. Bu çağrılar, API yanıtını tüketen herhangi bir yardımcı veya servis sınıfına yayılmış durumdadır.

Çözüm: Kod tabanınızda tüm SelectMany ve w.Symbols desenlerini arayın ve bunlarıIronOCR sonuç nesneleri üzerinde doğrudan özellik erişimi ile değiştirin. sonuçları okuma kılavuzu, OcrResult, OcrResult.Page, OcrResult.Paragraph, OcrResult.Line ve OcrResult.Word üzerindeki mevcut her özelliği kapsar:

# Find all Protobuf symbol concatenation patterns
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .
grep -rn "w\.Symbols\.Select" --include="*.cs" .
# Find all Protobuf symbol concatenation patterns
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .
grep -rn "w\.Symbols\.Select" --include="*.cs" .
SHELL

Her oluşumu değiştirin:

// Before: symbol concatenation required by Protobuf schema
var text = string.Join("", paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text));

// After: direct property on OcrResult.Paragraph
var text = paragraph.Text;
// Before: symbol concatenation required by Protobuf schema
var text = string.Join("", paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text));

// After: direct property on OcrResult.Paragraph
var text = paragraph.Text;
' Before: symbol concatenation required by Protobuf schema
Dim text = String.Join("", paragraph.Words.SelectMany(Function(w) w.Symbols).Select(Function(s) s.Text))

' After: direct property on OcrResult.Paragraph
Dim text = paragraph.Text
$vbLabelText   $csharpLabel

Sorun 3: Storage.V1 Kaldırıldıktan Sonra PDF İşleme Kodu Derlenmiyor

Google Cloud Vision: Google.Cloud.Storage.V1 kaldırıldıktan sonra, StorageClient, UploadObjectAsync, DeleteObjectAsync, AsyncAnnotateFileRequest, GcsSource, GcsDestination ve PollUntilCompletedAsync 'a başvuran tüm kodlar derlenemeyecektir. Bu kod birkaç hizmet sınıfı üzerinde yayılabilir ve genellikle tek en büyük değişiklik bloğunu temsil eder.

Çözüm: Tüm GCS hattını silin. 50'den fazla satırdan oluşan asenkron yöntemi IronOCR'nin üç satırlık eşdeğeri ile değiştirin. Çağırıcı uyumluluğu için asenkron bir imza koruyan kod için, Task.Run ile sarın:

// Delete: StorageClient, GCS upload, AsyncBatchAnnotateFilesAsync,
//         PollUntilCompletedAsync, output download, DeleteObjectAsync

// Replace with:
public async Task<string> ProcessPdfAsync(string pdfPath)
{
    return await Task.Run(() =>
    {
        using var input = new OcrInput();
        input.LoadPdf(pdfPath);
        return new IronTesseract().Read(input).Text;
    });
}
// Delete: StorageClient, GCS upload, AsyncBatchAnnotateFilesAsync,
//         PollUntilCompletedAsync, output download, DeleteObjectAsync

// Replace with:
public async Task<string> ProcessPdfAsync(string pdfPath)
{
    return await Task.Run(() =>
    {
        using var input = new OcrInput();
        input.LoadPdf(pdfPath);
        return new IronTesseract().Read(input).Text;
    });
}
Imports System.Threading.Tasks

Public Async Function ProcessPdfAsync(pdfPath As String) As Task(Of String)
    Return Await Task.Run(Function()
                              Using input As New OcrInput()
                                  input.LoadPdf(pdfPath)
                                  Return New IronTesseract().Read(input).Text
                              End Using
                          End Function)
End Function
$vbLabelText   $csharpLabel

Yeni kod için, Task.Run sarmalayıcı yerine yerel asenkron OCR desteğini kullanın. PDF girdi kılavuzu, sayfa aralığı seçimi ve şifre korumalı PDF yüklemeyi kapsar.

Sorun 4: Hız Sınırı Yeniden Deneme Mantığı Artık Gerekli Değil

Google Cloud Vision: RpcException'i StatusCode.ResourceExhausted ile yakalayan ve bir bekle-ve-yeniden dene modelini uygulayan herhangi bir kod, dakikada 1.800 istek kotasını karşılayacak şekilde yazılmıştır. Bu yeniden deneme mantığı, orta katmanda, boru hattı adımlarında veya toplu işleme döngülerinde gömülü olabilir.

Çözüm: Kota hatalarıyla ilişkili tüm yeniden deneme mantığını kaldırın. IronOCR, harici kota olmadan yerel olarak işler. Hata işleyici sözleşmesi, iki RpcException durumuna değişir.

// Remove: all RpcException handlers for ResourceExhausted, PermissionDenied,
//         Unavailable, DeadlineExceeded, Unauthenticated

//IronOCR error surface:
try
{
    var result = new IronTesseract().Read(imagePath);
    if (result.Confidence < 50)
        input.DeNoise(); // add preprocessing for low-confidence results
    return result.Text;
}
catch (IOException ex)
{
    // File not found or locked
    throw new InvalidOperationException($"Cannot read: {imagePath}", ex);
}
catch (IronOcr.Exceptions.OcrException ex)
{
    // Processing failure — not a transient network error
    throw new InvalidOperationException($"OCR failed: {ex.Message}", ex);
}
// Remove: all RpcException handlers for ResourceExhausted, PermissionDenied,
//         Unavailable, DeadlineExceeded, Unauthenticated

//IronOCR error surface:
try
{
    var result = new IronTesseract().Read(imagePath);
    if (result.Confidence < 50)
        input.DeNoise(); // add preprocessing for low-confidence results
    return result.Text;
}
catch (IOException ex)
{
    // File not found or locked
    throw new InvalidOperationException($"Cannot read: {imagePath}", ex);
}
catch (IronOcr.Exceptions.OcrException ex)
{
    // Processing failure — not a transient network error
    throw new InvalidOperationException($"OCR failed: {ex.Message}", ex);
}
Imports IronOcr
Imports System.IO

' Remove: all RpcException handlers for ResourceExhausted, PermissionDenied,
'         Unavailable, DeadlineExceeded, Unauthenticated

'IronOCR error surface:
Try
    Dim result = New IronTesseract().Read(imagePath)
    If result.Confidence < 50 Then
        input.DeNoise() ' add preprocessing for low-confidence results
    End If
    Return result.Text
Catch ex As IOException
    ' File not found or locked
    Throw New InvalidOperationException($"Cannot read: {imagePath}", ex)
Catch ex As IronOcr.Exceptions.OcrException
    ' Processing failure — not a transient network error
    Throw New InvalidOperationException($"OCR failed: {ex.Message}", ex)
End Try
$vbLabelText   $csharpLabel

Sorun 5: Çok Sayfalı TIFF Kare Çıkarma Döngüsü Gerektirir

Google Cloud Vision: Mevcut TIFF işleme kodu, muhtemelen System.Drawing.Image kullanarak kareleri çıkarır, her kareyi bir geçici dizine JPEG olarak kaydeder, her JPEG'i ayrı bir API çağrısı olarak gönderir ve ardından geçici dosyaları siler. Bu model her kare başına bir kota birimi tüketir ve çökme olduğunda yetim geçici dosyalar bırakabilir.

Çözüm: Çerçeve çıkarma döngüsünü ve geçici dosya yönetimini input.LoadImageFrames() ile değiştirin. Tüm System.Drawing kare döngüsü silinir:

// Remove: System.Drawing frame extraction, temp file writes, per-frame API calls

// Replace with:
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);   // all frames, no temp files
var result = new IronTesseract().Read(input);
// Remove: System.Drawing frame extraction, temp file writes, per-frame API calls

// Replace with:
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);   // all frames, no temp files
var result = new IronTesseract().Read(input);
Imports IronOcr

Dim input As New OcrInput()
input.LoadImageFrames(tiffPath) ' all frames, no temp files
Dim result = (New IronTesseract()).Read(input)
$vbLabelText   $csharpLabel

Çoklu kare işleme seçenekleri, çerçeve aralığı seçimi dahil, TIFF ve GIF giriş kılavuzuna bakın.

Sorun 6: BoundingPoly Köşe Hesaplamaları Bozulur

Google Cloud Vision: annotation.BoundingPoly.Vertices'dan sınır kutusu koordinatlarını okuyan kod, X, Y, Genislik ve Yükseklik'i köşe indeksi aritmetiği ile hesapladı: vertices[0].X ile X, vertices[1].X - vertices[0].X ile Genislik, vertices[2].Y - vertices[0].Y ile Yükseklik. Göçten sonra, bu ifadeler IronOCR'da bir karşılığı olmadığı için, çünkü Vertices yoktur.

Çözüm: Köşe aritmetiğini doğrudan int özellikleriyle değiştirin. Hesaplamaya gerek yok:

// Before: vertex index arithmetic
int x = word.BoundingBox.Vertices[0].X;
int y = word.BoundingBox.Vertices[0].Y;
int width  = word.BoundingBox.Vertices[1].X - word.BoundingBox.Vertices[0].X;
int height = word.BoundingBox.Vertices[2].Y - word.BoundingBox.Vertices[0].Y;

// After: direct properties
int x      = word.X;
int y      = word.Y;
int width  = word.Width;
int height = word.Height;
// Before: vertex index arithmetic
int x = word.BoundingBox.Vertices[0].X;
int y = word.BoundingBox.Vertices[0].Y;
int width  = word.BoundingBox.Vertices[1].X - word.BoundingBox.Vertices[0].X;
int height = word.BoundingBox.Vertices[2].Y - word.BoundingBox.Vertices[0].Y;

// After: direct properties
int x      = word.X;
int y      = word.Y;
int width  = word.Width;
int height = word.Height;
' Before: vertex index arithmetic
Dim x As Integer = word.BoundingBox.Vertices(0).X
Dim y As Integer = word.BoundingBox.Vertices(0).Y
Dim width As Integer = word.BoundingBox.Vertices(1).X - word.BoundingBox.Vertices(0).X
Dim height As Integer = word.BoundingBox.Vertices(2).Y - word.BoundingBox.Vertices(0).Y

' After: direct properties
Dim x As Integer = word.X
Dim y As Integer = word.Y
Dim width As Integer = word.Width
Dim height As Integer = word.Height
$vbLabelText   $csharpLabel

Google Cloud Vision OCRGeçiş Kontrol Listesi

Öncesi-Geçiş

Değişiklik yapmadan önce herGoogle Cloud Visionbağımlılığını belirlemek için kod tabanını denetleyin:

# Find allGoogle Cloud Visionnamespace imports
grep -rn "using Google.Cloud.Vision" --include="*.cs" .
grep -rn "using Google.Cloud.Storage" --include="*.cs" .
grep -rn "using Grpc.Core" --include="*.cs" .

# Find ImageAnnotatorClient usage
grep -rn "ImageAnnotatorClient" --include="*.cs" .

# Find GCS pipeline code
grep -rn "StorageClient\|UploadObjectAsync\|DeleteObjectAsync" --include="*.cs" .
grep -rn "AsyncBatchAnnotateFilesAsync\|PollUntilCompleted" --include="*.cs" .

# Find Protobuf symbol concatenation
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .

# Find BoundingPoly vertex calculations
grep -rn "BoundingPoly\|BoundingBox\.Vertices" --include="*.cs" .

# Find rate limit retry handlers
grep -rn "ResourceExhausted\|StatusCode\." --include="*.cs" .

# Find environment variable references
grep -rn "GOOGLE_APPLICATION_CREDENTIALS" .
# Find allGoogle Cloud Visionnamespace imports
grep -rn "using Google.Cloud.Vision" --include="*.cs" .
grep -rn "using Google.Cloud.Storage" --include="*.cs" .
grep -rn "using Grpc.Core" --include="*.cs" .

# Find ImageAnnotatorClient usage
grep -rn "ImageAnnotatorClient" --include="*.cs" .

# Find GCS pipeline code
grep -rn "StorageClient\|UploadObjectAsync\|DeleteObjectAsync" --include="*.cs" .
grep -rn "AsyncBatchAnnotateFilesAsync\|PollUntilCompleted" --include="*.cs" .

# Find Protobuf symbol concatenation
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .

# Find BoundingPoly vertex calculations
grep -rn "BoundingPoly\|BoundingBox\.Vertices" --include="*.cs" .

# Find rate limit retry handlers
grep -rn "ResourceExhausted\|StatusCode\." --include="*.cs" .

# Find environment variable references
grep -rn "GOOGLE_APPLICATION_CREDENTIALS" .
SHELL

Başlamadan önce tamamlanacak envanter notları:

  • OCR giriş/çıkışı için oluşturulan tüm GCS kovaliklerini listeleyin — geçişten sonra temizlemeyi planlayın
  • GCP Konsolu'nda geçiş sonrası devre dışı bırakılabilmesi için hizmet hesabı e-posta adresini belgeleyin
  • GOOGLE_APPLICATION_CREDENTIALS yapılandırıldığı tüm ortamları belirleyin
  • Yapılandırmadan GCP proje kimliklerini veya kova adlarını okuyan herhangi bir kodu not edin — geçiş sonrası bunları kaldır

Kod Geçişi

  1. Tüm projelerden Google.Cloud.Vision.V1 NuGet paketini kaldırın
  2. Tüm projelerden Google.Cloud.Storage.V1 NuGet paketini kaldırın
  3. OCR işlemi gerçekleştiren tüm projelere IronOcr NuGet paketini yükleyin
  4. Uygulama başlangıcında IronOcr.License.LicenseKey başlatmasını ekleyin
  5. Tüm using Google.Cloud.Vision.V1 içe aktarımlarını using IronOcr ile değiştirin
  6. Tüm using Google.Cloud.Storage.V1 ve using Grpc.Core içe aktarımlarını değiştirin
  7. ImageAnnotatorClient.Create() ile new IronTesseract() değiştirin
  8. Tüm GCS boru hattı yöntemlerini (StorageClient, UploadObjectAsync, asenkron açıklama, anket, indirme, silme) silin
  9. Tüm PDF işleme yolları için input.LoadPdf() değiştirin (asenkron GCS orkestrasyonunu kaldırma)
  10. Tüm Protobuf sembol birleştirme döngülerini, OcrResult nesnelerde doğrudan .Text özellik erişimi ile değiştirin
  11. BoundingPoly.Vertices indeks hesaplamalarını word.X, word.Y, word.Width, word.Height ile değiştirin
  12. RpcException yakalama bloklarının tümünü silin, ResourceExhausted, PermissionDenied, Unavailable, DeadlineExceeded ve Unauthenticated için.
  13. Çerçeve başına TIFF döngüsünü input.LoadImageFrames() ile değiştirin
  14. Ardışık toplu işleri, iş parçacığı başına IronTesseract olan Parallel.ForEach'ye dönüştürün
  15. Tüm ortam yapılandırmalarından, CI/CD boru hatlarından, Docker Compose dosyalarından ve Kubernetes gizli anahtarlarından GOOGLE_APPLICATION_CREDENTIALS'i kaldırın

Geçiş Sonrası

  • RpcException veya GoogleApiException türlerinin hata işleme kodunda artık referans edilmediğinden emin olun
  • GOOGLE_APPLICATION_CREDENTIALS'nın tüm dağıtım ortamı yapılandırmalarında yok olduğunu doğrulayın
  • Üretimde kullanılan aynı örnek belgeler üzerinde OCR boru hattını çalıştırın ve metin çıkış kalitesini karşılaştırın
  • Daha önce GCS asenkron boru hattı tarafından işlenen belgeler üzerinde PDF işlemeyi test edin ve aynı metin çıktısını onaylayın
  • Daha önce desteklenmeyen input.LoadPdf(path, Password: "...") ile parola korumalı PDF'leri test edin
  • input.LoadImageFrames() kullanarak çok sayfalı TIFF işleme test edin ve tüm karelerin işlendiğini doğrulayın
  • Temsilci bir örnek üzerinde toplu işleyiciyi çalıştırın ve çıktı kalitesinin önceki sonuçlarla eşleştiğini onaylayın
  • Belge koleksiyonunuz için result.Confidence değerlerinin kabul edilebilir aralıkta olduğundan emin olun
  • Daha önce ayrı bir PDF kütüphanesi gerektiren belgeler için result.SaveAsSearchablePdf() kullanarak aranabilir PDF çıktısını doğrulayın
  • Çıkış internet bağlantısı olmayan bir ortamda uygulamayı çalıştırın ve OCR'nin doğru çalıştığını onaylayın

IronOCR'a Geçişin Ana Faydaları

Kimlik Bilgisi Yüzeyi Sıfır Dosyaya İndirildi. Göçten sonra, altyapınızda JSON anahtar dosyaları, GCS bucket yapılandırmaları, IAM rolleri, hizmet hesapları ve GOOGLE_APPLICATION_CREDENTIALS ortam değişkenleri yoktur. Tüm kimlik bilgisi yüzeyi, bir lisans anahtarı dizisi içeren bir ortam değişkenidir.Google Cloud Visionile zorunlu bir periyodik işlem olan anahtar döndürme artık uygulanan bir kavram değildir. Birden fazla bölgede veya bulut sağlayıcısında faaliyet gösteren ekipler için, dağıtım yapılandırma karmaşıklığının azaltılması anlık olarak fark edilir.

Dış Bağımlılıklar Olmadan PDF ve TIFF İşleme. GCS asenkron boru hattı ve System.Drawing TIFF kare döngüsü tamamen silinmiştir. input.LoadPdf() ve input.LoadImageFrames() ikame öğeleridir — her ikisi de senkron, her ikisi de yerel, her ikisi de çağrı ile sonuç arasında üç satır.Google Cloud Visionile olanaklı olmayan şifre korumalı PDF'ler, ek bir parametre ile çalışır. PDF OCR rehberi ve TIFF girdi rehberi, tam giriş API'sini kapsar.

CPU Hızıyla Toplu İşleme. Dakikada 1.800 istek kotasının kaldırılması ve zorunlu 60 saniyelik tekrar deneme sürelerinin ortadan kalkması, daha önce sınırlı hıza tabi olan toplu işlerin artık mevcut işlemci çekirdeklerinin hızında çalıştığı anlamına gelir. 16 çekirdekli bir makine, harici onay olmadan 16 belgeyi aynı anda işler. Parallel.ForEach deseni, boğulmuş sıralı döngünün doğrudan yedek parçasıdır, iş parçacığı başına IronTesseract örnekleri ile. hız optimizasyon kılavuzu, belirli belge türleri için verimliliği ayarlamak üzere motor yapılandırma seçeneklerini kapsar.

Protobuf Olmadan Yapılandırılmış Veri. Her OcrResult, türlenmiş .NET özellikleri olarak Text, Confidence, Pages, Paragraphs, Lines, Words ve Characters açığa çıkarır, hiçbir Protobuf ad alanı bağımlılığı, sembol birleştirme ve sınır kutuları için köşe aritmetiği yok. Daha önce paragraf metni çıkarmak için 20 satırlık iç içe döngüler gerektiren kod, result.Paragraphs.Select(p => p.Text)'ye indirgenir. Belge yerleşim analizi için kelime düzeyinde konumlandırma gereken kullanım durumları için, word.X, word.Y, word.Width ve word.Height doğrudan mevcuttur. OCR sonuçları özellikler sayfası, sonuç modelindeki her özelliği belgelendirir.

Aranabilir PDF Çıkışı Dahili Olarak Sunulur.Google Cloud Visionyalnızca metin döndürür — aranabilir bir PDF üretmek, başka bir API'yi öğrenmeyi ve başka bir lisanslamayı değerlendirmeyi gerektirirdi. IronOCR'nin result.SaveAsSearchablePdf(outputPath)'ı, herhangi bir OCR sonucundan bir satırda tamamen aranabilir bir PDF üretir. Belge arşivleme iş akışları ve yasal bulgu hatları için, bu bir bütün bağımlılığı ortadan kaldırır. Aranabilir PDF örneği, modeli baştan sona gösterir.

Düzenleyici Endüstriler İçin Veri Egemenliği.IronOCR tarafından işlenen belgeler sunucuyu asla terk etmez. HIPAA kapsamındaki sağlık kayıtları, ITAR kontrollü teknik veriler, CMMC kapsamındaki savunma müteahhit malzemeleri, avukat-müvekkil gizli yasal belgeler ve PCI-DSS kapsamında finansal kayıtlar için, yerel yerleşim mimarisi, üçüncü taraf veri işleyici kategorisini uyumluluk alanından tamamen çıkarır. Karşılıklı İş Ortağı Anlaşması yapmak, Veri Koruma Sözleşmesi imzalamak ve Google veri saklama politikasını gözden geçirmek gerekmez. IronOCR belgeleri merkezi, veri yerleşim gereksinimlerinin uygulandığı Docker, Linux, Azure ve AWS ortamları için dağıtım yapılandırmalarını kapsar.

Lütfen dikkate alınGoogle Cloud Vision, Tesseract ve iText, sahiplerinin tescilli markalarıdır. Bu site, Google veya iText Grubu ile ilişkilendirilmemiş, onaylanmamış veya onların sponsorluğunda değildir. Tüm ürün adları, logoları ve markaları, sahiplerinin mülkiyetinde olup, tescilli olarak tanımlanmıştı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

Neden Google Cloud Vision API'dan IronOCR'ye 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.

Google Cloud Vision API'dan IronOCR'ye geçişteki ana kod değişiklikleri nelerdir?

Google Cloud Vision başlangıç dizilerini IronTesseract örneği ile değiştirin, COM yaşam döngüsü yönetimini (açık Create/Load/Close desenleri) kaldırın ve sonuç özellik adlarını güncelleyin. Sonuç, önemli ölçüde daha az boilerplate 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, Google Cloud Vision API'nin standart iş belgeleri için OCR doğruluğunu karşılıyor mu?

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, Google Cloud Vision API'nin ayrı kurduğu dil verilerini nasıl yönetiyor?

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.

Google Cloud Vision API'dan IronOCR'ye geçiş, dağıtım altyapısında değişiklik gerektiriyor mu?

IronOCR, Google Cloud Vision API'dan daha az altyapı değişikliği gerektirir. SDK ikili yolları, lisans dosyası yerleşimleri veya lisans sunucu yapılandırmaları yoktur. NuGet paketi, tam OCR motorunu içerir ve lisans anahtarı uygulama kodunda belirlenmiş bir dizgedir.

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 Google Cloud Vision 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'ın fiyatlandırması, ölçeklendirme iş yükleri için Google Cloud Vision API'dan daha öngörülebilir mi?

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.

Google Cloud Vision API'dan IronOCR'ye geçtikten sonra mevcut testlerime ne olacak?

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