Extrayez les données de réception avec l'API de Mindee à l'aide de Python

Jonathan Grandperrin

Jonathan Grandperrin

Dans ce tutoriel, vous allez apprendre à analyser une image de reçu à l'aide de python. Cela peut vous aider à extraire automatiquement les données des reçus sans interaction humaine et à les utiliser dans vos applications principales à de nombreuses fins comptables.

Le script final peut être utilisé dans n'importe quelle application middleware python ou API REST desservant vos interfaces frontales.

À la fin de ce tutoriel, nous allons vous montrer comment surlignez les champs de réception extraits sur l'image à l'aide de la bibliothèque open source de vision par ordinateur OpenCV.

Le résultat final ressemble à ceci :

Prérequis de l'API

  1. Python doit être installé dans votre environnement. Nous utilisons la version 3.7 dans ce tutoriel.
  2. Vous aurez besoin d'un compte Mindee gratuit. INSCRIVEZ-VOUS et confirmez votre adresse e-mail pour vous connecter.
  3. Un reçu. Cherchez un article récent dans votre sac/portefeuille, ou faites un Recherche d'images sur Google pour obtenir un reçu et téléchargez-en quelques-uns pour les tester.

Configuration du projet

Créez un répertoire vide où vous le souhaitez sur votre ordinateur portable, nous appellerons le nôtre « python_receipt » et y créerons un fichier « main.py ».

Ouvrez un terminal et accédez au répertoire que vous venez de créer. Dans ce didacticiel, nous utiliserons les « requêtes » de la bibliothèque Python pour appeler l'API. S'il n'est pas installé dans votre environnement, vous pouvez l'installer en exécutant :

pip install requests

Assurez-vous d'avoir une image du reçu quelque part sur votre ordinateur portable et de connaître le chemin.

C'est tout pour la configuration, appelons l'API.

Appelez l'API de réception Mindee

Connectez-vous au Mindee et entrez dans votre Environnement API de réception des dépenses en cliquant sur la carte suivante.

Si vous ne possédez pas encore de jeton d'API pour cette API, accédez à la section « informations d'identification » et créez une nouvelle clé d'API.

Cliquez sur la section documentation dans la barre de navigation, puis cliquez sur le lien Python dans la zone d'exemple de code. Copiez le code.

Ouvrez le main.py fichier que vous avez créé il y a quelques minutes et collez votre exemple de code, il devrait ressembler à :

import requests
url = "https://api.mindee.net/products/expense_receipts/v2/predict"
with open("/path/to/my/file", "rb") as myfile:
files = {"file": myfile}
headers = {"X-Inferuser-Token": "my-token-here"}
response = requests.post(url, files=files, headers=headers)
print(response.text)

Remplacez le « chemin/vers/my/file » espace réservé dans le code avec le chemin de l'image du reçu dont vous souhaitez extraire les données.

Remplacez le « mon-jeton-ici » avec le jeton d'API que vous avez créé précédemment sur la plateforme.

Vous pouvez revenir à votre console et exécuter le script

python main.py

Vous devriez voir un objet json dans votre console avec les résultats extraits de l'API d'analyse des reçus. Analysons maintenant ce fichier json pour obtenir les données dont nous avons besoin.

Analyser le résultat

L'API extrait une liste des différents champs du reçu (montant total, taxes, date...). Vous trouverez une description de tous ces champs dans l'onglet « documentation » de la page de la plateforme d'API Mindee.

Maintenant que nous avons codé la demande d'API, nous allons utiliser l'objet json et obtenir quelques fonctionnalités extraites.

Tout d'abord, créons une fonction d'analyse qui renvoie le le montant total du reçu, la date et l'heure du paiement et la catégorie de dépenses. Nous nous concentrerons uniquement sur ces quatre fonctionnalités pour le didacticiel.

Les caractéristiques se trouvent à l'intérieur de l'objet de prédiction dans la réponse json. Comme vous pouvez envoyer un pdf de plusieurs pages à l'API, l'objet de prédictions est un tableau, avec un objet de prédiction pour chaque page.

