Intégrer une API OCR semble se résumer à « envoyer une image, récupérer du texte ». Ce qui décide pourtant de la mise en production est ailleurs : formats et tailles d'image, appel synchrone ou asynchrone, définition des coordonnées et des champs, et stratégie de repli lorsque les résultats sont instables. Ces points passent inaperçus en démonstration, mais les vraies factures et les scans les révèlent.
Cet article s'appuie sur les interfaces compatibles OpenAI et les services OCR courants pour décrire la chaîne de l'envoi à la sortie structurée, avec des exemples, le prétraitement, le diagnostic des erreurs et une liste de vérification pour la migration.
Remarque : OpenAI, Google, Microsoft, Alibaba Cloud, Tencent Cloud, Baidu et les autres marques citées appartiennent à leurs détenteurs respectifs. Cet article est purement technique et n'implique aucun lien d'affiliation avec ces sociétés ; les interfaces, modèles, limites d'image et règles de facturation font foi dans la documentation officielle de chaque plateforme et sur les pages du site.
1. Interface et authentification
Deux formes d'intégration OCR sont courantes ; identifiez d'abord la vôtre :
- Interface OCR dédiée : point d'accès autonome recevant une image ou un PDF et renvoyant des blocs de texte, des coordonnées et des scores de confiance ; certains prennent en charge les modèles de factures, de pièces d'identité et de tableaux.
- Interface de dialogue multimodale : passe par
/v1/chat/completions, place l'image dans le message et demande au modèle visuel de produire du texte ou du JSON ; adaptée aux mises en page complexes, à l'écriture manuscrite et aux tâches de compréhension.
L'authentification d'une interface compatible OpenAI est généralement :
POST https://ai.zhongshangqihang.com/v1/chat/completions
Authorization: Bearer sk-votre-cle
Content-Type: application/json
L'URL de base s'arrête à /v1 ; n'ajoutez pas vous-même le chemin avant de le confier au SDK, sous peine de 404. Certains fournisseurs cloud utilisent une signature Access Key + Secret Key ou échangent d'abord un access_token ; le schéma Bearer ne s'applique pas directement, référez-vous à la documentation officielle.
2. Comment envoyer l'image : URL, Base64 et fichier
Trois modes d'envoi sont courants ; le choix dépend de l'emplacement de l'image et de ce que l'interface accepte :
| Méthode | Adaptée à | Points d'attention |
|---|---|---|
| URL publique | Image déjà sur un stockage objet ou un CDN | Le serveur doit pouvoir y accéder ; lien valable assez longtemps ; éviter les images sensibles publiques |
| Data URL Base64 | Fichier local, image intranet, test ponctuel | Volume augmenté d'environ un tiers ; préfixe ou encodage erroné provoque un 400 |
| Envoi multipart | Interface OCR dédiée d'un fournisseur | Noms de champs, encodage et taille selon la documentation |
Le format Base64 est généralement data:image/jpeg;base64,<contenu>. Erreurs fréquentes : préfixe manquant, saut de ligne dans la chaîne, ou encodage URL-safe non restauré.
Côté formats, JPEG, PNG et WebP sont les plus courants ; GIF, TIFF, BMP et PDF dépendent de l'interface. Une image fait souvent de quelques Mo à 20 Mo ; un dépassement renvoie généralement 413 ou 400. Une résolution plus élevée n'est pas toujours meilleure : le serveur peut redimensionner. Les scans utilisent souvent 200 à 300 DPI ; pour une photo de téléphone, comptez au moins 1600 à 2400 pixels sur le grand côté, puis validez sur des échantillons réels.
3. Synchrone ou asynchrone
L'interface synchrone convient à une image unique et aux scénarios interactifs : la requête attend le résultat. Le risque est le délai d'attente, surtout avec une grande image, un PDF multi-pages ou une file d'attente côté serveur : la connexion peut être coupée avant la réponse.
L'interface asynchrone convient aux lots et aux documents multi-pages. Le déroulement typique est :
- Soumettre l'image ou le fichier et obtenir un ID de tâche.
- Interroger l'état ou attendre une notification de rappel.
- Télécharger ou consulter le résultat une fois la tâche terminée.
- Les résultats ont souvent une durée de conservation : stockez-les rapidement.
Ne jugez pas seulement la simplicité de l'interface. Une requête de plusieurs dizaines de secondes en mode synchrone immobilise connexions et threads, et les reprises amplifient la pression. En asynchrone, gérez l'idempotence, les soumissions en double, le backoff de polling et l'expiration des résultats. En production, créez une table des ID de tâches avec état et emplacement du résultat.
4. Exemple d'appel curl
Voici une reconnaissance d'image via une interface compatible OpenAI. Le nom du modèle est celui de la page Tarifs des modèles ; choisissez un modèle acceptant les images en entrée :
export ZSQH_API_KEY="sk-votre-cle"
curl "https://ai.zhongshangqihang.com/v1/chat/completions" \
-H "Authorization: Bearer $ZSQH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Reconnais le texte de l'image, une ligne par élément, sans explication."},
{"type": "image_url", "image_url": {"url": "https://example.com/facture.jpg"}}
]
}
]
}'
En cas de 401, vérifiez d'abord la clé et les en-têtes ; en cas de 400, vérifiez que l'URL de l'image est accessible et le format accepté ; en cas de 404, vérifiez l'URL de base et l'absence de chemin dupliqué.
5. Appel Python et sortie structurée
Un vrai projet veut rarement du texte brut : il veut des champs. Demandez au modèle un JSON conforme à un schéma, puis validez localement :
import base64
import json
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ZSQH_API_KEY"],
base_url="https://ai.zhongshangqihang.com/v1",
)
with open("facture.jpg", "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
schema_hint = '{"invoice_no": "", "date": "", "amount": "", "seller": ""}'
resp = client.chat.completions.create(
model=os.environ["OCR_MODEL"], # nom du modèle acceptant les images, page tarifs
messages=[{
"role": "user",
"content": [
{"type": "text", "text": f"Reconnais la facture et réponds dans ce JSON, null si un champ est absent : {schema_hint}"},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_b64}"}},
],
}],
)
data = json.loads(resp.choices[0].message.content)
print(data)
Ce code fonctionne, mais cela ne suffit pas pour la production. La sortie peut contenir un bloc de code, du texte explicatif ou des champs superflus, et json.loads échouera. En pratique : privilégiez le mode JSON ou la sortie structurée de la plateforme ; retirez les balises de bloc de code avant analyse ; validez les types avec Pydantic ou jsonschema ; en cas d'échec, renvoyez l'erreur au modèle pour une nouvelle tentative, puis basculez en vérification humaine. Montants, dates et numéros fiscaux doivent aussi être recoupés.
6. Coordonnées, tableaux et champs structurés
L'OCR traditionnel renvoie le contenu, les coordonnées et le score de confiance de chaque bloc ; un modèle multimodal suit le prompt et ses coordonnées ne sont pas toujours fiables. Vérifiez d'abord le format : polygone à quatre points, [x1, y1, x2, y2] ou [x, y, w, h] ; l'unité est-elle le pixel ou une normalisation de 0 à 1000 ; l'origine est-elle en haut à gauche ; les coordonnées doivent être converties après rotation ou recadrage.
Si l'image a été redimensionnée avant reconnaissance, les coordonnées doivent être remappées vers l'original, sinon les cadres de surbrillance se décalent. Pour les tableaux, définissez clairement lignes, colonnes, cellules fusionnées et règles de valeurs vides ; un tableau complexe passe mieux par une interface dédiée, puis par un modèle pour la mise en forme.
Définissez le schéma des champs à l'avance : nom, type, obligation, représentation de l'absence, normalisation des dates et montants. Pour les factures, pensez à la devise, à la taxe et à la cohérence entre montants. Le score de confiance peut servir à orienter : les champs peu sûrs partent en vérification humaine au lieu d'être supprimés.
7. Prétraitement : rendre la reconnaissance plus stable
La plupart des erreurs de reconnaissance se décident avant la requête. Procédez dans cet ordre :
- Lisez l'orientation EXIF et faites pivoter l'image pour éviter une photo couchée.
- Recadrez sur la zone du document et supprimez les grands fonds et objets inutiles.
- Corrigez les petites inclinaisons ; en cas d'inclinaison marquée, détectez les bords.
- Contrôlez la résolution : 200 à 300 DPI pour un scan, 1600 à 2400 pixels sur le grand côté pour une photo.
- Pour un document pâle ou peu contrasté, convertissez en niveaux de gris et renforcez modérément le contraste.
- Découpez les PDF multi-pages ou les longues captures par page, avec un léger chevauchement aux jonctions.
Une image floue ne se sauve pas par une netteté artificielle, et un texte à basse résolution ne révèle pas de détails par agrandissement. Le prétraitement vise à réduire les perturbations, pas à embellir l'image. À chaque réglage, comparez la précision des champs sur le même lot d'échantillons réels.
8. Erreurs courantes et diagnostic
| Erreur | Cause fréquente | Traitement |
|---|---|---|
401 Unauthorized |
Clé erronée, expirée, en-tête mal formé | Vérifier le format Bearer, les espaces et les variables |
403 Forbidden |
Pas de droit sur le modèle, restriction régionale, sous-compte insuffisant | Vérifier les droits sur les modèles et la politique du compte |
400 erreur d'image |
Préfixe Base64 incorrect, fichier corrompu, format non pris en charge | Décoder et vérifier l'en-tête du fichier, passer en JPEG ou PNG |
413 Payload Too Large |
Image ou corps de requête trop volumineux | Compresser, redimensionner, recadrer ou passer en envoi de fichier/asynchrone |
429 Too Many Requests |
Fréquence ou concurrence dépassée | Réduire la concurrence, backoff exponentiel |
Délai ou 502 |
Grande image, document long, file d'attente serveur | Passer en tâche asynchrone ou réduire la requête |
| Résultat vide ou désordonné | Mauvaise orientation, faible résolution, mise en page complexe | Pivoter, améliorer la netteté, découper en colonnes |
Notez l'ID de requête, le nom du modèle, les dimensions de l'image et la durée. Beaucoup de « mauvais résultats du modèle » viennent en réalité d'une image mal envoyée, de coordonnées non converties ou d'un schéma incohérent.
9. Migration et vérification avant mise en production
Passer d'un service OCR à un autre ne se limite généralement pas à changer base_url et api_key. Avant la mise en production, vérifiez :
- Si la nouvelle interface est un OCR dédié ou une vision conversationnelle, et si la structure de requête est compatible.
- Les formats d'image, tailles, nombres de pages et résolutions acceptés.
- Le mode synchrone ou asynchrone, la durée de conservation des résultats et la nécessité d'une adresse publique pour les rappels.
- Le format, l'unité et l'origine des coordonnées par rapport à l'ancien service.
- Le schéma des champs, les langues et les types de documents couverts.
- L'existence d'un déploiement progressif permettant de comparer la précision sur une partie du trafic.
- L'existence d'un chemin de retour, en conservant l'ancienne clé et l'ancienne interface un certain temps.
Enveloppez l'OCR dans un client dédié, par exemple recognize(image, schema) -> Result, et isolez les différences de fournisseur dans une couche d'adaptation : le code métier n'aura pas à être réécrit lors d'un changement. Modèles, limites et prix font foi sur la page Tarifs des modèles.
Questions fréquentes
Une API OCR accepte-t-elle les PDF ?
Cela dépend de l'interface. Un service OCR dédié accepte souvent les PDF, les documents multi-pages passant plutôt en asynchrone ; une interface de dialogue compatible OpenAI traite généralement des images, et un PDF doit être découpé en pages ou passer par une interface fichier. Référez-vous à la documentation.
Quelle taille d'image maximale ?
Cela varie selon les fournisseurs, souvent de quelques Mo à 20 Mo par image, avec des limites de pixels et de pages. Compressez et redimensionnez avant l'envoi pour réduire les délais et le coût de transfert.
Pourquoi l'ordre du texte reconnu est-il incohérent ?
Cause fréquente : colonnes multiples, tableaux et images imbriqués. L'OCR traditionnel trie par coordonnées, le modèle multimodal génère selon l'ordre de lecture ; les deux peuvent se tromper. Découpez par colonne, demandez une sortie par zone ou utilisez une interface avec analyse de mise en page.
Quelle méthode pour des champs structurés fiables ?
Définissez le schéma, demandez un JSON et validez localement types, expressions régulières et règles métier. Si la plateforme propose une sortie structurée, privilégiez-la ; sinon, ajoutez une nouvelle tentative avec le message d'erreur, puis basculez en vérification humaine.
Que changer lors d'une migration d'un service OCR à un autre ?
Outre l'URL de base et la clé, vérifiez la structure de requête, le mode synchrone/asynchrone, les limites d'image, le format des coordonnées, le schéma et les règles de limitation. Déployez progressivement et comparez la précision des champs sur des échantillons réels avant la bascule complète.
Étape suivante
Pour valider une première requête, créez une clé à faible quota depuis la page d'inscription, puis testez l'envoi, la reconnaissance et la sortie JSON sur une facture réelle. Pour le choix définitif, consultez la page Tarifs des modèles et comparez la précision des champs sur un petit lot d'images annotées. Les prix évoluent ; référez-vous au site.
Pour aller plus loin :
- Clé API OCR : obtention, création et sécurisation
- Prix et facturation d'une API OCR : pages, champs et lots
- API OCR en relais : lots, facturation et migration
Remarque : OpenAI, Google, Microsoft, Alibaba Cloud, Tencent Cloud et Baidu sont des marques de leurs détenteurs respectifs. Cet article est purement technique et n'implique aucun lien d'affiliation avec ces sociétés ; les interfaces, limites et règles de facturation font foi dans la documentation officielle.
