[PYTHON] Déterminez les nombres dans l'image prise avec la webcam

Après avoir fait un exemple en utilisant MNIST dans l'introduction à l'apprentissage en profondeur, il peut y avoir des gens qui veulent faire quelque chose d'application mais ne peuvent pas penser à un bon exemple.

Cette fois, je voudrais aider ces personnes, et je vais essayer de faire quelque chose qui distingue les chiffres reflétés sur la caméra Web.

Projeter l'image de la webcam

Commençons par afficher l'image de la caméra Web. Cela semble facile à faire avec OpenCV.

Cette fois, j'utilise la "HD Webcam C270" de Logitech.

#!/usr/bin/python
#coding: utf-8

import cv2

def main():
    #Affichage de l'image de la caméra Web
    capture = cv2.VideoCapture(0)
    if capture.isOpened() is False:
            raise("IO Error")
    while True:
        #Capture vidéo de la caméra Web
        ret, image = capture.read()
        if ret == False:
            continue
        #Affichage de l'image de la caméra Web
        cv2.imshow("Capture", image)
        k = cv2.waitKey(10)
        #Fermez l'écran de capture avec la touche ESC
        if  k == 27:
            break
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

Lorsqu'on vous demande si vous souhaitez que votre logiciel de sécurité autorise l'accès à votre webcam au moment de l'exécution, autorisez-le.

Article de référence: Chaîne Venus ☆: Obtenez des images de la caméra Web avec OpenCV version Python

Obtenir et traiter des images

Plutôt que de discriminer constamment les nombres, je veux obtenir l'image à ce moment-là et la traiter lorsque j'appuie sur n'importe quelle touche. En fin de compte, je veux le passer au processus de discrimination des nombres, mais pour le moment, je vais simplement afficher un message pour vérifier le fonctionnement.

Veuillez vous référer à l'article de référence pour quelle clé est attribuée à quel numéro.

#!/usr/bin/python
#coding: utf-8

import cv2

def main():
    #Affichage de l'image de la caméra Web
    capture = cv2.VideoCapture(0)
    if capture.isOpened() is False:
            raise("IO Error")
    while True:
        #Capture vidéo de la caméra Web
        ret, image = capture.read()
        if ret == False:
            continue
        #Affichage de l'image de la caméra Web
        cv2.imshow("Capture", image)
        k = cv2.waitKey(10)
        #Exécuter le traitement avec la touche E
        if k == 101:
            print("Exécuter le traitement")
        #Fermez l'écran de capture avec la touche ESC
        if  k == 27:
            break
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

Article de référence: Liste des codes clés Highgui --Wasting Note

Prétraitement de l'image acquise

Je pensais que ce serait important de transmettre toute l'image acquise en entrée, alors j'aimerais découper la partie 100x100 au centre.

Vérifiez d'abord la taille de l'image acquise par la webcam.

if k == 101:
    print(image.shape)

Nous allons changer la partie traitement de la touche E. Dans OpenCV, l'image est un tableau Numpy, vous pouvez donc utiliser hogehoge.shape pour connaître la longueur de l'élément. Dans cet exemple, (480, 640, 3) est sorti, vous pouvez donc voir que la taille est de 480 (vertical) x 640 (horizontal).

Maintenant que nous connaissons la taille, le processus de découpe du centre 100 x 100 est le suivant. Sauvegardons l'image et voyons si le recadrage fonctionne.

if k == 101:
    img = image[190:290,270:370]
    cv2.imwrite("img.jpg ",img)

Il ne vous reste plus qu'à faire correspondre cette image recadrée au même format d'entrée que pour MNIST. Plus précisément, le traitement est le suivant.

  1. Les images de la caméra Web sont en couleur, faites-en d'abord une échelle de gris.
  2. Réduisez l'image à 28 x 28
  3. Effectuez le même traitement que pour MNIST

Combinez-le avec la découpe dans la partie centrale plus tôt et assemblez-le dans la fonction de prétraitement.

import numpy as np

def preprocessing(img):
    #Découpe au centre
    img = img[190:290,270:370]
    #Conversion en échelle de gris
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #Réduire l'image à 28 x 28
    img = cv2.resize(img, (28, 28))
    #Ci-dessous, effectuez le même traitement que lors de l'apprentissage
    img = 255 - img
    img = img.astype(np.float32)
    img /= 255
    img = np.array(img).reshape(1,784)
    return img

Paramètres MLP utilisés pour déterminer les nombres

Pour cette lecture des nombres, j'utiliserai le simple MLP qui est également utilisé dans l'introduction au chainer.

from chainer import Chain, serializers
import chainer.functions  as F
import chainer.links as L

#Paramètres du modèle Perceptron multicouche
class MyMLP(Chain):
    #Entrée 784, couche intermédiaire 500, sortie 10 dimensions
    def __init__(self, n_in=784, n_units=500, n_out=10):
        super(MyMLP, self).__init__(
            l1=L.Linear(n_in, n_units),
            l2=L.Linear(n_units, n_units),
            l3=L.Linear(n_units, n_out),
        )
    #Structure du réseau neuronal
    def __call__(self, x):
        h1 = F.relu(self.l1(x))
        h2 = F.relu(self.l2(h1))
        y = self.l3(h2)
        return y

