Comment installer Tesseract OCR sur Windows en C#
Ce guide accompagne les développeurs .NET dans le remplacement de Google Cloud Visionpar IronOCR , un moteur OCR local prêt à l'emploi. Il aborde la suppression des identifiants, le remplacement de l'analyse des annotations Protobuf, la simplification du traitement par lots des annotations et le traitement des documents multipages — les quatre changements structurels qui représentent la majeure partie du travail de migration.
Pourquoi migrer depuis Google Cloud VisionOCR
La décision de migrer commence presque toujours par l'un de ces deux constats : un audit de conformité bloque la transmission de documents dans le cloud, ou la surface opérationnelle de gestion des identifiants GCP, des compartiments GCS, de l'interrogation asynchrone et de la facturation par image devient plus coûteuse que l'OCR elle-même.
Cycle de vie de la clé JSON du compte de service. Chaque déploiement de votre application (machine de développement, pipeline CI/CD, serveur de préproduction, serveur de production, conteneur Docker, pod Kubernetes) requiert le même fichier de clé JSON pour le compte de service. Ce fichier contient une clé privée RSA. Il ne doit jamais être intégré au système de contrôle de version, doit être renouvelé régulièrement, doit être protégé par des permissions de système de fichiers et doit être mis à jour simultanément dans tous les environnements lors de chaque renouvellement. Une clé compromise donne accès à l'API jusqu'à sa révocation manuelle dans la console GCP. IronOCR remplace toute cette interface opérationnelle par une seule chaîne de clés de licence définie une seule fois au démarrage de l'application.
Facturation à la demande à grande échelle. À 1,50 $ pour 1 000 images et 0,0015 $ par page PDF, les coûts sont invisibles pendant le développement et problématiques en production. Un pipeline de traitement de documents gérant 200 000 pages par mois coûte 300 $ par mois rien qu'en frais d'API, avant les frais de stockage GCS et les coûts de sortie. Ces 300 dollars se répètent chaque mois indéfiniment. La licence perpétuelle d'IronOCR transforme l'OCR, initialement considérée comme une dépense d'exploitation mesurée, en un poste de dépense fixe dont l'exécution ne coûte rien la deuxième ou la troisième année.
Pipeline asynchrone GCS pour les PDF. Google Cloud Visionn'accepte pas les PDF comme entrée directe de l'API. Le pipeline complet nécessite un deuxième package NuGet (Google.Cloud.Storage.V1), un bucket GCS provisionné, un téléchargement asynchrone, un appel AsyncBatchAnnotateFilesAsync, une boucle de sondage, une analyse de la sortie JSON depuis GCS, et une étape de nettoyage. Ce pipeline s'étend sur plus de 50 lignes de code avant que tout texte ne soit extrait. IronOCR lit un PDF en trois lignes, de manière synchrone, sans dépendances externes.
Concaténation de symboles Protobuf. La réponse DOCUMENT_TEXT_DETECTION stocke le texte au niveau du symbole dans une hiérarchie Protobuf de Pages, Blocs, Paragraphes, Mots et Symboles. La lecture du texte des paragraphes nécessite de parcourir cinq boucles imbriquées et d'appeler .SelectMany(w => w.Symbols).Select(s => s.Text). IronOCR renvoie le texte des paragraphes comme paragraph.Text — une propriété chaîne typée.
1 800 requêtes par minute de quota par défaut. Les charges de travail par lots au-dessus du quota par défaut reçoivent des réponses StatusCode.ResourceExhausted qui bloquent le pipeline pendant 60 secondes par dépassement. L'augmentation du quota nécessite une demande via la console GCP et l'approbation de Google. IronOCR traite les données localement à la vitesse des cœurs de processeur disponibles — il n'y a pas de quota à gérer, pas d'approbation à demander et aucune logique de nouvelle tentative requise pour la limitation du débit.
Aucune prise en charge hors ligne ou en mode isolé. Google Cloud Visionnécessite une connexion Internet aux points de terminaison de Google. Les réseaux isolés, les centres de données classifiés et les systèmes de contrôle industriels ne peuvent pas l'utiliser, quel que soit leur niveau de complexité architecturale. IronOCR fonctionne sans aucune connectivité réseau sortante après la validation initiale de la licence.
Le problème fondamental
Google Cloud Vision nécessite un fichier de clé JSON sur le disque avant l'exécution de la première ligne de code OCR :
// Google Cloud Vision: JSON key file deployed to every server before this line works
// GOOGLE_APPLICATION_CREDENTIALS="/etc/secrets/service-account.json" must be set
// Key contains RSA private key — rotate manually, revoke if compromised
_client = ImageAnnotatorClient.Create();
var image = Image.FromFile("document.jpg");
var response = _client.DetectText(image); // document leaves your infrastructure
string text = response[0].Description;
IronOCR démarre avec une seule chaîne de caractères et s'exécute entièrement sur la machine locale :
// IronOCR: one string at startup, no key files, no environment variables
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read("document.jpg").Text; // local, no cloud
Comparaison des fonctionnalités IronOCR et de Google Cloud VisionOCR
Le tableau ci-dessous répertorie les fonctionnalités directement destinées aux équipes qui élaborent l'analyse de rentabilité de la migration.
| Fonction | Google Cloud VisionOCR | IronOCR |
|---|---|---|
| Lieu de traitement | Google Cloud (à distance) | Sur place (local) |
| Authentification | Clé JSON du compte de service + variable d'environnement | chaîne de clé de licence |
| Entrée PDF | Téléversement vers GCS + API asynchrone | input.LoadPdf() direct |
| PDF protégé par mot de passe | Non pris en charge | LoadPdf(path, Password: "...") |
| Entrée TIFF multipage | Limité | input.LoadImageFrames() |
| Sortie PDF consultable | Non disponible | result.SaveAsSearchablePdf() |
| Accès aux données structurées | Protobuf : Pages > Blocs > Paragraphes > Mots > Symboles | result.Paragraphs, result.Lines, result.Words (objets .NET typés) |
| Propriété du texte du paragraphe | Non — nécessite la concaténation de symboles | paragraph.Text propriété directe |
| scores de confiance | Par symbole (nécessite une boucle) | result.Confidence, word.Confidence |
| prétraitement automatique des images | Aucun (ML s'en charge) | Redresser, réduire le bruit, contraster, binariser, accentuer |
| OCR basé sur la région | Aucune culture indigène | CropRectangle sur OcrInput |
| Lecture de codes-barres | Fonctionnalité API distincte | ocr.Configuration.ReadBarCodes = true |
| Limites de débit | 1 800 requêtes/minute par défaut | Aucun (lié au processeur) |
| Hors ligne / isolé dans l'air | Non | Oui |
| Coût par document | 1,50 $ pour 1 000 images ; 0,0015 $/page PDF | Aucun (licence perpétuelle) |
| Langues prises en charge | ~50 | 125+ |
| Autorisation FedRAMP | Non autorisé | Non applicable (sur place) |
| Parcours de conformité HIPAA | Accord de partenariat commercial requis | Aucun traitement de données par des tiers |
| Prise en charge du .NET Framework | .NET Standard 2.0+ | .NET Framework 4.6.2+ et .NET 5/6/7/8/9 |
| Packages NuGet requis | Google.Cloud.Vision.V1 + Google.Cloud.Storage.V1 | IronOcr seulement |
| Modèle de tarification | Facturation à la demande | Perpetual ($999 Lite / $1,499 Plus / $2,999 Professional / $5,999 Unlimited) |
Démarrage rapide : Migration de Google Cloud VisionOCRvers IronOCR
Étape 1 : Remplacer le package NuGet
Supprimez les packages Google Cloud :
dotnet remove package Google.Cloud.Vision.V1
dotnet remove package Google.Cloud.Storage.V1
Installez IronOCR depuis la page du package NuGet :
Étape 2 : Mise à jour des espaces de noms
Remplacez les espaces de noms Google Cloud par l'espace de noms IronOCR :
// Before (Google Cloud Vision)
using Google.Cloud.Vision.V1;
using Google.Cloud.Storage.V1;
using Google.Protobuf;
using Grpc.Core;
// After (IronOCR)
using IronOcr;
Étape 3 : initialisation de la licence
Ajoutez l'initialisation de la licence une fois au démarrage de l'application, avant que toute instance de IronTesseract ne soit créée.
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"En production, lisez la clé à partir d'une variable d'environnement ou d'un gestionnaire de secrets :
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable not set.");
Exemples de migration de code
Suppression de la configuration des informations d'identification du compte de service
L'initialisation du client Google Cloud Visionressemble à une simple ligne de code, mais nécessite une infrastructure préalable importante. Chaque développeur qui rejoint le projet, chaque environnement de déploiement et chaque pipeline CI/CD doivent disposer d'une configuration d'identification complète avant que le constructeur ne se termine sans générer d'erreur.
Approche de Google Cloud Vision :
using Google.Cloud.Vision.V1;
// Prerequisites before this class can be instantiated:
// 1. GCP project created and Vision API enabled in GCP Console
// 2. Service account created with roles/cloudvision.user IAM role
// 3. JSON key file downloaded to every server that runs this code
// 4. GOOGLE_APPLICATION_CREDENTIALS env var pointing to the JSON file
// 5. JSON file excluded from source control via .gitignore
// 6. Key rotation schedule established (recommended: 90 days)
// 7. Separate credentials per environment (dev/staging/prod)
public class DocumentOcrService
{
private readonly ImageAnnotatorClient _client;
private readonly string _projectId;
public DocumentOcrService(string projectId)
{
_projectId = projectId;
// Throws RpcException(StatusCode.PermissionDenied) if any prerequisite is missing
_client = ImageAnnotatorClient.Create();
}
public string ReadDocument(string imagePath)
{
var image = Image.FromFile(imagePath);
var response = _client.DetectText(image);
return response.Count > 0 ? response[0].Description : string.Empty;
}
}
Approche IronOCR :
using IronOcr;
// Prerequisites: set the license key once at app startup
// Non JSON files, no environment variables beyond the key, no GCP Console configuration
// Non key rotation, no IAM roles, no per-environment credential sets
public class DocumentOcrService
{
private readonly IronTesseract _ocr;
public DocumentOcrService()
{
// IronTesseract is ready immediately — no external validation required
_ocr = new IronTesseract();
}
public string ReadDocument(string imagePath)
{
return _ocr.Read(imagePath).Text;
}
}
La différence opérationnelle est concrète : Google Cloud Visiongénère cinq catégories de RpcException à l'exécution — PermissionDenied, ResourceExhausted, Unavailable, DeadlineExceeded, et Unauthenticated — chacune représentant un mode de panne d'infrastructure différent. Les modes de panne d'IronOCR sont IOException (fichier non trouvé ou verrouillé) et OcrException (échec du traitement). Consultez le guide d'installation d'IronTesseract pour les options de configuration et la page produit IronOCR pour les détails de licence.
Remplacement des requêtes d'annotation par lots par plusieurs types de fonctionnalités
Google Cloud Vision prend en charge le regroupement de plusieurs images en un seul BatchAnnotateImagesRequest, chaque image étant configurée avec une liste de types de Feature. Ce modèle est utilisé lorsqu'un appel unique doit collecter à la fois les résultats de TEXT_DETECTION et de DOCUMENT_TEXT_DETECTION, ou lors de la soumission de nombreuses images pour minimiser les surcoûts de round-trip. La réponse Protobuf nécessite de faire correspondre chaque AnnotateImageResponse à sa demande d'origine par index.
Approche de Google Cloud Vision :
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
public class BatchAnnotationService
{
private readonly ImageAnnotatorClient _client;
public BatchAnnotationService()
{
_client = ImageAnnotatorClient.Create();
}
public List<string> BatchAnnotateImages(string[] imagePaths)
{
// Build one request per image with TEXT_DETECTION feature
var requests = imagePaths.Select(path => new AnnotateImageRequest
{
Image = Image.FromFile(path),
Features =
{
new Fonction { Type = Feature.Types.Type.TextDetection },
new Fonction { Type = Feature.Types.Type.DocumentTextDetection }
}
}).ToList();
// Single round-trip for all images in the batch
var batchResponse = _client.BatchAnnotateImages(requests);
// Match responses back to requests by index
var results = new List<string>();
for (int i = 0; i < batchResponse.Responses.Count; i++)
{
var response = batchResponse.Responses[i];
if (response.Error != null)
{
// Per-item error in batch — must handle individually
results.Add($"Error on {imagePaths[i]}: {response.Error.Message}");
continue;
}
// Prefer DOCUMENT_TEXT_DETECTION full text if available
var fullText = response.FullTextAnnotation?.Text
?? response.TextAnnotations.FirstOrDefault()?.Description
?? string.Empty;
results.Add(fullText);
}
return results;
}
}
Approche IronOCR :
using IronOcr;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
public class BatchAnnotationService
{
public List<string> BatchAnnotateImages(string[] imagePaths)
{
var results = new ConcurrentDictionary<int, string>();
// Parallel processing — no batch size limit, no network round-trips
Parallel.For(0, imagePaths.Length, i =>
{
var ocr = new IronTesseract(); // thread-safe: one instance per thread
results[i] = ocr.Read(imagePaths[i]).Text;
});
// Reconstruct in original order
return Enumerable.Range(0, imagePaths.Length)
.Select(i => results[i])
.ToList();
}
public OcrResult BatchAsDocument(string[] imagePaths)
{
// Load all images into a single OcrInput for combined document output
using var input = new OcrInput();
foreach (var path in imagePaths)
input.LoadImage(path);
return new IronTesseract().Read(input);
}
}
IronOCR exécute le traitement par lots en parallèle sur les cœurs du processeur sans aucune surcharge réseau. Il n'y a pas de plafonnement BatchSize, pas de correspondance d'index de réponse, et pas de gestion des erreurs par élément pour les échecs de réseau ou de credentials. Pour les charges de travail qui combinent plusieurs images en un seul document logique — des formulaires multi-pages scannés soumis sous forme de JPEG individuels, par exemple — BatchAsDocument charge toutes les images dans un seul OcrInput et renvoie un OcrResult unifié avec result.Pages indexé sur chaque image d'entrée. L' exemple de multithreading illustre les performances de référence pour le traitement parallèle.
Migration de l'extraction d'annotations au niveau des mots Protobuf
Les données de délimitation et de confiance au niveau des mots de Google Cloud Visionnécessitent de parcourir toute la hiérarchie Protobuf : Pages, puis Blocs, puis Paragraphes, puis Mots, puis Symboles. L'extraction de texte de mots nécessite de concaténer des Symboles de chaque Mot — l'objet Word n'a pas de propriété directe .Text. Les coordonnées de la boîte englobante sont stockées sous forme de BoundingPoly avec une liste de Vertices plutôt que sous forme de champs discrets X, Y, Largeur, Hauteur.
Approche de Google Cloud Vision :
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
public record WordAnnotation(string Text, int X, int Y, int Width, int Height, float Confidence);
public class WordLevelExtractor
{
private readonly ImageAnnotatorClient _client;
public WordLevelExtractor()
{
_client = ImageAnnotatorClient.Create();
}
public List<WordAnnotation> ExtractWordAnnotations(string imagePath)
{
var image = Image.FromFile(imagePath);
var annotation = _client.DetectDocumentText(image);
var words = new List<WordAnnotation>();
// Navigate: Pages -> Blocks -> Paragraphs -> Words
foreach (var page in annotation.Pages)
{
foreach (var block in page.Blocks)
{
foreach (var paragraph in block.Paragraphs)
{
foreach (var word in paragraph.Words)
{
// Word.Text does not exist — must concatenate Symbols
var text = string.Concat(word.Symbols.Select(s => s.Text));
// BoundingPoly has Vertices, not X/Y/Width/Height
var vertices = word.BoundingBox.Vertices;
int x = vertices[0].X;
int y = vertices[0].Y;
int width = vertices.Count > 1 ? vertices[1].X - vertices[0].X : 0;
int height = vertices.Count > 2 ? vertices[2].Y - vertices[0].Y : 0;
words.Add(new WordAnnotation(text, x, y, width, height, word.Confidence));
}
}
}
}
return words;
}
}
Approche IronOCR :
using IronOcr;
using System.Collections.Generic;
public record WordAnnotation(string Text, int X, int Y, int Width, int Height, double Confidence);
public class WordLevelExtractor
{
private readonly IronTesseract _ocr;
public WordLevelExtractor()
{
_ocr = new IronTesseract();
}
public List<WordAnnotation> ExtractWordAnnotations(string imagePath)
{
var result = _ocr.Read(imagePath);
// Words are a flat collection — no hierarchy traversal, no symbol concatenation
return result.Words.Select(w => new WordAnnotation(
Text: w.Text, // direct string property
X: w.X,
Y: w.Y,
Width: w.Width,
Height: w.Height,
Confidence: w.Confidence // double, no conversion needed
)).ToList();
}
}
La boucle de concaténation de symboles dans la version Google Cloud Visionn'est pas un choix de conception ; elle est requise par le schéma Protobuf. Word.Text n'est pas une propriété dans l'objet de réponse. Chaque équipe qui utilise l'API au niveau des mots écrit une boucle équivalente. La collection OcrResult.Words d'IronOCR expose Text, X, Y, Width, Height et Confidence en tant que propriétés de premier ordre. Le guide des résultats de lecture documente l'ensemble complet des propriétés disponibles à chaque niveau de granularité.
Traitement TIFF multipage vers un PDF interrogeable
Google Cloud Vision traite les fichiers TIFF multipages comme une série séquentielle d'images, chacune nécessitant un appel API distinct. Il n'existe pas d'appel API unique qui accepte un fichier TIFF et renvoie une sortie structurée pour toutes les images. La génération d'un PDF consultable à partir des résultats de Google Cloud Visionnécessite une bibliothèque de génération de PDF distincte — l'API ne renvoie que du texte.
Approche de Google Cloud Vision :
using Google.Cloud.Vision.V1;
using System.Collections.Generic;
using System.Drawing; // for TIFF frame extraction
using System.Drawing.Imaging;
public class TiffProcessingService
{
private readonly ImageAnnotatorClient _client;
public TiffProcessingService()
{
_client = ImageAnnotatorClient.Create();
}
public List<string> ProcessMultiPageTiff(string tiffPath)
{
var pageTexts = new List<string>();
// Load TIFF and extract frames manually using System.Drawing
using var tiff = System.Drawing.Image.FromFile(tiffPath);
var frameDimension = new FrameDimension(tiff.FrameDimensionsList[0]);
int frameCount = tiff.GetFrameCount(frameDimension);
for (int i = 0; i < frameCount; i++)
{
tiff.SelectActiveFrame(frameDimension, i);
// Save each frame to a temp file — Vision API does not accept TIFF frames directly
var tempPath = Path.Combine(Path.GetTempPath(), $"tiff-frame-{i}.jpg");
tiff.Save(tempPath, ImageFormat.Jpeg);
// One API call per frame — each call = one unit of quota
var visionImage = Google.Cloud.Vision.V1.Image.FromFile(tempPath);
var response = _client.DetectText(visionImage);
pageTexts.Add(response.FirstOrDefault()?.Description ?? string.Empty);
File.Delete(tempPath);
}
// Producing a searchable PDF requires a separate library (e.g., iTextSharp)
// Google Cloud Visionhas no PDF output capability
return pageTexts;
}
}
Approche IronOCR :
using IronOcr;
public class TiffProcessingService
{
private readonly IronTesseract _ocr;
public TiffProcessingService()
{
_ocr = new IronTesseract();
}
public string ProcessMultiPageTiff(string tiffPath)
{
using var input = new OcrInput();
// LoadImageFrames handles all TIFF frames in one call — no temp files, no frame loop
input.LoadImageFrames(tiffPath);
var result = _ocr.Read(input);
return result.Text;
}
public void ProcessMultiPageTiffToSearchablePdf(string tiffPath, string outputPdfPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
var result = _ocr.Read(input);
// Google Cloud Visionhas no equivalent — this single call produces a searchable PDF
result.SaveAsSearchablePdf(outputPdfPath);
}
public void ProcessLowQualityTiff(string tiffPath, string outputPdfPath)
{
using var input = new OcrInput();
input.LoadImageFrames(tiffPath);
// Preprocessing before OCR improves accuracy on degraded scans
input.Deskew();
input.DeNoise();
input.Contrast();
var result = _ocr.Read(input);
result.SaveAsSearchablePdf(outputPdfPath);
}
}
La version Google Cloud Visionnécessite System.Drawing pour l'extraction des images, des fichiers JPEG temporaires écrits sur le disque, un appel API par image (consommant un quota proportionnellement au nombre d'images) et une bibliothèque PDF distincte pour produire toute sortie autre que du texte brut. IronOCR gère les TIFF multi-cadres nativement via LoadImageFrames, traite tous les cadres en un seul appel Read, et produit une sortie PDF consultable via SaveAsSearchablePdf. Pour les documents TIFF archivés numérisés, le pipeline de prétraitement dans ProcessLowQualityTiff traite les problèmes de qualité les plus courants en une seule passe. Consultez la section relative aux entrées TIFF et GIF et à la sortie PDF consultable pour obtenir l'API complète.
Migration par lots à débit limité avec suivi de la progression
En production, le quota par défaut de 1 800 requêtes par minute de Google Cloud Visionnécessite soit une limitation du débit, soit une logique de nouvelle tentative avec un délai exponentiel. Le traitement de 5 000 documents en une seule tâche de nuit dépassera largement le quota. Chaque dépassement de quota bloque le pipeline pendant une attente obligatoire de 60 secondes. IronOCR n'a pas de limite de débit — le pipeline est uniquement limité par les cœurs du processeur et les threads disponibles.
Approche de Google Cloud Vision :
using Google.Cloud.Vision.V1;
using Grpc.Core;
using System.Collections.Generic;
public class ThrottledBatchProcessor
{
private readonly ImageAnnotatorClient _client;
private const int MaxRequestsPerMinute = 1800;
private const int RetryDelayMs = 60_000;
public ThrottledBatchProcessor()
{
_client = ImageAnnotatorClient.Create();
}
public async Task<Dictionary<string, string>> ProcessWithThrottlingAsync(
string[] imagePaths,
IProgress<(int completed, int total)> progress)
{
var results = new Dictionary<string, string>();
int completed = 0;
foreach (var path in imagePaths)
{
bool succeeded = false;
while (!succeeded)
{
try
{
var image = Google.Cloud.Vision.V1.Image.FromFile(path);
var response = _client.DetectText(image);
results[path] = response.FirstOrDefault()?.Description ?? string.Empty;
succeeded = true;
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.ResourceExhausted)
{
// Rate limit exceeded — wait and retry
await Task.Delay(RetryDelayMs);
}
}
progress.Report((++completed, imagePaths.Length));
}
return results;
}
}
Approche IronOCR :
using IronOcr;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class BatchProcessor
{
public Dictionary<string, string> ProcessBatch(
string[] imagePaths,
IProgress<(int completed, int total)> progress)
{
var results = new ConcurrentDictionary<string, string>();
int completed = 0;
// Aucune limite de débit — full parallelism, no retry logic needed
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
results[imagePath] = ocr.Read(imagePath).Text;
progress.Report((Interlocked.Increment(ref completed), imagePaths.Length));
});
return new Dictionary<string, string>(results);
}
public void ProcessBatchToSearchablePdfs(
string[] imagePaths,
string outputDirectory)
{
Parallel.ForEach(imagePaths, imagePath =>
{
var ocr = new IronTesseract();
var result = ocr.Read(imagePath);
var outputPath = Path.Combine(
outputDirectory,
Path.GetFileNameWithoutExtension(imagePath) + "-searchable.pdf");
result.SaveAsSearchablePdf(outputPath);
});
}
}
La version Google Cloud Visionest séquentielle car les requêtes parallèles multiplieraient l'exposition à la limite de débit. Chaque exception ResourceExhausted ajoute un blocage complet de 60 secondes. Un lot de 5 000 documents qui atteint le quota 10 fois ajoute 10 minutes d'attente inutile. La version d'IronOCR effectue le traitement en parallèle sur tous les cœurs disponibles, sans attente. Pour les lots de longue durée, l'API de suivi de progression fournit des callbacks de progression intégrés sans nécessiter de câblage Interlocked.Increment manuel. Pour les problèmes de qualité d'image dans les numérisations par lots, le guide de correction de la qualité de l'image couvre le pipeline de prétraitement qui peut être ajouté avant chaque appel Read.
Référence de mappage de l'API OCR de Google Cloud Visionvers IronOCR
| Google Cloud Vision | IronOCR | Notes |
|---|---|---|
ImageAnnotatorClient.Create() | new IronTesseract() | Initialisation du client ; aucun fichier d'accréditation n'est nécessaire |
Image.FromFile(path) | _ocr.Read(path) ou input.LoadImage(path) | Lecture de chemin direct disponible sur IronTesseract |
_client.DetectText(image) | _ocr.Read(path).Text | TEXT_DETECTION équivalent |
_client.DetectDocumentText(image) | _ocr.Read(path) | DOCUMENT_TEXT_DETECTION équivalent; le mode est automatique |
response[0].Description | result.Text | Texte intégral du document |
TextAnnotation | OcrResult | Conteneur de résultats de niveau supérieur |
annotation.Text | result.Text | Chaîne de texte complète |
annotation.Pages[i] | result.Pages[i] | Accès par page |
page.Blocks[i].Paragraphs[j] | result.Paragraphs[i] | IronOCR expose les paragraphes comme une collection plate |
paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text) | paragraph.Text | Propriété de chaîne directe ; pas d'itération de symbole |
word.BoundingBox.Vertices | word.X, word.Y, word.Width, word.Height | Propriétés de type entier discret au lieu d'une liste de sommets |
word.Confidence | word.Confidence | Score de confiance par mot |
page.Confidence | result.Confidence | Confiance globale dans les résultats |
Feature.Types.Type.DocumentTextDetection | Automatique | IronOCR sélectionne automatiquement le mode de traitement |
BatchAnnotateImagesRequest | Parallel.ForEach + new IronTesseract() par thread | Traitement local parallèle ; pas de limite de taille de lot |
_client.BatchAnnotateImages(requests) | new IronTesseract().Read(input) avec OcrInput multi-image | Un seul appel pour une entrée multi-images |
AsyncBatchAnnotateFilesAsync() | input.LoadPdf() ; _ocr.Read(entrée) | Le traitement des fichiers PDF est synchrone ; Aucun GCS requis |
StorageClient.Create() | Pas nécessaire | Aucune dépendance à GCS |
storageClient.UploadObjectAsync() | Pas nécessaire | Les fichiers PDF se chargent directement à partir d'un chemin local ou d'un flux. |
operation.PollUntilCompletedAsync() | Pas nécessaire | Le traitement est synchrone |
RpcException (StatusCode.ResourceExhausted) | Sans objet | Aucune limite de débit |
RpcException (StatusCode.PermissionDenied) | Sans objet | Aucune authentification à l'exécution |
GOOGLE_APPLICATION_CREDENTIALS env var | IronOcr.License.LicenseKey | Affectation de chaîne de caractères, et non chemin de fichier |
Problèmes de migration courants et solutions
Problème 1 : Le constructeur lève une exception sans GOOGLE_APPLICATION_CREDENTIALS
Google Cloud Vision: ImageAnnotatorClient.Create() lance RpcException avec StatusCode.Unauthenticated ou StatusCode.PermissionDenied si la variable d'environnement n'est pas définie ou pointe vers un fichier invalide. Cet échec survient au démarrage, pas lors du premier appel d'API, ce qui signifie que l'application entière échoue à s'initialiser si les identifiants manquent dans un des environnements.
Solution: Après avoir supprimé les packages de Google Cloud Vision, supprimez toutes les références à GOOGLE_APPLICATION_CREDENTIALS de vos configurations d'environnement, secrets du pipeline CI/CD, secrets Kubernetes et fichiers Docker Compose. Remplacez par une seule variable d'environnement IRONOCR_LICENSE:
// Remove this from every deployment environment:
// GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
// Add this once at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
?? throw new InvalidOperationException("IRONOCR_LICENSE environment variable is required.");
Problème n° 2 : Des erreurs se produisent lors de la concaténation de symboles Protobuf après la suppression de l'espace de noms.
Google Cloud Vision: Chaque emplacement dans votre code source où le texte de paragraphe ou de mot a été extrait en utilisant .SelectMany(w => w.Symbols).Select(s => s.Text) produira des erreurs de compilation après que le namespace Google.Cloud.Vision.V1 soit supprimé. Ces appels sont répartis entre les classes d'assistance ou de service qui ont consommé la réponse de l'API.
Solution: Recherchez tous les modèles SelectMany et w.Symbols dans votre code source et remplacez-les par un accès direct aux propriétés sur les objets de résultat IronOCR. Le guide sur la lecture des résultats couvre chaque propriété disponible sur OcrResult, OcrResult.Page, OcrResult.Paragraph, OcrResult.Line et OcrResult.Word:
# Find all Protobuf symbol concatenation patterns
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .
grep -rn "w\.Symbols\.Select" --include="*.cs" .
Remplacez chaque occurrence :
// Before: symbol concatenation required by Protobuf schema
var text = string.Join("", paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text));
// After: direct property on OcrResult.Paragraph
var text = paragraph.Text;
Problème 3 : Le code de traitement PDF ne compile pas après la suppression de Storage.V1
Google Cloud Vision: Après la suppression de Google.Cloud.Storage.V1, tout code qui fait référence à StorageClient, UploadObjectAsync, DeleteObjectAsync, AsyncAnnotateFileRequest, GcsSource, GcsDestination et PollUntilCompletedAsync échouera à la compilation. Ce code peut couvrir plusieurs classes de service et représente généralement le plus grand bloc unique de modifications.
Solution : Supprimez l'intégralité du pipeline GCS. Remplacez la méthode asynchrone de Plus de 50 lignes par son équivalent IronOCR en trois lignes. Pour le code qui maintenait une signature asynchrone pour la compatibilité des appelants, enveloppez avec Task.Run:
// Delete: StorageClient, GCS upload, AsyncBatchAnnotateFilesAsync,
// PollUntilCompletedAsync, output download, DeleteObjectAsync
// Replace with:
public async Task<string> ProcessPdfAsync(string pdfPath)
{
return await Task.Run(() =>
{
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return new IronTesseract().Read(input).Text;
});
}
Pour le nouveau code, utilisez le support natif de l'OCR asynchrone au lieu de l'enveloppe Task.Run. Le guide d'importation PDF couvre la sélection de la plage de pages et le chargement de PDF protégés par mot de passe.
Problème n°4 : La logique de nouvelle tentative de limitation de débit n'est plus nécessaire.
Google Cloud Vision: Tout code qui attrape RpcException avec StatusCode.ResourceExhausted et implémente un modèle d'attente et de réessai a été écrit pour gérer le quota de 1 800 requêtes par minute. Cette logique de nouvelle tentative peut être intégrée dans un middleware, des étapes de pipeline ou des boucles de traitement par lots.
Solution : Supprimer toute logique de nouvelle tentative associée aux erreurs de quota. IronOCR traite les données localement, sans quota externe. Le contrat du gestionnaire d'erreurs change de cinq cas RpcException à deux :
// Remove: all RpcException handlers for ResourceExhausted, PermissionDenied,
// Unavailable, DeadlineExceeded, Unauthenticated
// IronOCR error surface:
try
{
var result = new IronTesseract().Read(imagePath);
if (result.Confidence < 50)
input.DeNoise(); // add preprocessing for low-confidence results
return result.Text;
}
catch (IOException ex)
{
// File not found or locked
throw new InvalidOperationException($"Cannot read: {imagePath}", ex);
}
catch (IronOcr.Exceptions.OcrException ex)
{
// Processing failure — not a transient network error
throw new InvalidOperationException($"OCR failed: {ex.Message}", ex);
}
Problème 5 : Les fichiers TIFF multipages nécessitent une boucle d'extraction d'images
Google Cloud Vision: Le code de traitement de TIFF existant extrait probablement des cadres en utilisant System.Drawing.Image, enregistre chaque cadre sous forme de JPEG dans un répertoire temporaire, soumet chaque JPEG en tant qu'appel API distinct, puis supprime les fichiers temporaires ensuite. Ce modèle consomme une unité de quota par image et peut laisser des fichiers temporaires orphelins en cas de plantage.
Solution: Remplacez la boucle d'extraction de cadres et la gestion des fichiers temporaires par input.LoadImageFrames(). La boucle d'animation System.Drawing entière a été supprimée :
// Remove: System.Drawing frame extraction, temp file writes, per-frame API calls
// Replace with:
using var input = new OcrInput();
input.LoadImageFrames(tiffPath); // all frames, no temp files
var result = new IronTesseract().Read(input);
Consultez le guide d'entrée TIFF et GIF pour connaître les options de traitement multi-images, notamment la sélection de la plage d'images.
Problème 6 : Rupture des calculs de sommets de BoundingPoly
Google Cloud Vision: Le code qui lisait les coordonnées de la boîte englobante depuis annotation.BoundingPoly.Vertices calculait X, Y, Largeur et Hauteur à partir de l'arithmétique de l'index de vertex : vertices[0].X pour X, vertices[1].X - vertices[0].X pour la Largeur, vertices[2].Y - vertices[0].Y pour la Hauteur. Après la migration, ces expressions n'ont pas d'équivalent dans IronOCR parce que Vertices n'existe pas.
Solution : Remplacer l'arithmétique des sommets par des propriétés entières directes. Aucun calcul n'est nécessaire :
// Before: vertex index arithmetic
int x = word.BoundingBox.Vertices[0].X;
int y = word.BoundingBox.Vertices[0].Y;
int width = word.BoundingBox.Vertices[1].X - word.BoundingBox.Vertices[0].X;
int height = word.BoundingBox.Vertices[2].Y - word.BoundingBox.Vertices[0].Y;
// After: direct properties
int x = word.X;
int y = word.Y;
int width = word.Width;
int height = word.Height;
Liste de contrôle de migration OCR Google Cloud Vision
Pré-migration
Avant d'apporter des modifications, auditez le code source afin d'identifier toutes les dépendances à Google Cloud Vision :
# Find all Google Cloud Visionnamespace imports
grep -rn "using Google.Cloud.Vision" --include="*.cs" .
grep -rn "using Google.Cloud.Storage" --include="*.cs" .
grep -rn "using Grpc.Core" --include="*.cs" .
# Find ImageAnnotatorClient usage
grep -rn "ImageAnnotatorClient" --include="*.cs" .
# Find GCS pipeline code
grep -rn "StorageClient\|UploadObjectAsync\|DeleteObjectAsync" --include="*.cs" .
grep -rn "AsyncBatchAnnotateFilesAsync\|PollUntilCompleted" --include="*.cs" .
# Find Protobuf symbol concatenation
grep -rn "\.Symbols\." --include="*.cs" .
grep -rn "SelectMany.*Symbols" --include="*.cs" .
# Find BoundingPoly vertex calculations
grep -rn "BoundingPoly\|BoundingBox\.Vertices" --include="*.cs" .
# Find rate limit retry handlers
grep -rn "ResourceExhausted\|StatusCode\." --include="*.cs" .
# Find environment variable references
grep -rn "GOOGLE_APPLICATION_CREDENTIALS" .
Notes d'inventaire à compléter avant de commencer :
- Lister tous les compartiments GCS créés pour l'entrée/sortie OCR — planifier le nettoyage après la migration
- Documentez l'adresse e-mail du compte de service afin qu'elle puisse être désactivée dans la console GCP après la migration.
- Identifiez tous les environnements où
GOOGLE_APPLICATION_CREDENTIALSest configuré Notez que tout code lisant les ID de projet GCP ou les noms de compartiment à partir de la configuration doit être supprimé après la migration.
Migration de code
- Supprimez le package NuGet
Google.Cloud.Vision.V1de tous les projets - Supprimez le package NuGet
Google.Cloud.Storage.V1de tous les projets - Installez le package NuGet
IronOcrdans tous les projets qui effectuent l'OCR - Ajoutez l'initialisation
IronOcr.License.LicenseKeyau démarrage de l'application - Remplacez toutes les importations
using Google.Cloud.Vision.V1parusing IronOcr - Remplacez toutes les importations
using Google.Cloud.Storage.V1etusing Grpc.Core - Remplacez
ImageAnnotatorClient.Create()parnew IronTesseract() - Supprimez toutes les méthodes du pipeline GCS (
StorageClient,UploadObjectAsync, annotation async, sondage, téléchargement, suppression) - Remplacez
input.LoadPdf()pour tous les chemins de traitement PDF (suppression de l'orchestration GCS asynchrone) - Remplacez toutes les boucles de concaténation de symboles Protobuf par un accès direct aux propriétés
.Textsur les objetsOcrResult - Remplacez les calculs d'index
BoundingPoly.Verticesparword.X,word.Y,word.Width,word.Height - Supprimez tous les blocs
RpcExceptionpourResourceExhausted,PermissionDenied,Unavailable,DeadlineExceededetUnauthenticated - Remplacez la boucle TIFF par cadre par
input.LoadImageFrames() - Convertissez les boucles de lots séquentielles en
Parallel.ForEachavec des instancesIronTesseractpar thread - Supprimez
GOOGLE_APPLICATION_CREDENTIALSde toutes les configurations d'environnement, des pipelines CI/CD, des fichiers Docker Compose et des secrets Kubernetes
Après la migration
- Vérifiez qu'aucun type
RpcExceptionouGoogleApiExceptionne reste référencé dans le code de gestion des erreurs - Confirmez que
GOOGLE_APPLICATION_CREDENTIALSest absent de toutes les configurations d'environnements de déploiement - Exécutez le pipeline OCR sur le même ensemble de documents d'exemple que celui utilisé en production et comparez la qualité du texte obtenu.
- Tester le traitement PDF sur des documents précédemment traités par le pipeline asynchrone GCS et confirmer que le texte en sortie est identique.
- Testez les PDF protégés par mot de passe avec
input.LoadPdf(path, Password: "...")— précédemment non pris en charge - Testez le traitement des TIFF multi-pages en utilisant
input.LoadImageFrames()et vérifiez que tous les cadres sont traités - Exécutez le traitement par lots sur un échantillon représentatif et vérifiez que la qualité du résultat correspond aux résultats précédents.
- Confirmez que les valeurs
result.Confidencesont dans la plage acceptable pour votre corpus de document - Vérifiez la sortie PDF consultable en utilisant
result.SaveAsSearchablePdf()pour les documents qui nécessitaient auparavant une bibliothèque PDF distincte - Exécutez l'application dans un environnement sans connexion Internet sortante et vérifiez que la reconnaissance optique de caractères (OCR) fonctionne correctement.
Principaux avantages de la migration vers IronOCR
Surface de Credentials Réduite à Zéro Fichiers. Après la migration, il n'y a pas de fichiers de clés JSON, pas de configurations de bucket GCS, pas de rôles IAM, pas de comptes de service, et pas de variables d'environnement GOOGLE_APPLICATION_CREDENTIALS dans votre infrastructure. L'ensemble de la surface d'identification se résume à une variable d'environnement contenant une chaîne de clé de licence. La rotation des clés, qui était une opération périodique obligatoire avec Google Cloud Vision, n'est plus un concept d'actualité. Pour les équipes opérant dans plusieurs régions ou auprès de plusieurs fournisseurs de cloud, la réduction de la complexité de la configuration de déploiement est immédiate.
Traitement des fichiers PDF et TIFF sans dépendances externes. Le pipeline asynchrone GCS et la boucle d'images TIFF System.Drawing sont entièrement supprimés. input.LoadPdf() et input.LoadImageFrames() sont les remplacements — à la fois synchrones, à la fois locaux, à trois lignes de l'appel au résultat. Les PDF protégés par mot de passe, impossibles à créer avec Google Cloud Vision, fonctionnent désormais avec un seul paramètre supplémentaire. Le guide OCR PDF et le guide d'entrée TIFF couvrent l'intégralité de l'API d'entrée.
Traitement par lots à la vitesse du processeur. La suppression du quota de 1 800 requêtes par minute et des délais obligatoires de 60 secondes entre les tentatives permet désormais aux tâches par lots, auparavant limitées en débit, de s'exécuter à la vitesse des cœurs de processeur disponibles. Une machine à 16 cœurs traite simultanément 16 documents sans aucune approbation externe. Le modèle Parallel.ForEach avec des instances IronTesseract par thread est le remplacement direct pour la boucle séquentielle régulée. Le guide d'optimisation de vitesse couvre les options de configuration du moteur qui ajustent le débit pour des types de documents spécifiques.
Données Structurées Sans Protobuf. Chaque OcrResult expose Text, Confidence, Pages, Paragraphs, Lines, Words, et Characters comme propriétés .NET typées sans dépendance au namespace Protobuf, pas de concaténation de symboles, et pas d'arithmétique de vertex pour les boîtes englobantes. Le code qui nécessitait précédemment des boucles imbriquées de 20 lignes pour extraire le texte de paragraphe se réduit à result.Paragraphs.Select(p => p.Text). Pour les cas d'utilisation nécessitant un positionnement au niveau des mots pour l'analyse de la disposition des documents, word.X, word.Y, word.Width et word.Height sont disponibles directement. La page des résultats OCR documente chaque propriété du modèle de résultat.
Sortie PDF consultable intégrée. Google Cloud Visionne renvoie que du texte ; la production d'un PDF consultable nécessitait une bibliothèque de génération de PDF distincte, ajoutant une autre dépendance NuGet , une autre API à apprendre et des licences supplémentaires à évaluer. L'result.SaveAsSearchablePdf(outputPath) d'IronOCR produit un PDF entièrement consultable à partir de tout résultat OCR en une ligne. Pour les workflows d'archivage de documents et les pipelines de découverte légale, cela élimine toute une dépendance. L' exemple de PDF consultable illustre le modèle de bout en bout.
Souveraineté des données pour les industries réglementées. Les documents traités par IronOCR ne quittent jamais le serveur. Pour les dossiers médicaux couverts par la loi HIPAA, les données techniques contrôlées par l'ITAR, les documents des entrepreneurs de défense relevant du champ d'application du CMMC, les documents juridiques confidentiels entre l'avocat et son client et les dossiers financiers relevant du champ d'application du PCI-DSS, l'architecture sur site supprime entièrement la catégorie des sous-traitants de données tiers du champ d'application de la conformité. Il n'y a pas d'accord de partenariat commercial à négocier, pas d'accord de protection des données à signer et pas de politique de conservation des données Google à examiner. Le centre de documentation IronOCR couvre les configurations de déploiement pour les environnements Docker, Linux, Azure et AWS où des exigences de résidence des données s'appliquent.
