[Python] Obtenez les nombres dans l'image graphique avec OCR

Objectif

Je veux calculer le nombre de différence à partir de l'image graphique du site de données pachislot.

À ce moment-là, étant donné que le nombre de feuilles indiqué sur l'image graphique était requis, le nombre de feuilles affiché sur l'OCR est acquis.

20200713_p-bbnippori_126.png

Une telle image graphique.

Ce que vous voulez obtenir est le nombre indiqué en haut à gauche (2410 dans le cas de cette image)

Quoi préparer

・ Tesseract (4.0 ou version ultérieure) ・ PyOCR

La méthode d'installation, etc. est omise. Un lien de référence est affiché au bas de la page, veuillez donc l'utiliser.

Essayez l'OCR

20200713_p-bbnippori_126.png

Pour le moment, lisez cette image graphique telle quelle.

from PIL import Image
import pyocr
import pyocr.builders
import sys

file_path = 'Chemin du fichier'
#Chargement des outils
tools = pyocr.get_available_tools()
#Si vous ne trouvez pas l'outil
if len(tools) == 0:
    print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
    sys.exit(1)
tool = tools[0]
#Chargement d'image
img_org = Image.open(file_path)
# OCR
max_medals = tool.image_to_string(img_org, lang='jpn', builder=pyocr.builders.DigitBuilder(tesseract_layout=6))
print(f'max_medals:{max_medals}')

Résultat d'exécution


-

Je n'ai pas pu obtenir de chiffres.

Après avoir étudié diverses choses, il semble qu'il soit plus précis de faire de l'OCR numérique avec un ensemble de données anglais, j'ai donc changé le paramètre de langue en anglais.

Changer le paramètre de langue en anglais

from PIL import Image
import pyocr
import pyocr.builders
import sys

file_path = 'Chemin du fichier'
#Chargement des outils
tools = pyocr.get_available_tools()
#Si vous ne trouvez pas l'outil
if len(tools) == 0:
    print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
    sys.exit(1)
tool = tools[0]
#Chargement d'image
img_org = Image.open(file_path)
# OCR
max_medals = tool.image_to_string(img_org, lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=6))
print(f'max_medals:{max_medals}')

Résultat d'exécution


2410 1300160019.00

Cette fois, j'ai pu obtenir certains des chiffres indiqués.

Cependant, comme j'ai lu les parties inutiles, je la réécris pour que seule la partie que je souhaite lire soit découpée puis traitée.

OCR après avoir coupé le point de lecture

from PIL import Image
import pyocr
import pyocr.builders
import sys

file_path = 'Chemin du fichier'
#Chargement des outils
tools = pyocr.get_available_tools()
#Si vous ne trouvez pas l'outil
if len(tools) == 0:
    print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
    sys.exit(1)
tool = tools[0]
#Chargement d'image
img_org = Image.open(file_path)
#Découpez la partie de notation numérique
max_medals_img = img_org.crop((0, 0, 45, 15))
# OCR
max_medals = tool.image_to_string(max_medals_img , lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=6))
print(f'max_medals:{max_medals}')

Résultat d'exécution


max_medals:2410

Ça s'est bien passé!

mise à niveau de la précision

Comme cela fonctionnait bien avec le code précédent, j'ai augmenté le nombre d'images graphiques à lire et à réessayer.

from PIL import Image
import pyocr
import pyocr.builders
import sys
from glob import glob

file_path = 'Répertoire de stockage de fichiers'
#Créer une liste de fichiers à lire
file_list = [file for file in glob(f'{file_path}*.png')]
for file_path in file_list:
    #Chargement des outils
    tools = pyocr.get_available_tools()
    #Si vous ne trouvez pas l'outil
    if len(tools) == 0:
        print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
        sys.exit(1)
    tool = tools[0]
    #Chargement d'image
    img_org = Image.open(file_path)
    #Découpez la partie de notation numérique
    max_medals_img = img_org.crop((0, 0, 45, 15))
    # OCR
    max_medals = tool.image_to_string(max_medals_img, lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=6))
    print(f'max_medals:{max_medals}')