Dans notre cas, comme nous envoyons une simple image jpg, le tableau de prédictions ne contient qu'un seul objet.

def get_features(json_response):
parsed_data = {}
prediction = json_response["predictions"][0]
parsed_data["total_amount"] = prediction["total"]["amount"]
parsed_data["time"] = prediction["time"]["iso"]
parsed_data["date"] = prediction["date"]["iso"]
parsed_data["category"] = prediction["category"]["value"]
return parsed_data

Maintenant que notre fonction est prête, nous allons simplement imprimer le résultat dans la console et ajouter une simple vérification pour nous assurer que l'appel d'API a été bien effectué et que nous pouvons accéder au résultat. Vous pouvez remplacer le script main.py comme suit :

Maintenant que notre fonction est prête, nous allons simplement imprimer le résultat dans la console et ajouter une simple vérification pour nous assurer que l'appel d'API a été bien effectué et que nous pouvons accéder au résultat.

Vous pouvez remplacer main.py script pour ceci :

import requests
def get_features(json_response):
parsed_data = {}
prediction = json_response["predictions"][0]
parsed_data["total_amount"] = prediction["total"]["amount"]
parsed_data["time"] = prediction["time"]["iso"]
parsed_data["date"] = prediction["date"]["iso"]
parsed_data["category"] = prediction["category"]["value"]
return parsed_data

url = "https://api.mindee.net/products/expense_receipts/v2/predict"

with open("/path/to/my/file", "rb") as myfile:
files = {"file": myfile}
headers = {"X-Inferuser-Token": "my-token-here"}
response = requests.post(url, files=files, headers=headers)

if response.status_code != 200:
print("Request error")
else:
json_response = response.json()
features = get_features(json_response)
print("Date:", features["date"])
print("Time:", features["time"])
print("Total amount:", features["total_amount"])
print("Category:", features["category"])

Exécutez le script et vérifiez les résultats sur votre image.

Enfin, nous allons ajouter un dernier bout de code qui mettra en valeur les caractéristiques extraites sur l'image. Il peut vous aider, vous ou vos utilisateurs, à valider très rapidement l'extraction des données.

Surligner les caractéristiques de l'image

Essayons de mettre en évidence les fonctionnalités comme si quelqu'un l'avait fait avec un stylo.

Tout d'abord, vous devrez installer la bibliothèque Python de vision par ordinateur OpenCV si elle n'est pas déjà installée dans votre environnement. Pour ce faire, exécutez :

pip install opencv-python

Nous devons modifier légèrement notre fonction get_features pour renvoyer les coordonnées de chaque entité, car nous l'utilisons pour savoir où dessiner les rectangles.

def get_features(json_response):
parsed_data = {}
coordinates = []
prediction = json_response["predictions"][0]
parsed_data["total_amount"] = prediction["total"]["amount"]
parsed_data["time"] = prediction["time"]["iso"]
parsed_data["date"] = prediction["date"]["iso"]
parsed_data["category"] = prediction["category"]["value"]
coordinates.append(prediction["total"]["segmentation"]["bounding_box"])
coordinates.append(prediction["time"]["segmentation"]["bounding_box"])
coordinates.append(prediction["date"]["segmentation"]["bounding_box"])
return parsed_data, coordinates

Une fois que c'est fait, nous allons créez notre fonction de surligneur en différentes étapes, comme suit :

  1. Ouvrez l'image depuis le chemin
  2. Création d'une image de masque
  3. Faites une boucle sur les coordonnées de chaque caractéristique et tracez le rectangle caractéristique sur notre masque
  4. Superposez le masque et l'image d'origine avec de l'alpha
  5. Afficher l'image à l'utilisateur

Remarque : chaque coordonnée renvoyée par l'API est relative (en % de l'image). Vous verrez qu'il y a une conversion relative par rapport à une conversion absolue dans le code.

Voici le code étape par étape :

def highlight_features(img_path, coordinates):
# step 1: Open the image from path
cv_image = cv2.imread(img_path)

# step 2: create mask image
overlay = cv_image.copy()
h, w = cv_image.shape[:2]

