[PYTHON] J'ai essayé "License OCR" avec l'API Google Vision

introduction

Il existe une technologie appelée «OCR (reconnaissance optique de caractères)» qui lit les caractères imprimés ou manuscrits et les convertit en données de caractères.

Les services OCR sont fournis pour divers documents tels que factures, reçus, cartes de visite et licences. En utilisant l'OCR, vous pouvez réduire les problèmes de saisie de données. De plus, en établissant des liens avec d'autres systèmes, il est possible d'utiliser efficacement les données.

L'OCR fourni par chaque entreprise comprend des services pour les entreprises et les particuliers. En tant qu'OCR pouvant être utilisé par des particuliers, il existe "l'API Google Vision (ci-après dénommée API Vision)". Vision API est un service d'analyse d'images très performant fourni par Google. (Cliquez ici pour consulter la page d'essai gratuite (https://cloud.google.com/vision?hl=ja))

Cette fois, j'ai essayé une licence OCR simple en utilisant l'API Vision.

Licence OCR

environnement

L'environnement utilise Google Colaboratory. La version Python est ci-dessous.

import platform
print("python " + platform.python_version())
# python 3.6.9

Affichage de l'image

Maintenant écrivons le code. Tout d'abord, importez la bibliothèque requise pour afficher l'image.

import cv2
import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib

Je préparerai également un exemple d'image de la licence. Montrons l'image.

img = cv2.imread(input_file) # input_file est le chemin de l'image
plt.figure(figsize=[10,10])
plt.axis('off')
plt.imshow(img[:,:,::-1])

image.png

Configuration de l'API Vision

Maintenant, jetons cette image de reçu dans l'API Vision et faisons l'OCR.

Tout d'abord, effectuez les préparatifs nécessaires pour utiliser l'API Vision. Configurez en vous référant à ici. Vous devrez installer la bibliothèque cliente et émettre une clé de compte de service. L'installation de la bibliothèque cliente est la suivante.

pip install google-cloud-vision

Utilisez la clé de compte de service émise pour définir les variables d'environnement.

import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = json_path # json_path est le chemin de la clé du compte de service

Détection de texte

Maintenant, effectuons la détection de texte par OCR.

Cette fois, nous utiliserons l'option Vision API DOCUMENT_TEXT_DETECTION pour la détection de texte. Pour plus d'informations sur l'API Vision DOCUMENT_TEXT_DETECTION, cliquez ici (https://cloud.google.com/vision/docs/pdf?hl=ja).

Envoyer une demande à l'API / Obtenir une réponse

Maintenant, envoyons une demande à l'API Vision et obtenons une réponse.

import io

from google.cloud import vision
from google.cloud.vision import types

client = vision.ImageAnnotatorClient()
with io.open(input_file, 'rb') as image_file:
    content = image_file.read()
image = types.Image(content=content)
response = client.document_text_detection(image=image) #Détection de texte

S'il peut être exécuté sans aucune erreur, la requête à l'API peut être envoyée et la réponse peut être obtenue.

Cette réponse contient le résultat OCR de l'API Vision. Il contient diverses informations telles que les caractères lus, les coordonnées des caractères, la certitude et le type de langue. Ici, vérifions le texte intégral lu. Je vais l'afficher côte à côte avec l'image.

print(response.text_annotations[0].description)
Nom
Soleil
Réserver
Hanako
Né le 1er mai 1986)
Adresse Tokyo
2-1-2 Kasumi, Chiyoda-ku
Accordé le 7 mai 2001 12345
12024 (Imawa 06) 01 juin Inactif
Lunettes etc.
Licence
Conditions etc.
Échantillon
Excellent
Numéro | N ° 012345678900
| --01 avril 2003
Au milieu
Autres 01 juin 2005
(Trois sortes 01 août 2017
Permis de conduire
Type
Grand petit spécial
Cyclomoteur de taille moyenne
Ichiten
Tentoku Fuji
Grande autonomie
Fuou Hiki
Nakaji
00000
Commission de la sécurité publique
KA | ||
Q00

J'ai pu confirmer le résultat de la lecture.

L'API Vision contient des informations de coordonnées caractère par caractère. Tracons chaque coordonnée sur l'image et vérifions-la.

document = response.full_text_annotation
img_symbol = img.copy()
for page in document.pages:
  for block in page.blocks:
    for paragraph in block.paragraphs:
      for word in paragraph.words:
        for symbol in word.symbols:
          bounding_box = symbol.bounding_box
          xmin = bounding_box.vertices[0].x
          ymin = bounding_box.vertices[0].y
          xmax = bounding_box.vertices[2].x
          ymax = bounding_box.vertices[2].y
          cv2.rectangle(img_symbol, (xmin, ymin), (xmax, ymax), (0, 255, 0), thickness=1, lineType=cv2.LINE_AA)
plt.figure(figsize=[10,10])
plt.imshow(img_symbol[:,:,::-1]);plt.title("img_symbol")

image.png

Création de modèle

L'endroit où la licence est écrite pour chaque élément tel que «nom», «date de naissance» et «adresse» est fixe. Ce qui est écrit où et ce qui est écrit est appelé ** fixe ** dans la terminologie de l'industrie OCR. Et l'OCR d'un standard est appelé ** OCR standard **. Par contre, les reçus, cartes de visite, factures, etc. pour lesquels on ne sait pas où et ce qui est écrit sont appelés ** atypiques **, et leurs OCR sont appelés ** OCR atypiques **.

L'OCR standard vous permet de créer des modèles. En spécifiant la zone pour chaque élément dans le modèle et en extrayant les résultats OCR contenus dans la zone, le résultat de lecture pour chaque élément peut être sorti.

Créons maintenant un modèle. Cette fois, nous utiliserons l'outil d'annotation labelImg. L'annotation est l'ajout de certaines informations à une donnée. Ici, cela signifie que la zone entourée par le cadre est étiquetée comme "nom" ou "date de naissance". Le résultat de l'annotation avec labelImg est enregistré sous forme de fichier xml.

Voici un exemple de fichier xml de résultat d'annotation.

<annotation>
	<folder>Downloads</folder>
	<filename>drivers_license.jpg</filename>
	<path>/path/to/jpg_file</path>
	<source>
		<database>Unknown</database>
	</source>
	<size>
		<width>681</width>
		<height>432</height>
		<depth>3</depth>
	</size>
	<segmented>0</segmented>
	<object>
		<name>name</name>
		<pose>Unspecified</pose>
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>
			<xmin>78</xmin>
			<ymin>26</ymin>
			<xmax>428</xmax>
			<ymax>58</ymax>
		</bndbox>
	</object>
	<object>
		<name>birthday</name>
		<pose>Unspecified</pose>
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>
			<xmin>428</xmin>
			<ymin>27</ymin>
			<xmax>652</xmax>
			<ymax>58</ymax>
		</bndbox>
	</object>
<!--Omission-->
</annotation>

Chargement des informations du modèle

Maintenant, lisons le fichier xml ci-dessus. Pour confirmation, essayez de dessiner le cadre du modèle et les informations d'étiquette sur l'image.

import xml.etree.ElementTree as ET

tree = ET.parse(input_xml) # input_xml est le chemin de xml
root = tree.getroot()

img_labeled = img.copy()
for obj in root.findall("./object"):
  name = obj.find('name').text
  xmin = obj.find('bndbox').find('xmin').text
  ymin = obj.find('bndbox').find('ymin').text
  xmax = obj.find('bndbox').find('xmax').text
  ymax = obj.find('bndbox').find('ymax').text
  xmin, ymin, xmax, ymax = int(xmin), int(ymin), int(xmax), int(ymax)
  cv2.rectangle(img_labeled, (xmin, ymin), (xmax, ymax), (0, 255, 0), thickness=1, lineType=cv2.LINE_AA)
  cv2.putText(img_labeled, name, (xmin, ymin), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), thickness=1)
