[PYTHON] J'ai essayé la reconnaissance manuscrite des caractères des runes avec scikit-learn

Cet article est le 15e jour du calendrier de l'avent de Fujitsu Systems Web Technology. (Promesse) Le contenu de cet article est ma propre opinion et ne représente pas l'organisation à laquelle j'appartiens.

introduction

Dans cet article, ** en utilisant scikit-learn, la bibliothèque d'apprentissage automatique de Python Ceci est un résumé de la procédure et des résultats lorsque j'ai essayé la reconnaissance de caractères manuscrits des caractères runiques **. Alors que les pionniers de ce calendrier de l'Avent ont publié d'excellentes fonctionnalités et un savoir-faire qui semblent très utiles dans le travail réel, Je fais juste quelque chose qui est juste amusant pour moi, et je ne peux pas m'en empêcher. .. J'espère que vous pourrez y jeter un coup d'œil.

De plus, puisque l'auteur de cet article est un débutant en apprentissage automatique, il se peut qu'il y ait plus de contenu maintenant. Aussi pour ceux qui vont toucher python, scikit-learn Je ferai de mon mieux pour fournir des informations raisonnables. Je vous remercie.

Contexte

Je n'y touche pas du tout dans mon travail quotidien, mais je m'intéresse à l'apprentissage automatique et je veux apprendre les bases de l'apprentissage et du mouvement. J'ai touché scikit-learn. J'aurais pu essayer d'utiliser l'ensemble de données de la bibliothèque, mais Je veux savoir "quel type de données puis-je préparer et que puis-je faire?" J'ai décidé de commencer par préparer les données.

** (De côté) ** Les personnages runiques sont plutôt cool, n'est-ce pas?

Ce qui a été utilisé

--Anaconda: un package qui inclut Python lui-même et les bibliothèques couramment utilisées. --scikit-learn: Une bibliothèque qui facilite l'utilisation des réseaux de neurones en Python. C'est open source. Cette fois, nous utiliserons un modèle appelé MLP Classifier qui effectue une «classification».

--E-cutter: logiciel gratuit pour la division d'image. Utilisé pour diviser des images de texte manuscrites.

Préparation des données

Cette fois, nous nous concentrerons sur les "personnages de runes communs allemands (24 caractères)" parmi les personnages de runes. images.png

Il ne semble pas y avoir de données pratiques telles que "données de caractères runiques pour l'apprentissage automatique", alors préparez votre propre image. Cette fois, je l'ai créé par la méthode suivante.

(1) Créez une image dans laquelle les caractères manuscrits sont alignés à la main à intervalles réguliers. (Ce sera pratique plus tard si le nom du fichier image est dessiné avec un caractère (exemple: "ᚠ. Png")) (2) Divisez l'image en parties égales avec E-cutter (logiciel gratuit). 01_画像取得Ecutter.PNG L'image divisée a été enregistrée dans le dossier spécifié avec "[nom du fichier d'origine] _ [numéro de branche] .png ", ce qui était très pratique. Une fois, j'ai créé 18 données d'image pour chaque type de personnage runique.

Chargement des images

De là, nous traiterons en Python. Commencez par charger l'image.

import cv2 #Bibliothèque pour la conversion d'images
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import os, glob

#Tableau pour stocker les données d'image
X = []
#Caractères correspondant aux données d'image(répondre)Tableau à stocker
Y = []

#Fichier de répertoire de données d'entraînement
dir = "[Répertoire de stockage des données d'image]"
files = glob.glob(dir + "\\*.png ")

#Taille verticale et horizontale de l'image(pixel)
image_size = 50

#Lisez les fichiers du répertoire et ajoutez-les à la liste des données d'entraînement
for i, file in enumerate(files):
    image = Image.open(file)
    #Convertir en échelle de gris 8 bits
    image = image.convert("L")
    image = image.resize((image_size, image_size))
    data = np.asarray(image).flatten()
    X.append(data)
    moji = file.split("\\")[-1].split("_")[0]
    Y.append(moji)
 
X = np.array(X)
Y = np.array(Y)

Affichez l'image chargée.