Résultat d'exécution


max_medals:2410
max_medals:
max_medals:490
max_medals:2717
max_medals:689
max_medals:504
max_medals:1013
max_medals:
max_medals:862
max_medals:979
max_medals:835
max_medals:1683
max_medals:1587
max_medals:1010
max_medals:7
max_medals:1586
max_medals:1653
max_medals:413
max_medals:1167
max_medals:527

Certaines images n'ont pas été lues correctement.

J'ai déjà essayé l'OCR avec un autre format d'image auparavant, et à ce moment-là je n'ai eu aucune erreur, mais le format à ce moment

"Couleur d'arrière-plan: blanc, couleur du texte: noir"

Puisqu'il s'agissait d'une image du format, j'ai essayé d'inverser la couleur d'arrière-plan et la couleur du texte.

Inverser la couleur d'arrière-plan et la couleur du texte

from PIL import Image, ImageOps
import pyocr
import pyocr.builders
import sys
from glob import glob

file_path = 'Répertoire de stockage de fichiers'
#Créer une liste de fichiers à lire
file_list = [file for file in glob(f'{file_path}*.png')]
for file_path in file_list:
    #Chargement des outils
    tools = pyocr.get_available_tools()
    #Si vous ne trouvez pas l'outil
    if len(tools) == 0:
        print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
        sys.exit(1)
    tool = tools[0]
    #Chargement d'image
    img_org = Image.open(file_path)
    #Découpez la partie de notation numérique
    max_medals_img = img_org.crop((0, 0, 45, 15))
    #Inverser la couleur d'arrière-plan et la couleur du texte (convertir du texte blanc en texte noir)
    max_medals_img = ImageOps.invert(max_medals_img.convert('RGB'))
    # OCR
    max_medals = tool.image_to_string(max_medals_img, lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=6))
    print(f'max_medals:{max_medals}')

Résultat d'exécution


max_medals:2410
max_medals:440
max_medals:490
max_medals:2717
max_medals:689
max_medals:504
max_medals:1013
max_medals:791
max_medals:862
max_medals:979
max_medals:835
max_medals:1683
max_medals:1587
max_medals:1010
max_medals:1132
max_medals:1586
max_medals:1653
max_medals:413
max_medals:1167
max_medals:527

Les images qui ne pouvaient pas être reconnues normalement étaient également reconnues normalement.

J'ai essayé d'augmenter le nombre d'échantillons de lecture d'image avec ce code ...

Résultat d'exécution


max_medals:1908.
max_medals:
max_medals:1000-
max_medals:10

Il existe encore de rares cas où des caractères qui ne sont pas écrits de cette manière sont mélangés, le nombre de chiffres est incorrect ou les nombres ne peuvent pas être reconnus en premier lieu.

(7 sur 10000)

Changement du mode OCR pour améliorer encore la précision.

Changer de mode de 6 à 8 (mode qui considère les images comme des mots)

from PIL import Image, ImageOps
import pyocr
import pyocr.builders
import sys
from glob import glob

file_path = 'Répertoire de stockage de fichiers'
#Créer une liste de fichiers à lire
file_list = [file for file in glob(f'{file_path}*.png')]
for file_path in file_list:
    #Chargement des outils
    tools = pyocr.get_available_tools()
    #Si vous ne trouvez pas l'outil
    if len(tools) == 0:
        print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
        sys.exit(1)
    tool = tools[0]
    #Chargement d'image
    img_org = Image.open(file_path)
    #Découpez la partie de notation numérique
    max_medals_img = img_org.crop((0, 0, 45, 15))
    #Inverser la couleur d'arrière-plan et la couleur du texte (convertir du texte blanc en texte noir)
    max_medals_img = ImageOps.invert(max_medals_img.convert('RGB'))
    # OCR
    max_medals = tool.image_to_string(max_medals_img, lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=8))
    print(f'max_medals:{max_medals}')