plt.figure(figsize=[10,10])
plt.imshow(img_labeled[:,:,::-1]);plt.title("img_labeled")

image.png

J'ai pu confirmer que les informations du modèle étaient correctement définies. J'utilise labelImg pour encadrer et étiqueter les éléments que je souhaite lire, tels que mon nom et ma date de naissance.

Correspondance de modèle

Maintenant, faisons correspondre le modèle avec le résultat OCR.

Classez les chaînes de caractères dans le cadre du modèle comme résultat pour chaque élément. Le résultat de la correspondance des modèles est affiché côte à côte avec l'image.

text_infos = []
document = response.full_text_annotation
for page in document.pages:
  for block in page.blocks:
    for paragraph in block.paragraphs:
      for word in paragraph.words:
        for symbol in word.symbols:
          bounding_box = symbol.bounding_box
          xmin = bounding_box.vertices[0].x
          ymin = bounding_box.vertices[0].y
          xmax = bounding_box.vertices[2].x
          ymax = bounding_box.vertices[2].y
          xcenter = (xmin+xmax)/2
          ycenter = (ymin+ymax)/2
          text = symbol.text
          text_infos.append([text, xcenter, ycenter])

result_dict = {}
for obj in root.findall("./object"):
  name = obj.find('name').text
  xmin = obj.find('bndbox').find('xmin').text
  ymin = obj.find('bndbox').find('ymin').text
  xmax = obj.find('bndbox').find('xmax').text
  ymax = obj.find('bndbox').find('ymax').text
  xmin, ymin, xmax, ymax = int(xmin), int(ymin), int(xmax), int(ymax)
  texts = ''
  for text_info in text_infos:
    text = text_info[0]
    xcenter = text_info[1]
    ycenter = text_info[2]
    if xmin <= xcenter <= xmax and ymin <= ycenter <= ymax:
      texts += text
  result_dict[name] = texts

