1. """An example of how to use your own dataset to train a classifier that recognizes people.
  2. """
  3. # MIT License
  4. #
  5. # Copyright (c) 2016 David Sandberg
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in all
  15. # copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. # SOFTWARE.
  24.  
  25. # @ 调用格式:
  26. # @
  27. # @ 训练模型记住人脸(不是训练网络,网络在这之前已经先训练好了)。
  28. # @ ../lfw/ 是lfw数据集经过 mtcnn 截取以后的结果。否则会影响效果(去除数据集中的人脸外部干扰)
  29. # @ python classifier.py TRAIN ../lfw/ 20170511-185253/ train_20180419_2048.pkl
  30. # @
  31. # @ 测试模型记住人脸的结果。(../data 是测试用的图的路径。)
  32. # @ python classifier.py CLASSIFY ../data/ 20170511-185253/ train_20180419_2048.pkl
  33.  
  34. from __future__ import absolute_import
  35. from __future__ import division
  36. from __future__ import print_function
  37.  
  38. import tensorflow as tf
  39. import numpy as np
  40. import argparse
  41. import facenet
  42. import os
  43. import sys
  44. import math
  45. import pickle
  46. from sklearn.svm import SVC
  47.  
  48. # @ args内中参数见函数 parse_arguments
  49. def main(args):
  50. # @ 声明一个计算图,都这么写,没有就是默认一个。
  51. with tf.Graph().as_default():
  52. # @ 声明一个 Session
  53. with tf.Session() as sess:
  54.  
  55. # @ Part I
  56. # @ 这部分是计算人脸的 embedding 特征。费时。
  57. # @
  58.  
  59. # @ 加随机数seed,调用np.random.random()的结果都会相同。
  60. np.random.seed(seed=args.seed)
  61.  
  62. if args.use_split_dataset:
  63. dataset_tmp = facenet.get_dataset(args.data_dir)
  64. train_set, test_set = split_dataset(dataset_tmp, args.min_nrof_images_per_class, args.nrof_train_images_per_class)
  65. if (args.mode=='TRAIN'):
  66. dataset = train_set
  67. elif (args.mode=='CLASSIFY'):
  68. dataset = test_set
  69. else:
  70. dataset = facenet.get_dataset(args.data_dir)
  71.  
  72. # Check that there are at least one training image per class
  73. # @ cls.image_paths 是每张图的路径,包含文件名。
  74. for cls in dataset:
  75. assert(len(cls.image_paths)>0, 'There must be at least one image for each class in the dataset')
  76.  
  77. # @ 分离出图片路径名paths,和类型labels(人脸所属人名)
  78. paths, labels = facenet.get_image_paths_and_labels(dataset)
  79.  
  80. print('Number of classes: %d' % len(dataset))
  81. print('Number of images: %d' % len(paths))
  82.  
  83. # Load the model
  84. # @ 这里加的 model 使用于生成人脸的 embedding 特征的网络。
  85. # @ 这个网络是事先已经生成好的。
  86. # @ 网络可以根据运行的平台,设计成不同大小。比如基于GoogleNet/AlexNet等
  87. print('Loading feature extraction model')
  88. facenet.load_model(args.model)
  89.  
  90. # Get input and output tensors
  91. # @ TensorFlow的参数准备。embeddings 是网络的输出,是后续分类的输入。
  92. images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
  93. embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
  94. phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
  95. embedding_size = embeddings.get_shape()[1]
  96.  
  97. # Run forward pass to calculate embeddings
  98. print('Calculating features for images')
  99. nrof_images = len(paths) # @ 图片总数
  100. nrof_batches_per_epoch = int(math.ceil(1.0*nrof_images / args.batch_size))
  101. emb_array = np.zeros((nrof_images, embedding_size))
  102. for i in range(nrof_batches_per_epoch):
  103. start_index = i*args.batch_size
  104. end_index = min((i+1)*args.batch_size, nrof_images)
  105. paths_batch = paths[start_index:end_index]
  106. images = facenet.load_data(paths_batch, False, False, args.image_size)
  107. feed_dict = { images_placeholder:images, phase_train_placeholder:False }
  108. emb_array[start_index:end_index,:] = sess.run(embeddings, feed_dict=feed_dict)
  109.  
  110. # @ emb_array 是 embedding 结果。一个 embedding 有 18 维。
  111. # @ 接下来就是用机器学习的方法分类。
  112. classifier_filename_exp = os.path.expanduser(args.classifier_filename)
  113.  
  114. # @ Part II 也较费时。
  115. # @ 这部分是训练分类人脸的机器学习模型,这里使用的SVC,是SVM的一种。
  116. # @ 若是 CLASSIFY ,则是加载训练结果,建立 SVC 分类器。
  117.  
  118. if (args.mode=='TRAIN'):
  119. # Train classifier
  120. # @ SVC是SVM的一种Type,是用来的做分类的;同样还有SVR,是SVM的另一种Type,是用来的做回归的。
  121. print('Training classifier')
  122. model = SVC(kernel='linear', probability=True)
  123. model.fit(emb_array, labels) # @ 训练过程
  124.  
  125. # @ 训练结束,保存数据
  126. # Create a list of class names
  127. class_names = [ cls.name.replace('_', ' ') for cls in dataset]
  128.  
  129. # Saving classifier model
  130. with open(classifier_filename_exp, 'wb') as outfile:
  131. pickle.dump((model, class_names), outfile)
  132. print('Saved classifier model to file "%s"' % classifier_filename_exp)
  133.  
  134. elif (args.mode=='CLASSIFY'):
  135. # Classify images
  136. print('Testing classifier')
  137. # @ 加载数据,建立分类器
  138. with open(classifier_filename_exp, 'rb') as infile:
  139. (model, class_names) = pickle.load(infile)
  140.  
  141. print('Loaded classifier model from file "%s"' % classifier_filename_exp)
  142.  
  143. # @ 预测,标签结果应该是 one_hot 的。
  144. predictions = model.predict_proba(emb_array)
  145. best_class_indices = np.argmax(predictions, axis=1) # @ 输出每列最大的序号。
  146. best_class_probabilities = predictions[np.arange(len(best_class_indices)), best_class_indices]
  147.  
  148. for i in range(len(best_class_indices)):
  149. print('%4d %s: %.3f' % (i, class_names[best_class_indices[i]], best_class_probabilities[i]))
  150.  
  151. # @ 评估结果。labels 是测试集的实际结果,best_class_indices是预测结果。
  152. accuracy = np.mean(np.equal(best_class_indices, labels))
  153. print('Accuracy: %.3f' % accuracy)
  154.  
  155. # @ 将数据集分成训练集和测试集
  156. def split_dataset(dataset, min_nrof_images_per_class, nrof_train_images_per_class):
  157. train_set = []
  158. test_set = []
  159. for cls in dataset:
  160. paths = cls.image_paths
  161. # Remove classes with less than min_nrof_images_per_class
  162. if len(paths)>=min_nrof_images_per_class:
  163. np.random.shuffle(paths)
  164. train_set.append(facenet.ImageClass(cls.name, paths[:nrof_train_images_per_class]))
  165. test_set.append(facenet.ImageClass(cls.name, paths[nrof_train_images_per_class:]))
  166. return train_set, test_set
  167.  
  168. # @ 命令行参数,使用的系统库 argparse
  169. # @ ** 写法值得记住 **
  170. def parse_arguments(argv):
  171. parser = argparse.ArgumentParser()
  172.  
  173. parser.add_argument('mode', type=str, choices=['TRAIN', 'CLASSIFY'],
  174. help='Indicates if a new classifier should be trained or a classification ' +
  175. 'model should be used for classification', default='CLASSIFY')
  176. parser.add_argument('data_dir', type=str,
  177. help='Path to the data directory containing aligned LFW face patches.')
  178. parser.add_argument('model', type=str,
  179. help='Could be either a directory containing the meta_file and ckpt_file or a model protobuf (.pb) file')
  180. parser.add_argument('classifier_filename',
  181. help='Classifier model file name as a pickle (.pkl) file. ' +
  182. 'For training this is the output and for classification this is an input.')
  183. parser.add_argument('--use_split_dataset',
  184. help='Indicates that the dataset specified by data_dir should be split into a training and test set. ' +
  185. 'Otherwise a separate test set can be specified using the test_data_dir option.', action='store_true')
  186. parser.add_argument('--test_data_dir', type=str,
  187. help='Path to the test data directory containing aligned images used for testing.')
  188. parser.add_argument('--batch_size', type=int,
  189. help='Number of images to process in a batch.', default=90)
  190. parser.add_argument('--image_size', type=int,
  191. help='Image size (height, width) in pixels.', default=160)
  192. parser.add_argument('--seed', type=int,
  193. help='Random seed.', default=666)
  194. parser.add_argument('--min_nrof_images_per_class', type=int,
  195. help='Only include classes with at least this number of images in the dataset', default=20)
  196. parser.add_argument('--nrof_train_images_per_class', type=int,
  197. help='Use this number of images from each class for training and the rest for testing', default=10)
  198.  
  199. return parser.parse_args(argv)
  200.  
  201. # @ 主函数
  202. # @ sys.argv[1:] 就是命令行输入的 classify.py 后面的所有字符串,以空格分隔。
  203. if __name__ == '__main__':
  204. main(parse_arguments(sys.argv[1:]))

  