Puisque nous déterminerons le nombre plusieurs fois, nous chargerons d'abord le modèle entraîné (my.model2 dans cet exemple).

  • Ajouté le 10 juillet 2017 Cette fois, j'utilise le résultat (my.model2) de l'entraînement MLP défini ci-dessus en utilisant les données MNIST. Si le lecteur utilise les données entraînées préparées par lui-même, il sera facile de réécrire le contenu de la classe My MLP sur le même que celui utilisé pour la formation.

Ensuite, lorsque vous appuyez sur la touche E, ajoutons un processus pour déterminer le nombre à l'aide du modèle entraîné et afficher le résultat.

def main():
    #Chargement du modèle entraîné
    net = MyMLP()###Partie supplémentaire###
    serializers.load_npz('my.model2', net)###Partie supplémentaire###
    #Affichage de l'image de la caméra Web
    capture = cv2.VideoCapture(0)
    if capture.isOpened() is False:
            raise("IO Error")
    while True:
        #Capture vidéo de la caméra Web
        ret, image = capture.read()
        if ret == False:
            continue
        #Affichage de l'image de la caméra Web
        cv2.imshow("Capture", image)
        k = cv2.waitKey(10)
        #Exécuter le traitement avec la touche E
        if k == 101:
            img = preprocessing(image)
            num = net(img)###Partie supplémentaire###
            print(num.data)###Partie supplémentaire###
            print(np.argmax(num.data))###Partie supplémentaire###
        #Fermez l'écran de capture avec la touche ESC
        if  k == 27:
            break
    cv2.destroyAllWindows()

Vous devriez maintenant avoir tout ce dont vous avez besoin.

Affichage de la pièce à découper

Il n'y a pas de problème de traitement, mais il est pratique de savoir où se trouve la partie découpée lors de l'utilisation de la webcam. Par conséquent, la partie à découper dans l'image de la webcam est indiquée dans le cadre rouge.

Affichage vidéo d'une partie de la caméra Web de main ()

cv2.imshow("Capture", image)

Ici

cv2.rectangle(image,(270,190),(370,290),(0,0,255),3)
cv2.imshow("Capture", image)

Fais juste ça.

Essaie

Lorsque vous l'exécutez, un cadre rouge apparaît au centre de l'image sur la caméra Web comme celui-ci, alors mettons le numéro dans le cadre et appuyez sur la touche E.

ca65d9ec37ef3523fd80340fc1235bfa.png

Cependant, je ne pense pas qu'il sera jugé comme 2!

En regardant ce qui arrive à l'image pendant le prétraitement,

def preprocessing(img):
    img = img[190:290,270:370]
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.GaussianBlur(img, (3, 3), 0)
    img = cv2.resize(img, (28, 28))
    img = 255 - img
    img = img.astype(np.float32)
    cv2.imwrite("img.jpg ",img)###État pendant le prétraitement###
    img /= 255
    img = np.array(img).reshape(1,784)
    return img

img.jpg 前処理中の状態

Il semble que l'extraction de la partie numérique ne se passe pas bien en raison du fond sombre.

Essayez de définir un seuil et d'extraire uniquement la partie noire foncée.

def preprocessing(img):
    img = img[190:290,270:370]
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.GaussianBlur(img, (3, 3), 0)
    img = cv2.resize(img, (28, 28))
    res, img = cv2.threshold(img, 70 , 255, cv2.THRESH_BINARY)###Traitement ajouté par seuil###
    img = 255 - img
    img = img.astype(np.float32)
    cv2.imwrite("img.jpg ",img)
    img /= 255
    img = np.array(img).reshape(1,784)
    return img