# step 3: Loop on each feature coordinates and draw the feature rectangle on our mask
for coord in coordinates:
pt1 = (int(w*coord[0][0]), int(h*coord[0][1]))
pt2 = (int(w*coord[2][0]), int(h*coord[2][1]))
cv2.rectangle(overlay, pt1, pt2, (70, 230, 244), cv2.FILLED)

# step 4: Overlay the mask and original image with alpha
final_image = cv2.addWeighted(overlay, 0.5, cv_image, 0.5, 0)

# step 5: Display image to the user
cv2.imshow("highlghted_image", cv2.resize(final_image, (400, int(400*h/w))))
cv2.waitKey(0)

Enfin, il suffit de modifier un peu le code pour exécuter la fonction de surlignage et imprimer les résultats. Voici à quoi ressemble le code final :

import requests
import cv2
def get_features(json_response):
parsed_data = {}
coordinates = []
prediction = json_response["predictions"][0]
parsed_data["total_amount"] = prediction["total"]["amount"]
parsed_data["time"] = prediction["time"]["iso"]
parsed_data["date"] = prediction["date"]["iso"]
parsed_data["category"] = prediction["category"]["value"]
coordinates.append(prediction["total"]["segmentation"]["bounding_box"])
coordinates.append(prediction["time"]["segmentation"]["bounding_box"])
coordinates.append(prediction["date"]["segmentation"]["bounding_box"])
return parsed_data, coordinates

def highlight_features(img_path, coordinates):
# step 1: Open the image from path
cv_image = cv2.imread(img_path)

# step 2: create mask image
overlay = cv_image.copy()
h, w = cv_image.shape[:2]

# step 3: Loop on each feature coordinates and draw the feature rectangle on our mask
for coord in coordinates:
pt1 = (int(w*coord[0][0]), int(h*coord[0][1]))
pt2 = (int(w*coord[2][0]), int(h*coord[2][1]))
cv2.rectangle(overlay, pt1, pt2, (70, 230, 244), cv2.FILLED)

# step 4: Overlay the mask and original image with alpha
final_image = cv2.addWeighted(overlay, 0.5, cv_image, 0.5, 0)

# step 5: Display image to the user
cv2.imshow("highlghted_image", cv2.resize(final_image, (400, int(400*h/w))))
cv2.waitKey(0)

url = "https://api.mindee.net/products/expense_receipts/v2/predict"
with open("/path/to/my/file", "rb") as myfile:
files = {"file": myfile}
headers = {"X-Inferuser-Token": "my-token-here"}
response = requests.post(url, files=files, headers=headers)

if response.status_code != 200:
print("Request error")
else:
json_response = response.json()
features, coords = get_features(json_response)
print("Date:", features["date"])
print("Time:", features["time"])
print("Total amount:", features["total_amount"])
print("Category:", features["category"])
highlight_features("path/to/my/file", coords)

Dans la dernière ligne de code, n'oubliez pas de remplacer l'espace réservé chemin/vers/mon/fichier vers le chemin actuel de votre image.

Et le résultat final !

Conclusion

En un peu plus d'une seconde, un reçu a été téléchargé, l'API a extrait les données du reçu, puis le résultat a été analysé et surligné dans l'image. Cool, non ?

Si vous souhaitez utiliser ce type de script pour afficher les résultats à vos utilisateurs, je vous conseille de les surligner dans l'application frontale, car le renvoi d'images depuis votre intergiciel n'est pas la meilleure option en raison de la taille de la charge utile. L'autre solution serait de stocker l'image finale en utilisant cv2.imwrite (...) mais cela obligerait votre client à télécharger le résultat. Pour vous aider à effectuer le rendu côté client de vos images, vous pouvez consulter notre SDK ReactJS open source.

Si vous avez des questions, n'hésitez pas à nous contacter !

À propos

Qu'il s'agisse de simples photos, de fichiers PDF complexes ou de fichiers manuscrits, l'API de Mindee transforme les données de vos documents en JSON structuré de manière hautement fiable. Aucune formation sur les modèles n'est requise. Tous les alphabets et toutes les langues sont pris en charge.

,
,

Key Takeway

Key Takeway