08-人脸识别-FaceNet-classify.py代码阅读(说明见注释)的更多相关文章

  1. TensorFlow环境 人脸识别 FaceNet 应用(一)验证测试集

    TensorFlow环境 人脸识别 FaceNet 应用(一)验证测试集 前提是TensorFlow环境以及相关的依赖环境已经安装,可以正常运行. 一.下载FaceNet源代码工程 git clone ...

  2. 第三十七节、人脸检测MTCNN和人脸识别Facenet(附源码)

    在说到人脸检测我们首先会想到利用Harr特征提取和Adaboost分类器进行人脸检测(有兴趣的可以去一看这篇博客第九节.人脸检测之Haar分类器),其检测效果也是不错的,但是目前人脸检测的应用场景逐渐 ...

  3. 人脸识别FaceNet+TensorFlow

    一.本文目标 利用facenet源码实现从摄像头读取视频,实时检测并识别视频中的人脸.换句话说:把facenet源码中contributed目录下的real_time_face_recognition ...

  4. 基于 Python + OpenCV 进行人脸识别,视频追踪代码全注释

    先来普及一下概念, 计算机对人脸是如何识别的呢? 或者说图像是如何识别的.主要是获取单张图片的特征值记录了特征值以后,如果下一张图片来了以后两张图片特征值进行对比,如果相似度很高那么计算机就认定这两个 ...

  5. Python的开源人脸识别库:离线识别率高达99.38%

    Python的开源人脸识别库:离线识别率高达99.38%   github源码:https://github.com/ageitgey/face_recognition#face-recognitio ...

  6. Python的开源人脸识别库:离线识别率高达99.38%(附源码)

    Python的开源人脸识别库:离线识别率高达99.38%(附源码) 转https://cloud.tencent.com/developer/article/1359073   11.11 智慧上云 ...

  7. html5与EmguCV前后端实现——人脸识别篇(一)

    上个月因为出差的关系,断更了很久,为了补偿大家长久的等待,送上一个新的系列,之前几个系列也会抽空继续更新. 大概半年多前吧,因为工作需要,我开始研究图像识别技术.OpenCV在这方面已经有了很多技术积 ...

  8. facenet 人脸识别(二)——创建人脸库搭建人脸识别系统

    搭建人脸库 选择的方式是从百度下载明星照片 照片下载,downloadImageByBaidu.py # coding=utf-8 """ 爬取百度图片的高清原图 &qu ...

  9. opencv face-detection 代码分析 (1)人脸识别后的数据

    2014,3,16   老师的工作建议如下:   1. 与四民沟通下,把openCV这边的源代码和调用接口发给四民同时抄送给我. 2. 根据openCV的实时检测结果,实现对屏幕的调整(下周一前基本实 ...

随机推荐

  1. [LeetCode] 14. Longest Common Prefix 最长共同前缀

    Write a function to find the longest common prefix string amongst an array of strings. If there is n ...

  2. Salesforce 开发新工具 - Visual Studio Code

    最近尝试使用Visual Studio Code来做Salesforce的开发工具,体验上比Sublime好用不少,介绍下详细步骤 第一步:下载对应版本的Visual Studio Code 下载地址 ...

  3. div 中 id 和 class使用详解【转】

    原文地址:https://blog.csdn.net/zxw136511485/article/details/71191053 在div 标签中,我们比较常见的属性是id 和class,那么这两个属 ...

  4. android 自定义gridview(导航)

    最近又重新做回安卓,做了个小项目.下绝心使用android studio,通过这一回实战,终于用上了.综合了前人的经验,搞了个自己满意的导航界面,用的是gridview. 代码: package co ...

  5. boolean 属性的定义规范

    [强制]POJO类中的任何布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误.说明:在本文MySQL规约中的建表约定第一条,表达是与否的值采用is_xxx的命名方式,所以,需要在< ...

  6. K8S 如何实现将git代码下拉到指定的容器路径中

    gitRepo 是 kubernetes Volume类型中的一种,gitRepo volume可以实现将git代码下拉到指定的容器路径中. 备注:实现此功能,Pod运行的节点都必需要安装git.换句 ...

  7. 通过欧拉计划学Rust(第1~6题)

    最近想学习Libra数字货币的MOVE语言,发现它是用Rust编写的,看来想准确理解MOVE的机制,还需要对Rust有深刻的理解,所以开始了Rust的快速入门学习. 看了一下网上有关Rust的介绍,都 ...

  8. 【RS】Automatic recommendation technology for learning resources with convolutional neural network - 基于卷积神经网络的学习资源自动推荐技术

    [论文标题]Automatic recommendation technology for learning resources with convolutional neural network ( ...

  9. Appium+python自动化(五)- 模拟器(超详解)

    简介 Appium是做安卓自动化的一个比较流行的工具,对于想要学习该工具但是又局限于或许当前有些小伙伴没 android 手机来说,可以通过安卓模拟器来解决该问题,下面就讲解使用appium连接安卓模 ...

  10. Go语言-1-标识符与变量

    目录 1. Go标识符 1.1 Go关键字 1.2 常量标识符(4个) 1.3 空白标识符(1个) 1.4 内置数据类型标识符 1.5 内置函数(15个) 2. Go语言操作符 3. Go语言变量 3 ...