Azure Computer Vision OCR'dan
Bu kılavuz,Azure Computer VisionOCR'nin yerini almak için .NET geliştiricilerini, bulut altyapısı olmadan belgeleri yerel olarak işleyen on-premise bir OCR kütüphanesi olan IronOCR ile tanıştırır. NuGet paketini ve ad alanlarını değiştirmenin mekanik adımlarını, Azure async anket modelini eşzamanlı yerel çağrılara çevirme ve spesifik desenleri — bağımlılık injeksiyonu bağlama, Form Recognizer anket döngüleri, çok sayfalı TIFF işleme ve toplu geçirme kapasitesi — taşınma sırasında en fazla dikkat gerektiren konuları ele alır.
Azure Computer VisionOCR'den Neden Geçilmelidir
Geçiş kararı soyut değildir. Ekipler tipik olarak üretimdeAzure Computer Visionile bir veya daha fazla somut operasyonel problemlerle karşılaştıktan sonra karar verirler.
Endpoint ve API anahtarı yönetimi asla bitmez. Her dağıtım ortamı — geliştirme, aşama, üretim, felaket kurtarma — bir Azure Cognitive Services kaynağı, bir endpoint URL ve en az bir API anahtarı gerektirir. Anahtarlar döndürülmelidir. Kaynaklar bölgeleri değiştirdiklerinde endpoint değişir. Her ortamın, cognitiveservices.azure.com ulaşmak için dışa yönelik güvenlik duvarı kurallarına ihtiyacı vardır. Ekiple birlikte her ortam ve geliştiriciyle birlikte operasyonel yüzey alanı büyür. IronOCR, tüm bunları yalnızca uygulama başlangıcında ayarlanan tek bir dize lisans anahtarı ile değiştirir; döngü programı yoktur ve dışa yönelik ağ gereksinimi de yoktur.
Sayfa başına faturalama, çok sayfalı belgeleri cezalandırır.Azure Computer Visionher PDF sayfasını ayrı bir işlem olarak sayar. 20 sayfalık bir sözleşme 20 faturalandırılabilir çağrıdır. 1.000 işlem başına $1.00 üzerinden, ayda 4 sayfa ortalamasıyla 50.000 çok sayfalı belge işleyen bir ekip 200.000 işlem üretir — ücretsiz kademenin üstünde aylık $195, yıllık $2.340. Bu, dört aydan kısa sürede IronOCR Lite ($999) karşısında dengeli bir noktadır, sonrasında her ek sayfa ücretsizdir.
Async yayılım, tüm çağrı yığını boyunca yayılır.Azure Computer Visioneşzamanlı dönemez — bulut G/Ç ağ gecikmesine sahiptir. await gereksinimi AnalyzeAsync üstünde tüm çağrı yöntemlerini async olmaya zorlar ve bu modelin hizmet katmanından denetleyicilere, arka plan çalışanlarına ve uyum sağlamak için yeniden yapılandırılması gereken senkron kodlara yayılmasına neden olur. Form Recognizer'ın oylamaya dayalı işlemleri bunu bileşik hale getirir: WaitUntil.Completed iş parçacığını engeller ve gerçek non-blocking davranış, UpdateStatusAsync oylama döngülerini manuel olarak yönetmeyi gerektirir.
Belgeler her çağrıda ağı terk eder. HIPAA kapsamındaki sağlık bilgilerini işleyen, ITAR kontrolündeki savunma belgelerini, avukat-müvekkil gizli iletişimlerini veya veri ikametgahı kurallarına tabi herhangi bir belge kategorisini işleyen ekipler için, zorunlu bulut iletimi mimari bir uyumsuzluktur, bir telafisi değildir. Belge içeriğinin Microsoft veri merkezlerine gönderilmesini önleyen birAzure Computer Visionmodu yoktur.
Oran sınırlamaları throughput tavanları oluşturur. Azure Computer Vision'un S1 seviyesi 10 işlem/saniyelik bir sınır koyar. : bir saat içindeki 3.600 görüntü işleme kapasitesine sahip bir toplu işlem tam tavanı vurur. Bunu aşmak HTTP 429 yanıtları döndürür, her bir çağrı yolunda üssel geri çekilme ile yeniden deneme mantığı gerektirir. IronOCR'un throughput tavanı, barındırma donanımıdır — hizmet tarafından konulmuş bir sınır yoktur, bu yüzden tekrar deneme altyapısı gerekli değildir.
Görüntü OCR vePDF OCRiki ayrı hizmet gerektirir. Standart görüntü OCR, ImageAnalysisClient __Azure.AI.Vision.ImageAnalysis kullanır. Tam PDF işleme, DocumentAnalysisClient başka bir NuGet paketi, farklı bir Azure kaynağı, farklı bir uç nokta ve farklı bir sonuç şeması olan Azure.AI.FormRecognizer.DocumentAnalysis gerektirir. Hem görüntüleri hem de PDF'leri işleyen her uygulama bu iki katı yapılandırma yükünü taşır. IronOCR, her ikisini de IronTesseract.Read() ve tek bir OcrInput yükleyici ile ele alır.
Temel Sorun
// Azure: endpoint URL + API key + async + nested block traversal — before a single character
var client = new ImageAnalysisClient(new Uri(endpoint), new AzureKeyCredential(apiKey));
using var stream = File.OpenRead(imagePath);
var result = await client.AnalyzeAsync(BinaryData.FromStream(stream), VisualFeatures.Read);
var text = string.Join("\n", result.Value.Read.Blocks.SelectMany(b => b.Lines).Select(l => l.Text));
// IronOCR: no endpoint, no key rotation, no async, no traversal
var text = new IronTesseract().Read(imagePath).Text;
// Azure: endpoint URL + API key + async + nested block traversal — before a single character
var client = new ImageAnalysisClient(new Uri(endpoint), new AzureKeyCredential(apiKey));
using var stream = File.OpenRead(imagePath);
var result = await client.AnalyzeAsync(BinaryData.FromStream(stream), VisualFeatures.Read);
var text = string.Join("\n", result.Value.Read.Blocks.SelectMany(b => b.Lines).Select(l => l.Text));
// IronOCR: no endpoint, no key rotation, no async, no traversal
var text = new IronTesseract().Read(imagePath).Text;
Imports System
Imports System.IO
Imports Azure
Imports Azure.AI.Vision
Imports IronOcr
' Azure: endpoint URL + API key + async + nested block traversal — before a single character
Dim client As New ImageAnalysisClient(New Uri(endpoint), New AzureKeyCredential(apiKey))
Using stream As FileStream = File.OpenRead(imagePath)
Dim result = Await client.AnalyzeAsync(BinaryData.FromStream(stream), VisualFeatures.Read)
Dim text As String = String.Join(vbLf, result.Value.Read.Blocks.SelectMany(Function(b) b.Lines).Select(Function(l) l.Text))
End Using
' IronOCR: no endpoint, no key rotation, no async, no traversal
Dim text As String = New IronTesseract().Read(imagePath).Text
IronOCR vsAzure Computer VisionOCR: Özellik Karşılaştırması
Aşağıdaki tablo, bu geçişi değerlendiren ekipler için en alakalı yetenekleri kapsamaktadır.
| Özellik | Azure Computer Vision OCR | IronOCR |
|---|---|---|
| İşleme yeri | Microsoft Azure bulutu | Yerel, yerinde |
| İnternet gerekli | Evet, her istekte | Hayır |
| Azure aboneliği gerektirir | Evet | Hayır |
| Fiyatlandırma modeli | İşlem başına ($1.00/1.000 işlem) | Süresiz lisans ($999 dan) |
| Çok sayfalı PDF'lerde sayfa başına faturalama | Evet — her sayfa = 1 işlem | Sayfa başına maliyet yok |
| Ücretsiz seviye | 5.000 işlem/ay | Deneme modu (filigranlı) |
| Image OCR API'si | AnalyzeAsync (sadece async) |
Read() (senkron) |
| PDF OCR | Ayrı Form Recognizer servisi | Yerleşik, aynı Read() çağrısı |
| Şifre korumalı PDF | Form Recognizer aracılığıyla | input.LoadPdf(path, Password: "x") |
| Aranabilir PDF çıktısı | Manuel yapı | result.SaveAsSearchablePdf() |
| Çok sayfalı TIFF | Desteklenmiyor | input.LoadImageFrames() |
| Otomatik görüntü ön işleme | Opak sunucu tarafı, yapılandırılamaz | Yeniden hizalama, Gürültü Giderme, Kontrast, İkiliye Çevirme, Keskinleştirme, Ölçekleme |
| Derin gürültü temizleme | Hayır | input.DeepCleanBackgroundNoise() |
| OCR sırasında barkod okuma | Ayrı Image Analysis özelliği | ocr.Configuration.ReadBarCodes = true |
| Bölge bazlı OCR | Doğrudan değil (yüklemeden önce manuel kırpma) | CropRectangle OcrInput üzerinde |
| Oran sınırlamaları | S1 seviyesinde 10 TPS | Sadece donanım kısıtlı |
| Yeniden deneme mantığı gerekli | Evet (HTTP 429, 5xx) | Hayır |
| İzole dağıtım | İmkansız | Tam destekli |
| Desteklenen diller | 164+ (sunucu tarafından yönetilen) | 125+ (NuGet dil paketleri) |
| Çoklu dil aynı anda | Evet | Evet (OcrLanguage.French + OcrLanguage.German) |
| Kelime sınırlayıcı kutuları | Çokgen (değişken köşe sayısı) | Dikdörtgen (x, y, genişlik, yükseklik) |
| Güven puanlama | Kelime başına float (0,0-1,0) | Kelime başına ve genel (0-100 ölçek) |
| hOCR içeri aktarma | Hayır | result.SaveAsHocrFile() |
| Yapılandırılmış çıktı hiyerarşisi | Bloklar / Satırlar / Kelimeler | Sayfalar / Paragraflar / Satırlar / Kelimeler / Karakterler |
| .NET uyumluluğu | .NET Standard 2.0+ | .NET Framework 4.6.2+, .NET Core, .NET 5–9 |
| Çapraz platform | Windows, Linux, macOS (bulut üzerinden) | Windows, Linux, macOS, Docker, ARM64 |
| Ticari destek | Azure destek planları | IronOCR lisansına dahil destek |
Hızlı Başlangıç:Azure Computer VisionOCR'den IronOCR'ye Geçiş
Adım 1: NuGet Paketini Değiştirin
Azure Computer Vision paketini kaldırın:
dotnet remove package Azure.AI.Vision.ImageAnalysis
dotnet remove package Azure.AI.Vision.ImageAnalysis
Proje ayrıca PDF işleme için Form Recognizer kullanıyorsa, o paketi de kaldırın:
dotnet remove package Azure.AI.FormRecognizer
dotnet remove package Azure.AI.FormRecognizer
NuGet kullanarak IronOCR'u yükleyin:
dotnet add package IronOcr
Adım 2: Ad Alanlarını Güncelleyin
// Before (Azure Computer Vision)
using Azure;
using Azure.AI.Vision.ImageAnalysis;
// For PDF processing:
// using Azure.AI.FormRecognizer.DocumentAnalysis;
// After (IronOCR)
using IronOcr;
// Before (Azure Computer Vision)
using Azure;
using Azure.AI.Vision.ImageAnalysis;
// For PDF processing:
// using Azure.AI.FormRecognizer.DocumentAnalysis;
// After (IronOCR)
using IronOcr;
Imports IronOcr
' Before (Azure Computer Vision)
' Imports Azure
' Imports Azure.AI.Vision.ImageAnalysis
' For PDF processing:
' Imports Azure.AI.FormRecognizer.DocumentAnalysis
' After (IronOCR)
Adım 3: Lisansa İzin Verin
OCR çağrısından önce uygulama başlatma sırasında lisans anahtarını bir kez ekleyin:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Üretimde anahtarı bir ortam değişkeni olarak saklayın:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
Imports System
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
Kod Göç Örnekleri
Bağımlılık Enjeksiyonu ile Azure İstemci Yapılandırmasının Değiştirilmesi
Önerilen Azure SDK modelini izleyen ekipler, ImageAnalysisClient DI kabında IOptions<AzureComputerVisionOptions> veya doğrudan IConfiguration bağlayarak kaydeder. Bu yapılandırma, uç nokta URL'lerini ve API anahtarlarını appsettings.json alır ve her dağıtım ortamında dışa yönelik ağ yapılandırması gerektirir.
Azure Computer Vision Yöntemi:
// appsettings.json binds to this class
public class AzureComputerVisionOptions
{
public string Endpoint { get; set; } // "https://your-resource.cognitiveservices.azure.com/"
public string ApiKey { get; set; } // rotated periodically
}
// Program.cs / Startup.cs
services.Configure<AzureComputerVisionOptions>(
configuration.GetSection("AzureComputerVision"));
services.AddSingleton<ImageAnalysisClient>(sp =>
{
var opts = sp.GetRequiredService<IOptions<AzureComputerVisionOptions>>().Value;
return new ImageAnalysisClient(
new Uri(opts.Endpoint),
new AzureKeyCredential(opts.ApiKey));
});
services.AddScoped<IOcrService, AzureOcrService>();
// appsettings.json binds to this class
public class AzureComputerVisionOptions
{
public string Endpoint { get; set; } // "https://your-resource.cognitiveservices.azure.com/"
public string ApiKey { get; set; } // rotated periodically
}
// Program.cs / Startup.cs
services.Configure<AzureComputerVisionOptions>(
configuration.GetSection("AzureComputerVision"));
services.AddSingleton<ImageAnalysisClient>(sp =>
{
var opts = sp.GetRequiredService<IOptions<AzureComputerVisionOptions>>().Value;
return new ImageAnalysisClient(
new Uri(opts.Endpoint),
new AzureKeyCredential(opts.ApiKey));
});
services.AddScoped<IOcrService, AzureOcrService>();
' appsettings.json binds to this class
Public Class AzureComputerVisionOptions
Public Property Endpoint As String ' "https://your-resource.cognitiveservices.azure.com/"
Public Property ApiKey As String ' rotated periodically
End Class
' Program.vb / Startup.vb
services.Configure(Of AzureComputerVisionOptions)(
configuration.GetSection("AzureComputerVision"))
services.AddSingleton(Of ImageAnalysisClient)(Function(sp)
Dim opts = sp.GetRequiredService(Of IOptions(Of AzureComputerVisionOptions))().Value
Return New ImageAnalysisClient(
New Uri(opts.Endpoint),
New AzureKeyCredential(opts.ApiKey))
End Function)
services.AddScoped(Of IOcrService, AzureOcrService)()
// AzureOcrService.cs
public class AzureOcrService : IOcrService
{
private readonly ImageAnalysisClient _client;
public AzureOcrService(ImageAnalysisClient client)
{
_client = client;
}
public async Task<string> ReadAsync(string imagePath)
{
using var stream = File.OpenRead(imagePath);
var data = BinaryData.FromStream(stream);
var result = await _client.AnalyzeAsync(data, VisualFeatures.Read);
return string.Join("\n",
result.Value.Read.Blocks
.SelectMany(b => b.Lines)
.Select(l => l.Text));
}
}
// AzureOcrService.cs
public class AzureOcrService : IOcrService
{
private readonly ImageAnalysisClient _client;
public AzureOcrService(ImageAnalysisClient client)
{
_client = client;
}
public async Task<string> ReadAsync(string imagePath)
{
using var stream = File.OpenRead(imagePath);
var data = BinaryData.FromStream(stream);
var result = await _client.AnalyzeAsync(data, VisualFeatures.Read);
return string.Join("\n",
result.Value.Read.Blocks
.SelectMany(b => b.Lines)
.Select(l => l.Text));
}
}
Imports System.IO
Imports System.Threading.Tasks
Public Class AzureOcrService
Implements IOcrService
Private ReadOnly _client As ImageAnalysisClient
Public Sub New(client As ImageAnalysisClient)
_client = client
End Sub
Public Async Function ReadAsync(imagePath As String) As Task(Of String) Implements IOcrService.ReadAsync
Using stream = File.OpenRead(imagePath)
Dim data = BinaryData.FromStream(stream)
Dim result = Await _client.AnalyzeAsync(data, VisualFeatures.Read)
Return String.Join(vbLf, result.Value.Read.Blocks _
.SelectMany(Function(b) b.Lines) _
.Select(Function(l) l.Text))
End Using
End Function
End Class
IronOCR Yaklaşımı:
// Program.cs / Startup.cs
// One-time license key — no endpoint, no credential class, no options binding
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// Register IronTesseract as a singleton — it is thread-safe
services.AddSingleton<IronTesseract>();
services.AddScoped<IOcrService, IronOcrService>();
// Program.cs / Startup.cs
// One-time license key — no endpoint, no credential class, no options binding
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// Register IronTesseract as a singleton — it is thread-safe
services.AddSingleton<IronTesseract>();
services.AddScoped<IOcrService, IronOcrService>();
' Program.vb / Startup.vb
' One-time license key — no endpoint, no credential class, no options binding
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
' Register IronTesseract as a singleton — it is thread-safe
services.AddSingleton(Of IronTesseract)()
services.AddScoped(Of IOcrService, IronOcrService)()
// IronOcrService.cs
public class IronOcrService : IOcrService
{
private readonly IronTesseract _ocr;
public IronOcrService(IronTesseract ocr)
{
_ocr = ocr;
}
public string Read(string imagePath)
{
return _ocr.Read(imagePath).Text;
}
}
// IronOcrService.cs
public class IronOcrService : IOcrService
{
private readonly IronTesseract _ocr;
public IronOcrService(IronTesseract ocr)
{
_ocr = ocr;
}
public string Read(string imagePath)
{
return _ocr.Read(imagePath).Text;
}
}
' IronOcrService.vb
Public Class IronOcrService
Implements IOcrService
Private ReadOnly _ocr As IronTesseract
Public Sub New(ocr As IronTesseract)
_ocr = ocr
End Sub
Public Function Read(imagePath As String) As String Implements IOcrService.Read
Return _ocr.Read(imagePath).Text
End Function
End Class
DI yapılandırması, iki yapılandırma sınıfından (seçenekler + istemci fabrikası) tek bir AddSingleton<IronTesseract>() çağrısına düşer. appsettings.json Azure bölümü, anahtar kasası referansları ve cognitiveservices.azure.com için dışa yönelik güvenlik duvarı kuralları tamamen kaldırılır. IronTesseract kurulum kılavuzu, tekil örnek üzerindeki yapılandırma seçeneklerini kapsar.
Form Recognizer Anket Döngüsünün Ortadan Kaldırılması
Form Recognizer'ın AnalyzeDocumentAsync bir LongRunningOperation döndürür. WaitUntil.Completed bulut işi tamamlanana kadar çağrı iş parçacığını engeller — genellikle belge başına 2–10 saniye. Non-blocking davranış için, ekipler hiçbir OCR mantığı içermeyen 30–50 satırlık altyapı kodu ekleyerek gecikmeli bir UpdateStatusAsync oylama döngüsü yazar.
Azure Computer Vision Yöntemi:
// DocumentAnalysisClient — separate from ImageAnalysisClient, separate resource
public class FormRecognizerPdfService
{
private readonly DocumentAnalysisClient _client;
public FormRecognizerPdfService(string endpoint, string apiKey)
{
_client = new DocumentAnalysisClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey));
}
// Blocking wait — thread is held for the duration of cloud processing
public async Task<string> ExtractPdfTextBlocking(string pdfPath)
{
using var stream = File.OpenRead(pdfPath);
var operation = await _client.AnalyzeDocumentAsync(
WaitUntil.Completed, // blocks until Azure finishes
"prebuilt-read",
stream);
var docResult = operation.Value;
var sb = new StringBuilder();
foreach (var page in docResult.Pages)
{
foreach (var line in page.Lines)
{
sb.AppendLine(line.Content); // .Content, not .Text
}
}
return sb.ToString();
}
// True async — manual polling loop required
public async Task<string> ExtractPdfTextNonBlocking(string pdfPath)
{
using var stream = File.OpenRead(pdfPath);
var operation = await _client.AnalyzeDocumentAsync(
WaitUntil.Started, // returns immediately, not complete yet
"prebuilt-read",
stream);
// Poll every 500ms until the operation finishes
while (!operation.HasCompleted)
{
await Task.Delay(500);
await operation.UpdateStatusAsync();
}
var docResult = operation.Value;
var sb = new StringBuilder();
foreach (var page in docResult.Pages)
{
foreach (var line in page.Lines)
{
sb.AppendLine(line.Content);
}
}
return sb.ToString();
}
}
// DocumentAnalysisClient — separate from ImageAnalysisClient, separate resource
public class FormRecognizerPdfService
{
private readonly DocumentAnalysisClient _client;
public FormRecognizerPdfService(string endpoint, string apiKey)
{
_client = new DocumentAnalysisClient(
new Uri(endpoint),
new AzureKeyCredential(apiKey));
}
// Blocking wait — thread is held for the duration of cloud processing
public async Task<string> ExtractPdfTextBlocking(string pdfPath)
{
using var stream = File.OpenRead(pdfPath);
var operation = await _client.AnalyzeDocumentAsync(
WaitUntil.Completed, // blocks until Azure finishes
"prebuilt-read",
stream);
var docResult = operation.Value;
var sb = new StringBuilder();
foreach (var page in docResult.Pages)
{
foreach (var line in page.Lines)
{
sb.AppendLine(line.Content); // .Content, not .Text
}
}
return sb.ToString();
}
// True async — manual polling loop required
public async Task<string> ExtractPdfTextNonBlocking(string pdfPath)
{
using var stream = File.OpenRead(pdfPath);
var operation = await _client.AnalyzeDocumentAsync(
WaitUntil.Started, // returns immediately, not complete yet
"prebuilt-read",
stream);
// Poll every 500ms until the operation finishes
while (!operation.HasCompleted)
{
await Task.Delay(500);
await operation.UpdateStatusAsync();
}
var docResult = operation.Value;
var sb = new StringBuilder();
foreach (var page in docResult.Pages)
{
foreach (var line in page.Lines)
{
sb.AppendLine(line.Content);
}
}
return sb.ToString();
}
}
Imports System
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Imports Azure
Imports Azure.AI.FormRecognizer.DocumentAnalysis
' DocumentAnalysisClient — separate from ImageAnalysisClient, separate resource
Public Class FormRecognizerPdfService
Private ReadOnly _client As DocumentAnalysisClient
Public Sub New(endpoint As String, apiKey As String)
_client = New DocumentAnalysisClient(
New Uri(endpoint),
New AzureKeyCredential(apiKey))
End Sub
' Blocking wait — thread is held for the duration of cloud processing
Public Async Function ExtractPdfTextBlocking(pdfPath As String) As Task(Of String)
Using stream = File.OpenRead(pdfPath)
Dim operation = Await _client.AnalyzeDocumentAsync(
WaitUntil.Completed, ' blocks until Azure finishes
"prebuilt-read",
stream)
Dim docResult = operation.Value
Dim sb = New StringBuilder()
For Each page In docResult.Pages
For Each line In page.Lines
sb.AppendLine(line.Content) ' .Content, not .Text
Next
Next
Return sb.ToString()
End Using
End Function
' True async — manual polling loop required
Public Async Function ExtractPdfTextNonBlocking(pdfPath As String) As Task(Of String)
Using stream = File.OpenRead(pdfPath)
Dim operation = Await _client.AnalyzeDocumentAsync(
WaitUntil.Started, ' returns immediately, not complete yet
"prebuilt-read",
stream)
' Poll every 500ms until the operation finishes
While Not operation.HasCompleted
Await Task.Delay(500)
Await operation.UpdateStatusAsync()
End While
Dim docResult = operation.Value
Dim sb = New StringBuilder()
For Each page In docResult.Pages
For Each line In page.Lines
sb.AppendLine(line.Content)
Next
Next
Return sb.ToString()
End Using
End Function
End Class
IronOCR Yaklaşımı:
// One class handles both images and PDFs — no second client or second resource
public class IronOcrDocumentService
{
private readonly IronTesseract _ocr;
public IronOcrDocumentService(IronTesseract ocr)
{
_ocr = ocr;
}
// Synchronous — returns immediately when local processing completes
public string ExtractPdfText(string pdfPath)
{
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return _ocr.Read(input).Text;
}
// Specific page range — no per-page billing penalty
public string ExtractPageRange(string pdfPath, int startPage, int endPage)
{
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return _ocr.Read(input).Text;
}
// If an async signature is required by an interface or controller
public Task<string> ExtractPdfTextAsync(string pdfPath)
{
return Task.Run(() => ExtractPdfText(pdfPath));
}
}
// One class handles both images and PDFs — no second client or second resource
public class IronOcrDocumentService
{
private readonly IronTesseract _ocr;
public IronOcrDocumentService(IronTesseract ocr)
{
_ocr = ocr;
}
// Synchronous — returns immediately when local processing completes
public string ExtractPdfText(string pdfPath)
{
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return _ocr.Read(input).Text;
}
// Specific page range — no per-page billing penalty
public string ExtractPageRange(string pdfPath, int startPage, int endPage)
{
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return _ocr.Read(input).Text;
}
// If an async signature is required by an interface or controller
public Task<string> ExtractPdfTextAsync(string pdfPath)
{
return Task.Run(() => ExtractPdfText(pdfPath));
}
}
Imports System.Threading.Tasks
' One class handles both images and PDFs — no second client or second resource
Public Class IronOcrDocumentService
Private ReadOnly _ocr As IronTesseract
Public Sub New(ocr As IronTesseract)
_ocr = ocr
End Sub
' Synchronous — returns immediately when local processing completes
Public Function ExtractPdfText(pdfPath As String) As String
Using input As New OcrInput()
input.LoadPdf(pdfPath)
Return _ocr.Read(input).Text
End Using
End Function
' Specific page range — no per-page billing penalty
Public Function ExtractPageRange(pdfPath As String, startPage As Integer, endPage As Integer) As String
Using input As New OcrInput()
input.LoadPdfPages(pdfPath, startPage, endPage)
Return _ocr.Read(input).Text
End Using
End Function
' If an async signature is required by an interface or controller
Public Function ExtractPdfTextAsync(pdfPath As String) As Task(Of String)
Return Task.Run(Function() ExtractPdfText(pdfPath))
End Function
End Class
Anket döngüsü ve gecikme mantığı tamamen ortadan kaybolur. LoadPdfPages sayfa aralığı seçimini yönetir — sayfa başına ayrı çağrı yok, işlem sayma yok. PDF giriş kılavuzu tam detayda akış girişi, byte dizisi yükleme ve sayfa aralığı parametrelerini kapsar.
Azure Kelime Seviyesindeki SonuçlarıIronOCR Yapılandırılmış Çıktıya Eşleme
Azure Computer Vision, kelime sınırlayıcı kutularını değişken sayıda köşesi olan çokgenler olarak döndürür — tipik olarak dört, ancak garantili değildir. Sonuç hiyerarşisi Blocks → Lines → Words ve güven float 0.0–1.0 ölçeğinde. Kelime konumlarını okuyan kod, çokgen köşe dizisini yönetmeli ve herhangi bir eşik karşılaştırması için güven ölçeğini normalleştirmelidir.
Azure Computer Vision Yöntemi:
public async Task<List<WordResult>> ExtractWordPositionsAsync(string imagePath)
{
using var stream = File.OpenRead(imagePath);
var imageData = BinaryData.FromStream(stream);
var response = await _client.AnalyzeAsync(imageData, VisualFeatures.Read);
var words = new List<WordResult>();
foreach (var block in response.Value.Read.Blocks)
{
foreach (var line in block.Lines)
{
foreach (var word in line.Words)
{
// BoundingPolygon is a list of ImagePoint — variable vertex count
var polygon = word.BoundingPolygon;
int minX = polygon.Min(p => p.X);
int minY = polygon.Min(p => p.Y);
int maxX = polygon.Max(p => p.X);
int maxY = polygon.Max(p => p.Y);
words.Add(new WordResult
{
Text = word.Text,
// Azure confidence: 0.0 to 1.0 — multiply by 100 for comparison
Confidence = (double)word.Confidence * 100.0,
X = minX,
Y = minY,
Width = maxX - minX,
Height = maxY - minY
});
}
}
}
return words;
}
public record WordResult(string Text, double Confidence, int X, int Y, int Width, int Height);
public async Task<List<WordResult>> ExtractWordPositionsAsync(string imagePath)
{
using var stream = File.OpenRead(imagePath);
var imageData = BinaryData.FromStream(stream);
var response = await _client.AnalyzeAsync(imageData, VisualFeatures.Read);
var words = new List<WordResult>();
foreach (var block in response.Value.Read.Blocks)
{
foreach (var line in block.Lines)
{
foreach (var word in line.Words)
{
// BoundingPolygon is a list of ImagePoint — variable vertex count
var polygon = word.BoundingPolygon;
int minX = polygon.Min(p => p.X);
int minY = polygon.Min(p => p.Y);
int maxX = polygon.Max(p => p.X);
int maxY = polygon.Max(p => p.Y);
words.Add(new WordResult
{
Text = word.Text,
// Azure confidence: 0.0 to 1.0 — multiply by 100 for comparison
Confidence = (double)word.Confidence * 100.0,
X = minX,
Y = minY,
Width = maxX - minX,
Height = maxY - minY
});
}
}
}
return words;
}
public record WordResult(string Text, double Confidence, int X, int Y, int Width, int Height);
Imports System.IO
Imports System.Threading.Tasks
Imports System.Linq
Public Class ImageAnalyzer
Private _client As SomeClientType ' Replace with the actual type of _client
Public Async Function ExtractWordPositionsAsync(imagePath As String) As Task(Of List(Of WordResult))
Using stream = File.OpenRead(imagePath)
Dim imageData = BinaryData.FromStream(stream)
Dim response = Await _client.AnalyzeAsync(imageData, VisualFeatures.Read)
Dim words = New List(Of WordResult)()
For Each block In response.Value.Read.Blocks
For Each line In block.Lines
For Each word In line.Words
' BoundingPolygon is a list of ImagePoint — variable vertex count
Dim polygon = word.BoundingPolygon
Dim minX = polygon.Min(Function(p) p.X)
Dim minY = polygon.Min(Function(p) p.Y)
Dim maxX = polygon.Max(Function(p) p.X)
Dim maxY = polygon.Max(Function(p) p.Y)
words.Add(New WordResult With {
.Text = word.Text,
' Azure confidence: 0.0 to 1.0 — multiply by 100 for comparison
.Confidence = CDbl(word.Confidence) * 100.0,
.X = minX,
.Y = minY,
.Width = maxX - minX,
.Height = maxY - minY
})
Next
Next
Next
Return words
End Using
End Function
End Class
Public Class WordResult
Public Property Text As String
Public Property Confidence As Double
Public Property X As Integer
Public Property Y As Integer
Public Property Width As Integer
Public Property Height As Integer
End Class
IronOCR Yaklaşımı:
public List<WordResult> ExtractWordPositions(string imagePath)
{
var result = new IronTesseract().Read(imagePath);
var words = new List<WordResult>();
foreach (var page in result.Pages)
{
foreach (var line in page.Lines)
{
foreach (var word in line.Words)
{
// Rectangle-based bounding box — no polygon math required
// Confidence is already 0–100, matching the converted Azure scale
words.Add(new WordResult
{
Text = word.Text,
Confidence = word.Confidence, // 0–100, no conversion needed
X = word.X,
Y = word.Y,
Width = word.Width,
Height = word.Height
});
}
}
}
return words;
}
// Filter to only high-confidence words — common post-processing pattern
public IEnumerable<string> ExtractHighConfidenceWords(string imagePath, double threshold = 80.0)
{
var result = new IronTesseract().Read(imagePath);
return result.Words
.Where(w => w.Confidence >= threshold)
.Select(w => w.Text);
}
public record WordResult(string Text, double Confidence, int X, int Y, int Width, int Height);
public List<WordResult> ExtractWordPositions(string imagePath)
{
var result = new IronTesseract().Read(imagePath);
var words = new List<WordResult>();
foreach (var page in result.Pages)
{
foreach (var line in page.Lines)
{
foreach (var word in line.Words)
{
// Rectangle-based bounding box — no polygon math required
// Confidence is already 0–100, matching the converted Azure scale
words.Add(new WordResult
{
Text = word.Text,
Confidence = word.Confidence, // 0–100, no conversion needed
X = word.X,
Y = word.Y,
Width = word.Width,
Height = word.Height
});
}
}
}
return words;
}
// Filter to only high-confidence words — common post-processing pattern
public IEnumerable<string> ExtractHighConfidenceWords(string imagePath, double threshold = 80.0)
{
var result = new IronTesseract().Read(imagePath);
return result.Words
.Where(w => w.Confidence >= threshold)
.Select(w => w.Text);
}
public record WordResult(string Text, double Confidence, int X, int Y, int Width, int Height);
Imports System.Collections.Generic
Imports System.Linq
Public Class WordExtractor
Public Function ExtractWordPositions(imagePath As String) As List(Of WordResult)
Dim result = New IronTesseract().Read(imagePath)
Dim words = New List(Of WordResult)()
For Each page In result.Pages
For Each line In page.Lines
For Each word In line.Words
' Rectangle-based bounding box — no polygon math required
' Confidence is already 0–100, matching the converted Azure scale
words.Add(New WordResult With {
.Text = word.Text,
.Confidence = word.Confidence, ' 0–100, no conversion needed
.X = word.X,
.Y = word.Y,
.Width = word.Width,
.Height = word.Height
})
Next
Next
Next
Return words
End Function
' Filter to only high-confidence words — common post-processing pattern
Public Function ExtractHighConfidenceWords(imagePath As String, Optional threshold As Double = 80.0) As IEnumerable(Of String)
Dim result = New IronTesseract().Read(imagePath)
Return result.Words _
.Where(Function(w) w.Confidence >= threshold) _
.Select(Function(w) w.Text)
End Function
End Class
Public Class WordResult
Public Property Text As String
Public Property Confidence As Double
Public Property X As Integer
Public Property Y As Integer
Public Property Width As Integer
Public Property Height As Integer
End Class
Çokgen-dikdörtgen dönüşüm ortadan kaybolur. Güven değerleri doğrudan eşleşir, mevcut her eşik mantığı, bu tek ayar ile çözülür. yapılandırılmış veri çıktısı kılavuzu tam hiyerarşiyi ve koordinat özelliklerini belgeler. Özellikle güven puanlama modeli için güven puanları kılavuzunu inceleyin.
Bulut Yüklemesi Olmadan Çok Sayfalı TIFF İşleme
Azure Computer Vision'ın ImageAnalysisClient tek görüntüleri kabul eder. Çok çerçeveli TIFF dosyaları — belge tarama iş akışlarında, faks arşivlerinde ve tıbbi görüntü işleme hatlarında yaygın olarak — ya yüklemeden önce TIFF'i tek tek görüntülere bölmeyi (çerçeve başına bir işlem) ya da ayrı yapılandırması ile birlikte Form Recognizer'a geçmeyi gerektirir. Hiçbir yol temiz değildir.
Azure Computer Vision Yöntemi:
// Azure does not support multi-frame TIFF directly via ImageAnalysisClient
// Must split frames manually and upload each as a separate transaction
public async Task<string> ExtractMultiFrameTiffAsync(string tiffPath)
{
// Load TIFF using System.Drawing or a third-party library
using var bitmap = new System.Drawing.Bitmap(tiffPath);
int frameCount = bitmap.GetFrameCount(
System.Drawing.Imaging.FrameDimension.Page);
var allText = new StringBuilder();
for (int i = 0; i < frameCount; i++)
{
// Select frame, save to temporary PNG, upload to Azure
bitmap.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
using var ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.Position = 0;
// Each frame = 1 Azure transaction = $0.001
var imageData = BinaryData.FromStream(ms);
var result = await _client.AnalyzeAsync(imageData, VisualFeatures.Read);
foreach (var block in result.Value.Read.Blocks)
foreach (var line in block.Lines)
allText.AppendLine(line.Text);
}
return allText.ToString();
}
// Azure does not support multi-frame TIFF directly via ImageAnalysisClient
// Must split frames manually and upload each as a separate transaction
public async Task<string> ExtractMultiFrameTiffAsync(string tiffPath)
{
// Load TIFF using System.Drawing or a third-party library
using var bitmap = new System.Drawing.Bitmap(tiffPath);
int frameCount = bitmap.GetFrameCount(
System.Drawing.Imaging.FrameDimension.Page);
var allText = new StringBuilder();
for (int i = 0; i < frameCount; i++)
{
// Select frame, save to temporary PNG, upload to Azure
bitmap.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
using var ms = new MemoryStream();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.Position = 0;
// Each frame = 1 Azure transaction = $0.001
var imageData = BinaryData.FromStream(ms);
var result = await _client.AnalyzeAsync(imageData, VisualFeatures.Read);
foreach (var block in result.Value.Read.Blocks)
foreach (var line in block.Lines)
allText.AppendLine(line.Text);
}
return allText.ToString();
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Text
Imports System.Threading.Tasks
Public Class TiffProcessor
Private _client As ImageAnalysisClient
Public Async Function ExtractMultiFrameTiffAsync(tiffPath As String) As Task(Of String)
' Load TIFF using System.Drawing or a third-party library
Using bitmap As New Bitmap(tiffPath)
Dim frameCount As Integer = bitmap.GetFrameCount(FrameDimension.Page)
Dim allText As New StringBuilder()
For i As Integer = 0 To frameCount - 1
' Select frame, save to temporary PNG, upload to Azure
bitmap.SelectActiveFrame(FrameDimension.Page, i)
Using ms As New MemoryStream()
bitmap.Save(ms, Imaging.ImageFormat.Png)
ms.Position = 0
' Each frame = 1 Azure transaction = $0.001
Dim imageData As BinaryData = BinaryData.FromStream(ms)
Dim result = Await _client.AnalyzeAsync(imageData, VisualFeatures.Read)
For Each block In result.Value.Read.Blocks
For Each line In block.Lines
allText.AppendLine(line.Text)
Next
Next
End Using
Next
Return allText.ToString()
End Using
End Function
End Class
IronOCR Yaklaşımı:
//IronOCR handles multi-frame TIFF natively — single call, no frame splitting
public string ExtractMultiFrameTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // all frames loaded automatically
var result = new IronTesseract().Read(input);
return result.Text;
}
// Access per-page data for frame-level reporting
public void ExtractTiffWithPageStats(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
var ocr = new IronTesseract();
var result = ocr.Read(input);
Console.WriteLine($"Total frames processed: {result.Pages.Length}");
foreach (var page in result.Pages)
{
Console.WriteLine($"Frame {page.PageNumber}: " +
$"{page.Words.Length} words, " +
$"confidence {page.Confidence:F1}%");
}
}
// Combine with preprocessing for scanned TIFF archives
public string ExtractLowQualityTiffArchive(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
input.Deskew();
input.DeNoise();
input.Contrast();
var result = new IronTesseract().Read(input);
return result.Text;
}
//IronOCR handles multi-frame TIFF natively — single call, no frame splitting
public string ExtractMultiFrameTiff(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // all frames loaded automatically
var result = new IronTesseract().Read(input);
return result.Text;
}
// Access per-page data for frame-level reporting
public void ExtractTiffWithPageStats(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
var ocr = new IronTesseract();
var result = ocr.Read(input);
Console.WriteLine($"Total frames processed: {result.Pages.Length}");
foreach (var page in result.Pages)
{
Console.WriteLine($"Frame {page.PageNumber}: " +
$"{page.Words.Length} words, " +
$"confidence {page.Confidence:F1}%");
}
}
// Combine with preprocessing for scanned TIFF archives
public string ExtractLowQualityTiffArchive(string tiffPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
input.Deskew();
input.DeNoise();
input.Contrast();
var result = new IronTesseract().Read(input);
return result.Text;
}
Imports System
' IronOCR handles multi-frame TIFF natively — single call, no frame splitting
Public Function ExtractMultiFrameTiff(tiffPath As String) As String
Using input As New OcrInput()
input.LoadImageFrames(tiffPath) ' all frames loaded automatically
Dim result = New IronTesseract().Read(input)
Return result.Text
End Using
End Function
' Access per-page data for frame-level reporting
Public Sub ExtractTiffWithPageStats(tiffPath As String)
Using input As New OcrInput()
input.LoadImageFrames(tiffPath)
Dim ocr As New IronTesseract()
Dim result = ocr.Read(input)
Console.WriteLine($"Total frames processed: {result.Pages.Length}")
For Each page In result.Pages
Console.WriteLine($"Frame {page.PageNumber}: " &
$"{page.Words.Length} words, " &
$"confidence {page.Confidence:F1}%")
Next
End Using
End Sub
' Combine with preprocessing for scanned TIFF archives
Public Function ExtractLowQualityTiffArchive(tiffPath As String) As String
Using input As New OcrInput()
input.LoadImageFrames(tiffPath)
input.Deskew()
input.DeNoise()
input.Contrast()
Dim result = New IronTesseract().Read(input)
Return result.Text
End Using
End Function
Çerçeve başına işlem maliyeti sıfıra düşer. System.Drawing çerçeve çıkarma döngüsü ve onun geçici PNG serileştirme adımı tamamen kaldırılır. Doküman kalitesinin değişken olduğu faks arşiv iş akışları için, TIFF ve GIF giriş kılavuzu çerçeve seçim seçeneklerini kapsar ve görüntü kalitesi düzeltme kılavuzu tam ön işleme filtre setini belgeler.
Oran Limiti Kuyruklaması Olmadan Paralel Toplu İşleme
Azure Computer Vision'un S1 seviyesi throughput'u saniyede 10 işlemle sınırlar. Bu oranı aşan toplu görevler HTTP 429 yanıtlarını alır. Üretim uygulamaları, sınır içinde kalmak için hız sınırlaması saran bir katman, bir semafor veya bir kuyruklama katmanı gerektirir.IronOCR API, tasarım gereğince iş parçacığı güvendedir — iş parçacığı başına bir IronTesseract örneği oluşturun ve Parallel.ForEach ile çalıştırın.
Azure Computer Vision Yöntemi:
// Must throttle to 10 TPS to avoid 429 errors on S1 tier
public class ThrottledAzureBatchProcessor
{
private readonly ImageAnalysisClient _client;
// Semaphore limits concurrent Azure calls to stay under 10 TPS
private readonly SemaphoreSlim _throttle = new SemaphoreSlim(10, 10);
public async Task<Dictionary<string, string>> ProcessBatchAsync(
IEnumerable<string> imagePaths)
{
var results = new ConcurrentDictionary<string, string>();
var tasks = imagePaths.Select(async path =>
{
await _throttle.WaitAsync();
try
{
using var stream = File.OpenRead(path);
var data = BinaryData.FromStream(stream);
var response = await _client.AnalyzeAsync(data, VisualFeatures.Read);
var text = string.Join("\n",
response.Value.Read.Blocks
.SelectMany(b => b.Lines)
.Select(l => l.Text));
results[path] = text;
// Respect 1-second window for the 10 TPS ceiling
await Task.Delay(100);
}
catch (RequestFailedException ex) when (ex.Status == 429)
{
// Rate limited despite throttling — back off and retry
await Task.Delay(2000);
// Re-queue or log failure — simplified here
results[path] = string.Empty;
}
finally
{
_throttle.Release();
}
});
await Task.WhenAll(tasks);
return new Dictionary<string, string>(results);
}
}
// Must throttle to 10 TPS to avoid 429 errors on S1 tier
public class ThrottledAzureBatchProcessor
{
private readonly ImageAnalysisClient _client;
// Semaphore limits concurrent Azure calls to stay under 10 TPS
private readonly SemaphoreSlim _throttle = new SemaphoreSlim(10, 10);
public async Task<Dictionary<string, string>> ProcessBatchAsync(
IEnumerable<string> imagePaths)
{
var results = new ConcurrentDictionary<string, string>();
var tasks = imagePaths.Select(async path =>
{
await _throttle.WaitAsync();
try
{
using var stream = File.OpenRead(path);
var data = BinaryData.FromStream(stream);
var response = await _client.AnalyzeAsync(data, VisualFeatures.Read);
var text = string.Join("\n",
response.Value.Read.Blocks
.SelectMany(b => b.Lines)
.Select(l => l.Text));
results[path] = text;
// Respect 1-second window for the 10 TPS ceiling
await Task.Delay(100);
}
catch (RequestFailedException ex) when (ex.Status == 429)
{
// Rate limited despite throttling — back off and retry
await Task.Delay(2000);
// Re-queue or log failure — simplified here
results[path] = string.Empty;
}
finally
{
_throttle.Release();
}
});
await Task.WhenAll(tasks);
return new Dictionary<string, string>(results);
}
}
Imports System.Collections.Concurrent
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
' Must throttle to 10 TPS to avoid 429 errors on S1 tier
Public Class ThrottledAzureBatchProcessor
Private ReadOnly _client As ImageAnalysisClient
' Semaphore limits concurrent Azure calls to stay under 10 TPS
Private ReadOnly _throttle As New SemaphoreSlim(10, 10)
Public Async Function ProcessBatchAsync(imagePaths As IEnumerable(Of String)) As Task(Of Dictionary(Of String, String))
Dim results As New ConcurrentDictionary(Of String, String)()
Dim tasks = imagePaths.Select(Async Function(path)
Await _throttle.WaitAsync()
Try
Using stream = File.OpenRead(path)
Dim data = BinaryData.FromStream(stream)
Dim response = Await _client.AnalyzeAsync(data, VisualFeatures.Read)
Dim text = String.Join(vbLf,
response.Value.Read.Blocks _
.SelectMany(Function(b) b.Lines) _
.Select(Function(l) l.Text))
results(path) = text
' Respect 1-second window for the 10 TPS ceiling
Await Task.Delay(100)
End Using
Catch ex As RequestFailedException When ex.Status = 429
' Rate limited despite throttling — back off and retry
Await Task.Delay(2000)
' Re-queue or log failure — simplified here
results(path) = String.Empty
Finally
_throttle.Release()
End Try
End Function)
Await Task.WhenAll(tasks)
Return New Dictionary(Of String, String)(results)
End Function
End Class
IronOCR Yaklaşımı:
//Hayırrate limiting needed — throughput is hardware-bound
public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
var results = new ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, imagePath =>
{
// Each thread gets its own IronTesseract instance — fully thread-safe
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
});
return new Dictionary<string, string>(results);
}
// With controlled parallelism for memory-constrained environments
public Dictionary<string, string> ProcessBatchControlled(
IEnumerable<string> imagePaths, int maxDegreeOfParallelism = 4)
{
var results = new ConcurrentDictionary<string, string>();
var options = new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism };
Parallel.ForEach(imagePaths, options, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
});
return new Dictionary<string, string>(results);
}
//Hayırrate limiting needed — throughput is hardware-bound
public Dictionary<string, string> ProcessBatch(IEnumerable<string> imagePaths)
{
var results = new ConcurrentDictionary<string, string>();
Parallel.ForEach(imagePaths, imagePath =>
{
// Each thread gets its own IronTesseract instance — fully thread-safe
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
});
return new Dictionary<string, string>(results);
}
// With controlled parallelism for memory-constrained environments
public Dictionary<string, string> ProcessBatchControlled(
IEnumerable<string> imagePaths, int maxDegreeOfParallelism = 4)
{
var results = new ConcurrentDictionary<string, string>();
var options = new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism };
Parallel.ForEach(imagePaths, options, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
});
return new Dictionary<string, string>(results);
}
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Threading.Tasks
Public Class BatchProcessor
' Hayırrate limiting needed — throughput is hardware-bound
Public Function ProcessBatch(imagePaths As IEnumerable(Of String)) As Dictionary(Of String, String)
Dim results = New ConcurrentDictionary(Of String, String)()
Parallel.ForEach(imagePaths, Sub(imagePath)
' Each thread gets its own IronTesseract instance — fully thread-safe
Dim ocr = New IronTesseract()
Dim result = ocr.Read(imagePath)
results(imagePath) = result.Text
End Sub)
Return New Dictionary(Of String, String)(results)
End Function
' With controlled parallelism for memory-constrained environments
Public Function ProcessBatchControlled(imagePaths As IEnumerable(Of String), Optional maxDegreeOfParallelism As Integer = 4) As Dictionary(Of String, String)
Dim results = New ConcurrentDictionary(Of String, String)()
Dim options = New ParallelOptions With {.MaxDegreeOfParallelism = maxDegreeOfParallelism}
Parallel.ForEach(imagePaths, options, Sub(imagePath)
Dim ocr = New IronTesseract()
Dim result = ocr.Read(imagePath)
results(imagePath) = result.Text
End Sub)
Return New Dictionary(Of String, String)(results)
End Function
End Class
Semafor, 100ms gecikme ve HTTP 429 catch bloğu tümüyle kaldırılır. Paralellik sadece CPU çekirdekleri ve mevcut bellekle sınırlıdır, bir hizmet seviyesi ile değil. çoklu iş parçacığı örneği tam deseni zamanlama karşılaştırmaları ile gösterir ve hız optimizasyon rehberi toplu iş yükleri için motor yapılandırma ayarlarını kapsar.
Azure'un Reddettiği Düşük Kaliteli Tarama Ön İşlemesi
Azure Computer Vision sunucu tarafında görüntü geliştirme yapar, ancak opak ve yapılandırılamaz. Çok eğimli, çok gürültülü veya düşük kontrastlı belgeler, müdahale etme yolu olmadan düşük güven sonuçları veya boş metin döndürür. IronOCR, ön işleme hattını doğrudan OcrInput üzerinde açığa çıkarır.
Azure Computer Vision Yöntemi:
//Hayırclient-side preprocessing API — must preprocess externally before upload
public async Task<string> ExtractFromLowQualityScanAsync(string imagePath)
{
// Option 1: Accept whatever Azure returns (may be empty or low-quality)
using var stream = File.OpenRead(imagePath);
var imageData = BinaryData.FromStream(stream);
var result = await _client.AnalyzeAsync(imageData, VisualFeatures.Read);
//Hayırway to know if the server applied enhancement
//Hayırconfidence on the overall result — only per-word
var text = string.Join("\n",
result.Value.Read.Blocks
.SelectMany(b => b.Lines)
.Select(l => l.Text));
if (string.IsNullOrWhiteSpace(text))
{
// Option 2: Apply external preprocessing using System.Drawing, SkiaSharp,
// or ImageMagick, re-serialize to stream, re-upload — second billable transaction
throw new Exception("Azure returned empty result; manual preprocessing needed");
}
return text;
}
//Hayırclient-side preprocessing API — must preprocess externally before upload
public async Task<string> ExtractFromLowQualityScanAsync(string imagePath)
{
// Option 1: Accept whatever Azure returns (may be empty or low-quality)
using var stream = File.OpenRead(imagePath);
var imageData = BinaryData.FromStream(stream);
var result = await _client.AnalyzeAsync(imageData, VisualFeatures.Read);
//Hayırway to know if the server applied enhancement
//Hayırconfidence on the overall result — only per-word
var text = string.Join("\n",
result.Value.Read.Blocks
.SelectMany(b => b.Lines)
.Select(l => l.Text));
if (string.IsNullOrWhiteSpace(text))
{
// Option 2: Apply external preprocessing using System.Drawing, SkiaSharp,
// or ImageMagick, re-serialize to stream, re-upload — second billable transaction
throw new Exception("Azure returned empty result; manual preprocessing needed");
}
return text;
}
Imports System.IO
Imports System.Threading.Tasks
Public Class YourClassName
Public Async Function ExtractFromLowQualityScanAsync(imagePath As String) As Task(Of String)
' Option 1: Accept whatever Azure returns (may be empty or low-quality)
Using stream = File.OpenRead(imagePath)
Dim imageData = BinaryData.FromStream(stream)
Dim result = Await _client.AnalyzeAsync(imageData, VisualFeatures.Read)
' No way to know if the server applied enhancement
' No confidence on the overall result — only per-word
Dim text = String.Join(vbCrLf,
result.Value.Read.Blocks _
.SelectMany(Function(b) b.Lines) _
.Select(Function(l) l.Text))
If String.IsNullOrWhiteSpace(text) Then
' Option 2: Apply external preprocessing using System.Drawing, SkiaSharp,
' or ImageMagick, re-serialize to stream, re-upload — second billable transaction
Throw New Exception("Azure returned empty result; manual preprocessing needed")
End If
Return text
End Using
End Function
End Class
IronOCR Yaklaşımı:
// Preprocessing is part of the same call — no re-upload, no second transaction
public string ExtractFromLowQualityScan(string imagePath)
{
using var input = new OcrInput();
input.LoadImage(imagePath);
// Correct common scanning defects before OCR
input.Deskew(); // Fix rotated documents
input.DeNoise(); // Remove scanner noise
input.Contrast(); // Improve contrast for faded documents
input.Binarize(); // Convert to black and white
var ocr = new IronTesseract();
var result = ocr.Read(input);
Console.WriteLine($"Confidence after preprocessing: {result.Confidence:F1}%");
return result.Text;
}
// For severely degraded documents
public string ExtractFromDegradedDocument(string imagePath)
{
using var input = new OcrInput();
input.LoadImage(imagePath);
input.DeepCleanBackgroundNoise(); // Deep learning-based noise removal
input.Deskew();
input.Scale(150); // Upscale for better character resolution
var result = new IronTesseract().Read(input);
return result.Text;
}
// Preprocessing is part of the same call — no re-upload, no second transaction
public string ExtractFromLowQualityScan(string imagePath)
{
using var input = new OcrInput();
input.LoadImage(imagePath);
// Correct common scanning defects before OCR
input.Deskew(); // Fix rotated documents
input.DeNoise(); // Remove scanner noise
input.Contrast(); // Improve contrast for faded documents
input.Binarize(); // Convert to black and white
var ocr = new IronTesseract();
var result = ocr.Read(input);
Console.WriteLine($"Confidence after preprocessing: {result.Confidence:F1}%");
return result.Text;
}
// For severely degraded documents
public string ExtractFromDegradedDocument(string imagePath)
{
using var input = new OcrInput();
input.LoadImage(imagePath);
input.DeepCleanBackgroundNoise(); // Deep learning-based noise removal
input.Deskew();
input.Scale(150); // Upscale for better character resolution
var result = new IronTesseract().Read(input);
return result.Text;
}
Imports System
Public Class OcrProcessor
' Preprocessing is part of the same call — no re-upload, no second transaction
Public Function ExtractFromLowQualityScan(imagePath As String) As String
Using input As New OcrInput()
input.LoadImage(imagePath)
' Correct common scanning defects before OCR
input.Deskew() ' Fix rotated documents
input.DeNoise() ' Remove scanner noise
input.Contrast() ' Improve contrast for faded documents
input.Binarize() ' Convert to black and white
Dim ocr As New IronTesseract()
Dim result = ocr.Read(input)
Console.WriteLine($"Confidence after preprocessing: {result.Confidence:F1}%")
Return result.Text
End Using
End Function
' For severely degraded documents
Public Function ExtractFromDegradedDocument(imagePath As String) As String
Using input As New OcrInput()
input.LoadImage(imagePath)
input.DeepCleanBackgroundNoise() ' Deep learning-based noise removal
input.Deskew()
input.Scale(150) ' Upscale for better character resolution
Dim result = New IronTesseract().Read(input)
Return result.Text
End Using
End Function
End Class
Dış ön işleme bağımlılığı - System.Drawing, SkiaSharp veya ImageMagick - kaldırılır. Yeniden yükleme ve ikinci işlem maliyeti ortadan kaybolur. Ön işleme hattı, OcrInput yaşam döngüsünün bir parçasıdır, bu nedenle görüntü OCR motoruna ulaşmadan önce uygulanır. görüntü filtreleri eğitimi her filtreyi öncesi/sonrası doğruluk karşılaştırmaları ile ele alır.
Azure Computer Vision OCRAPI'den IronOCR Eşleme Referansı
| Azure Computer Vision | IronOCR Karşılığı |
|---|---|
ImageAnalysisClient |
IronTesseract |
new AzureKeyCredential(apiKey) |
IronOcr.License.LicenseKey = key |
new Uri(endpoint) |
Gerekli değil |
client.AnalyzeAsync(data, VisualFeatures.Read) |
ocr.Read(imagePath) |
BinaryData.FromStream(stream) |
input.LoadImage(stream) |
BinaryData.FromBytes(bytes) |
input.LoadImage(bytes) |
result.Value.Read.Blocks |
result.Pages[i].Paragraphs |
block.Lines |
result.Pages[i].Lines |
line.Text |
line.Text |
line.Words |
line.Words |
word.Text |
word.Text |
word.Confidence (0.0–1.0 float) |
word.Confidence (0–100 double) |
word.BoundingPolygon |
word.X, word.Y, word.Width, word.Height |
DocumentAnalysisClient |
IronTesseract + OcrInput |
AnalyzeDocumentAsync(WaitUntil.Completed, "prebuilt-read", stream) |
ocr.Read(input) input.LoadPdf(path) ile |
operation.Value.Pages |
result.Pages |
page.Lines[i].Content |
result.Lines[i].Text |
UpdateStatusAsync() oylama döngüsü |
Gerekli değil — eşzamanlı sonuç |
RequestFailedException (durum 429) |
Geçerli değil — hız sınırları yok |
RequestFailedException (durum 5xx) |
Geçerli değil — hizmet hataları yok |
VisualFeatures.Read enum bayrak |
Örtük — Read() her zaman metin çıkartır |
Form Recognizer prebuilt-read modeli |
Dahili OCR motoru (model seçimi yok) |
Azure uç nokta URL'si appsettings.json içinde |
Gerekli değil |
| API anahtarı rotasyon prosedürleri | Gerekli değil |
Yaygın Göç Sorunları ve Çözümleri
Sorun 1: Değiştirilemeyen Async Arabirim Sözleşmeleri
Azure Computer Vision: Hizmet arayüzleri genellikle Azure async gerektirdiği için Task<string> dönüş türlerini beyan eder. Çağrı yapan kod, kontrolörler ve arka plan çalışanları, tamamı async yöntemleri olarak yazılır. IronOCR'ye geçiş, OCR katmanında async gereksinimini ortadan kaldırır, ancak her bir arabirim imzasını değiştirmek büyük bir kod tabanında her zaman mümkün değildir.
Çözüm: Mevcut arayüze uyum sağlamak için senkron IronOCR çağrısını refaktör etmeksizin Task.Run sarın:
// Existing interface — do not change it
public interface IOcrService
{
Task<string> ReadAsync(string imagePath);
}
// New IronOCR implementation — fulfills the contract
public class IronOcrService : IOcrService
{
private readonly IronTesseract _ocr;
public IronOcrService(IronTesseract ocr) => _ocr = ocr;
public Task<string> ReadAsync(string imagePath)
{
// Task.Run offloads to thread pool — no await chain needed
return Task.Run(() => _ocr.Read(imagePath).Text);
}
}
// Existing interface — do not change it
public interface IOcrService
{
Task<string> ReadAsync(string imagePath);
}
// New IronOCR implementation — fulfills the contract
public class IronOcrService : IOcrService
{
private readonly IronTesseract _ocr;
public IronOcrService(IronTesseract ocr) => _ocr = ocr;
public Task<string> ReadAsync(string imagePath)
{
// Task.Run offloads to thread pool — no await chain needed
return Task.Run(() => _ocr.Read(imagePath).Text);
}
}
Imports System.Threading.Tasks
' Existing interface — do not change it
Public Interface IOcrService
Function ReadAsync(imagePath As String) As Task(Of String)
End Interface
' New IronOCR implementation — fulfills the contract
Public Class IronOcrService
Implements IOcrService
Private ReadOnly _ocr As IronTesseract
Public Sub New(ocr As IronTesseract)
_ocr = ocr
End Sub
Public Function ReadAsync(imagePath As String) As Task(Of String) Implements IOcrService.ReadAsync
' Task.Run offloads to thread pool — no await chain needed
Return Task.Run(Function() _ocr.Read(imagePath).Text)
End Function
End Class
Bu geçerli bir ara adımdır. Tam async entegrasyonunun tercih edildiği senaryolar için IronOCR'un yerleşik async desteğini async OCR kılavuzu kapsar.
Sorun 2: Yanlış Sonuçlar Üreten Güven Eşik Mantığı
Azure Computer Vision: Azure, kelime güvenini 0.0 ile 1.0 arasında bir float döndürür. Mevcut filtreleme kodu word.Confidence > 0.85f gibi eşikleri kullanır. Geçişten sonra, bu karşılaştırmalar her zaman yanlış değerlendirir çünkü IronOCR güven 0–100, 0–1 arasında değil.
Çözüm: Ortam filtresi mantığı güncellenirken mevcut Azure eşiklerini 100 ile çarpın:
// Before: Azure threshold (0.0 - 1.0 scale)
var highConfidenceWords = azureWords
.Where(w => w.Confidence > 0.85f)
.Select(w => w.Text);
// After:IronOCR threshold (0 - 100 scale)
var result = new IronTesseract().Read(imagePath);
var highConfidenceWords = result.Words
.Where(w => w.Confidence > 85.0)
.Select(w => w.Text);
// Overall document confidence — also on 0-100 scale
if (result.Confidence < 70.0)
{
// Document may need preprocessing or manual review
}
// Before: Azure threshold (0.0 - 1.0 scale)
var highConfidenceWords = azureWords
.Where(w => w.Confidence > 0.85f)
.Select(w => w.Text);
// After:IronOCR threshold (0 - 100 scale)
var result = new IronTesseract().Read(imagePath);
var highConfidenceWords = result.Words
.Where(w => w.Confidence > 85.0)
.Select(w => w.Text);
// Overall document confidence — also on 0-100 scale
if (result.Confidence < 70.0)
{
// Document may need preprocessing or manual review
}
Imports System.Linq
' Before: Azure threshold (0.0 - 1.0 scale)
Dim highConfidenceWords = azureWords _
.Where(Function(w) w.Confidence > 0.85F) _
.Select(Function(w) w.Text)
' After: IronOCR threshold (0 - 100 scale)
Dim result = New IronTesseract().Read(imagePath)
Dim highConfidenceWords = result.Words _
.Where(Function(w) w.Confidence > 85.0) _
.Select(Function(w) w.Text)
' Overall document confidence — also on 0-100 scale
If result.Confidence < 70.0 Then
' Document may need preprocessing or manual review
End If
Sorun 3: Form Recognizer'ın Önceden Yapılandırılmış Model Alanı Çıkarmasının IronOCR Eşdeğeri Yoktur
Azure Computer Vision: Form Recognizer'ın önceden oluşturulmuş fatura ve makbuz modelleri, sayfa üzerinde bu alanların nerede göründüğünü belirtmeden, adlandırılmış alanları otomatik olarak çıkarır — InvoiceTotal, VendorName, InvoiceDate. Çıkarma mantığı Azure modeline gömülüdür.
Çözüm: Model tabanlı alan çıkarımını, CropRectangle kullanarak bölge tabanlı OCR ile değiştirin. Bu, belge düzenini bilmeyi gerektirir, ancak çoğu gerçek dünya dağıtımları zaten sabit şablonlara sahiptir:
var ocr = new IronTesseract();
// Define extraction zones for a known invoice template
var headerZone = new CropRectangle(50, 40, 400, 60);
var totalZone = new CropRectangle(350, 600, 250, 50);
var dateZone = new CropRectangle(400, 100, 200, 40);
string header, total, date;
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg", headerZone);
header = ocr.Read(input).Text.Trim();
}
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg", totalZone);
total = ocr.Read(input).Text.Trim();
}
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg", dateZone);
date = ocr.Read(input).Text.Trim();
}
var ocr = new IronTesseract();
// Define extraction zones for a known invoice template
var headerZone = new CropRectangle(50, 40, 400, 60);
var totalZone = new CropRectangle(350, 600, 250, 50);
var dateZone = new CropRectangle(400, 100, 200, 40);
string header, total, date;
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg", headerZone);
header = ocr.Read(input).Text.Trim();
}
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg", totalZone);
total = ocr.Read(input).Text.Trim();
}
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg", dateZone);
date = ocr.Read(input).Text.Trim();
}
Imports IronOcr
Dim ocr As New IronTesseract()
' Define extraction zones for a known invoice template
Dim headerZone As New CropRectangle(50, 40, 400, 60)
Dim totalZone As New CropRectangle(350, 600, 250, 50)
Dim dateZone As New CropRectangle(400, 100, 200, 40)
Dim header As String
Dim total As String
Dim date As String
Using input As New OcrInput()
input.LoadImage("invoice.jpg", headerZone)
header = ocr.Read(input).Text.Trim()
End Using
Using input As New OcrInput()
input.LoadImage("invoice.jpg", totalZone)
total = ocr.Read(input).Text.Trim()
End Using
Using input As New OcrInput()
input.LoadImage("invoice.jpg", dateZone)
date = ocr.Read(input).Text.Trim()
End Using
bölge tabanlı OCR kılavuzu koordinat sistemi detayları ve çok bölgeli toplu işlemeyi kapsar.
Problem 4: Eksik hOCR ve Yapılandırılmış Dışa Aktarım
Azure Computer Vision: Azure, hOCR çıktısı sağlamaz. Aşağı kesme belge analiz araçları için standartlaştırılmış düzen verilerine ihtiyaç duyan ekipler, bağlama kutularını Azure yanıtından manuel olarak çıkarır ve kendi çıktı formatlarını oluştururlar.
Çözüm: IronOCR, tek bir çağrıda standartları uyumlu hOCR üretir:
var result = new IronTesseract().Read("document.jpg");
// Write hOCR file — recognized by most document analysis tools
result.SaveAsHocrFile("document.hocr");
// Searchable PDF — alternative for archive and search indexing workflows
result.SaveAsSearchablePdf("document-searchable.pdf");
var result = new IronTesseract().Read("document.jpg");
// Write hOCR file — recognized by most document analysis tools
result.SaveAsHocrFile("document.hocr");
// Searchable PDF — alternative for archive and search indexing workflows
result.SaveAsSearchablePdf("document-searchable.pdf");
Dim result = (New IronTesseract()).Read("document.jpg")
' Write hOCR file — recognized by most document analysis tools
result.SaveAsHocrFile("document.hocr")
' Searchable PDF — alternative for archive and search indexing workflows
result.SaveAsSearchablePdf("document-searchable.pdf")
Probleme 5: Diğer Azure Paketleri ile Azure SDK Sürüm Çatışmaları
Azure Computer Vision: Birden fazla Azure SDK paketi (Azure.Storage.Blobs, Azure.Identity, Azure.KeyVault.Secrets) kullanan projeler, Azure.Core transitif bağımlılıklar arasında sürüm çakışmaları ile karşılaşabilir. Azure SDK'nın monorepo sürümleme politikası yardımcı olur ancak tüm çakışmaları ortadan kaldıramaz, özellikle GA ve önizleme SDK sürümleri karıştırıldığında.
Çözüm: Azure.AI.Vision.ImageAnalysis ve Azure.AI.FormRecognizer kaldırılması, bu SDK paketlerini bağımlılık ağacından çıkarır. Proje Azure'u sadece OCR için kullanıyorsa, tüm Azure.* bağımlılık seti kaldırılır. Diğer Azure hizmetleri kalırsa, azaltılmış paket sayısı çatışma alanını azaltır:
# Remove only the OCR-related Azure packages
dotnet remove package Azure.AI.Vision.ImageAnalysis
dotnet remove package Azure.AI.FormRecognizer
# Verify remaining Azure packages have no new conflicts
dotnet restore
dotnet build
# Remove only the OCR-related Azure packages
dotnet remove package Azure.AI.Vision.ImageAnalysis
dotnet remove package Azure.AI.FormRecognizer
# Verify remaining Azure packages have no new conflicts
dotnet restore
dotnet build
Problem 6: Taratılmış Belge Kalitesi, Azure Kabul Eşiğinin Altında
Azure Computer Vision: Çok düşük çözünürlüklü görüntüler (~150 DPI'nın altında) veya ciddi şekilde eğilmiş taramalar, Azure'un sunucu tarafı hattından minimum veya boş metin döndürür ve hangi iyileştirmenin denendiğine dair bir geri bildirim sağlamaz. Çağrıcı, dış ön işlem olmadan sonucu iyileştirmenin bir yoluna sahip değil.
Çözüm: IronOCR'un ön işleme hattını kullanarak görüntüyü OCR öncesinde hazırlayın:
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();
input.DeNoise();
input.Scale(200); // Upscale to improve character resolution
input.Contrast();
input.Sharpen();
var result = new IronTesseract().Read(input);
Console.WriteLine($"Extraction confidence: {result.Confidence:F1}%");
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();
input.DeNoise();
input.Scale(200); // Upscale to improve character resolution
input.Contrast();
input.Sharpen();
var result = new IronTesseract().Read(input);
Console.WriteLine($"Extraction confidence: {result.Confidence:F1}%");
Imports IronOcr
Using input As New OcrInput()
input.LoadImage("low-quality-scan.jpg")
input.Deskew()
input.DeNoise()
input.Scale(200) ' Upscale to improve character resolution
input.Contrast()
input.Sharpen()
Dim result = New IronTesseract().Read(input)
Console.WriteLine($"Extraction confidence: {result.Confidence:F1}%")
End Using
görüntü yönü düzeltme kılavuzu, özellikle deskew ve döndürme algılamasını kapsar.
Azure Computer Vision OCRGeçiş Kontrol Listesi
Öncesi-Geçiş
Kod tabanında tümAzure Computer Visionve Form Recognizer kullanım yerlerini bulun:
# Find all Azure OCR-related using statements
grep -r "Azure.AI.Vision.ImageAnalysis" --include="*.cs" .
grep -r "Azure.AI.FormRecognizer" --include="*.cs" .
grep -r "ImageAnalysisClient" --include="*.cs" .
grep -r "DocumentAnalysisClient" --include="*.cs" .
grep -r "AnalyzeAsync" --include="*.cs" .
grep -r "AnalyzeDocumentAsync" --include="*.cs" .
grep -r "VisualFeatures.Read" --include="*.cs" .
grep -r "WaitUntil.Completed" --include="*.cs" .
grep -r "UpdateStatusAsync" --include="*.cs" .
grep -r "AzureKeyCredential" --include="*.cs" .
# Find all Azure OCR-related using statements
grep -r "Azure.AI.Vision.ImageAnalysis" --include="*.cs" .
grep -r "Azure.AI.FormRecognizer" --include="*.cs" .
grep -r "ImageAnalysisClient" --include="*.cs" .
grep -r "DocumentAnalysisClient" --include="*.cs" .
grep -r "AnalyzeAsync" --include="*.cs" .
grep -r "AnalyzeDocumentAsync" --include="*.cs" .
grep -r "VisualFeatures.Read" --include="*.cs" .
grep -r "WaitUntil.Completed" --include="*.cs" .
grep -r "UpdateStatusAsync" --include="*.cs" .
grep -r "AzureKeyCredential" --include="*.cs" .
Azure OCR uç noktalarını ve anahtarlarını içeren yapılandırma dosyalarını belirleyin:
grep -r "cognitiveservices.azure.com" --include="*.json" .
grep -r "AzureComputerVision\|FormRecognizer" --include="*.json" .
grep -r "ComputerVision\|FormRecognizer" --include="appsettings*.json" .
grep -r "cognitiveservices.azure.com" --include="*.json" .
grep -r "AzureComputerVision\|FormRecognizer" --include="*.json" .
grep -r "ComputerVision\|FormRecognizer" --include="appsettings*.json" .
Kodlamaya başlanmadan önce envanter öğeleri:
- Azure OCR hizmet desenleri uygulayan sınıf sayısı
- OCR çağrılarından yayılan asenkron yöntem zincirlerinin sayısı
- 0.0–1.0 Azure ölçeği kullanılarak herhangi bir kelime güvence eşiği belirleyin
- Bölge tabanlı değişiklik gerektiren Form Recognizer önceden hazırlanmış model kullanımı (fatura, makbuz, kimlik)
- Şu anda kare başına yükleme için bölünmüş çok kareli TIFF girişlerini tanımlayın
- Artık gerekli olmayacak dışa giden Azure ağ kuralları için Docker ve CI/CD yapılandırmalarını kontrol edin
Kod Geçişi
Azure.AI.Vision.ImageAnalysisNuGet paketini kullanan tüm projelerden kaldırınAzure.AI.FormRecognizerNuGet paketini kullanan tüm projelerden kaldırın- Her etkilenen projede
dotnet add package IronOcrçalıştırın - Uygulama başlangıcında
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")ekleyin using Azure; using Azure.AI.Vision.ImageAnalysis;withusing IronOcr;- DI'de bir singleton olarak
IronTesseractkaydettirin (services.AddSingleton<IronTesseract>()) AzureComputerVisionOptionsya da eşdeğer yapılandırma sınıflarını kaldırın;appsettings.jsonAzure OCR bölümlerini kaldırın- Bütün hizmet sınıflarında
ImageAnalysisClientyapıcı enjeksiyonuIronTesseractenjeksiyonu ile değiştirin AnalyzeAsync(BinaryData.FromStream(stream), VisualFeatures.Read)çağrılarını, uygun olduğu yerlerdeocr.Read(imagePath)veyaocr.Read(input)ileOcrInputile değiştirin- Tüm
UpdateStatusAsyncoylama döngülerini veWaitUntil.Completedörüntülerini kaldırın;DocumentAnalysisClient,IronTesseract+OcrInput.LoadPdf()ile değiştirin - Kelime güvence eşiği karşılaştırmalarını güncelleyin: Tüm Azure 0.0–1.0 değerlerini 100 ile çarpın
- Çokgen sınırlayıcı kutu erişimini (
word.BoundingPolygon.Min/Max) doğrudanword.X,word.Y,word.Width,word.Heightözellikleri ile değiştirin - Çoklu çerçeveli TIFF'e çerçeve başına yükleme döngülerini
input.LoadImageFrames(tiffPath)ile değiştirin - Form Recognizer önceden oluşturulmuş model alan çıkarımını bilinen belge şablonları için
CropRectangletabanlı bölge OCR'ine dönüştürün - HTTP 429 ve 5xx için
RequestFailedExceptionyakalama bloklarını kaldırın; hata işleme yalnızca dosya sistemi ve giriş doğrulama istisnalarına basitleştirilir
Geçiş Sonrası
- Düz metin çıkarma çıktısının, 20+ dökümanın temsilci bir örneği için Azure sonuçlarına eşit veya daha iyi olduğunu doğrulayın
- Çok sayfalı PDF işlemenin, izleme sırasında sayfa başına hiçbir ücretlendirme sayacı olmaksızın tüm sayfalar için metin ürettiğini teyit edin
- Çok kareli TIFF işlemenin, kaynak kare sayısı ile aynı sayfa sayısını döndürdüğünü test edin
- Kelime güvence değerlerinin 0-100 aralığında olduğunu ve eşik karşılaştırmalarının doğru çalıştığını doğrulayın
- Kelime bağlantı kutusu koordinatlarının doğru bir şekilde kaynak görüntü koordinat sistemi ile hizalandığını doğrulayın
- Toplu işleme yolunu çalıştırın ve hız sınırlama hatası veya semaphore çekişmesi olmadan tamamlandığını doğrulayın
- Çıkış internet erişimi olmayan bir ortamda test edin, hiçbir Azure uç nokta çağrısı olmadığını doğrulayın
- Docker ve konteyner yapılandırmalarının,
cognitiveservices.azure.comiçin dışa yönelik güvenlik duvarı kuralları olmadan başarıyla başladığını doğrulayın - DI kabı yapısının başarıyla tamamlandığını ve
IronTesseractsingleton'ının düzgün bir şekilde çözüldüğünü kontrol edin - Tüm dağıtım ortamlarında
IRONOCR_LICENSEortam değişkeninin ayarlandığını ve OCR'nin lisanslı (su işaretsiz) çıktılar ürettiğini doğrulayın
IronOCR'a Geçişin Ana Faydaları
Maliyet tahmin edilebilir hale gelir. Azure Computer Vision'un işlem başına sayaç sürekli olarak çalışır. Yüksek belge hacmine sahip tek bir ay, bir IronOCR lisansının yıllık maliyetini aşabilir. Geçişten sonra, OCR bütçesi sabit bir kalem öğesi olur. İşleme hacmi, iş geliştirme, toplu yeniden işleme veya geçici artışlar nedeniyle büyüyebilir ve bu, daha büyük bir fatura üretmeden olabilir. IronOCR lisanslama sayfası $999 tek geliştirici lisansından, sınırsız geliştiriciler için $2.999'a kadar kademeli seçenekler sunar.
Uygulama yığını daha basit hale geliyor. Azure.AI.Vision.ImageAnalysis ve Azure.AI.FormRecognizer kaldırılması, iki NuGet paketini, iki Azure kaynak yapılandırmasını, iki set kimlik bilgisini ve tüm async oylama altyapısını ortadan kaldırır. Daha önce bulut I/O nedeniyle bir async Task<string> imzası gerektiren hizmet sınıfları, senkron yöntemler haline gelir. Ağ hatalarından, oran sınırlamalarından ve hizmet kullanılabilirliğinden dosya sistemi ve giriş doğrulamaya kadar hata işleme daralır. Bu kod tabanında çalışan her gelecekteki geliştirici daha az kodla karşılaşacaktır.
Doküman verileri organizasyonun kontrolünde kalır. Geçişten sonra, OCR işleme yerel bir işlem haline gelir. Belgeler kurumsal sınırları geçmez, Azure telemetrisinde görünmez ve Microsoft'un veri saklama veya işleme politikalarına tabi olmaz. HIPAA kapsama alanı olan kuruluşlar, ITAR yüklenicileri, GDPR ile düzenlenmiş kuruluşlar ve veri yerleşim gereksinimi olan herhangi bir ekip, bulut üçüncü taraf uyumluluk incelemesi yapmaksızın belgeleri işleyebilir. Linux dağıtım kılavuzu ve Docker dağıtım kılavuzu, IronOCR'nin sınırlı ortamlarda nasıl dağıtılacağını gösterir.
Toplu işlem kapasitesi donanıma göre ölçeklenir. Azure'un S1 katmanındaki 10 TPS tavanı, kuyruklama, kısıtlama veya katman yükseltmeleri gerektiren zor bir sınırdır. Geçişten sonra, eşzamanlı OCR işleri, hizmet tarafından dayatılan bir sınır olmadan mevcut CPU çekirdeklerini doyurur. Dört çekirdekli bir sunucu, aynı anda dört paralel IronTesseract örneği çalıştırabilir. çok iş parçacıklı örnek, deseni gösterir ve çekirdek sayısı ile kapasite artışını gösterir.
Ön işleme hataları kodda çözülebilir. Azure Computer Vision'ın sunucu tarafı görüntü iyileştirmesi kara kutudur. Tarama boş veya düşük güvenli geri dönerse, kabul etmek veya ek maliyetle yeniden yüklemeden önce harici olarak ön işleme yapmak dışında seçenek yoktur. IronOCR'un OcrInput boru hattı, dengeleme, gürültü azaltma, kontrast, ikilestirme, ölçek, keskinleştirme ve derin gürültü giderme işlemlerini birinci sınıf yöntemler olarak açığa çıkarır. Sorunlu tarama türleri ayarlanabilir parametreler haline gelir. ön işleme özellikleri sayfası, hangi filtrelerin hangi tarama hatalarını giderdiğine dair rehberle birlikte eksiksiz filtre setini listeler.
Sıkça Sorulan Sorular
Neden Azure Computer Vision OCR'dan 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.
Azure Computer Vision OCR'dan IronOCR'a geçişteki ana kod değişiklikleri nelerdir?
Azure Computer Vision 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, Azure Computer Vision OCR'nin 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, Azure Computer Vision OCR'nin 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.
Azure Computer Vision OCR'dan IronOCR'a geçiş, dağıtım altyapısında değişiklikler gerektirir mi?
IronOCR, Azure Computer Vision OCR'dan 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 Azure Computer 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'un fiyatlandırması, Azure Computer Vision OCR'dan 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.
Azure Computer Vision OCR'dan 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.