Passé à un mode dans lequel une image elle-même est considérée comme un mot. (Ce mode doit être optimal car l'OCR est effectué après avoir coupé uniquement la partie de notation numérique) Ce mode est plus précis.

(Réduit à environ 4 sur 10000)

Cependant, comme il y avait des cas où il n'était pas reconnu normalement, j'ai ajouté un code pour exclure les caractères autres que les valeurs numériques pour le moment.

Exclure les caractères non numériques

import re
from PIL import Image, ImageOps
import pyocr
import pyocr.builders
import sys
from glob import glob

file_path = 'Répertoire de stockage de fichiers'
#Créer une liste de fichiers à lire
file_list = [file for file in glob(f'{file_path}*.png')]
for file_path in file_list:
    #Chargement des outils
    tools = pyocr.get_available_tools()
    #Si vous ne trouvez pas l'outil
    if len(tools) == 0:
        print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
        sys.exit(1)
    tool = tools[0]
    #Chargement d'image
    img_org = Image.open(file_path)
    #Découpez la partie de notation numérique
    max_medals_img = img_org.crop((0, 0, 45, 15))
    #Inverser la couleur d'arrière-plan et la couleur du texte (convertir du texte blanc en texte noir)
    max_medals_img = ImageOps.invert(max_medals_img.convert('RGB'))
    # OCR
    max_medals = tool.image_to_string(max_medals_img, lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=8))
    #Supprimer les caractères non numériques
    max_medals = re.sub(r'\D', '', max_medals)
    print(f'max_medals:{max_medals}')

Cela évite le cas où des caractères autres que des nombres non marqués tels que "-" et "." Sont mélangés.

Cependant, dans de rares cas, la valeur numérique elle-même n'a pas pu être reconnue ou le nombre de chiffres était incorrect.

Je me demande quoi faire et je conçois diverses mesures d'amélioration

Obtenez la notation numérique en haut à gauche et en bas à gauche de l'image ↓ Comparez les deux ↓ Adoptez une personne qui semble normale

J'ai pensé à quelques schémas de logique, mais le code était long et compliqué, donc je vais revenir un peu ici.

** "En premier lieu, si vous pouvez améliorer la précision de la reconnaissance dans l'OCR, vous n'avez pas à écrire de code gênant." **

J'ai eu l'idée que c'était assez naturel et j'ai essayé de changer la taille de la découpe de notation numérique du prétraitement OCR de différentes manières.

Code final

import re
from PIL import Image, ImageOps
import pyocr
import pyocr.builders
import sys
from glob import glob

file_path = 'Répertoire de stockage de fichiers'
#Créer une liste de fichiers à lire
file_list = [file for file in glob(f'{file_path}*.png')]
for file_path in file_list:
    #Chargement des outils
    tools = pyocr.get_available_tools()
    #Si vous ne trouvez pas l'outil
    if len(tools) == 0:
        print('Je ne trouve pas pyocr. Veuillez installer pyocr.')
        sys.exit(1)
    tool = tools[0]
    #Chargement d'image
    img_org = Image.open(file_path)
    #Découpez la partie de notation numérique
    max_medals_img = img_org.crop((0, 0, 44, 14))
    #Inverser la couleur d'arrière-plan et la couleur du texte (convertir du texte blanc en texte noir)
    max_medals_img = ImageOps.invert(max_medals_img.convert('RGB'))
    # OCR
    max_medals = tool.image_to_string(max_medals_img, lang='eng', builder=pyocr.builders.DigitBuilder(tesseract_layout=8))
    #Supprimer les caractères non numériques
    max_medals = re.sub(r'\D', '', max_medals)
    print(f'max_medals:{max_medals}')

