"Shenzhen" est l'une des villes chinoises les plus développées en informatique. D'après ce que j'entends, des paiements dans les dépanneurs aux distributeurs automatiques, vous pouvez effectuer des paiements simplement en tenant votre visage. Que ce soit bon ou mauvais, c'est incroyable. C'est futuriste et cool. Alors fais moi aussi! Je l'ai fait l'année dernière avec une colle comme w, mais je ne pouvais pas en faire un article, alors j'ai décidé de le faire cette fois. Le système et le programme introduits cette fois sont les premiers travaux qui ont touché Python correctement, et les premiers travaux mémorables qui ont touché l'apprentissage automatique.
Prenez une image de votre visage à l'aide de l'appareil photo de votre PC, traitez et gonflez l'image à l'aide de la bibliothèque OpenCV, puis créez un programme pour identifier l'individu en apprenant le visage avec traincascade. Le langage utilisé était Python3.
Cette fois, nous avons créé deux types de traitement d'image de visage, un programme d'apprentissage et un programme de reconnaissance faciale.
① Démarrez la caméra PC avec la capture vidéo (2) Enregistrez 40 cadres de reconnaissance de visage en tant qu'images ③ Ajoutez 40 images sous différentes formes pour augmenter les données d'entraînement ④ Générer une commande d'apprentissage ⑤ Tapez la commande générée dans la console pour commencer l'apprentissage. ⑥ Générez un fichier en cascade une fois l'apprentissage terminé
① Lire le fichier en cascade du déclarant (2) Passez chaque image dans un fichier en cascade pour identifier les individus.
face_learner/
├─face_learner.py
├─haarcascade_frontalface_default.xml
├─neg.txt
├─pos.txt
├─cascade/
├─neg/
├─neg1.jpg
├─neg2.jpg
├─neg3.jpg
…
└─neg265.jpg
├─pic/
├─pic1.jpg
├─pic2.jpg
├─pic3.jpg
…
└─pic1639.jpg
└─pos.vec
Cette structure de dossiers ne contient que les fichiers autour du programme d'apprentissage. Le programme d'identification personnelle n'est pas inclus.
Veuillez vous référer à l'explication en commentaire de ce qu'il faut faire facilement dans le code source. .. Deux types d'image correcte (image positive) et d'image incorrecte (image négative) sont nécessaires pour l'apprentissage. L'image correcte est l'image du visage que vous souhaitez apprendre, et vous avez également besoin d'informations de coordonnées sur l'emplacement du visage dans l'image. L'image de réponse incorrecte peut être autre chose que l'image de réponse correcte. Cette fois, 265 images d'animaux mignons sont préparées et stockées à l'avance dans le répertoire neg.
Nous commencerons par collecter ces images correctes. Pour obtenir une image de réponse correcte, prenez d'abord 40 images faciales, puis augmentez le nombre à environ 1640 pour améliorer la précision d'apprentissage. Plus le nombre d'images correctes est élevé, plus la précision d'apprentissage est élevée, il est donc conseillé d'augmenter le nombre selon le cas. Je pense qu'il y a une consultation avec les spécifications du PC. Puisque vous allez apprendre un nouveau visage, vous devez supprimer toutes les données inutiles que vous avez utilisées auparavant. Vous devriez être capable de le gérer intelligemment ici (rires). La collecte d'images faciales est le but principal de ce programme. En utilisant le fichier en cascade préchargé pour la reconnaissance faciale, le visage est reconnu et 40 images de visage sont prises en premier. Commencez à ajouter de l'eau à partir d'ici. L'ajout d'eau se fait en ajoutant divers ajouts à l'image. Il semble qu'il y ait déjà un outil dans cette partie, il est donc absolument rapide de l'utiliser. Cette fois, j'ai aussi fait ma propre pratique de programmation.
[Type de modification d'image] • Retourner horizontalement • Changer la saturation • Changer le contraste • Changer la luminosité • Changement de netteté • Rotation de ± 15 degrés
Il y a beaucoup de place pour l'amélioration du traitement ici. Tout d'abord, il est absolument bon de rendre chaque partie de traitement fonctionnelle. Dans ce programme, le nombre de photos est compté et ajouté à chaque fois, il vaut donc mieux l'appliquer un peu plus intelligemment. Après avoir collecté les images, il est nécessaire de créer un fichier texte qui résume les informations de l'image correcte. Il s'agit du chemin du fichier image, dont la partie de laquelle l'image a le visage, et des informations de coordonnées du quadrilatère à quatre côtés qui entoure la partie avec le visage. Le format est [Nombre de faces de chemin Coordonnées (x) Coordonnées (y) Coordonnées (w) Coordonnées (h)]. w est la largeur et h est la hauteur. Un exemple est présenté ci-dessous.
pos.txt
pic/pic1389.jpg 1 454 328 547 547
pic/pic302.jpg 1 565 85 380 380
pic/pic464.jpg 1 947 389 31 31
pic/pic470.jpg 1 663 238 341 341
pic/pic1438.jpg 1 658 341 540 540
pic/pic316.jpg 1 620 88 376 376
pic/pic1376.jpg 1 795 414 376 376
pic/pic1410.jpg 1 476 408 379 379
pic/pic1404.jpg 1 497 394 383 383
pic/pic1362.jpg 1 754 400 372 372
pic/pic869.jpg 1 625 235 420 420
pic/pic855.jpg 1 380 185 381 381
pic/pic666.jpg 1 361 241 424 424
pic/pic100.jpg 1 312 91 360 360
pic/pic64.jpg 1 622 101 371 371
pic/pic114.jpg 1 279 84 375 375
pic/pic70.jpg 1 618 89 382 382
pic/pic672.jpg 1 1213 216 43 43
pic/pic672.jpg 1 369 274 385 385
pic/pic882.jpg 1 721 313 353 353
.
.
.
Une fois que vous avez généré le texte, il ne vous reste plus qu'à générer la commande. Tout d'abord, une commande pour convertir en fichier vectoriel en utilisant les informations de l'image correcte. La prochaine commande à apprendre. python a la capacité d'exécuter des commandes Linux à partir de programmes python, tels que les fonctions os.system () et subprocess.call (), mais je ne l'ai pas compris, donc je peux le faire manuellement. J'essaye de générer une commande vers. Si quelqu'un peut me parler de cette partie, je vais étudier! Lorsque l'apprentissage est terminé, le fichier cascade.xml est créé dans le répertoire cascade, alors lisez-le et effectuez une identification individuelle. Il sera plus facile de comprendre si le nom de fichier est un nom individuel, le cas échéant.
Cela utilise le fichier en cascade créé précédemment pour identifier les individus. La seule bibliothèque chargée par ce programme est OpenCV (cv2). Passez l'image capturée par la caméra à travers le fichier en cascade à chaque fois, et lorsque le visage est relevé, entourez la partie fermée d'un cadre. Premièrement, lorsque le visage d'une personne est reconnu, il est entouré d'un cadre blanc, et lorsqu'une personne est reconnue, il est entouré d'un cadre bleu et le nom est dessiné dessus.
Avec ce genre de sentiment, vous pouvez identifier les individus en temps réel avec un appareil photo!
Je suis vraiment réticent à exposer du code sale, mais je suis sûr que cela aidera, et je publierai tout le code. Veuillez noter qu'il est assez long pour mourir.
face_leaner.py
import os
import re
import numpy as np
import time
import glob
import shutil
import PIL.Image
from PIL import ImageEnhance
import subprocess
import cv2
#uer_name = input("Who are you")
cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#----------------------------------------------
#mov, pic,Effacer la position
os.chdir('cascade')
for x in glob.glob('*.xml'):
os.remove(x)
os.chdir('../')
os.chdir('pic')
for x in glob.glob('*.jpg'):
os.remove(x)
os.chdir('../')
os.chdir('pos')
for x in glob.glob('*.jpg'):
os.remove(x)
os.chdir('../')
os.remove('pos.txt')
#----------------------------------------------
#pos.Créer un txt
f = open('pos.txt', 'a')
#----------------------------------------------
#Recueillir des images faciales
cap = cv2.VideoCapture(0)
cascade_path1 = "haarcascade_frontalface_default.xml"
cascade_path2 = 'lbpcascade_profileface.xml'
cascade1 = cv2.CascadeClassifier(cascade_path1)
cascade2 = cv2.CascadeClassifier(cascade_path2)
color = (255,255,255)
picture_num = 1
while True:
ret, frame = cap.read()
facerect1 = cascade1.detectMultiScale(frame, scaleFactor=1.7, minNeighbors=4, minSize=(100,100))
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame, str(picture_num), (10,500), font, 4,(0,0,0),2,cv2.LINE_AA)
if len(facerect1) > 0:
for (x,y,w,h) in facerect1:
#cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
picture_name = 'pic/pic' + str(picture_num) + '.jpg'
cv2.imwrite(picture_name, frame)
#text = picture_name + ' 1 ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' + str(h) + '\n'
#f.write(text)
picture_num = picture_num + 1
cv2.imshow("frame", frame)
if picture_num == 41:
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
#----------------------------------------------
#Commencer le rembourrage
#Comptez le nombre d'images dans les images
dir = os.getcwd()
dirPic = dir + "/pic"
files = os.listdir(dirPic)
count = 0
for file in files:
count = count + 1
os.chdir('pic')
#Nombre de photos
imageNum = count
#Retourner horizontalement
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
img = cv2.imread(name)
yAxis = cv2.flip(img, 1)
newName = 'pic' + str(imageNum) + '.jpg'
cv2.imwrite(newName,yAxis)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
#Nombre de photos
imageNum = count
#Fix imageNum
picNum = imageNum
SATURATION = 0.5
CONTRAST = 0.5
BRIGHTNESS = 0.5
SHARPNESS = 2.0
#Changer la saturation
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
print('NO')
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
img = PIL.Image.open(name)
saturation_converter = ImageEnhance.Color(img)
saturation_img = saturation_converter.enhance(SATURATION)
newName = 'pic' + str(imageNum) + '.jpg'
saturation_img.save(newName)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
#Nombre de photos
imageNum = count
count = picNum
#Changer le contraste
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
print('NO')
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
img = PIL.Image.open(name)
contrast_converter = ImageEnhance.Contrast(img)
contrast_img = contrast_converter.enhance(CONTRAST)
newName = 'pic' + str(imageNum) + '.jpg'
contrast_img.save(newName)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
#Nombre de photos
imageNum = count
count = picNum
#Changer la luminosité
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
print('NO')
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
img = PIL.Image.open(name)
brightness_converter = ImageEnhance.Brightness(img)
brightness_img = brightness_converter.enhance(BRIGHTNESS)
newName = 'pic' + str(imageNum) + '.jpg'
brightness_img.save(newName)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
#Nombre de photos
imageNum = count
count = picNum
#Changer la netteté
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
print('NO')
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
img = PIL.Image.open(name)
sharpness_converter = ImageEnhance.Sharpness(img)
sharpness_img = sharpness_converter.enhance(SHARPNESS)
newName = 'pic' + str(imageNum) + '.jpg'
sharpness_img.save(newName)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
#Nombre de photos
imageNum = count
#Fix imageNum
picNum = imageNum
#Rotation de 15 degrés
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
print('NO')
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
#Chargement d'image
img = cv2.imread(name)
h, w = img.shape[:2]
size = (w, h)
#Spécification de l'angle de rotation
angle = 15
angle_rad = angle/180.0*np.pi
#Calculer la taille de l'image après la rotation
w_rot = int(np.round(h*np.absolute(np.sin(angle_rad))+w*np.absolute(np.cos(angle_rad))))
h_rot = int(np.round(h*np.absolute(np.cos(angle_rad))+w*np.absolute(np.sin(angle_rad))))
size_rot = (w_rot, h_rot)
#Rotation autour du centre de l'image d'origine
center = (w/2, h/2)
scale = 1.0
rotation_matrix = cv2.getRotationMatrix2D(center, angle, scale)
#Ajouter un mouvement parallèle(rotation + translation)
affine_matrix = rotation_matrix.copy()
affine_matrix[0][2] = affine_matrix[0][2] -w/2 + w_rot/2
affine_matrix[1][2] = affine_matrix[1][2] -h/2 + h_rot/2
img_rot = cv2.warpAffine(img, affine_matrix, size_rot, flags=cv2.INTER_CUBIC)
cv2.imwrite(newName, img_rot)
newName = 'pic' + str(imageNum) + '.jpg'
saturation_img.save(newName)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
#Nombre de photos
imageNum = count
#-Rotation de 15 degrés
for num in range(1, count+1):
name = 'pic' + str(num) + '.jpg'
if os.path.exists(name) :
pass
else :
print('NO')
continue
if os.path.getsize(name) == 0:
os.remove(name)
continue
#Chargement d'image
img = cv2.imread(name)
h, w = img.shape[:2]
size = (w, h)
#Spécification de l'angle de rotation
angle = -15
angle_rad = angle/180.0*np.pi
#Calculer la taille de l'image après la rotation
w_rot = int(np.round(h*np.absolute(np.sin(angle_rad))+w*np.absolute(np.cos(angle_rad))))
h_rot = int(np.round(h*np.absolute(np.cos(angle_rad))+w*np.absolute(np.sin(angle_rad))))
size_rot = (w_rot, h_rot)
#Rotation autour du centre de l'image d'origine
center = (w/2, h/2)
scale = 1.0
rotation_matrix = cv2.getRotationMatrix2D(center, angle, scale)
#Ajouter un mouvement parallèle(rotation + translation)
affine_matrix = rotation_matrix.copy()
affine_matrix[0][2] = affine_matrix[0][2] -w/2 + w_rot/2
affine_matrix[1][2] = affine_matrix[1][2] -h/2 + h_rot/2
img_rot = cv2.warpAffine(img, affine_matrix, size_rot, flags=cv2.INTER_CUBIC)
cv2.imwrite(newName, img_rot)
newName = 'pic' + str(imageNum) + '.jpg'
saturation_img.save(newName)
imageNum = imageNum + 1
print('OK')
print('NEXT STAGE')
#Comptez le nombre de photos
dir = os.getcwd()
files = os.listdir(dir)
count = 0
for file in files:
count = count + 1
print(count)
print('OK')
print('COMPLETE')
#------------------------------------------------------
#Création de fichier texte
#cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#os.chdir('pic')
for num in glob.glob('*.jpg'):
img = cv2.imread(num)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = cascade.detectMultiScale(gray)
for (x,y,w,h) in faces:
text = 'pic/' + num + ' 1 ' + str(x) + ' ' + str(y) + ' ' + str(w) + ' ' + str(h) + '\n'
f.write(text)
cmd = 'opencv_createsamples -info pos.txt -vec pos.vec -num ' + str(count)
print(cmd)
cmd = 'opencv_traincascade -data ./cascade -vec pos.vec -bg neg.txt -numPos 1500 numNeg 255'
print(cmd)
print('COMPLETE.')
face_id.py
# coding: utf-8
import cv2
font = cv2.FONT_HERSHEY_SIMPLEX
if __name__ == "__main__":
cap = cv2.VideoCapture(0)
cascade_path_human = 'haarcascade_frontalface_default.xml'
cascade_path_hirosugu = "cascade_hirosugu.xml"
cascade_path_kenta = 'cascade_kenta.xml'
cascade_hirosugu = cv2.CascadeClassifier(cascade_path_hirosugu)
cascade_human = cv2.CascadeClassifier(cascade_path_human)
cascade_kenta = cv2.CascadeClassifier(cascade_path_kenta)
color = (255,0,0)
while True:
ret, frame = cap.read()
facerect_human = cascade_human.detectMultiScale(frame, scaleFactor=1.7, minNeighbors=4, minSize=(100,100))
facerect_hirosugu = cascade_hirosugu.detectMultiScale(frame, scaleFactor=1.7, minNeighbors=4, minSize=(100,100))
facerect_kenta = cascade_kenta.detectMultiScale(frame, scaleFactor=1.7, minNeighbors=4, minSize=(100,100))
if len(facerect_human) > 0:
for rect in facerect_human:
cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (255,255,255), thickness=2)
if len(facerect_hirosugu) > 0:
for rect in facerect_hirosugu:
cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), color, thickness=2)
cv2.putText(frame, 'Hirosugu Takeshita', tuple(rect[0:2]), font, 2,(0,0,0),2,cv2.LINE_AA)
if len(facerect_kenta) > 0:
for rect in facerect_kenta:
cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), color, thickness=2)
cv2.putText(frame, 'Kenta Suzuki', tuple(rect[0:2]), font, 2,(0,0,0),2,cv2.LINE_AA)
cv2.imshow("frame", frame)
#Appuyez sur la touche q pour terminer la boucle
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
Au fait, il est recommandé de placer le fichier cascade généré (fichier d'apprentissage .xml) dans la même hiérarchie que le programme de reconnaissance faciale!
Droite? N'est-ce pas facile? C'est un programme poubelle pour les professionnels! Vous pourriez penser cela, mais vous pouvez vous appeler un ingénieur Ese ML. Si c'est vrai, la précision sera encore améliorée si vous faites l'extraction de fonctionnalités et écrivez vous-même le NN (je ne sais pas car je ne suis pas très familier avec cela).
De plus, il existe de nombreux articles sur OpenCV, veuillez donc vous y référer également. Étant donné que cet article n'est qu'une trace assez mince, il est recommandé d'étudier en profondeur le mécanisme détaillé et les autres commandes pendant l'apprentissage.
Eh bien, cette fois, c'est une identification personnelle par apprentissage automatique, alors je leur ai demandé de ramener uniquement la connaissance qu'il serait plus facile de collecter des images de visage de cette manière, et je vais créer un identifiant de visage plus précis et l'introduire. Je serais reconnaissant si tu pouvais!
Merci d'avoir lu pendant longtemps!
Recommended Posts