Cet article présente principalement les méthodes détaillées de détection et de reconnaissance des visages impliquées dans le système. Le système est basé sur l'environnement python2.7.10/opencv2/tensorflow1.7.0 et implémente les fonctions de lecture vidéo de la caméra, de détection de visages, et reconnaître les visages, c'est-à-dire implémenter un système de connexion par reconnaissance faciale basé sur mtcnn/facenet/tensorflow.
Le fichier de modèle étant trop volumineux, git ne peut pas le télécharger. L'intégralité du code source du projet est placé sur Baidu Cloud Disk
Adresse : . https://pan.baidu.com/s/1TaalpwQwPTqlCIfXInS_LA
La reconnaissance faciale est un point chaud dans le domaine de la recherche en vision par ordinateur. À l'heure actuelle, dans les environnements de laboratoire, de nombreuses reconnaissances faciales ont rattrapé (dépassé) la précision de la reconnaissance manuelle (taux de précision : 0,9427 ~ 0,9920), comme face++, DeepID3, FaceNet, etc. (Pour plus de détails, veuillez vous référer à : Face technologie de reconnaissance basée sur l’examen du deep learning).
Cependant, en raison de divers facteurs tels que la lumière, l'angle, l'expression, l'âge, etc., la technologie de reconnaissance faciale ne peut pas être largement utilisée dans la vie réelle. Cet article est basé sur l'environnement python/opencv/tensorflow et utilise FaceNet (LFW : 0.9963) pour créer un système de détection et de reconnaissance des visages en temps réel afin d'explorer les difficultés des systèmes de reconnaissance faciale dans les applications réelles.
Le contenu principal ci-dessous est le suivant :
1. Utilisez la balise vidéo htm5 pour ouvrir la caméra afin de collecter des avatars et utilisez le composant jquery.faceDeaction pour détecter grossièrement. visages
2. Téléchargez l'image du visage sur le serveur, utilisez mtcnn pour détecter le visage
3 Utilisez la transformation affine d'opencv pour aligner le visage et enregistrez le visage aligné
4. Utilisez le facenet pré-entraîné intégrant les visages détectés dans des fonctionnalités à 512 dimensions 5. Créez un index de gêne efficace pour les fonctionnalités d'intégration de visages pour la détection des visagesCollection de visagesEn utilisant la balise vidéo html5, il est très pratique de lire les images vidéo de la caméra. Le code suivant implémente la lecture des images vidéo de la caméra après que faceDection ait reconnu le visage. Capturez des images et téléchargez-les sur le serveur. Ajoutez la vidéo au fichier html. Balise Canvas
Ouvrez la webcam<div class="booth"> <video id="video" width="400" height="300" muted class="abs" ></video> <canvas id="canvas" width="400" height="300"></canvas> </div>
var video = document.getElementById('video'),var vendorUrl = window.URL || window.webkitURL; //媒体对象 navigator.getMedia = navigator.getUserMedia || navagator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; navigator.getMedia({video: true, //使用摄像头对象audio: false //不适用音频}, function(strem){ video.src = vendorUrl.createObjectURL(strem); video.play(); });
Si le visage d'une personne est détecté, prenez une capture d'écran et convertissez l'image au format base64 pour un téléchargement facile
$('#canvas').faceDetection()
context.drawImage(video, 0, 0, video.width, video.height); var base64 = canvas.toDataURL('images/png');
//上传人脸图片 function upload(base64) { $.ajax({ "type":"POST", "url":"/upload.php", "data":{'img':base64}, 'dataType':'json', beforeSend:function(){}, success:function(result){ console.log(result) img_path = result.data.file_path } }); }
function base64_image_content($base64_image_content,$path){ //匹配出图片的格式 if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){ $type = $result[2]; $new_file = $path."/"; if(!file_exists($new_file)){ //检查是否有该文件夹,如果没有就创建,并给予最高权限 mkdir($new_file, 0700,true); } $new_file = $new_file.time().".{$type}"; if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){ return $new_file; }else{ return false; } }else{ return false; } }
Détection de visageIl existe de nombreuses méthodes de détection de visage, comme le visage fourni avec le classificateur de fonctionnalités opencv Haar et la méthode de détection de visage dlib, etc. La méthode de détection des visages d'opencv est simple et rapide ; le problème est que l'effet de détection des visages n'est pas bon. Cette méthode peut détecter les visages frontaux/verticaux/avec un bon éclairage, tandis que les visages latéraux/de biais/avec un mauvais éclairage ne peuvent pas être détectés.
Par conséquent, cette méthode n’est pas adaptée à une application sur le terrain. Pour la méthode de détection de visage dlib, l'effet est meilleur que la méthode opencv, mais la force de détection est également difficile à répondre aux normes d'application sur le terrain.
Dans cet article, nous utilisons le système de détection de visage mtcnn (mtcnn : Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Neural Networks) basé sur des méthodes d'apprentissage profond.
La méthode de détection de visage mtcnn est plus robuste aux changements de lumière, d'angle et d'expression faciale dans l'environnement naturel, et l'effet de détection de visage est meilleur en même temps, la consommation de mémoire n'est pas importante et réelle ; -la détection des visages dans le temps peut être obtenue.
Le mtcnn utilisé dans cet article est basé sur l'implémentation de python et tensorflow (le code vient de Davidsandberg, le code d'implémentation de caffe peut être trouvé à l'adresse : kpzhang93)
Pour du code spécifique, veuillez vous référer à fcce_detect.pymodel= os.path.abspath(face_comm.get_conf('mtcnn','model')) class Detect: def __init__(self): self.detector = MtcnnDetector(model_folder=model, ctx=mx.cpu(0), num_worker=4, accurate_landmark=False) def detect_face(self,image): img = cv2.imread(image) results =self.detector.detect_face(img) boxes=[] key_points = [] if results is not None: #box框 boxes=results[0] #人脸5个关键点 points = results[1] for i in results[0]: faceKeyPoint = [] for p in points: for i in range(5): faceKeyPoint.append([p[i], p[i + 5]]) key_points.append(faceKeyPoint) return {"boxes":boxes,"face_key_point":key_points}
Alignement du visageParfois, les visages et les avatars que nous capturons peuvent être tordus afin d'améliorer la qualité. détection, nous devons corriger les visages à la même position standard, cette position est définie par nous. Supposons que l'avatar de détection standard que nous définissons soit comme ceci
Supposons que le. les coordonnées des trois points des yeux et du nez sont a(10,30) b(20,30) c(15,45) Pour des paramètres spécifiques, veuillez vous référer à l'élément de configuration du bloc d'alignement du fichier config.ini
<. 🎜> Utilisez la transformation affine opencv pour l'alignement et obtenez la matrice de transformation affine
Transformation affine :
dst_point=【a,b,c】 tranform = cv2.getAffineTransform(source_point, dst_point)
Pour un code spécifique, veuillez vous référer au fichier face_alignment.py
img_new = cv2.warpAffine(img, tranform, imagesize)
Aligner les avatars, les placer dans un facenet pré-entraîné pour intégrer les visages détectés, les intégrer dans des fonctionnalités à 512 dimensions et enregistrer dans le fichier lmdb sous la forme de (id, vector)
Pour un code spécifique, veuillez vous référer à face_encoder.py
facenet.load_model(facenet_model_checkpoint) images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0") embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0") phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0") face=self.dectection.find_faces(image) prewhiten_face = facenet.prewhiten(face.image) # Run forward pass to calculate embeddings feed_dict = {images_placeholder: [prewhiten_face], phase_train_placeholder: False} return self.sess.run(embeddings, feed_dict=feed_dict)[0]
人脸识别的时候不能对每一个人脸都进行比较,太慢了,相同的人得到的特征索引都是比较类似,可以采用KNN分类算法去识别,这里采用是更高效annoy算法对人脸特征创建索引,annoy索引算法的有个假设就是,每个人脸特征可以看做是在高维空间的一个点,如果两个很接近(相识),任何超平面 都无法把他们分开,也就是说如果空间的点很接近,用超平面去分隔,相似的点一定会分在同一个平面空间(具体参看:https://github.com/spotify/annoy)
#人脸特征先存储在lmdb文件中格式(id,vector),所以这里从lmdb文件中加载 lmdb_file = self.lmdb_file if os.path.isdir(lmdb_file): evn = lmdb.open(lmdb_file) wfp = evn.begin() annoy = AnnoyIndex(self.f) for key, value in wfp.cursor(): key = int(key) value = face_comm.str_to_embed(value) annoy.add_item(key,value) annoy.build(self.num_trees) annoy.save(self.annoy_index_path)
具体代码可参看face_annoy.py
人脸识别
经过上面三个步骤后,得到人脸特征,在索引中查询最近几个点并就按欧式距离,如果距离小于0.6(更据实际情况设置的阈值)则认为是同一个人,然后根据id在数据库查找到对应人的信息即可
#根据人脸特征找到相似的 def query_vector(self,face_vector): n=int(face_comm.get_conf('annoy','num_nn_nearst')) return self.annoy.get_nns_by_vector(face_vector,n,include_distances=True)
具体代码可参看face_annoy.py
安装部署
系统采用有两个模块组成:
face_web:提供用户注册登录,人脸采集,php语言实现
face_server: 提供人脸检测,裁剪,对齐,识别功能,python语言实现
模块间采用socket方式通信通信格式为: length+content
face_server相关的配置在config.ini文件中
1.使用镜像
face_serverdocker镜像: shareclz/python2.7.10-face-image
face_web镜像: skiychan/nginx-php7
假设项目路径为/data1/face-login
2.安装face_server容器
docker run -it --name=face_server --net=host -v /data1:/data1 shareclz/python2.7.10-face-image /bin/bash cd /data1/face-login python face_server.py
3.安装face_web容器
docker run -it --name=face_web --net=host -v /data1:/data1 skiychan/nginx-php7 /bin/bash cd /data1/face-login; php -S 0.0.0.0:9988 -t ./web/
最终效果:
face_server加载mtcnn模型和facenet模型后等待人脸请求
未注册识别失败
人脸注册
注册后登录成功
感谢PHP中文网热心网友的投稿,其GitHub地址为:https://github.com/chenlinzhong/face-login
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!