Après avoir essayé différentes tailles, le taux de reconnaissance de l'image graphique que j'avais avec ce code est devenu 100%!

En conséquence, il valait mieux trouver la meilleure pratique de taille de coupe que de penser à la logique (rires)

Conclusion

Si vous ne reconnaissez pas bien les personnages

** Douter de l'image en premier lieu> Vérifiez les paramètres, etc.> Ajustez en ajoutant une autre logique **

Je pense qu'il sera plus difficile de devenir accro si vous travaillez dans cet ordre.

Cette fois, même s'il ne reconnaît que des valeurs numériques, il est extrêmement précis, l'OCR.

Lien de référence

Reconnaissance de caractères avec Python et Tesseract OCR Comment exécuter l'OCR en Python

Recommended Posts

[Python] Obtenez les nombres dans l'image graphique avec OCR
[Python] Récupérez les fichiers dans le dossier avec Python
Déterminez les nombres dans l'image prise avec la webcam
Tweet avec image en Python
Convertissez l'image au format .zip en PDF avec Python
Obtenez des résultats au format dict avec Python psycopg2
Tester avec des nombres aléatoires en Python
Obtenez le chemin du bureau en Python
Obtenez la météo avec les requêtes Python
Obtenez la météo avec les requêtes Python 2
Obtenez le chemin du script en Python
Obtenez le chemin du bureau en Python
Obtenez le nom d'hôte en Python
Démarrez avec Python avec Blender
Obtenez des données supplémentaires vers LDAP avec python
[Python] Définissez la plage du graphique avec matplotlib
[Python] Récupère le nom de la variable avec str
Afficher Python 3 dans le navigateur avec MAMP
Commençons avec TopCoder en Python (version 2020)
Traitez facilement des images en Python avec Pillow
Obtenir la liste de codes EDINET en Python
Lire des caractères dans des images avec Python OCR
Comment obtenir la différence de date et d'heure en secondes avec Python
Obtenez et convertissez l'heure actuelle dans le fuseau horaire local du système avec python
Lisez l'image du graphique avec OpenCV et obtenez les coordonnées du point final du graphique
J'ai essayé de "lisser" l'image avec Python + OpenCV
Obtenez la météo à Osaka via l'API Web (python)
J'ai essayé de "différencier" l'image avec Python + OpenCV
Récupérer l'appelant d'une fonction en Python
Qu'est-ce que wheezy dans l'image Docker Python?
[Automation] Extraire le tableau en PDF avec Python
Obtenir l'URL de l'image à l'aide de l'API Flickr en Python
Obtenez le titre de la fenêtre du système X Window en Python
Détecter les dossiers avec la même image dans ImageHash
J'ai essayé de "binariser" l'image avec Python + OpenCV
Créer une image avec des caractères avec python (japonais)
Comment obtenir les fichiers dans le dossier [Python]
Obtenez le fichier, la fonction, le numéro de ligne en cours d'exécution en python
Dessin graphique avec python
Format d'image en Python
Obtenir la date en Python
Traitement d'image avec Python
Obtenez date avec python
Nombre premier en Python
Dessiner un graphique avec python
Obtenez des informations sur les 100 utilisateurs techniques de Twitter les plus influents au monde avec python.
Obtenez le cours de l'action d'une entreprise japonaise avec Python et faites un graphique
Comment obtenir une liste de fichiers dans le même répertoire avec python
Comment obtenir le nombre de chiffres en Python
[python] Récupère la liste des classes définies dans le module
Obtenez une sortie standard en temps réel avec le sous-processus Python
Explorez l'URL contenue dans le tweet Twitter avec python
Ecrire des caractères dans l'illustration de la carte avec OpenCV python
Obtenir la taille (nombre d'éléments) de Union Find en Python
Obtenez la valeur sélectionnée dans le menu déroulant Selenium Python VBA
Obtenez l'état de fonctionnement de JR West avec Python
Obtenez l'URL de la destination de la redirection HTTP en Python