Référence [Traitement des seuils d'image - documentation OpenCV-Python Tutorials 1](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_thresholding/py_thresholding. html)

En ajoutant un traitement de seuil, la partie numérique peut être extraite et bien jugée.

img.jpg前処理中の状態(閾値処理追加後)

d99b548adc6fb7541dbda4e6726280e2.png

J'ai écrit d'autres nombres et les ai essayés, mais certains d'entre eux étaient difficiles à lire sans ajuster la position et la taille. Il peut être intéressant de réfléchir à la manière dont nous pouvons faire mieux à l'étape suivante.

De plus, je pense que la gamme de jeu sera élargie en se connectant à une caméra Web, j'espère donc que cela vous donnera l'occasion d'essayer quelque chose.

Enfin, je posterai l'intégralité du code de ce que j'ai réalisé cette fois.

#!/usr/bin/python
#coding: utf-8

import cv2
import numpy as np
from chainer import Chain, serializers
import chainer.functions  as F
import chainer.links as L

#Paramètres du modèle Perceptron multicouche
class MyMLP(Chain):
    #Entrée 784, couche intermédiaire 500, sortie 10 dimensions
    def __init__(self, n_in=784, n_units=500, n_out=10):
        super(MyMLP, self).__init__(
            l1=L.Linear(n_in, n_units),
            l2=L.Linear(n_units, n_units),
            l3=L.Linear(n_units, n_out),
        )
    #Structure du réseau neuronal
    def __call__(self, x):
        h1 = F.relu(self.l1(x))
        h2 = F.relu(self.l2(h1))
        y = self.l3(h2)
        return y

def preprocessing(img):
    img = img[190:290,270:370]
    img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img = cv2.GaussianBlur(img, (3, 3), 0)
    img = cv2.resize(img, (28, 28))
    res, img = cv2.threshold(img, 70 , 255, cv2.THRESH_BINARY)
    img = 255 - img
    img = img.astype(np.float32)
    cv2.imwrite("img.jpg ",img)
    img /= 255
    img = np.array(img).reshape(1,784)
    return img

def main():
    #Chargement du modèle entraîné
    net = MyMLP()
    serializers.load_npz('my.model2', net)
    #Affichage de l'image de la caméra Web
    capture = cv2.VideoCapture(0)
    if capture.isOpened() is False:
            raise("IO Error")
    while True:
        #Capture vidéo de la caméra Web
        ret, image = capture.read()
        if ret == False:
            continue
        #Affichage de l'image de la caméra Web
        cv2.rectangle(image,(270,190),(370,290),(0,0,255),3)
        cv2.imshow("Capture", image)
        k = cv2.waitKey(10)
        #Exécuter le traitement avec la touche E
        if k == 101:
            img = preprocessing(image)
            num = net(img)
            #cv2.imwrite("img.jpg ",img)
            print(num.data)
            print(np.argmax(num.data))
        #Fermez l'écran de capture avec la touche ESC
        if  k == 27:
            break
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

Recommended Posts

Déterminez les nombres dans l'image prise avec la webcam
[Python] Obtenez les nombres dans l'image graphique avec OCR
Affichage de l'image prise avec l'ISIGHT intégré
Détecter les dossiers avec la même image dans ImageHash
Convertissez l'image au format .zip en PDF avec Python
Juger les nombres premiers avec python
Tweet avec image en Python
Tester avec des nombres aléatoires en Python
Détecter les points de mosaïque dans l'image
Essayez de brouiller l'image avec opencv2
J'ai essayé de traiter l'image en "style croquis" avec OpenCV
J'ai essayé de traiter l'image dans un "style de dessin au crayon" avec OpenCV
Comportement lors du retour dans le bloc with
Afficher Python 3 dans le navigateur avec MAMP
Faites un clic droit sur l'image → Réalisez "Compresser avec TinyPNG"
J'ai essayé de jouer avec l'image avec Pillow
Traitez facilement des images en Python avec Pillow
Disposez les nombres en forme de spirale
Extraire la couleur de l'objet dans l'image avec le clustering Mask R-CNN et K-Means
Comment afficher dans toute la fenêtre lors de la définition de l'image d'arrière-plan avec tkinter
J'ai essayé de "lisser" l'image avec Python + OpenCV
Connectez-vous à un serveur distant avec SSH
[Python] Récupérez les fichiers dans le dossier avec Python
Coupez l'image aux coins arrondis avec pythonista
J'ai essayé de "différencier" l'image avec Python + OpenCV
Qu'est-ce que wheezy dans l'image Docker Python?
[Automation] Extraire le tableau en PDF avec Python
J'ai essayé de "binariser" l'image avec Python + OpenCV
Créer une image avec des caractères avec python (japonais)
[Python] Déterminez le type d'iris avec SVM
L'histoire qui s'inscrit dans l'installation de pip
Afficher l'image après l'augmentation des données avec Pytorch
Résolution du problème selon lequel l'image n'était pas affichée dans ROMol lors du chargement avec PandasTools.LoadSDF.
Extraire le tableau des fichiers image avec OneDrive et Python
Modifier le fuseau horaire dans Oracle Database Docker
Complétez la bibliothèque mise en anaconda avec jedi-vim
Déterminer le seuil à l'aide de la méthode P-tile en python
Identifiez le nom de l'image de la fleur avec des keras (flux tenseur)
Explorez l'URL contenue dans le tweet Twitter avec python
Obtenez des résultats au format dict avec Python psycopg2
Lire la liste de liens au format csv avec l'outil graphique
Afficher le numéro de ligne de l'éditeur vim (avec les paramètres par défaut)
Ecrire des caractères dans l'illustration de la carte avec OpenCV python
Essayez de charger l'image dans un thread séparé (OpenCV-Python)
Chargez le module du même nom dans un autre emplacement
Déterminer si un attribut est défini dans l'objet
Visualisez les fluctuations des nombres sur les sites Web avec Datadog
POSTER l'image avec json et la recevoir avec flask
Participé à la première ISUCON avec l'équipe "Ranchu" # ISUCON10 Qualifying
Python Open CV a essayé d'afficher l'image sous forme de texte.
Mélangez les images dans n'importe quel répertoire avec Python et enregistrez-les dans un autre dossier avec des numéros de série.
Lors de la lecture d'une image avec SimpleITK, il y a un problème s'il y a du japonais dans le chemin