for k, v in result_dict.items():
  print('{} : {}'.format(k, v))
nom: Hanako Nihon
anniversaire: Né le 1 mai 1986
adresse: 2-1-2 Kasumi, Chiyoda-ku, Tokyo
date d'émission: 07 mai 2001 12345
date d'expiration: 2024 (Imawa 06) 01 juin Inactif
numéro: No. 012345678900
permis de conduire: permis de conduire
Commission de la sécurité publique: 00000 Commission de la sécurité publique

À la suite de l'appariement des modèles, il a été confirmé que les résultats de l'OCR pouvaient être classés par élément.

Détection facial

Jusqu'à présent, nous avons examiné la détection de texte par OCR.

En passant, lors du jugement de l'image d'une carte d'identité telle qu'une licence, il est également possible de vérifier la photo du visage. Vision API dispose de diverses fonctions d'analyse d'image autres que l'OCR, et la détection de visage en fait partie. Pour plus d'informations sur la détection des visages de l'API Vision, cliquez ici (https://cloud.google.com/vision/docs/detecting-faces?hl=ja).

Utilisons maintenant l'API Vision pour effectuer également la détection des visages.

Envoyer une demande à l'API / Obtenir une réponse

Maintenant, comme la détection de texte, envoyons une demande à l'API Vision et obtenons une réponse.

import io

from google.cloud import vision

client = vision.ImageAnnotatorClient()
with io.open(input_file, 'rb') as image_file:
    content = image_file.read()
image = types.Image(content=content)
response2 = client.face_detection(image=image) #Détection facial

Cette réponse2 contient le résultat de la détection de visage de l'API Vision. Il contient diverses informations telles que les coordonnées faciales détectées, les points caractéristiques, la certitude et la possibilité d'émotions (en colère ou en riant, etc.).

Maintenant, affichons les coordonnées du visage détecté.

faces = response2.face_annotations

img_face = img.copy()

for face in faces:
  bounding_poly = face.bounding_poly
  fd_bounding_poly = face.fd_bounding_poly
  xmin = bounding_poly.vertices[0].x
  ymin = bounding_poly.vertices[0].y
  xmax = bounding_poly.vertices[2].x
  ymax = bounding_poly.vertices[2].y
  cv2.rectangle(img_face, (xmin, ymin), (xmax, ymax), (0, 255, 0), thickness=1, lineType=cv2.LINE_AA)
  cv2.putText(img_face, 'bounding_poly', (xmin, ymin), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), thickness=1)

  xmin = fd_bounding_poly.vertices[0].x
  ymin = fd_bounding_poly.vertices[0].y
  xmax = fd_bounding_poly.vertices[2].x
  ymax = fd_bounding_poly.vertices[2].y
  cv2.rectangle(img_face, (xmin, ymin), (xmax, ymax), (0, 255, 0), thickness=1, lineType=cv2.LINE_AA)
  cv2.putText(img_face, 'fd_bounding_poly', (xmin, ymin), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), thickness=1)

plt.figure(figsize=[10,10])
plt.imshow(img_face[:,:,::-1]);plt.title("img_face")

image.png

J'ai pu confirmer que le visage a été détecté.

Maintenant, affichons le niveau de confiance de la détection des visages. Il est également possible de fixer un seuil à l'avance et de juger que le visage a été détecté s'il est au-dessus du seuil. Cela vous permet de supprimer les images floues et celles qui ne peuvent pas être distinguées des photographies du visage, et de se limiter aux images fiables.

for face in faces:
  detection_confidence = face.detection_confidence
  if detection_confidence > 0.90:
    print('Face detected')
    print('detection_confidence : ' + str(detection_confidence))

# Face detected
# detection_confidence : 0.953563392162323

Dans ce qui précède, j'ai fixé le seuil à 0,90 et essayé de juger de la fiabilité de la photographie du visage. Le degré de certitude cette fois est aussi élevé que 0,95, et on peut dire qu'il est fiable comme une photographie de visage.

Résumé

Comment était-ce?

Cette fois, j'ai essayé d'effectuer l'OCR de licence à l'aide de l'API Vision.

