ABBYY FineReader vs Tesseract: OCR Karşılaştırması
OCR.space'in NuGet paketi yok. Bu tek gerçek, bir .NET geliştiricisinin onu seçerken yaptığı her entegrasyon kararını tanımlar: kendi özel HttpClient kodunuzu yazarsınız, belgelerinizi base64 kodlar, https://api.ocr.space/parse/image POST edersiniz, JSON yanıtını elle işler, HTTP 429'larını yakalarsınız, üstel geri alma uygularsınız, oran sınırlayıcı defter tutucusu oluşturur ve uygulamanıza bir metin karakteri gelmeden önce kendi özel hata türlerinizi belirlersiniz. Bu makale, bu DIY yükün kod, zaman ve üretim güvenilirliğinde ne maliyeti olduğunu incelemekte ve bunu, tek bir NuGet paketi olarak teslim edilen IronOCR ile doğrudan karşılaştırmaktadır.
OCR.space Anlama
OCR.space, OCR.space tarafından işletilen uzak sunucular üzerinde görüntü ve PDF işleyen freemium bir REST API'dir. Hizmet, kredi kartı gerektirmeyen aylık 25.000 talebi içeren ücretsiz katman etrafında konumlanıyor, bu da OCR ile denemeler yapan geliştiricilere veya kişisel projelerini geliştirenlere hitap ediyor. NuGet paketi yok, resmi .NET SDK yok ve herhangi bir dilde güçlü bir şekilde uyarlanmış istemci kütüphanesi yok. Her .NET entegrasyonu el yapımıdır ve HttpClient üzerine inşa edilmiştir.
.NET geliştiricileri için mimari gerçeklik:
- NuGet paketi yok: İlk sınıf .NET desteği sıfır. IntelliSense yok, uyarlanmış modeller yok, entegre hata işleme yok.
- Sadece bulutta işleme: Her belge altyapınızı terk eder. Yerinde (on-premise) bir seçenek ve kendi barındırılan dağıtım yolu yok.
- Manuel REST entegrasyonu: Geliştiriciler dosyaları base64'e kodlar,
FormUrlEncodedContentveyaMultipartFormDataContentoluşturur ve ham JSON yanıtlarını işler. - DIY hız sınır yapısı: Ücretsiz katman, IP başına dakikada 60 istek ve günlük 500 istek zorlar. Üretim uygulamaları bu mantığı kendileri inşa etmelidir.
- Dosya boyutu sınırlamaları: Ücretsiz katman, 5 MB üzeri dosyaları reddeder. Çok sayfalı PDF'ler genellikle bu limiti aşar.
- Ücretsiz katmanda düz PDF çıktısı: Ücretsiz katmandaki aranabilir PDF oluşturma, OCR.space filigranlarını yerleştirir, çıktının müşteri teslimatı veya belge arşivleme için kullanılmaz hale getirir.
- SLA yok: Ücretsiz katman, çalışma zamanı taahhüdü taşımaz. Ücretli planlar daha yüksek sınırlar sunar, ancak aynı mimari kısıtlamalara sahiptir.
REST Entegrasyonu Geliştiriciler Yazmalıdır
OCR.space'in belgeleri, geliştiricileri REST uç noktasına yönlendirir ve diğer her şeyi inşa etmeleri için bırakır. Minimum sürdürülebilir .NET istemcisi — üretim sertleştirmesi düşüncesi öncesinde — böyle görünür:
// OCR.space: what you build before the first line of your actual application
public class OcrSpaceApiClient : IDisposable
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
private readonly SemaphoreSlim _rateLimiter;
private const string ApiEndpoint = "https://api.ocr.space/parse/image";
private const int MaxFileSizeFree = 5 * 1024 * 1024; // 5MB — hard limit on free tier
private const int RateLimitPerMinute = 60;
public OcrSpaceApiClient(string apiKey)
{
_apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey));
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromSeconds(120);
_rateLimiter = new SemaphoreSlim(RateLimitPerMinute, RateLimitPerMinute);
}
public async Task<OcrResult> ExtractTextFromFileAsync(
string filePath,
string language = "eng",
CancellationToken cancellationToken = default)
{
if (!File.Exists(filePath))
throw new FileNotFoundException("Image file not found", filePath);
var fileInfo = new FileInfo(filePath);
if (fileInfo.Length > MaxFileSizeFree)
{
throw new InvalidOperationException(
$"File size {fileInfo.Length / 1024 / 1024}MB exceeds free tier limit of 5MB.");
}
await _rateLimiter.WaitAsync(cancellationToken);
try
{
// Document leaves your infrastructure here
byte[] imageBytes = await File.ReadAllBytesAsync(filePath, cancellationToken);
string base64Image = Convert.ToBase64String(imageBytes);
string mimeType = GetMimeType(filePath);
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:{mimeType};base64,{base64Image}"),
new KeyValuePair<string, string>("language", language),
new KeyValuePair<string, string>("isOverlayRequired", "false"),
new KeyValuePair<string, string>("filetype", Path.GetExtension(filePath).TrimStart('.')),
new KeyValuePair<string, string>("detectOrientation", "true"),
new KeyValuePair<string, string>("scale", "true"),
new KeyValuePair<string, string>("OCREngine", "2")
});
var response = await _httpClient.PostAsync(ApiEndpoint, formContent, cancellationToken);
if (!response.IsSuccessStatusCode)
{
string errorBody = await response.Content.ReadAsStringAsync(cancellationToken);
throw new OcrSpaceException(
$"OCR.space API returned {response.StatusCode}: {errorBody}",
(int)response.StatusCode);
}
string jsonResponse = await response.Content.ReadAsStringAsync(cancellationToken);
return ParseOcrResponse(jsonResponse);
}
finally
{
_ = Task.Run(async () =>
{
await Task.Delay(60000 / RateLimitPerMinute);
_rateLimiter.Release();
});
}
}
private OcrResult ParseOcrResponse(string jsonResponse)
{
using var doc = JsonDocument.Parse(jsonResponse);
var root = doc.RootElement;
if (root.TryGetProperty("IsErroredOnProcessing", out var isErrored) && isErrored.GetBoolean())
{
string errorMessage = "OCR processing failed";
if (root.TryGetProperty("ErrorMessage", out var errorMessages))
{
// Parse the array of error strings manually
var messages = new List<string>();
if (errorMessages.ValueKind == JsonValueKind.Array)
{
foreach (var msg in errorMessages.EnumerateArray())
messages.Add(msg.GetString() ?? "Unknown error");
}
errorMessage = string.Join("; ", messages);
}
throw new OcrSpaceException(errorMessage, 500);
}
var result = new OcrResult();
if (root.TryGetProperty("ParsedResults", out var parsedResults))
{
foreach (var parsedResult in parsedResults.EnumerateArray())
{
if (parsedResult.TryGetProperty("ParsedText", out var parsedText))
result.ParsedText += parsedText.GetString();
if (parsedResult.TryGetProperty("FileParseExitCode", out var exitCode))
result.ExitCodes.Add(exitCode.GetInt32());
}
}
return result;
}
private string GetMimeType(string filePath) =>
Path.GetExtension(filePath).ToLowerInvariant() switch
{
".png" => "image/png",
".jpg" or ".jpeg" => "image/jpeg",
".bmp" => "image/bmp",
".tiff" or ".tif" => "image/tiff",
".pdf" => "application/pdf",
_ => "application/octet-stream"
};
public void Dispose()
{
_httpClient?.Dispose();
_rateLimiter?.Dispose();
}
}
// Custom models — no SDK means you define these yourself
public class OcrResult
{
public string ParsedText { get; set; } = string.Empty;
public List<string> Warnings { get; } = new();
public List<int> ExitCodes { get; } = new();
}
public class OcrSpaceException : Exception
{
public int StatusCode { get; }
public OcrSpaceException(string message, int statusCode) : base(message)
=> StatusCode = statusCode;
}
// OCR.space: what you build before the first line of your actual application
public class OcrSpaceApiClient : IDisposable
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
private readonly SemaphoreSlim _rateLimiter;
private const string ApiEndpoint = "https://api.ocr.space/parse/image";
private const int MaxFileSizeFree = 5 * 1024 * 1024; // 5MB — hard limit on free tier
private const int RateLimitPerMinute = 60;
public OcrSpaceApiClient(string apiKey)
{
_apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey));
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromSeconds(120);
_rateLimiter = new SemaphoreSlim(RateLimitPerMinute, RateLimitPerMinute);
}
public async Task<OcrResult> ExtractTextFromFileAsync(
string filePath,
string language = "eng",
CancellationToken cancellationToken = default)
{
if (!File.Exists(filePath))
throw new FileNotFoundException("Image file not found", filePath);
var fileInfo = new FileInfo(filePath);
if (fileInfo.Length > MaxFileSizeFree)
{
throw new InvalidOperationException(
$"File size {fileInfo.Length / 1024 / 1024}MB exceeds free tier limit of 5MB.");
}
await _rateLimiter.WaitAsync(cancellationToken);
try
{
// Document leaves your infrastructure here
byte[] imageBytes = await File.ReadAllBytesAsync(filePath, cancellationToken);
string base64Image = Convert.ToBase64String(imageBytes);
string mimeType = GetMimeType(filePath);
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:{mimeType};base64,{base64Image}"),
new KeyValuePair<string, string>("language", language),
new KeyValuePair<string, string>("isOverlayRequired", "false"),
new KeyValuePair<string, string>("filetype", Path.GetExtension(filePath).TrimStart('.')),
new KeyValuePair<string, string>("detectOrientation", "true"),
new KeyValuePair<string, string>("scale", "true"),
new KeyValuePair<string, string>("OCREngine", "2")
});
var response = await _httpClient.PostAsync(ApiEndpoint, formContent, cancellationToken);
if (!response.IsSuccessStatusCode)
{
string errorBody = await response.Content.ReadAsStringAsync(cancellationToken);
throw new OcrSpaceException(
$"OCR.space API returned {response.StatusCode}: {errorBody}",
(int)response.StatusCode);
}
string jsonResponse = await response.Content.ReadAsStringAsync(cancellationToken);
return ParseOcrResponse(jsonResponse);
}
finally
{
_ = Task.Run(async () =>
{
await Task.Delay(60000 / RateLimitPerMinute);
_rateLimiter.Release();
});
}
}
private OcrResult ParseOcrResponse(string jsonResponse)
{
using var doc = JsonDocument.Parse(jsonResponse);
var root = doc.RootElement;
if (root.TryGetProperty("IsErroredOnProcessing", out var isErrored) && isErrored.GetBoolean())
{
string errorMessage = "OCR processing failed";
if (root.TryGetProperty("ErrorMessage", out var errorMessages))
{
// Parse the array of error strings manually
var messages = new List<string>();
if (errorMessages.ValueKind == JsonValueKind.Array)
{
foreach (var msg in errorMessages.EnumerateArray())
messages.Add(msg.GetString() ?? "Unknown error");
}
errorMessage = string.Join("; ", messages);
}
throw new OcrSpaceException(errorMessage, 500);
}
var result = new OcrResult();
if (root.TryGetProperty("ParsedResults", out var parsedResults))
{
foreach (var parsedResult in parsedResults.EnumerateArray())
{
if (parsedResult.TryGetProperty("ParsedText", out var parsedText))
result.ParsedText += parsedText.GetString();
if (parsedResult.TryGetProperty("FileParseExitCode", out var exitCode))
result.ExitCodes.Add(exitCode.GetInt32());
}
}
return result;
}
private string GetMimeType(string filePath) =>
Path.GetExtension(filePath).ToLowerInvariant() switch
{
".png" => "image/png",
".jpg" or ".jpeg" => "image/jpeg",
".bmp" => "image/bmp",
".tiff" or ".tif" => "image/tiff",
".pdf" => "application/pdf",
_ => "application/octet-stream"
};
public void Dispose()
{
_httpClient?.Dispose();
_rateLimiter?.Dispose();
}
}
// Custom models — no SDK means you define these yourself
public class OcrResult
{
public string ParsedText { get; set; } = string.Empty;
public List<string> Warnings { get; } = new();
public List<int> ExitCodes { get; } = new();
}
public class OcrSpaceException : Exception
{
public int StatusCode { get; }
public OcrSpaceException(string message, int statusCode) : base(message)
=> StatusCode = statusCode;
}
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading
Imports System.Threading.Tasks
' OCR.space: what you build before the first line of your actual application
Public Class OcrSpaceApiClient
Implements IDisposable
Private ReadOnly _httpClient As HttpClient
Private ReadOnly _apiKey As String
Private ReadOnly _rateLimiter As SemaphoreSlim
Private Const ApiEndpoint As String = "https://api.ocr.space/parse/image"
Private Const MaxFileSizeFree As Integer = 5 * 1024 * 1024 ' 5MB — hard limit on free tier
Private Const RateLimitPerMinute As Integer = 60
Public Sub New(apiKey As String)
_apiKey = If(apiKey, Throw New ArgumentNullException(NameOf(apiKey)))
_httpClient = New HttpClient()
_httpClient.Timeout = TimeSpan.FromSeconds(120)
_rateLimiter = New SemaphoreSlim(RateLimitPerMinute, RateLimitPerMinute)
End Sub
Public Async Function ExtractTextFromFileAsync(filePath As String, Optional language As String = "eng", Optional cancellationToken As CancellationToken = Nothing) As Task(Of OcrResult)
If Not File.Exists(filePath) Then
Throw New FileNotFoundException("Image file not found", filePath)
End If
Dim fileInfo = New FileInfo(filePath)
If fileInfo.Length > MaxFileSizeFree Then
Throw New InvalidOperationException($"File size {fileInfo.Length \ 1024 \ 1024}MB exceeds free tier limit of 5MB.")
End If
Await _rateLimiter.WaitAsync(cancellationToken)
Try
' Document leaves your infrastructure here
Dim imageBytes As Byte() = Await File.ReadAllBytesAsync(filePath, cancellationToken)
Dim base64Image As String = Convert.ToBase64String(imageBytes)
Dim mimeType As String = GetMimeType(filePath)
Dim formContent = New FormUrlEncodedContent(New KeyValuePair(Of String, String)() {
New KeyValuePair(Of String, String)("apikey", _apiKey),
New KeyValuePair(Of String, String)("base64Image", $"data:{mimeType};base64,{base64Image}"),
New KeyValuePair(Of String, String)("language", language),
New KeyValuePair(Of String, String)("isOverlayRequired", "false"),
New KeyValuePair(Of String, String)("filetype", Path.GetExtension(filePath).TrimStart("."c)),
New KeyValuePair(Of String, String)("detectOrientation", "true"),
New KeyValuePair(Of String, String)("scale", "true"),
New KeyValuePair(Of String, String)("OCREngine", "2")
})
Dim response = Await _httpClient.PostAsync(ApiEndpoint, formContent, cancellationToken)
If Not response.IsSuccessStatusCode Then
Dim errorBody = Await response.Content.ReadAsStringAsync(cancellationToken)
Throw New OcrSpaceException($"OCR.space API returned {response.StatusCode}: {errorBody}", CInt(response.StatusCode))
End If
Dim jsonResponse = Await response.Content.ReadAsStringAsync(cancellationToken)
Return ParseOcrResponse(jsonResponse)
Finally
_ = Task.Run(Async Function()
Await Task.Delay(60000 \ RateLimitPerMinute)
_rateLimiter.Release()
End Function)
End Try
End Function
Private Function ParseOcrResponse(jsonResponse As String) As OcrResult
Using doc = JsonDocument.Parse(jsonResponse)
Dim root = doc.RootElement
If root.TryGetProperty("IsErroredOnProcessing", ByRef isErrored) AndAlso isErrored.GetBoolean() Then
Dim errorMessage As String = "OCR processing failed"
If root.TryGetProperty("ErrorMessage", ByRef errorMessages) Then
' Parse the array of error strings manually
Dim messages = New List(Of String)()
If errorMessages.ValueKind = JsonValueKind.Array Then
For Each msg In errorMessages.EnumerateArray()
messages.Add(msg.GetString() OrElse "Unknown error")
Next
End If
errorMessage = String.Join("; ", messages)
End If
Throw New OcrSpaceException(errorMessage, 500)
End If
Dim result = New OcrResult()
If root.TryGetProperty("ParsedResults", ByRef parsedResults) Then
For Each parsedResult In parsedResults.EnumerateArray()
If parsedResult.TryGetProperty("ParsedText", ByRef parsedText) Then
result.ParsedText &= parsedText.GetString()
End If
If parsedResult.TryGetProperty("FileParseExitCode", ByRef exitCode) Then
result.ExitCodes.Add(exitCode.GetInt32())
End If
Next
End If
Return result
End Using
End Function
Private Function GetMimeType(filePath As String) As String
Return Path.GetExtension(filePath).ToLowerInvariant() Select Case
Case ".png" : Return "image/png"
Case ".jpg", ".jpeg" : Return "image/jpeg"
Case ".bmp" : Return "image/bmp"
Case ".tiff", ".tif" : Return "image/tiff"
Case ".pdf" : Return "application/pdf"
Case Else : Return "application/octet-stream"
End Select
End Function
Public Sub Dispose() Implements IDisposable.Dispose
_httpClient?.Dispose()
_rateLimiter?.Dispose()
End Sub
End Class
' Custom models — no SDK means you define these yourself
Public Class OcrResult
Public Property ParsedText As String = String.Empty
Public ReadOnly Property Warnings As New List(Of String)()
Public ReadOnly Property ExitCodes As New List(Of Integer)()
End Class
Public Class OcrSpaceException
Inherits Exception
Public ReadOnly Property StatusCode As Integer
Public Sub New(message As String, statusCode As Integer)
MyBase.New(message)
Me.StatusCode = statusCode
End Sub
End Class
Bu, ilk iş mantığı yönteminden önce var olan 90+ satır altyapı kodudur. Her OCR.space entegrasyonu bu şablonu (veya eşdeğer bir şeyi) gönderir ve bunu yazan her ekip aynı sorunu çözüyor, OCR.space onların adına çözmemeyi seçmiştir.
IronOCR'u Anlamak
IronOCR, .NET için ticari bir OCR kütüphanesidir ve IronOcr NuGet paketi aracılığıyla yüklenir. Bu, otomatik ön işleme, yerel PDF girişi, aranabilir PDF çıkışı, 125+ dil paketi ve yapılandırılmış sonuç çıkarımı ile optimize edilmiş bir Tesseract 5 motorunu kapsar — hepsi bulut bağımlılığı, API anahtarları veya istek başına ücretler olmadan. Belgeler, .NET uygulamasını çalıştıran herhangi bir altyapı üzerinde yerel olarak işlenir.
Anahtar özellikler:
- Tek NuGet paketi:
dotnet add package IronOcrtam kurulumdur. Yönetilecek yerel ikililer yok, tessdata dizinleri yok, ortam değişkenleri yok. - Güçlü tipte API:
IronTesseract,OcrInput,OcrResultveCropRectangle, tam IntelliSense desteğine sahip birinci sınıf .NET türleridir. - Otomatik ön işleme: Deskew, DeNoise, Kontrast, Binarize ve EnhanceResolution filtreleri, harici kütüphaneler olmadan otomatik olarak veya isteğe bağlı olarak uygulanır.
- Yerel PDF desteği: Hem taranmış PDF'leri okuma hem de aranabilir PDF'ler oluşturma yerleşiktir. Kullanılabilir belleğin ötesinde boyut sınırlaması yok.
- Yerel yürütme: OCR sırasında hiçbir ağ çağrısı gerçekleşmez. Kütüphane tamamen sürecin içinde çalışır. İzole ortamlarda yapılandırma değişiklikleri olmaksızın çalışır.
- İş parçacığı güvenli: Birden fazla
IronTesseractörneği kilitleme veya çekişme yönetimi olmadan aynı anda çalışır. - Süresiz lisanslama: $999 Lite / $1,499 Plus / $2,999 Professional. Herhangi bir hacimde istek başına ücret yok.
Özellik Karşılaştırması
| Özellik | OCR.space | IronOCR |
|---|---|---|
| NuGet paketi | Yok — REST API sadece | IronOcr — tam .NET desteği |
| İşleme yeri | OCR.space bulut sunucuları | Yerel — altyapınız |
| Ücretsiz katman | 25.000 istek/ay (sınırlı) | Deneme mevcut |
| Ücretli fiyatlandırma | Güncel fiyatlandırma için OCR.space ile iletişime geçin | $2,999 bir kerelik süresiz |
| Hız sınırlama | 60 istek/dak, 500/gün (ücretsiz) | None |
| Çevrimdışı yetenek | Hayır | Evet — tamamen izole |
| Veri gizliliği | Belgeler üçüncü tarafa gönderilir | Belgeler sunucularınızda kalır |
Ayrıntılı Özellik Karşılaştırması
| Özellik | OCR.space | IronOCR |
|---|---|---|
| Entegrasyon | ||
| NuGet paketi | None | Evet (IronOcr) |
| Kuvvetli-tipli modeller | Yok — elle JSON çözümüleme | Evet (OcrResult, OcrInput) |
| IntelliSense desteği | None | Tam |
| Özel istisna türleri | Kendiniz tanımlamalısınız | Yerleşik |
| Yeniden deneme mantığı | Kendiniz inşa etmelisiniz | Yerleşik |
| İşleme | ||
| İşleme yeri | Bulut sunucular | Yerel işlem içinde |
| İnternet gerekli | Evet — her çağrı | Hayır |
| İzole destek | Hayır | Evet |
| Oran sınırlamaları | Evet — tüm planlar | None |
| Dosya boyutu sınırları | 5 MB (ücretsiz katman) | Sadece bellek |
| OCR Yetenekleri | ||
| Görüntü OCR | Evet | Evet |
| PDF OCR | Evet (sınırlı) | Evet (yerel, boyut sınırı yok) |
| Aranabilir PDF çıktısı | Ücretsiz katmanda filigranlı | Temiz çıktı, filigran yok |
| Otomatik ön işlem | Yok (sadece sunucu tarafı) | Deskew, DeNoise, Contrast, Binarize, EnhanceResolution |
| Elle ön işleme kontrolü | None | Tam filtre API'si |
| Dil desteği | ~25 dil | 125+ NuGet dil paketleri aracılığıyla |
| Her belge için çoklu dil | Sınırlı | Evet — birincil + ikincil diller |
| Yapılandırılmış çıktı (kelimeler/satırlar/sayfalar) | Yok — sadece düz metin | Evet — sayfalar, paragraflar, satırlar, kelimeler koordinatlarla |
| Güven skoru | Hayır | Evet — her sonuç ve kelime başına |
| Bölge bazlı OCR | Hayır | Evet — CropRectangle |
| OCR sırasında barkod okuma | Hayır | Evet — ReadBarCodes = true |
| Dağıtım | ||
| Docker | Dışa doğru internet gerektirir | Kutudan çıkar çıkmaz çalışır |
| Linux | Dışa doğru internet gerektirir | Tam destekli |
| HIPAA uyumlu | Risk — belgeler kontrolünüzden çıkar | Evet — dışa aktarım yok |
| GDPR uyumlu | Risk — AB veri transferi belirsiz | Evet — üçüncü taraf veri işleme yok |
| Fiyatlandırma | ||
| Fiyatlandırma modeli | Aylık abonelik | Tek seferlik süresiz lisans |
| Giriş fiyatı | Güncel fiyatlandırma için OCR.space ile iletişime geçin | $999 bir kerelik |
| Ölçekli belge başına maliyet | Evet | None |
| SLA | Yok (ücretsiz), değişir (ücretli) | KurumsalSLAmevcut |
SDK Derinliği vs. Ham HTTP: Entegrasyon Maliyeti
OCR.space ile yerel bir SDK arasındaki fark bir stil tercihi değildir. Geliştirme süresinde, hata alanı yüzeyinde ve her dağıtımda bakım yükünde ölçülür.
OCR.space Yaklaşımı
OCR.space'i kullanan her .NET geliştiricisi kendi HTTP istemcisini yazar. En basit olası uygulama — yeniden deneme mantığı olmadan, toplu destek olmadan ve ön işleme yapmadan — hala50+satırdır:
// OCR.space: minimum viable extraction —50+lines before business logic
public class OcrSpaceBasicExtraction
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
public OcrSpaceBasicExtraction(string apiKey)
{
_apiKey = apiKey;
_httpClient = new HttpClient();
}
public async Task<string> ExtractText(string imagePath)
{
// Read file and encode — document leaves your infrastructure
byte[] imageBytes = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(imageBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}"),
new KeyValuePair<string, string>("language", "eng")
});
// Send to cloud
var response = await _httpClient.PostAsync(
"https://api.ocr.space/parse/image", content);
if (!response.IsSuccessStatusCode)
throw new Exception($"API error: {response.StatusCode}");
// Parse JSON manually — no typed models
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
return doc.RootElement
.GetProperty("ParsedResults")[0]
.GetProperty("ParsedText")
.GetString() ?? string.Empty;
}
}
// OCR.space: minimum viable extraction —50+lines before business logic
public class OcrSpaceBasicExtraction
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
public OcrSpaceBasicExtraction(string apiKey)
{
_apiKey = apiKey;
_httpClient = new HttpClient();
}
public async Task<string> ExtractText(string imagePath)
{
// Read file and encode — document leaves your infrastructure
byte[] imageBytes = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(imageBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}"),
new KeyValuePair<string, string>("language", "eng")
});
// Send to cloud
var response = await _httpClient.PostAsync(
"https://api.ocr.space/parse/image", content);
if (!response.IsSuccessStatusCode)
throw new Exception($"API error: {response.StatusCode}");
// Parse JSON manually — no typed models
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
return doc.RootElement
.GetProperty("ParsedResults")[0]
.GetProperty("ParsedText")
.GetString() ?? string.Empty;
}
}
Imports System.Net.Http
Imports System.IO
Imports System.Threading.Tasks
Imports System.Text.Json
Public Class OcrSpaceBasicExtraction
Private ReadOnly _httpClient As HttpClient
Private ReadOnly _apiKey As String
Public Sub New(apiKey As String)
_apiKey = apiKey
_httpClient = New HttpClient()
End Sub
Public Async Function ExtractText(imagePath As String) As Task(Of String)
' Read file and encode — document leaves your infrastructure
Dim imageBytes As Byte() = File.ReadAllBytes(imagePath)
Dim base64 As String = Convert.ToBase64String(imageBytes)
Dim content = New FormUrlEncodedContent(New KeyValuePair(Of String, String)() {
New KeyValuePair(Of String, String)("apikey", _apiKey),
New KeyValuePair(Of String, String)("base64Image", $"data:image/png;base64,{base64}"),
New KeyValuePair(Of String, String)("language", "eng")
})
' Send to cloud
Dim response = Await _httpClient.PostAsync("https://api.ocr.space/parse/image", content)
If Not response.IsSuccessStatusCode Then
Throw New Exception($"API error: {response.StatusCode}")
End If
' Parse JSON manually — no typed models
Dim json As String = Await response.Content.ReadAsStringAsync()
Using doc = JsonDocument.Parse(json)
Return doc.RootElement _
.GetProperty("ParsedResults")(0) _
.GetProperty("ParsedText") _
.GetString() OrElse String.Empty
End Using
End Function
End Class
Toplu işlem ekleyin ve satır sayısı, çünkü her toplu istek hız sınırı daraltması, yeniden deneme mantığı üssel geri adımla ve HTTP 429 yanıtlarına açıkça düzenleme gerektirir. PDF işlemi ekleyin ve her çağrıdan önce 5 MB dosya boyutu kontrolü eklemeniz gerektiği için satır sayısı, çünkü ücretsiz katman, daha büyük dosyaları bir uyarı yerine bir hatayla reddedecektir.
IronOCR Yaklaşımı
IronOCR'yi NuGet'ten yüklemek, var olan yöntem çağrıları ile tüm bu altyapı kodunu değiştirir:
// IronOCR: complete implementation
var result = new IronTesseract().Read("invoice.png");
Console.WriteLine(result.Text);
// IronOCR: complete implementation
var result = new IronTesseract().Read("invoice.png");
Console.WriteLine(result.Text);
IronTesseract sınıfı, dosya okuma, ön işleme, motor çalıştırma ve sonuç yapımı işlemlerini yönetir. Hiçbir HTTP istemcisi yok. Base64 kodlama yok. JSON çözümleme yok. API anahtarı yok. Hız sınırlandırıcı yok. Giriş varyasyonlarını kapsayan görüntülerden metin okuma eğitimi, - dosya yolları, bayt dizileri, akışlar, bit eşlemeler - aynı tek çağrı desenini takip eder.
Kaynak dosyalardaki kod karmaşıklığı sayıları varsayımsal değildir:
| Senaryo | OCR.space Satırları | IronOCR Satırları |
|---|---|---|
| Temel çıkarım | 50+ | 3 |
| PDF işlemi | 60+ | 12 |
| Toplu işlem | 80+ | 15 |
| Hata işleme | 70+ | 15 |
| Tam istemci altyapısı | 200+ | 0 (NuGet sağlar) |
Toplu İşleme ve Hız Sınırları
Hız sınırı sorunu, OCR.space'in ücretsiz katmanının gerçek üretim koşulları altında açıkça bozulduğu yerdir.
OCR.space Yaklaşımı
OCR.space altında yığın işleme, 60 istek-dakika başı kısıtlaması içinde kalmak için bir SemaphoreSlim oluşturmayı ve yönetmeyi gerektirir, artı semafor mantığı hassas olmadığında veya paylaşılan altyapı bir IP adresi paylaştığında gönderilen HTTP 429 yanıtları için üstel geri alma deneme mantığı eklenmelidir:
// OCR.space batch:80+lines of rate-limit plumbing before actual work
public class OcrSpaceBatchProcessing
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
private readonly SemaphoreSlim _rateLimiter;
public OcrSpaceBatchProcessing(string apiKey)
{
_apiKey = apiKey;
_httpClient = new HttpClient();
_rateLimiter = new SemaphoreSlim(60, 60); // Free tier: 60/minute
}
public async Task<Dictionary<string, string>> ProcessBatch(string[] imagePaths)
{
var results = new Dictionary<string, string>();
foreach (var imagePath in imagePaths)
{
await _rateLimiter.WaitAsync();
try
{
string text = await ProcessWithRetry(imagePath);
results[imagePath] = text;
}
finally
{
_ = Task.Run(async () =>
{
await Task.Delay(1000); // 1 second spacing
_rateLimiter.Release();
});
}
}
return results;
}
private async Task<string> ProcessWithRetry(string imagePath, int maxRetries = 3)
{
for (int attempt = 0; attempt < maxRetries; attempt++)
{
try
{
byte[] imageBytes = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(imageBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}"),
new KeyValuePair<string, string>("language", "eng")
});
var response = await _httpClient.PostAsync(
"https://api.ocr.space/parse/image", content);
if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
{
// Rate limited — exponential backoff
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
continue;
}
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
return doc.RootElement
.GetProperty("ParsedResults")[0]
.GetProperty("ParsedText")
.GetString() ?? string.Empty;
}
catch (HttpRequestException) when (attempt < maxRetries - 1)
{
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
throw new Exception($"Failed to process {imagePath} after {maxRetries} attempts");
}
}
// OCR.space batch:80+lines of rate-limit plumbing before actual work
public class OcrSpaceBatchProcessing
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
private readonly SemaphoreSlim _rateLimiter;
public OcrSpaceBatchProcessing(string apiKey)
{
_apiKey = apiKey;
_httpClient = new HttpClient();
_rateLimiter = new SemaphoreSlim(60, 60); // Free tier: 60/minute
}
public async Task<Dictionary<string, string>> ProcessBatch(string[] imagePaths)
{
var results = new Dictionary<string, string>();
foreach (var imagePath in imagePaths)
{
await _rateLimiter.WaitAsync();
try
{
string text = await ProcessWithRetry(imagePath);
results[imagePath] = text;
}
finally
{
_ = Task.Run(async () =>
{
await Task.Delay(1000); // 1 second spacing
_rateLimiter.Release();
});
}
}
return results;
}
private async Task<string> ProcessWithRetry(string imagePath, int maxRetries = 3)
{
for (int attempt = 0; attempt < maxRetries; attempt++)
{
try
{
byte[] imageBytes = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(imageBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}"),
new KeyValuePair<string, string>("language", "eng")
});
var response = await _httpClient.PostAsync(
"https://api.ocr.space/parse/image", content);
if (response.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
{
// Rate limited — exponential backoff
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
continue;
}
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
return doc.RootElement
.GetProperty("ParsedResults")[0]
.GetProperty("ParsedText")
.GetString() ?? string.Empty;
}
catch (HttpRequestException) when (attempt < maxRetries - 1)
{
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
}
}
throw new Exception($"Failed to process {imagePath} after {maxRetries} attempts");
}
}
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading
Imports System.Threading.Tasks
Public Class OcrSpaceBatchProcessing
Private ReadOnly _httpClient As HttpClient
Private ReadOnly _apiKey As String
Private ReadOnly _rateLimiter As SemaphoreSlim
Public Sub New(apiKey As String)
_apiKey = apiKey
_httpClient = New HttpClient()
_rateLimiter = New SemaphoreSlim(60, 60) ' Free tier: 60/minute
End Sub
Public Async Function ProcessBatch(imagePaths As String()) As Task(Of Dictionary(Of String, String))
Dim results As New Dictionary(Of String, String)()
For Each imagePath In imagePaths
Await _rateLimiter.WaitAsync()
Try
Dim text As String = Await ProcessWithRetry(imagePath)
results(imagePath) = text
Finally
_ = Task.Run(Async Function()
Await Task.Delay(1000) ' 1 second spacing
_rateLimiter.Release()
End Function)
End Try
Next
Return results
End Function
Private Async Function ProcessWithRetry(imagePath As String, Optional maxRetries As Integer = 3) As Task(Of String)
For attempt As Integer = 0 To maxRetries - 1
Try
Dim imageBytes As Byte() = File.ReadAllBytes(imagePath)
Dim base64 As String = Convert.ToBase64String(imageBytes)
Dim content = New FormUrlEncodedContent(New KeyValuePair(Of String, String)() {
New KeyValuePair(Of String, String)("apikey", _apiKey),
New KeyValuePair(Of String, String)("base64Image", $"data:image/png;base64,{base64}"),
New KeyValuePair(Of String, String)("language", "eng")
})
Dim response = Await _httpClient.PostAsync("https://api.ocr.space/parse/image", content)
If response.StatusCode = System.Net.HttpStatusCode.TooManyRequests Then
' Rate limited — exponential backoff
Await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)))
Continue For
End If
response.EnsureSuccessStatusCode()
Dim json As String = Await response.Content.ReadAsStringAsync()
Using doc = JsonDocument.Parse(json)
Return doc.RootElement _
.GetProperty("ParsedResults")(0) _
.GetProperty("ParsedText") _
.GetString() OrElse String.Empty
End Using
Catch ex As HttpRequestException When attempt < maxRetries - 1
Await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)))
End Try
Next
Throw New Exception($"Failed to process {imagePath} after {maxRetries} attempts")
End Function
End Class
Ücretsiz katmandaki 500 günlük isteği daha fazla sınırlar. Tek bir günde 600 belge işleyen bir uygulama, ertesi takvim günü otomatik devir olmaksızın yarı yolda başarısız olacak.
IronOCR Yaklaşımı
IronOCR'de hız sınırları yoktur. Toplu işlem bir döngüdür:
//IronOCR batch: 8 lines, no rate limits, no retries needed
public Dictionary<string, string> ProcessBatch(string[] imagePaths)
{
var results = new Dictionary<string, string>();
var ocr = new IronTesseract();
foreach (var imagePath in imagePaths)
{
//Hayırrate limits, no retries, no cloud dependency
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
}
return results;
}
//IronOCR batch: 8 lines, no rate limits, no retries needed
public Dictionary<string, string> ProcessBatch(string[] imagePaths)
{
var results = new Dictionary<string, string>();
var ocr = new IronTesseract();
foreach (var imagePath in imagePaths)
{
//Hayırrate limits, no retries, no cloud dependency
var result = ocr.Read(imagePath);
results[imagePath] = result.Text;
}
return results;
}
Imports System.Collections.Generic
Public Function ProcessBatch(imagePaths As String()) As Dictionary(Of String, String)
Dim results As New Dictionary(Of String, String)()
Dim ocr As New IronTesseract()
For Each imagePath As String In imagePaths
Dim result = ocr.Read(imagePath)
results(imagePath) = result.Text
Next
Return results
End Function
Yığın boyunca IronTesseract örneğini yeniden kullanmak, tekrar eden motor başlatma maliyetinden kaçınır. İşleme hızı uzak bir API'nin kısıtlama politikası ile değil, yerel CPU ve disk I/O ile sınırlıdır. Çok iş parçacıklı örnek, yığın söz konusu olduğunda çekirdekler arasında paralel nasıl çalışılacağını gösterir.
PDF İşleme
PDF desteği ikinci ana yapısal boşluğu illüstre eder.
OCR.space Yaklaşımı
OCR.space, ücretli planlarda ve kısmen ücretsiz katmanda PDF yüklemeleri kabul eder, ancak ücretsiz hesaplarda 5 MB dosya boyutu tavanı çoğu çok sayfalı belgeyi dışlar. Ücretsiz katmanla aranabilir PDF çıkışı filigran içerir. Uygulama, her talep öncesinde sayfa başına sonuç çıkışını ve açık dosya boyutu kontrolü gerektirir:
// OCR.space PDF: size check required, watermarks on free tier
public async Task<List<string>> ExtractTextFromPdf(string pdfPath)
{
var pageTexts = new List<string>();
// Reject before wasting a request quota entry
var fileInfo = new FileInfo(pdfPath);
if (fileInfo.Length > 5 * 1024 * 1024)
throw new InvalidOperationException("File exceeds 5MB free tier limit. Upgrade or split PDF.");
byte[] pdfBytes = File.ReadAllBytes(pdfPath);
string base64 = Convert.ToBase64String(pdfBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:application/pdf;base64,{base64}"),
new KeyValuePair<string, string>("language", "eng"),
new KeyValuePair<string, string>("filetype", "PDF"),
new KeyValuePair<string, string>("isCreateSearchablePdf", "false") // Watermarked on free tier
});
var response = await _httpClient.PostAsync("https://api.ocr.space/parse/image", content);
if (!response.IsSuccessStatusCode)
throw new Exception($"API error: {response.StatusCode}");
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("ParsedResults", out var results))
{
foreach (var result in results.EnumerateArray())
{
if (result.TryGetProperty("ParsedText", out var text))
pageTexts.Add(text.GetString() ?? string.Empty);
}
}
return pageTexts;
}
// OCR.space PDF: size check required, watermarks on free tier
public async Task<List<string>> ExtractTextFromPdf(string pdfPath)
{
var pageTexts = new List<string>();
// Reject before wasting a request quota entry
var fileInfo = new FileInfo(pdfPath);
if (fileInfo.Length > 5 * 1024 * 1024)
throw new InvalidOperationException("File exceeds 5MB free tier limit. Upgrade or split PDF.");
byte[] pdfBytes = File.ReadAllBytes(pdfPath);
string base64 = Convert.ToBase64String(pdfBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:application/pdf;base64,{base64}"),
new KeyValuePair<string, string>("language", "eng"),
new KeyValuePair<string, string>("filetype", "PDF"),
new KeyValuePair<string, string>("isCreateSearchablePdf", "false") // Watermarked on free tier
});
var response = await _httpClient.PostAsync("https://api.ocr.space/parse/image", content);
if (!response.IsSuccessStatusCode)
throw new Exception($"API error: {response.StatusCode}");
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("ParsedResults", out var results))
{
foreach (var result in results.EnumerateArray())
{
if (result.TryGetProperty("ParsedText", out var text))
pageTexts.Add(text.GetString() ?? string.Empty);
}
}
return pageTexts;
}
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading.Tasks
Public Class OCRSpaceClient
Private ReadOnly _apiKey As String
Private ReadOnly _httpClient As HttpClient
Public Sub New(apiKey As String, httpClient As HttpClient)
_apiKey = apiKey
_httpClient = httpClient
End Sub
Public Async Function ExtractTextFromPdf(pdfPath As String) As Task(Of List(Of String))
Dim pageTexts As New List(Of String)()
' Reject before wasting a request quota entry
Dim fileInfo As New FileInfo(pdfPath)
If fileInfo.Length > 5 * 1024 * 1024 Then
Throw New InvalidOperationException("File exceeds 5MB free tier limit. Upgrade or split PDF.")
End If
Dim pdfBytes As Byte() = File.ReadAllBytes(pdfPath)
Dim base64 As String = Convert.ToBase64String(pdfBytes)
Dim content As New FormUrlEncodedContent(New KeyValuePair(Of String, String)() {
New KeyValuePair(Of String, String)("apikey", _apiKey),
New KeyValuePair(Of String, String)("base64Image", $"data:application/pdf;base64,{base64}"),
New KeyValuePair(Of String, String)("language", "eng"),
New KeyValuePair(Of String, String)("filetype", "PDF"),
New KeyValuePair(Of String, String)("isCreateSearchablePdf", "false") ' Watermarked on free tier
})
Dim response As HttpResponseMessage = Await _httpClient.PostAsync("https://api.ocr.space/parse/image", content)
If Not response.IsSuccessStatusCode Then
Throw New Exception($"API error: {response.StatusCode}")
End If
Dim json As String = Await response.Content.ReadAsStringAsync()
Using doc As JsonDocument = JsonDocument.Parse(json)
If doc.RootElement.TryGetProperty("ParsedResults", results) Then
For Each result In results.EnumerateArray()
If result.TryGetProperty("ParsedText", text) Then
pageTexts.Add(If(text.GetString(), String.Empty))
End If
Next
End If
End Using
Return pageTexts
End Function
End Class
IronOCR Yaklaşımı
IronOCR, PDF'leri yerel olarak okur. Limit, keyfi bir dosya boyutu eşiği değil, mevcut bellektir. Aranabilir PDF çıktısı, her lisans katmanında filigransız temiz dosyalar üretir:
//IronOCR PDF: native support, no size limit, no watermarks
public List<string> ExtractTextFromPdf(string pdfPath)
{
var pageTexts = new List<string>();
using var input = new OcrInput();
input.LoadPdf(pdfPath); //Hayır5MB ceiling
var result = new IronTesseract().Read(input);
foreach (var page in result.Pages)
pageTexts.Add(page.Text);
return pageTexts;
}
// Generate searchable PDF — no watermarks
public void CreateSearchablePdf(string inputPath, string outputPath)
{
var result = new IronTesseract().Read(inputPath);
result.SaveAsSearchablePdf(outputPath);
}
//IronOCR PDF: native support, no size limit, no watermarks
public List<string> ExtractTextFromPdf(string pdfPath)
{
var pageTexts = new List<string>();
using var input = new OcrInput();
input.LoadPdf(pdfPath); //Hayır5MB ceiling
var result = new IronTesseract().Read(input);
foreach (var page in result.Pages)
pageTexts.Add(page.Text);
return pageTexts;
}
// Generate searchable PDF — no watermarks
public void CreateSearchablePdf(string inputPath, string outputPath)
{
var result = new IronTesseract().Read(inputPath);
result.SaveAsSearchablePdf(outputPath);
}
Imports System.Collections.Generic
'IronOCR PDF: native support, no size limit, no watermarks
Public Function ExtractTextFromPdf(pdfPath As String) As List(Of String)
Dim pageTexts As New List(Of String)()
Using input As New OcrInput()
input.LoadPdf(pdfPath) 'Hayır5MB ceiling
Dim result = New IronTesseract().Read(input)
For Each page In result.Pages
pageTexts.Add(page.Text)
Next
End Using
Return pageTexts
End Function
' Generate searchable PDF — no watermarks
Public Sub CreateSearchablePdf(inputPath As String, outputPath As String)
Dim result = New IronTesseract().Read(inputPath)
result.SaveAsSearchablePdf(outputPath)
End Sub
Şifre korumalı PDF'ler tek bir parametredir: input.LoadPdf("encrypted.pdf", Password: "secret"). PDF OCR nasıl yapılır kılavuzu, sayfa aralığı seçimi ve şifre işlemini ayrıntılı olarak ele almaktadır. Aranabilir PDF oluşturma kalıpları için aranabilir PDF nasıl yapılır kılavuzuna bakın.
Hata Yönetimi
OCR.space, hataları iki ayrı kanal üzerinden iletir: HTTP durum kodları ve bir JSON IsErroredOnProcessing bayrağı. Üretim kodu her ikisini de kontrol etmeli, IsErroredOnProcessing doğru olduğunda JSON hata dizisini parçalara ayırmalı ve kısmi arızalar için sayfa başına FileParseExitCode değerlerini incelemelidir. Bunların hiçbiri tiplenmiş değildir — her şey JsonDocument üzerinden metin ayrımıdır:
// OCR.space: two error layers, all string-based
public async Task<string> SafeExtract(HttpClient client, string apiKey, string imagePath)
{
try
{
byte[] imageBytes = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(imageBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}")
});
var response = await client.PostAsync("https://api.ocr.space/parse/image", content);
if (!response.IsSuccessStatusCode)
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.Unauthorized:
throw new Exception("Invalid API key");
case System.Net.HttpStatusCode.TooManyRequests:
throw new Exception("Rate limit exceeded — wait and retry");
case System.Net.HttpStatusCode.PaymentRequired:
throw new Exception("Quota exceeded — upgrade plan");
default:
throw new Exception($"API error: {response.StatusCode}");
}
}
// Second error layer: JSON-level failures
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("IsErroredOnProcessing", out var isError)
&& isError.GetBoolean())
{
var messages = new List<string>();
if (doc.RootElement.TryGetProperty("ErrorMessage", out var errors))
{
foreach (var e in errors.EnumerateArray())
messages.Add(e.GetString() ?? "Unknown error");
}
throw new Exception(string.Join("; ", messages));
}
// Third layer: per-page exit codes
if (doc.RootElement.TryGetProperty("ParsedResults", out var results))
{
foreach (var result in results.EnumerateArray())
{
if (result.TryGetProperty("FileParseExitCode", out var exitCode)
&& exitCode.GetInt32() != 1)
throw new Exception($"Page parse failed: exit code {exitCode.GetInt32()}");
}
}
return doc.RootElement
.GetProperty("ParsedResults")[0]
.GetProperty("ParsedText")
.GetString() ?? string.Empty;
}
catch (JsonException ex)
{
throw new Exception($"Invalid API response: {ex.Message}");
}
catch (HttpRequestException ex)
{
throw new Exception($"Network error: {ex.Message}");
}
}
// OCR.space: two error layers, all string-based
public async Task<string> SafeExtract(HttpClient client, string apiKey, string imagePath)
{
try
{
byte[] imageBytes = File.ReadAllBytes(imagePath);
string base64 = Convert.ToBase64String(imageBytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}")
});
var response = await client.PostAsync("https://api.ocr.space/parse/image", content);
if (!response.IsSuccessStatusCode)
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.Unauthorized:
throw new Exception("Invalid API key");
case System.Net.HttpStatusCode.TooManyRequests:
throw new Exception("Rate limit exceeded — wait and retry");
case System.Net.HttpStatusCode.PaymentRequired:
throw new Exception("Quota exceeded — upgrade plan");
default:
throw new Exception($"API error: {response.StatusCode}");
}
}
// Second error layer: JSON-level failures
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
if (doc.RootElement.TryGetProperty("IsErroredOnProcessing", out var isError)
&& isError.GetBoolean())
{
var messages = new List<string>();
if (doc.RootElement.TryGetProperty("ErrorMessage", out var errors))
{
foreach (var e in errors.EnumerateArray())
messages.Add(e.GetString() ?? "Unknown error");
}
throw new Exception(string.Join("; ", messages));
}
// Third layer: per-page exit codes
if (doc.RootElement.TryGetProperty("ParsedResults", out var results))
{
foreach (var result in results.EnumerateArray())
{
if (result.TryGetProperty("FileParseExitCode", out var exitCode)
&& exitCode.GetInt32() != 1)
throw new Exception($"Page parse failed: exit code {exitCode.GetInt32()}");
}
}
return doc.RootElement
.GetProperty("ParsedResults")[0]
.GetProperty("ParsedText")
.GetString() ?? string.Empty;
}
catch (JsonException ex)
{
throw new Exception($"Invalid API response: {ex.Message}");
}
catch (HttpRequestException ex)
{
throw new Exception($"Network error: {ex.Message}");
}
}
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports System.Threading.Tasks
Public Class OCRSpace
Public Async Function SafeExtract(client As HttpClient, apiKey As String, imagePath As String) As Task(Of String)
Try
Dim imageBytes As Byte() = File.ReadAllBytes(imagePath)
Dim base64 As String = Convert.ToBase64String(imageBytes)
Dim content As New FormUrlEncodedContent(New KeyValuePair(Of String, String)() {
New KeyValuePair(Of String, String)("apikey", apiKey),
New KeyValuePair(Of String, String)("base64Image", $"data:image/png;base64,{base64}")
})
Dim response As HttpResponseMessage = Await client.PostAsync("https://api.ocr.space/parse/image", content)
If Not response.IsSuccessStatusCode Then
Select Case response.StatusCode
Case System.Net.HttpStatusCode.Unauthorized
Throw New Exception("Invalid API key")
Case System.Net.HttpStatusCode.TooManyRequests
Throw New Exception("Rate limit exceeded — wait and retry")
Case System.Net.HttpStatusCode.PaymentRequired
Throw New Exception("Quota exceeded — upgrade plan")
Case Else
Throw New Exception($"API error: {response.StatusCode}")
End Select
End If
' Second error layer: JSON-level failures
Dim json As String = Await response.Content.ReadAsStringAsync()
Using doc As JsonDocument = JsonDocument.Parse(json)
If doc.RootElement.TryGetProperty("IsErroredOnProcessing", ByRef isError) AndAlso isError.GetBoolean() Then
Dim messages As New List(Of String)()
If doc.RootElement.TryGetProperty("ErrorMessage", ByRef errors) Then
For Each e In errors.EnumerateArray()
messages.Add(e.GetString() ?? "Unknown error")
Next
End If
Throw New Exception(String.Join("; ", messages))
End If
' Third layer: per-page exit codes
If doc.RootElement.TryGetProperty("ParsedResults", ByRef results) Then
For Each result In results.EnumerateArray()
If result.TryGetProperty("FileParseExitCode", ByRef exitCode) AndAlso exitCode.GetInt32() <> 1 Then
Throw New Exception($"Page parse failed: exit code {exitCode.GetInt32()}")
End If
Next
End If
Return doc.RootElement _
.GetProperty("ParsedResults")(0) _
.GetProperty("ParsedText") _
.GetString() ?? String.Empty
End Using
Catch ex As JsonException
Throw New Exception($"Invalid API response: {ex.Message}")
Catch ex As HttpRequestException
Throw New Exception($"Network error: {ex.Message}")
End Try
End Function
End Class
IronOCR, açık mesajlarla standart .NET istisnalarını yükseltir. JSON ayrıştırma yok, HTTP durum kodu değiştirme yok, katmanlı hata çıkarımı yok:
// IronOCR: standard .NET exceptions
public string SafeExtract(string imagePath)
{
try
{
var result = new IronTesseract().Read(imagePath);
return result.Text;
}
catch (FileNotFoundException)
{
throw; // File not found — straightforward
}
catch (Exception ex) when (ex.Message.Contains("corrupt"))
{
throw new Exception($"Image file is corrupt: {imagePath}");
}
//HayırJSON errors.HayırHTTP errors.Hayırrate limit errors.
}
// IronOCR: standard .NET exceptions
public string SafeExtract(string imagePath)
{
try
{
var result = new IronTesseract().Read(imagePath);
return result.Text;
}
catch (FileNotFoundException)
{
throw; // File not found — straightforward
}
catch (Exception ex) when (ex.Message.Contains("corrupt"))
{
throw new Exception($"Image file is corrupt: {imagePath}");
}
//HayırJSON errors.HayırHTTP errors.Hayırrate limit errors.
}
Imports System
Imports IronOcr
Public Function SafeExtract(imagePath As String) As String
Try
Dim result = New IronTesseract().Read(imagePath)
Return result.Text
Catch ex As FileNotFoundException
Throw ' File not found — straightforward
Catch ex As Exception When ex.Message.Contains("corrupt")
Throw New Exception($"Image file is corrupt: {imagePath}")
End Try
End Function
IronTesseract API referans dokümanı ve OcrResult API referans dokümanı, çıkarım kalitesinin değerlendirilmesi için Confidence özelliği de dahil olmak üzere tiplenmiş sonuç yapısını belgeler.
API Eşleme Başvurusu
| OCR.space Konsepti | IronOCR Karşılığı |
|---|---|
POST https://api.ocr.space/parse/image |
new IronTesseract().Read(path) |
FormUrlEncodedContent / MultipartFormDataContent |
OcrInput |
base64Image parametresi |
input.LoadImage(path) veya input.LoadImage(bytes) |
language parametresi |
ocr.Language = OcrLanguage.English |
OCREngine parametresi |
Motor dahili olarak yönetiliyor |
isOverlayRequired parametresi |
result.Words / result.Lines (her zaman mevcut) |
isCreateSearchablePdf parametresi |
result.SaveAsSearchablePdf(outputPath) |
filetype=PDF parametresi |
input.LoadPdf(path) |
ParsedResults[0].ParsedText |
result.Text |
ParsedResults[n] (sayfa başına) |
result.Pages[n].Text |
IsErroredOnProcessing JSON bayrağı |
Standart .NET istisnası |
FileParseExitCode sayfa başına bayrak |
Standart .NET istisnası |
ProcessingTimeInMilliseconds |
Varsayılan – ekstra ayrıştırma gerekmez |
| HTTP 429 / oran limiti | Geçerli değil — hız sınırları yok |
Özel OcrResult POCO (kullanıcı tanımlı) |
IronOcr.OcrResult (NuGet tarafından sağlanır) |
Özel OcrSpaceException (kullanıcı tanımlı) |
Standart .NET istisna türleri |
SemaphoreSlim hız sınırlayıcı (kullanıcı tarafından yapılmış) |
Gerekli değil |
| Her istekte API anahtarı | IronOcr.License.LicenseKey (başlangıçta bir kez) |
Takımlar OCR.space'den IronOCR'ye Geçmeyi Düşündüklerinde
Yük Testi Sırasında Ücretsiz Katmanı Aşmak
OCR.space'in IP başına günlük 500 istek tavanı, yumuşak bir öneri değil, katı bir duvardır. Ekipler bunu, bir ofis IP adresini paylaşan birden çok geliştiricinin olduğu yük testi veya sahne dağıtımlarında keşfeder. OCR.space'e karşı entegrasyon testleri yürüten paylaşılan bir CI/CD hattı, iş günü bitmeden günlük kotayı tüketecektir. Bu noktada uygulama hata verir, çünkü kod yanlış olduğu için değil, üçüncü bir tarafın sayacı keyfi bir eşik seviyesine ulaştığı için. Yerel işleme geçmek, bu hata kategorisini tamamen ortadan kaldırır – işleme işlemi yerinde çalıştığı için tükenilecek bir kota yoktur.
Uyumluluk ve Veri Sınıflandırması İncelemeleri
Belgeleri PII, PHI veya finansal olarak hassas olarak sınıflandıran güvenlik incelemeleri, OCR.space için ikili bir sorun yaratır: hizmetin dahili dağıtım yolu yoktur. HIPAA senaryoları için belgelenmiş bir İş Ortağı Anlaşması (BAA) eşdeğeri, GDPR altında AB veri aktarımlarını net bir şekilde yöneten bir Veri İşleme Anlaşması yapısı ve belgenin gönderilmesini engelleyecek bir teknik mekanizma, sözleşme kontrolleri olsa bile, yoktur. Bulut üzerinden aktarılan belge işlemeye karşı uyumluluk bulguları alan ekiplerin yerel bir çözüme ihtiyacı vardır. IronOCR, bu gereksinimi tasarım gereği karşılar – belgeler asla uygulama sunucusunu terk etmez. Lisansa ilişkin sayfa, bulut-sağlayıcı incelemesini kapsamdan çıkararak uyumluluk dokümantasyonunu basitleştiren süresiz lisans yapısını belgeliyor.
Entegrasyon Kodu Bakım Yükü
OCR.space entegrasyonları, özellik gereksinimlerine orantılı olarak teknik borç biriktirir. Başlangıçtaki HTTP istemcisi yönetilebilir. Sonrasında ekip, tekrar deneme mantığını ekler. Sonra ekip, bir adresi paylaşan birden fazla hizmet nedeniyle, toplam IP oranı limiti izlemeyi ekler. Daha sonra dosya boyutu ön-doğrulama adımını eklerler. Ardından JSON hata yapısının Motor 1 ve Motor 2 yanıtları arasında farklılık gösterdiğini keşfederler ve bir dal eklerler. Altı ay sonra, OCR.space entegrasyonu, OCR ile ilgili herhangi bir şeye dokunmadan önce her yeni ekip üyesinin anlaması gereken 400 satır altyapı kodu olur. O ekip, bakım maliyetini bir $999 bir kerelik IronOCR lisansına karşı değerlendirirken aritmetik basittir.
Yapılandırılmış Çıktı Gereksinimleri
OCR.space yalnızca düz metin döndürür ve başka hiçbir şey sağlamaz. Yanıtta kelime koordinatları, satır sınırları, paragraf segmentasyonu veya kelime başına güven skorları yoktur. Fatura alanlarından belirli alanları çıkartmak isteyen uygulamalar – bilinen bir bölgede satıcı ismi, sağ alt köşede toplam tutar – OCR.space'in çıktısından oluşturmak için yapılandırılmış bir temele sahip değildir. IronOCR, her ayrıntı düzeyinde koordinatlar ve güvenlik değerleriyle tam bir belge hiyerarşisini açığa çıkarır: sayfalar, paragraflar, satırlar ve bireysel kelimeler. Bölgeye dayalı işleme, tüm sayfa çıktısını sonradan işlemeye gerek kalmadan, belirli belge bölgelerini hedefleme imkanı sağlar. Sonuç okuma nasıl yapılır ve bölgeye dayalı OCR rehberi bu kalıpları ayrıntılı olarak ele almaktadır.
Ücretsiz Katmanın Ötesinde Hacim Büyümesi
Ayda 25.000 istek için ücretsiz katman, düşük hacimli senaryolar için işlevseldir. Bunun ötesinde, ücretli katmanlar uygulanır — güncel fiyatlandırma için OCR.space ile iletişime geçin. Bu maliyetler zamanla birikir ve karşılaştırma, bir $999 ile sürekli bir lisans ile, asla istek başına ücretlendirilmeden yapılır. Aylık 25.000'den fazla belge hacmi büyümesi projeksiyonu yapan ekipler için yerel işlemeye yönelik basit bir maliyet durumu vardır.
Genel Geçiş Dikkat Edilmesi Gereken Hususlar
HTTP İstemcisini Bir Yöntem Çağrısıyla Değiştirme
OCR.space'den IronOCR'ya geçiş, belgelerden gelen metni her ikisi de döndürdüğü için mimari olarak basittir. HTTP istemcisi, JSON ayrıştırıcısı, oran sınırlayıcı ve özel istisna türleri ortadan kalkar. Yerine geçen tek şey bir NuGet paketi ve yöntem çağrılarıdır. Hizmet sınırındaki önce/sonra:
// Before: OCR.space service (simplified — actual implementation is200+lines)
public class OcrSpaceService : IDisposable
{
private readonly HttpClient _client = new();
private readonly string _apiKey;
public OcrSpaceService(string apiKey) => _apiKey = apiKey;
public async Task<string> ProcessDocument(string path)
{
byte[] bytes = File.ReadAllBytes(path);
string base64 = Convert.ToBase64String(bytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}")
});
var response = await _client.PostAsync("https://api.ocr.space/parse/image", content);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
return doc.RootElement.GetProperty("ParsedResults")[0].GetProperty("ParsedText").GetString()!;
}
public void Dispose() => _client.Dispose();
}
// After:IronOCR service — no HttpClient, no JSON, no API key
public class IronOcrService
{
private readonly IronTesseract _ocr = new();
public string ProcessDocument(string path)
{
return _ocr.Read(path).Text;
}
//HayırDispose — no external connections to close
}
// Before: OCR.space service (simplified — actual implementation is200+lines)
public class OcrSpaceService : IDisposable
{
private readonly HttpClient _client = new();
private readonly string _apiKey;
public OcrSpaceService(string apiKey) => _apiKey = apiKey;
public async Task<string> ProcessDocument(string path)
{
byte[] bytes = File.ReadAllBytes(path);
string base64 = Convert.ToBase64String(bytes);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("apikey", _apiKey),
new KeyValuePair<string, string>("base64Image", $"data:image/png;base64,{base64}")
});
var response = await _client.PostAsync("https://api.ocr.space/parse/image", content);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
return doc.RootElement.GetProperty("ParsedResults")[0].GetProperty("ParsedText").GetString()!;
}
public void Dispose() => _client.Dispose();
}
// After:IronOCR service — no HttpClient, no JSON, no API key
public class IronOcrService
{
private readonly IronTesseract _ocr = new();
public string ProcessDocument(string path)
{
return _ocr.Read(path).Text;
}
//HayırDispose — no external connections to close
}
Imports System
Imports System.IO
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.Text.Json
Public Class OcrSpaceService
Implements IDisposable
Private ReadOnly _client As New HttpClient()
Private ReadOnly _apiKey As String
Public Sub New(apiKey As String)
_apiKey = apiKey
End Sub
Public Async Function ProcessDocument(path As String) As Task(Of String)
Dim bytes As Byte() = File.ReadAllBytes(path)
Dim base64 As String = Convert.ToBase64String(bytes)
Dim content = New FormUrlEncodedContent(New KeyValuePair(Of String, String)() {
New KeyValuePair(Of String, String)("apikey", _apiKey),
New KeyValuePair(Of String, String)("base64Image", $"data:image/png;base64,{base64}")
})
Dim response = Await _client.PostAsync("https://api.ocr.space/parse/image", content)
response.EnsureSuccessStatusCode()
Dim json As String = Await response.Content.ReadAsStringAsync()
Using doc = JsonDocument.Parse(json)
Return doc.RootElement.GetProperty("ParsedResults")(0).GetProperty("ParsedText").GetString()
End Using
End Function
Public Sub Dispose() Implements IDisposable.Dispose
_client.Dispose()
End Sub
End Class
Public Class IronOcrService
Private ReadOnly _ocr As New IronTesseract()
Public Function ProcessDocument(path As String) As String
Return _ocr.Read(path).Text
End Function
End Class
IDisposable uygulaması ortadan kalkar çünkü yönetilecek HttpClient yoktur.
API Anahtarının Kaldırılması
OCR.space her HTTP isteğinde bir API anahtarı gerektirir. Bu anahtar güvenli bir şekilde saklanmalı, ifşa edildiğinde döndürülmeli ve kaynak denetiminden hariç tutulmalıdır. IronOCR, genellikle bir ortam değişkeni veya yapılandırma sistemi üzerinden, uygulama başlatıldığında bir kez ayarlanan bir lisans anahtarı kullanır:
// At application startup — once, not per request
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// At application startup — once, not per request
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' At application startup — once, not per request
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
Geçişten sonra, API anahtar döndürme süreci, gizli yönetim yapılandırması ve istek başına anahtar enjeksiyon mantığı tümüyle gereksiz hale gelir.
Göçten Sonra Ön İşleme
OCR.space, sonuçları geri göndermeden önce sunucu tarafında işleme uygular, ancak geliştiricilerin o işlemenin neyi içerdiği veya içermediği konusunda kontrolü yoktur. IronOCR, açık ön işleme yöntemleri sağlar. Belge kalitesi bir endişe ise — eğimli taramalar, düşük kontrastlı fotokopiler, gürültülü faks çıktıları — ön işleme boru hattı üç ila beş yöntem çağrısıdır:
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();
input.DeNoise();
input.Contrast();
input.Binarize();
input.EnhanceResolution(300);
var result = new IronTesseract().Read(input);
using var input = new OcrInput();
input.LoadImage("low-quality-scan.jpg");
input.Deskew();
input.DeNoise();
input.Contrast();
input.Binarize();
input.EnhanceResolution(300);
var result = new IronTesseract().Read(input);
Imports IronOcr
Using input As New OcrInput()
input.LoadImage("low-quality-scan.jpg")
input.Deskew()
input.DeNoise()
input.Contrast()
input.Binarize()
input.EnhanceResolution(300)
Dim result = New IronTesseract().Read(input)
End Using
Görüntü kalitesi düzeltme rehberi ve görüntü renk düzeltme rehberi mevcut filtrelerin tümünü ve doğruluk farklarını gösteren örneklerle belgelemektedir.
Async vs. Senkron
OCR.space aramaları, HTTP turu içerdiği için doğası gereği asenkroniktir.IronOCR aramaları varsayılan olarak senkroniktir, bu da web dışı bağlamlarda kodu basitleştirir. ASP.NET ve engellemeyen yürütme gerektiren sunucu senaryoları için, IronOCR, Task.Run saran veya doğrudan bir async API üzerinden asenkron çalışmayı destekler. Asenkron OCR rehberi kalıpları kapsar. Önceden bir bulut çağrısı bekleyen bir hizmet yönteminden await kaldırmak, async yalnızca OCR.space gerektirdiği için benimsendiği bağlamlarda çağrı yığınını basitleştirir.
Ek IronOCR Yetenekleri
Yukarıdaki bölümlerde ele alınmayan, OCR.space ile eşdeğer fonksiyonellik taşımayan her bir özellik:
- hOCR dışa aktarma:
result.SaveAsHocrFile("output.hocr")downstream belge işleme boru hatları için standartlara uygun hOCR çıkışı üretir. - İlerleme takibi: Uzun süreli çok sayfalı toplu işlem operasyonları için ilerleme olaylarına abone olun, UI uygulamalarında ilerleme çubukları ve ETA hesaplamalarına olanak tanır.
- Tablo çıkarımı: Yapılandırılmış tablo verilerine sonuç modeli ile erişilebilir, kolon hizalamasını gerektiren fatura kalem çıkarılması gibi kullanım senaryolarını destekler.
- Özelleşmiş belge okuma: Pasaport MRZ alanları, plaka, MICR çek yatay çizgileri ve el yazısı tanıma gibi amaç için geliştirilmiş özellikler, aynı
IronTesseractAPI aracılığıyla erişilebilir.
.NET Uyumluluğu ve Geleceğe Hazırlık
IronOCR, .NET 6, .NET 7, .NET 8 ve .NET 9 hedef alır, her LTS ve STS sürümü için etkin destek sağlar. Kütüphane Windows x64, Windows x86,Linuxx64, macOS, Docker, AWS Lambda ve Azure App Service üzerinde çalışır — hepsi tek bir NuGet paketi üzerinden işletim sistemine özgü bir yapılandırma olmadan. OCR.space, her dağıtım ortamından çıkış yönlü HTTPS gerektirir, bu da hava boşluklu ağları, kısıtlayıcı kurumsal proxy'leri ve politika gereğince üçüncü taraf API'lere çıkış yönlü trafiğin engellendiği altyapıyı hariç tutar. IronOCR'nin çalışma zamanı ağ gereksinimleri yoktur; yürütmeyi tamamen yerinde yapar. .NET 10'un 2026 sonlarına doğru yayına girmesiyle birlikte, IronOCR'nin .NET büyük sürümlerindeki uygunluğunu koruma geçmişi entegrasyon değişiklikleri olmadan süreklilik sağlar.
Sonuç
OCR.space, gerçek ve yararlı bir nişi işgal eder: bir hafta sonu boyunca bir OCR özelliği prototiplemek isteyen geliştiriciler, metin çıkarımı kavramlarını araştıran öğrenciler veya aylık 25.000 belgenin altında hacmi olan uyumluluk gereksinimi olmayan kişisel araçlar için. Bu kitle için, ücretsiz katman gerçek bir değer sunar.
Sorun, .NET geliştiricilerinin genellikle hafta sonu prototipleri oluşturmuyor olmasıdır. Onlar faturalama sistemleri, tıbbi kayıt işlemcileri, belge arşivleme boru hatları ve uyumluluk duyarlı iş uygulamaları geliştirir. Bu bağlamlar için, OCR.space'in mevcut olmayan NuGet paketi bir rahatsızlık değildir — yapısal bir uyumsuzluktur. HTTP istemcisi, oran sınırlayıcı, JSON ayrıştırıcısı ve tekrar deneme altyapısını kurmak için harcanan her saat, uygulamanın gerçek gereksinimlerini karşılamaya harcanmayan bir saattir. Bu maliyet önden yüklü, ancak entegrasyonun ömrü boyunca bakım maliyeti devam eder.
IronOCR, her OCR.space entegrasyonunu tanımlayan spesifik hata modunu ele alır: gerçek bir SDK'nın yokluğu. Bir NuGet paketi, bir yöntem çağırma, HTTP tesisatı yok, oran sınırlamaları yok, dış sunuculara belge aktarma yok. $999 giriş fiyatı tek seferlik bir maliyettir; artan OCR.space abonelik maliyetleri, özellikle hacim arttıkça zaman içinde bunu aşacaktır. Uyum gereksinimleri olan ekipler için, yerel işlem maliyeti ne olursa olsun tek seçenektir.
Karşılaştırma sonunda tek bir soruya indirgenir: uygulama, harici bir REST bağımlılığı olarak mı yoksa bir kütüphane işlevi olarak mı OCR gerektirir? .NET üretim uygulamaları için cevap neredeyse her zaman ikincisidir.
Sıkça Sorulan Sorular
OCR.space API nedir?
OCR.space API, geliştiriciler ve işletmeler tarafından görüntülerden ve belgelerden metin çıkarmak için kullanılan bir OCR çözümüdür. .NET uygulama geliştirmesi için IronOCR ile birlikte değerlendirilen birkaç OCR seçeneğinden biridir.
IronOCR, .NET geliştiricileri için OCR.space API ile nasıl karşılaştırılır?
IronOCR, IronTesseract'ı çekirdek motoru olarak kullanan, NuGet-native bir .NET OCR kütüphanesidir. OCR.space API ile karşılaştırıldığında, daha basit bir dağıtım (SDK yükleyicileri yok), sabit fiyatlandırma ve COM interop veya bulut bağımlılıkları olmadan temiz bir C# API sunar.
IronOCR, OCR.space API'den daha mı kolay kuruluyor?
IronOCR, tek bir NuGet paketi aracılığıyla yüklenir. SDK kurulumları, kopyalamak için lisans dosyaları, kaydedilecek COM bileşenleri veya yönetilecek ayrı çalışma zamanı ikili dosyaları yoktur. Tüm OCR motoru paket içinde yer alır.
OCR.space API ve IronOCR arasındaki doğruluk farkları nelerdir?
IronOCR, standart iş belgeleri, faturalar, makbuzlar ve taranmış formlar için yüksek tanıma doğruluğu sağlar. Çok kötü durumda olan belgeler ya da nadir yazılar için ise doğruluk, kaynak kalitesine göre değişiklik gösterebilir. IronOCR, düşük kaliteli girişlerde tanımayı geliştirmek için görüntü ön işleme filtreleri içerir.
IronOCR, PDF metin çıkarma desteği sunuyor mu?
Evet. IronOCR, tek bir çağrıda hem yerel PDF'lerden hem de taranmış PDF görüntülerinden metin çıkarır. Çok sayfalı TIFF dosyaları, görüntüler ve akıntılar da desteklenir. Taranmış PDF'ler için, OCR sayfa bazında uygulanır ve her sayfa için sonuç nesneleri sağlanır.
OCR.space API lisanslaması IronOCR ile nasıl karşılaştırılır?
IronOCR, sayfa veya tarama başına ücret içermeyen sabit oranlı bir süresiz lisans kullanır. Yüksek belge hacmi işleyen kuruluşlar, hacme rağmen aynı lisans maliyetini öder. Ayrıntılar ve hacim fiyatlandırması IronOCR lisans sayfasında mevcuttur.
IronOCR hangi dilleri destekliyor?
IronOCR, ayrı NuGet dil paketleri aracılığıyla 127 dili destekler. Bir dil eklemek için tek bir 'dotnet add package IronOcr.Languages.{Language}' komutu gerekir. Manuel dosya yerleştirme veya yol yapılandırması gerekmez.
.NET projesine IronOCR'yi nasıl kurarım?
NuGet üzerinden kurun: 'Install-Package IronOcr' Package Manager Console'da veya 'dotnet add package IronOcr' CLI'de. Ek dil paketleri aynı şekilde yüklenir. Yerel SDK kurucusu gerekmez.
IronOCR, OCR.space'ten farklı olarak Docker ve konteyner tabanlı dağıtımlar için uygun mudur?
Evet. IronOCR, NuGet paketi aracılığıyla Docker konteynerlerinde çalışır. Lisans anahtarı, bir ortam değişkeni aracılığıyla ayarlanır. Lisans dosyaları, SDK yolları veya OCR motoru için hacimlerin bağlanmasına gerek yoktur.
IronOCR'u OCR.space ile karşılaştırarak satın almadan önce deneyebilir miyim?
Evet. IronOCR deneme modu, belgeleri işler ve çıkış üzerine bir filigran eklemeli OCR sonuçları döndürür. Lisans satın almadan önce kendi belgeleriniz üzerinde doğruluğu kontrol edebilirsiniz.
IronOCR, metin çıkarma yanında barkod okuma desteği sunar mı?
IronOCR, metin çıkarma ve OCR'ye odaklanır. Barkod okuma için Iron Software, eşlik eden bir kütüphane olan IronBarcode'u sağlar. Her ikisi de ayrı ayrı veya Iron Suite paketi olarak mevcuttur.
OCR.space API'den IronOCR'a geçiş kolay mı?
OCR.space API'den IronOCR'a geçiş genellikle başlangıç dizilimlerini IronTesseract örneklemesiyle değiştirmek, COM yaşam döngüsü yönetimini kaldırmak ve API çağrılarını güncellemekle ilgilidir. Çoğu geçiş, kod karmaşıklığını önemli ölçüde azaltır.

