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.
L'environnement utilise Google Colaboratory. La version Python est ci-dessous.
import platform
print("python " + platform.python_version())
# python 3.6.9
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])
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
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).
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")
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>
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")
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.
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.
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.
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")
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.
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