Tout d'abord, nous avons effectué une détection de texte. J'ai également créé un modèle distinct en utilisant labelImg. En faisant correspondre le résultat OCR avec le modèle, le résultat de la lecture a été classé pour chaque élément. Pour ce faire, nous avons utilisé les informations de coordonnées caractère par caractère incluses à la suite de l'API Vision. Avec un OCR standard tel qu'une licence, il est possible de créer un modèle et de sortir le résultat pour chaque élément que vous souhaitez lire.

Nous avons également effectué une détection de visage. Cette fois, nous n'avons utilisé que les coordonnées faciales détectées, mais la réponse comprend également les coordonnées des points caractéristiques et la possibilité d'émotions. Je pense qu'il serait intéressant d'essayer la détection de visage pour des photographies faciales avec différentes expressions faciales.

Vision API est un outil qui peut effectuer diverses analyses d'images. En plus de la détection de texte et de détection de visage introduite cette fois, pourquoi ne pas essayer diverses choses?

Recommended Posts

J'ai essayé "License OCR" avec l'API Google Vision
J'ai essayé "Receipt OCR" avec l'API Google Vision
J'ai essayé d'utiliser l'API Google Cloud Vision
J'ai essayé Google Sign-In avec Spring Boot + Spring Security REST API
J'ai essayé l'API Google Cloud Vision pour la première fois
J'ai essayé d'extraire des caractères des sous-titres (OpenCV: API Google Cloud Vision)
J'ai essayé de découvrir notre obscurité avec l'API Chatwork
J'ai essayé de créer une application OCR avec PySimpleGUI
J'ai essayé de frapper l'API avec le client python d'echonest
J'ai essayé fp-growth avec python
J'ai essayé de gratter avec Python
J'ai essayé Learning-to-Rank avec Elasticsearch!
J'ai essayé le clustering avec PyCaret
J'ai essayé gRPC avec Python
J'ai essayé de gratter avec du python
J'ai essayé de connecter Raspeye et conect + avec l'API Web
J'ai essayé la gestion du suivi avec l'API Twitter et Python (facile)
J'ai essayé de sauvegarder l'historique des demandes d'API DRF avec django-request
J'ai essayé de créer l'API Quip
J'ai essayé le roman Naro API 2
J'ai essayé de résumer des phrases avec summpy
J'ai essayé l'apprentissage automatique avec liblinear
J'ai essayé webScraping avec python.
J'ai essayé de déplacer de la nourriture avec SinGAN
J'ai essayé d'implémenter DeepPose avec PyTorch
J'ai touché l'API de Tesla
J'ai essayé la détection de visage avec MTCNN
J'ai essayé l'API du roman Naruro
J'ai essayé d'exécuter prolog avec python 3.8.2.
J'ai essayé la communication SMTP avec Python
J'ai essayé la génération de phrases avec GPT-2
J'ai essayé d'apprendre LightGBM avec Yellowbrick
Présentation de l'API Google Map avec rails
J'ai essayé la reconnaissance faciale avec OpenCV
J'ai essayé d'utiliser l'API checkio
J'ai essayé d'automatiser tout, y compris l'authentification en deux étapes de Google OAuth
J'ai essayé ChatOps avec Slack x API Gateway x Lambda (Python) x RDS
J'ai essayé d'utiliser l'API de reconnaissance vocale docomo et l'API Google Speech en Java
J'ai essayé d'utiliser l'API Google avec Ruby et Python - Faites de la base de données une feuille de calcul et gérez-la avec Google Drive
Exemple d'API Google Cloud Vision pour python
J'ai essayé l'analyse de régression multiple avec régression polypoly
J'ai essayé d'utiliser Amazon SQS avec django-celery
J'ai essayé de supprimer régulièrement les mauvais tweets avec l'API AWS Lambda + Twitter
Reconnaissance vocale en streaming avec l'API Google Cloud Speech
J'ai essayé d'implémenter Autoencoder avec TensorFlow
J'ai essayé linebot avec flacon (anaconda) + heroku
J'ai essayé de commencer avec Hy
J'ai essayé d'utiliser l'API de données YOUTUBE V3
J'ai essayé d'utiliser du sélénium avec du chrome sans tête
J'ai essayé l'analyse factorielle avec des données Titanic!
J'ai essayé d'apprendre avec le Titanic de Kaggle (kaggle②)
J'ai essayé le rendu non réaliste avec Python + opencv
J'ai essayé de créer un LINE BOT "Sakurai-san" avec API Gateway + Lambda
J'ai essayé d'obtenir le code d'authentification de l'API Qiita avec Python.
Utiliser l'API Google Cloud Vision de Python