#Visualisez les premières données
showimage = np.reshape(X[0], (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.show()
02_画像読み込み.PNG

Il peut être lu comme des données de taille 50 * 50.

◆ Apprenons et classons

Le nombre de données est assez petit, mais apprenons et classons avec ces données (24 (caractères) * 18 (feuilles)) une fois!

・ Données séparées pour la formation et les tests
#Divisez les données pour la formation et les tests
x_train, x_test, y_train, y_test = model_selection.train_test_split(X, Y, test_size=0.1, random_state=0)
・ Apprendre et juger
#Apprentissage
clf = MLPClassifier(hidden_layer_sizes=(200,))
clf.fit(x_train, y_train)

#Catégoriser les données de test
y_pred = clf.predict(x_test)

#Voir les résultats
print("---Réponse supposée---")
print(y_test)

print("---La réponse donnée par le modèle---")
print(y_pred)

print("---Taux de réponse correct---")
accuracy_score(y_test, y_pred)

·résultat

12120023_最初の結果_全然ダメ.PNG

** Le pourcentage de bonnes réponses est très faible ...! !! (7,1%) ouz **

La plupart d'entre eux sont classés comme "ᚱ", et les autres caractères jugés sont également incorrects ... Cependant, ceux classés autres que "ᚱ" semblent être classés comme des personnages de formes similaires parmi les caractères runiques. Je suis un peu heureux d'avoir un aperçu du germe d'intelligence (même si j'ai fait une erreur après tout).

Il semble que les données d'apprentissage soient encore insuffisantes, mais il est difficile d'ajouter plus de données de caractères manuscrites. Essayez l'augmentation des données.

Augmentation des données

Préparé [Type de caractère] * 18 images ne suffisent pas pour l'apprentissage, donc Convertissez les données pour augmenter la quantité de données.

L'article suivant a été très utile pour l'augmentation des données. https://products.sint.co.jp/aisia/blog/vol1-7#toc-3

Il semble qu'il existe des méthodes telles que «augmenter le bruit», «inverser», «déplacer» et «transformer». Cette fois, nous y effectuerons "transformation" et "rotation".

Déformation

#Transformez l'image
for i, file in enumerate(files):
    image = Image.open(file)   
    image = image.resize((image_size, image_size))
    image = image.convert("L")
    moji = file.split("\\")[-1].split("_")[0]
    
    #Inverser les bits de données dans un tableau
    image_array = cv2.bitwise_not(np.array(image))
    
    ##Transformation ①
    #Créer une carte de transformation de l'image
    pts1 = np.float32([[0,0],[0,100],[100,100],[100,0]])
    pts2 = np.float32([[0,0],[0, 98],[102,102],[100,0]])
    #Transformation d'image
    M = cv2.getPerspectiveTransform(pts1,pts2)
    dst1 = cv2.warpPerspective(image_array,M,(50, 50))
    
    X.append(dst1.flatten())
    Y.append(moji)
    
    ##Transformation ②
    #Créer une carte de transformation de l'image
    pts2 = np.float32([[0,0],[0, 102],[98, 98],[100,0]]) 
    #Transformation d'image
    M = cv2.getPerspectiveTransform(pts1,pts2)
    dst2 = cv2.warpPerspective(image_array,M,(50, 50))
    X.append(dst2.flatten())
    Y.append(moji)

#Afficher les dernières données
showimage = np.reshape(image_array, (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
Affichage de l'image déformée
03_画像変形.PNG

J'ai pu générer une image légèrement déformée par rapport à l'image d'origine. Générez deux images déformées pour chaque image originale et ajoutez-les aux données d'entraînement.

rotation

Pour augmenter davantage les données, créez une image avec l'image d'origine tournée de 15 degrés et ajoutez-la.

#Faire pivoter l'image
for i, file in enumerate(files):
    image = Image.open(file)   
    image = image.resize((image_size, image_size))
    image = image.convert("L")
    moji = file.split("\\")[-1].split("_")[0]
    
    #Inverser les bits de données dans un tableau
    image = cv2.bitwise_not(np.array(image))
    
    #1. 1. Rotation de 15 degrés dans le sens des aiguilles d'une montre
    #Spécifiez l'angle de rotation
    angle = -15.0
    #Spécifiez l'échelle
    scale = 1.0
    #Utilisez la fonction getRotationMatrix2D
    trans = cv2.getRotationMatrix2D((24, 24), angle , scale)
    #Conversion d'affine
    image1 = cv2.warpAffine(image, trans, (50, 50))
    X.append(image1.flatten())
    Y.append(moji)
    
    #2. Rotation de 15 degrés dans le sens antihoraire
    #Spécifiez l'angle de rotation
    angle = 15.0
    #Spécifiez l'échelle
    scale = 1.0
    #Utilisez la fonction getRotationMatrix2D(Arguments: position centrale, angle de rotation, échelle)
    trans = cv2.getRotationMatrix2D((24, 24), angle , scale)
    #Conversion d'affine
    image2 = cv2.warpAffine(image, trans, (50, 50))
    X.append(image2.flatten())
    Y.append(moji)

#Afficher les dernières données
showimage = np.reshape(image, (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(image1),plt.title('Output')
plt.show()

showimage = np.reshape(image, (50,50)) #Créer un double tableau 50x50 avec remodelage
plt.subplot(121),plt.imshow(showimage),plt.title('Input')
plt.subplot(122),plt.imshow(image2),plt.title('Output')
plt.show()
Affichage de l'image pivotée
03_画像回転.PNG

L'image d'origine a été tournée de 15 degrés vers la gauche et la droite pour générer chaque image. Cette image est également ajoutée aux données d'entraînement.

Avec cela, le nombre de données pour la formation est 5 fois supérieur à l'original (original, transformation ①, transformation ②, rotation droite, rotation gauche).

Apprentissage / reconnaissance [re]

Reconnaissons (classons) les images pour apprendre et tester à nouveau!

·résultat

12152147_次の結果_うまくいった!.PNG

** La précision s'est améliorée ...! (86,9%) **

Regarder en arrière

Quelles données étaient valides après tout

Le résultat était quelque chose comme "J'ai augmenté les données et la précision de l'analyse s'est améliorée! Je l'ai fait!" Après tout, je me demandais à quel point chacune des images déformées était efficace, alors En gros, j'ai essayé de vérifier le taux de réponse correct en modifiant la répartition des données à former. 雑まとめ.PNG J'ai pu confirmer que le taux de réponse correct était suffisamment élevé pour donner des variations à l'image.

Ce que je veux faire dans le futur

Je voudrais continuer à vérifier si d'autres méthodes ("rognage", "bruit" ...) amélioreront encore la précision. De plus, cette fois, je voudrais vérifier le modèle dans lequel le nombre de nœuds de couche cachés dans le réseau neuronal a été modifié, qui a été fixé à 200.

Merci pour la lecture!

Recommended Posts

J'ai essayé la reconnaissance manuscrite des caractères des runes avec scikit-learn
J'ai essayé la reconnaissance de caractères manuscrits des caractères runiques avec CNN en utilisant Keras
J'ai essayé la reconnaissance d'image de CIFAR-10 avec Keras-Learning-
J'ai essayé la reconnaissance d'image de CIFAR-10 avec la reconnaissance d'image Keras-
J'ai essayé la reconnaissance faciale avec OpenCV
J'ai essayé la reconnaissance d'image simple avec Jupyter
J'ai essayé des centaines de millions de SQLite avec python
J'ai essayé Flask avec des conteneurs distants de VS Code
J'ai essayé de faire la reconnaissance de caractères manuscrits de Kana Partie 3/3 Coopération avec l'interface graphique en utilisant Tkinter
J'ai essayé d'extraire des fonctionnalités avec SIFT d'OpenCV
[OpenCV / Python] J'ai essayé l'analyse d'image de cellules avec OpenCV
J'ai essayé la "conversion de morphologie" de l'image avec Python + OpenCV
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é la reconnaissance faciale avec Face ++
J'ai essayé le clustering avec PyCaret
Traitement parallèle avec Parallel de scikit-learn
J'ai essayé gRPC avec Python
J'ai essayé de gratter avec du python
J'ai essayé de trouver l'entropie de l'image avec python
J'ai essayé la "correction gamma" de l'image avec Python + OpenCV
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
J'ai essayé de démarrer le serveur de Django avec VScode au lieu de Pycharm
J'ai essayé d'exécuter Movidius NCS avec python de Raspberry Pi3
J'ai essayé la reconnaissance faciale du problème du rire en utilisant Keras.
J'ai essayé d'implémenter ListNet d'apprentissage de rang avec Chainer
J'ai essayé de simuler la probabilité d'un jeu de bingo avec Python
Recherche en grille d'hyper paramètres avec Scikit-learn
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'utiliser GrabCut d'OpenCV
J'ai essayé d'implémenter DeepPose avec PyTorch
J'ai essayé la détection de visage avec MTCNN
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
J'ai essayé de gratter le classement du calendrier de l'avent Qiita avec Python
J'ai essayé le déploiement autonome de play avec fabric [opération AWS avec boto] [déploiement de lecture]
J'ai essayé d'automatiser l'arrosage du pot avec Raspberry Pi
J'ai essayé la validation croisée basée sur le résultat de la recherche de grille avec scikit-learn
J'ai essayé de faire la reconnaissance de caractères manuscrits de Kana Partie 1/3 D'abord à partir de MNIST
J'ai essayé de créer une liste de nombres premiers avec python
J'ai essayé de corriger "J'ai essayé la simulation probabiliste du jeu de bingo avec Python"
J'ai essayé d'agrandir la taille du volume logique avec LVM
J'ai essayé d'exécuter la partie DNN d'OpenPose avec le processeur Chainer
J'ai essayé d'améliorer l'efficacité du travail quotidien avec Python
J'ai essayé de collecter automatiquement des images de Kanna Hashimoto avec Python! !!
J'ai essayé de créer un mécanisme de contrôle exclusif avec Go
J'ai essayé de vérifier l'identification du locuteur par l'API de reconnaissance du locuteur d'Azure Cognitive Services avec Python. # 1
J'ai essayé de vérifier l'identification du locuteur par l'API de reconnaissance du locuteur d'Azure Cognitive Services avec Python. # 2
J'ai essayé l'analyse de régression multiple avec régression polypoly
J'ai essayé d'envoyer un SMS avec Twilio
J'ai essayé d'utiliser Amazon SQS avec django-celery
J'ai essayé le serveur asynchrone de Django 3.0
J'ai essayé d'implémenter Autoencoder avec TensorFlow
J'ai essayé linebot avec flacon (anaconda) + heroku