基于Python的OpenCV+TensorFlow+Keras人脸识别实现

素颜马尾好姑娘i 2022-12-03 15:46 435阅读 0赞

前言:本节要讲的人脸识别主要是借鉴了 一位研究生前辈的文章 我只是在他的基础上进行了改动,让代码能在现在的TensorFlow2.X 等的环境下运行
先看一下效果图
完整工程请点击链接下载:人脸识别工程
在这里插入图片描述

一、准备工作,安装环境

注意:下列Python第三方包的版本比较重要,应为在这里用到的包比较多,如果两个包版本相差较大可能会导致错误,接下来我列出我用的包名及其版本信息供你参考

  • Python – 3.8.4
  • TensorFlow-GPU – 2.3.0
  • OpenCV – 4.4.0
  • keras – 2.0.9
  • sklearn – 0.19.0
  • scipy – 1.4.1
  • PIL – 7.2.0

注:这里说明一下,TensorFlow的CPU版本和GPU版本没太大区别,用哪个都行,只不过在GPU上运行代码会更快一点

二、人脸检测

实现人脸识别简单程序没几行,但是我们要实现的是识别这个是谁的脸。首先我们让系统识别人脸,这是opencv的工作,我们只需要调用其中的API函数就可以了。下面是调用opencv实现对于人脸的识别。咱们在程序下面对程序进行一些解释:

  1. import cv2
  2. import sys
  3. from PIL import Image
  4. def CatchUsbVideo(window_name, camera_idx):
  5. cv2.namedWindow(window_name)
  6. #视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
  7. cap = cv2.VideoCapture(camera_idx)
  8. #告诉OpenCV使用人脸识别分类器
  9. classfier = cv2.CascadeClassifier("H:\\OpenCV\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_alt2.xml")
  10. #识别出人脸后要画的边框的颜色,RGB格式
  11. color = (0, 255, 0)
  12. while cap.isOpened():
  13. ok, frame = cap.read() #读取一帧数据
  14. if not ok:
  15. break
  16. #将当前帧转换成灰度图像
  17. grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  18. #人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
  19. faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
  20. if len(faceRects) > 0: #大于0则检测到人脸
  21. for faceRect in faceRects: #单独框出每一张人脸
  22. x, y, w, h = faceRect
  23. cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, 2)
  24. #显示图像
  25. cv2.imshow(window_name, frame)
  26. c = cv2.waitKey(10)
  27. if c & 0xFF == ord('q'):
  28. break
  29. #释放摄像头并销毁所有窗口
  30. cap.release()
  31. cv2.destroyAllWindows()
  32. if __name__ == '__main__':
  33. if len(sys.argv) != 1:
  34. print("Usage:%s camera_id\r\n" % (sys.argv[0]))
  35. else:
  36. CatchUsbVideo("识别人脸区域", 0)

说明:
1、 第一行import cv2,实际上,”cv2”中的”2”并不表示OpenCV的版本号。我们知道,OpenCV是基于C/C++的,”cv”和”cv2”表示的是底 层CAPI和C++API的区别,”cv2”表示使用的是C++API。这主要是一个历史遗留问题,对于这个代码更详细的介绍请参见我专门写的一篇文章:基于Python的OpenCV人脸检测
2、 D:\pyproject\renlianshibie\haarcascades\haarcascade_frontalface_alt2.xml, 这个地址是我存放OpenCV人脸特征数据集的地址,可以点击下载
人脸检测器(默认):haarcascade_frontalface_default.xml
人脸检测器(快速Harr):haarcascade_frontalface_alt2.xml
人脸检测器(侧视):haarcascade_profileface.xml
眼部检测器(左眼):haarcascade_lefteye_2splits.xml
眼部检测器(右眼):haarcascade_righteye_2splits.xml
嘴部检测器:haarcascade_mcs_mouth.xml
鼻子检测器:haarcascade_mcs_nose.xml
身体检测器:haarcascade_fullbody.xml
人脸检测器(快速LBP):lbpcascade_frontalface.xml
***另外,如果我们想构建自己的分类器,比如识别火焰、汽车,数,花等,我们依然可以使用OpenCV训练构建。
注:这是我整个工程的所有文件路径,提供你做参考
在这里插入图片描述

3、
在这里插入图片描述
这个函数完成对人脸的识别以及用一个框框给框起来,其中grey是要识别的图像数据,转化为灰度可以减少计算量。scaleFactor:图像缩放比例,可以理解为同一个物体与相机距离不同,其大小亦不同,必须将其缩放到一定大小才方便识别,该参数指定每次缩放的比例。minNeighbors:对特征检测点周边多少有效点同时检测,这样可避免因选取的特征检测点太小而导致遗漏。minSize:特征检测点的最小值。
4、 对同一个画面有可能出现多张人脸,因此,我们需要用一个for循环将所有检测到的人脸都读取出来,然后逐个用矩形框框出来,这就是接下来的for语句的作用。Opencv会给出每张人脸在图像中的起始坐标(左上角,x、y)以及长、宽(h、w),我们据此就可以截取出人脸。其中,cv2.rectangle()完成画框的工作,在这里外扩了10个像素以框出比人脸稍大一点的区域。cv2.rectangle()函数的最后两个参数一个用于指定矩形边框的颜色,一个用于指定矩形边框线条的粗细程度。

三、模型训练

模型训练的目的是让电脑知道,这个脸的特征是什么,从而可以在视频流中识别。在训练之前必须先准备足够的脸部照片作为机器学习的资料。
1.keras简介
利用深度学习库keras来训练自己的人脸识别模型。 我这里找到一篇keras的中文文档可能对你有些帮助。另外关于Keras, Keras是由纯python编写的基于theano/tensorflow的深度学习框架。Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需求,可以优先选择Keras:

  1. a)简易和快速的原型设计(keras具有高度模块化,极简,和可扩充特性)
  2. b)支持CNNRNN,或二者的结合
  3. c)无缝CPUGPU切换

Keras的模块结构:
在这里插入图片描述
使用Keras搭建一个神经网络:
在这里插入图片描述
数据格式(data_format):

  1. 目前主要有两种方式来表示张量:
  2. a) th模式或channels_first模式,Theanocaffe使用此模式。
  3. btf模式或channels_last模式,TensorFlow使用此模式。

因为我装的是tensorflow因此我直接使用了keras的Tensorflow版,同时,为了验证其它深度学习库的效率和准确率,我还使用了Theano,利用CNN——卷积神经网络来训练我的人脸识别模型。本节专注把训练数据准备好。

完整代码如下:

  1. import os
  2. import sys
  3. import numpy as np
  4. import cv2
  5. IMAGE_SIZE = 64
  6. #按照指定图像大小调整尺寸
  7. def resize_image(image, height = IMAGE_SIZE, width = IMAGE_SIZE):
  8. top, bottom, left, right = (0, 0, 0, 0)
  9. #获取图像尺寸
  10. h, w, _ = image.shape
  11. #对于长宽不相等的图片,找到最长的一边
  12. longest_edge = max(h, w)
  13. #计算短边需要增加多上像素宽度使其与长边等长
  14. if h < longest_edge:
  15. dh = longest_edge - h
  16. top = dh // 2
  17. bottom = dh - top
  18. elif w < longest_edge:
  19. dw = longest_edge - w
  20. left = dw // 2
  21. right = dw - left
  22. else:
  23. pass
  24. #RGB颜色
  25. BLACK = [0, 0, 0]
  26. #给图像增加边界,是图片长、宽等长,cv2.BORDER_CONSTANT指定边界颜色由value指定
  27. constant = cv2.copyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value = BLACK)
  28. #调整图像大小并返回
  29. return cv2.resize(constant, (height, width))
  30. #读取训练数据
  31. images = []
  32. labels = []
  33. def read_path(path_name):
  34. for dir_item in os.listdir(path_name):
  35. #从初始路径开始叠加,合并成可识别的操作路径
  36. full_path = os.path.abspath(os.path.join(path_name, dir_item))
  37. if os.path.isdir(full_path): #如果是文件夹,继续递归调用
  38. read_path(full_path)
  39. else: #文件
  40. if dir_item.endswith('.jpg'):
  41. image = cv2.imread(full_path)
  42. image = resize_image(image, IMAGE_SIZE, IMAGE_SIZE)
  43. #放开这个代码,可以看到resize_image()函数的实际调用效果
  44. #cv2.imwrite('1.jpg', image)
  45. images.append(image)
  46. labels.append(path_name)
  47. return images,labels
  48. #从指定路径读取训练数据
  49. def load_dataset(path_name):
  50. images,labels = read_path(path_name)
  51. #将输入的所有图片转成四维数组,尺寸为(图片数量*IMAGE_SIZE*IMAGE_SIZE*3)
  52. #我和闺女两个人共1200张图片,IMAGE_SIZE为64,故对我来说尺寸为1200 * 64 * 64 * 3
  53. #图片为64 * 64像素,一个像素3个颜色值(RGB)
  54. images = np.array(images)
  55. print(images.shape)
  56. #标注数据,'liziqiang'文件夹下都是我的脸部图像,全部指定为0,另外一个文件夹下是同学的,全部指定为1
  57. labels = np.array([0 if label.endswith('liziqiang') else 1 for label in labels])
  58. return images, labels
  59. if __name__ == '__main__':
  60. if len(sys.argv) != 1:
  61. print("Usage:%s path_name\r\n" % (sys.argv[0]))
  62. else:
  63. images, labels = load_dataset("D:\\pyproject\\renlianshibie\\kyq")

这段代码我们只是在前面代码的基础上增加脸部图像存储功能,比较简单。

  1. def CatchPICFromVideo(window_name, camera_idx, catch_pic_num, path_name):

在函数定义中,几个参数,反别是窗口名字,摄像头系列号,捕捉照片数量,以及存储路径。根据自己需要进行修改,咱们这里为了精度高一点,选择捕捉1000张脸部照片。在你捕捉的时候由于精度的问题,会捕捉许多非脸部的照片,这时候需要你将不是脸部的照片清洗掉,使数据更加准确。另外,我们还需要捕捉另一个人的图片来提高模型的准确度。然后存储到另一个文件夹下,注意,一个人的照片存储到一个文件夹下,不可弄混。截图完成,就像下图这样。
在这里插入图片描述
2.模型训练
训练程序建立了一个包含4个卷积层的神经网络(CNN),程序利用这个网络训练我的人脸识别模型,并将最终训练结果保存到硬盘上。在我们实际动手操练之前我们必须先弄明白一个问题——什么是卷积神经网络(CNN)?

想知道你可以谷歌,另外有关神经网络我会另外写一篇博客。这里就不多做介绍了。

首先建立一个python文件,命名load_data.py。代码如下:

  1. import os
  2. import sys
  3. import numpy as np
  4. import cv2
  5. IMAGE_SIZE = 64
  6. #按照指定图像大小调整尺寸
  7. def resize_image(image, height = IMAGE_SIZE, width = IMAGE_SIZE):
  8. top, bottom, left, right = (0, 0, 0, 0)
  9. #获取图像尺寸
  10. h, w, _ = image.shape
  11. #对于长宽不相等的图片,找到最长的一边
  12. longest_edge = max(h, w)
  13. #计算短边需要增加多上像素宽度使其与长边等长
  14. if h < longest_edge:
  15. dh = longest_edge - h
  16. top = dh // 2
  17. bottom = dh - top
  18. elif w < longest_edge:
  19. dw = longest_edge - w
  20. left = dw // 2
  21. right = dw - left
  22. else:
  23. pass
  24. #RGB颜色
  25. BLACK = [0, 0, 0]
  26. #给图像增加边界,是图片长、宽等长,cv2.BORDER_CONSTANT指定边界颜色由value指定
  27. constant = cv2.copyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value = BLACK)
  28. #调整图像大小并返回
  29. return cv2.resize(constant, (height, width))
  30. #读取训练数据
  31. images = []
  32. labels = []
  33. def read_path(path_name):
  34. for dir_item in os.listdir(path_name):
  35. #从初始路径开始叠加,合并成可识别的操作路径
  36. full_path = os.path.abspath(os.path.join(path_name, dir_item))
  37. if os.path.isdir(full_path): #如果是文件夹,继续递归调用
  38. read_path(full_path)
  39. else: #文件
  40. if dir_item.endswith('.jpg'):
  41. image = cv2.imread(full_path)
  42. image = resize_image(image, IMAGE_SIZE, IMAGE_SIZE)
  43. #放开这个代码,可以看到resize_image()函数的实际调用效果
  44. #cv2.imwrite('1.jpg', image)
  45. images.append(image)
  46. labels.append(path_name)
  47. return images,labels
  48. #从指定路径读取训练数据
  49. def load_dataset(path_name):
  50. images,labels = read_path(path_name)
  51. #将输入的所有图片转成四维数组,尺寸为(图片数量*IMAGE_SIZE*IMAGE_SIZE*3)
  52. #我和闺女两个人共1200张图片,IMAGE_SIZE为64,故对我来说尺寸为1200 * 64 * 64 * 3
  53. #图片为64 * 64像素,一个像素3个颜色值(RGB)
  54. images = np.array(images)
  55. print(images.shape)
  56. #标注数据,'liziqiang'文件夹下都是我的脸部图像,全部指定为0,另外一个文件夹下是同学的,全部指定为1
  57. labels = np.array([0 if label.endswith('liziqiang') else 1 for label in labels])
  58. return images, labels
  59. if __name__ == '__main__':
  60. if len(sys.argv) != 1:
  61. print("Usage:%s path_name\r\n" % (sys.argv[0]))
  62. else:
  63. images, labels = load_dataset("D:\\pyproject\\renlianshibie\\kyq")

稍微解释一下resize_image()函数。这个函数的功能是判断图片是不是正方形,如果不是则增加短边的长度使之变成正方形。这样再调用cv2.resize()函数就可以实现等比例缩放了。因为我们指定缩放的比例就是64 x 64,只有缩放之前图像为正方形才能确保图像不失真。
然后再新建一个python文件,命名为:face_train。添加如下代码。

  1. import random
  2. import numpy as np
  3. from sklearn.model_selection import train_test_split
  4. from keras.preprocessing.image import ImageDataGenerator
  5. from keras.models import Sequential
  6. from keras.layers import Dense, Dropout, Activation, Flatten
  7. from keras.layers import Convolution2D, MaxPooling2D
  8. from keras.optimizers import SGD
  9. from keras.utils import np_utils
  10. from keras.models import load_model
  11. from keras import backend as K
  12. from load_data import load_dataset, resize_image, IMAGE_SIZE
  13. class Dataset:
  14. def __init__(self, path_name):
  15. #训练集
  16. self.train_images = None
  17. self.train_labels = None
  18. #验证集
  19. self.valid_images = None
  20. self.valid_labels = None
  21. #测试集
  22. self.test_images = None
  23. self.test_labels = None
  24. #数据集加载路径
  25. self.path_name = path_name
  26. #当前库采用的维度顺序
  27. self.input_shape = None
  28. #加载数据集并按照交叉验证的原则划分数据集并进行相关预处理工作
  29. def load(self, img_rows = IMAGE_SIZE, img_cols = IMAGE_SIZE,
  30. img_channels = 3, nb_classes = 2):
  31. #加载数据集到内存
  32. images, labels = load_dataset(self.path_name)
  33. train_images, valid_images, train_labels, valid_labels = train_test_split(images, labels, test_size = 0.3, random_state = random.randint(0, 100))
  34. _, test_images, _, test_labels = train_test_split(images, labels, test_size = 0.5, random_state = random.randint(0, 100))
  35. #当前的维度顺序如果为'th',则输入图片数据时的顺序为:channels,rows,cols,否则:rows,cols,channels
  36. #这部分代码就是根据keras库要求的维度顺序重组训练数据集
  37. if K.image_data_format() == 'channels_first' :
  38. train_images = train_images.reshape(train_images.shape[0], img_channels, img_rows, img_cols)
  39. valid_images = valid_images.reshape(valid_images.shape[0], img_channels, img_rows, img_cols)
  40. test_images = test_images.reshape(test_images.shape[0], img_channels, img_rows, img_cols)
  41. self.input_shape = (img_channels, img_rows, img_cols)
  42. else:
  43. train_images = train_images.reshape(train_images.shape[0], img_rows, img_cols, img_channels)
  44. valid_images = valid_images.reshape(valid_images.shape[0], img_rows, img_cols, img_channels)
  45. test_images = test_images.reshape(test_images.shape[0], img_rows, img_cols, img_channels)
  46. self.input_shape = (img_rows, img_cols, img_channels)
  47. #输出训练集、验证集、测试集的数量
  48. print(train_images.shape[0], 'train samples')
  49. print(valid_images.shape[0], 'valid samples')
  50. print(test_images.shape[0], 'test samples')
  51. #我们的模型使用categorical_crossentropy作为损失函数,因此需要根据类别数量nb_classes将
  52. #类别标签进行one-hot编码使其向量化,在这里我们的类别只有两种,经过转化后标签数据变为二维
  53. train_labels = np_utils.to_categorical(train_labels, nb_classes)
  54. valid_labels = np_utils.to_categorical(valid_labels, nb_classes)
  55. test_labels = np_utils.to_categorical(test_labels, nb_classes)
  56. #像素数据浮点化以便归一化
  57. train_images = train_images.astype('float32')
  58. valid_images = valid_images.astype('float32')
  59. test_images = test_images.astype('float32')
  60. #将其归一化,图像的各像素值归一化到0~1区间
  61. train_images /= 255
  62. valid_images /= 255
  63. test_images /= 255
  64. self.train_images = train_images
  65. self.valid_images = valid_images
  66. self.test_images = test_images
  67. self.train_labels = train_labels
  68. self.valid_labels = valid_labels
  69. self.test_labels = test_labels
  70. #CNN网络模型类
  71. class Model:
  72. def __init__(self):
  73. self.model = None
  74. #建立模型
  75. def build_model(self, dataset, nb_classes = 2):
  76. #构建一个空的网络模型,它是一个线性堆叠模型,各神经网络层会被顺序添加,专业名称为序贯模型或线性堆叠模型
  77. self.model = Sequential()
  78. #以下代码将顺序添加CNN网络需要的各层,一个add就是一个网络层
  79. self.model.add(Convolution2D(32, 3, 3, border_mode='same',
  80. input_shape = dataset.input_shape)) #1 2维卷积层
  81. self.model.add(Activation('relu')) #2 激活函数层
  82. self.model.add(Convolution2D(32, 3, 3)) #3 2维卷积层
  83. self.model.add(Activation('relu')) #4 激活函数层
  84. self.model.add(MaxPooling2D(pool_size=(2, 2))) #5 池化层
  85. self.model.add(Dropout(0.25)) #6 Dropout层
  86. self.model.add(Convolution2D(64, 3, 3, border_mode='same')) #7 2维卷积层
  87. self.model.add(Activation('relu')) #8 激活函数层
  88. self.model.add(Convolution2D(64, 3, 3)) #9 2维卷积层
  89. self.model.add(Activation('relu')) #10 激活函数层
  90. self.model.add(MaxPooling2D(pool_size=(2, 2))) #11 池化层
  91. self.model.add(Dropout(0.25)) #12 Dropout层
  92. self.model.add(Flatten()) #13 Flatten层
  93. self.model.add(Dense(512)) #14 Dense层,又被称作全连接层
  94. self.model.add(Activation('relu')) #15 激活函数层
  95. self.model.add(Dropout(0.5)) #16 Dropout层
  96. self.model.add(Dense(nb_classes)) #17 Dense层
  97. self.model.add(Activation('softmax')) #18 分类层,输出最终结果
  98. #输出模型概况
  99. self.model.summary()
  100. #训练模型
  101. def train(self, dataset, batch_size = 20, nb_epoch = 10, data_augmentation = True):
  102. sgd = SGD(lr = 0.01, decay = 1e-6,
  103. momentum = 0.9, nesterov = True) #采用SGD+momentum的优化器进行训练,首先生成一个优化器对象
  104. self.model.compile(loss='categorical_crossentropy',
  105. optimizer=sgd,
  106. metrics=['accuracy']) #完成实际的模型配置工作
  107. #不使用数据提升,所谓的提升就是从我们提供的训练数据中利用旋转、翻转、加噪声等方法创造新的
  108. #训练数据,有意识的提升训练数据规模,增加模型训练量
  109. if not data_augmentation:
  110. self.model.fit(dataset.train_images,
  111. dataset.train_labels,
  112. batch_size = batch_size,
  113. nb_epoch = nb_epoch,
  114. validation_data = (dataset.valid_images, dataset.valid_labels),
  115. shuffle = True)
  116. #使用实时数据提升
  117. else:
  118. #定义数据生成器用于数据提升,其返回一个生成器对象datagen,datagen每被调用一
  119. #次其生成一组数据(顺序生成),节省内存,其实就是python的数据生成器
  120. datagen = ImageDataGenerator(
  121. featurewise_center = False, #是否使输入数据去中心化(均值为0),
  122. samplewise_center = False, #是否使输入数据的每个样本均值为0
  123. featurewise_std_normalization = False, #是否数据标准化(输入数据除以数据集的标准差)
  124. samplewise_std_normalization = False, #是否将每个样本数据除以自身的标准差
  125. zca_whitening = False, #是否对输入数据施以ZCA白化
  126. rotation_range = 20, #数据提升时图片随机转动的角度(范围为0~180)
  127. width_shift_range = 0.2, #数据提升时图片水平偏移的幅度(单位为图片宽度的占比,0~1之间的浮点数)
  128. height_shift_range = 0.2, #同上,只不过这里是垂直
  129. horizontal_flip = True, #是否进行随机水平翻转
  130. vertical_flip = False) #是否进行随机垂直翻转
  131. #计算整个训练样本集的数量以用于特征值归一化、ZCA白化等处理
  132. datagen.fit(dataset.train_images)
  133. #利用生成器开始训练模型
  134. self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels,
  135. batch_size = batch_size),
  136. samples_per_epoch = dataset.train_images.shape[0],
  137. nb_epoch = nb_epoch,
  138. validation_data = (dataset.valid_images, dataset.valid_labels))
  139. MODEL_PATH = './kyq.face.model.h5'
  140. def save_model(self, file_path = MODEL_PATH):
  141. self.model.save(file_path)
  142. def load_model(self, file_path = MODEL_PATH):
  143. self.model = load_model(file_path)
  144. def evaluate(self, dataset):
  145. score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose = 1)
  146. print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100))
  147. #识别人脸
  148. def face_predict(self, image):
  149. #依然是根据后端系统确定维度顺序
  150. if K.image_dim_ordering() == 'th' and image.shape != (1, 3, IMAGE_SIZE, IMAGE_SIZE):
  151. image = resize_image(image) #尺寸必须与训练集一致都应该是IMAGE_SIZE x IMAGE_SIZE
  152. image = image.reshape((1, 3, IMAGE_SIZE, IMAGE_SIZE)) #与模型训练不同,这次只是针对1张图片进行预测
  153. elif K.image_dim_ordering() == 'tf' and image.shape != (1, IMAGE_SIZE, IMAGE_SIZE, 3):
  154. image = resize_image(image)
  155. image = image.reshape((1, IMAGE_SIZE, IMAGE_SIZE, 3))
  156. #浮点并归一化
  157. image = image.astype('float32')
  158. image /= 255
  159. #给出输入属于各个类别的概率,我们是二值类别,则该函数会给出输入图像属于0和1的概率各为多少
  160. result = self.model.predict_proba(image)
  161. print('result:', result)
  162. #给出类别预测:0或者1
  163. result = self.model.predict_classes(image)
  164. #返回类别预测结果
  165. return result[0]
  166. if __name__ == '__main__':
  167. dataset = Dataset('./')
  168. dataset.load()
  169. model = Model()
  170. model.build_model(dataset)
  171. #先前添加的测试build_model()函数的代码
  172. model.build_model(dataset)
  173. #测试训练函数的代码
  174. model.train(dataset)
  175. if __name__ == '__main__':
  176. dataset = Dataset('./')
  177. dataset.load()
  178. model = Model()
  179. model.build_model(dataset)
  180. model.train(dataset)
  181. model.save_model(file_path = './model/kyq.face.model.h5')
  182. if __name__ == '__main__':
  183. dataset = Dataset('./')
  184. dataset.load()
  185. #评估模型
  186. model = Model()
  187. model.load_model(file_path = './model/kyq.face.model.h5')
  188. model.evaluate(dataset)

运行程序结果:在这里插入图片描述在这里插入图片描述

在这里插入图片描述
可以看到,最后我们对数据进行了验证,准确率达到了99.83%。结果较为理想,并且在model下面也得到了我i们的训练数据。
在这里插入图片描述

由此,我们最重要的训练数据也完成了,加下来就是验证我们训练数据的效果的时候了。
3、识别人脸

新建python文件,命名:Face_recognition。代码如下:

  1. #-*- coding: utf-8 -*-
  2. import cv2
  3. import sys
  4. import gc
  5. from face_train import Model
  6. if __name__ == '__main__':
  7. if len(sys.argv) != 1:
  8. print("Usage:%s camera_id\r\n" % (sys.argv[0]))
  9. sys.exit(0)
  10. #加载模型
  11. model = Model()
  12. model.load_model(file_path = './model/kyq.face.model.h5')
  13. #框住人脸的矩形边框颜色
  14. color = (0, 255, 0)
  15. #捕获指定摄像头的实时视频流
  16. cap = cv2.VideoCapture(0)
  17. #人脸识别分类器本地存储路径
  18. cascade_path = "D:\\pyproject\\renlianshibie\\haarcascades\\haarcascade_frontalface_alt2.xml"
  19. #循环检测识别人脸
  20. while True:
  21. ret, frame = cap.read() #读取一帧视频
  22. if ret is True:
  23. #图像灰化,降低计算复杂度
  24. frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  25. else:
  26. continue
  27. #使用人脸识别分类器,读入分类器
  28. cascade = cv2.CascadeClassifier(cascade_path)
  29. #利用分类器识别出哪个区域为人脸
  30. faceRects = cascade.detectMultiScale(frame_gray, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
  31. if len(faceRects) > 0:
  32. for faceRect in faceRects:
  33. x, y, w, h = faceRect
  34. #截取脸部图像提交给模型识别这是谁
  35. image = frame[y - 10: y + h + 10, x - 10: x + w + 10]
  36. faceID = model.face_predict(image)
  37. #如果是“我”
  38. if faceID == 1:
  39. cv2.rectangle(frame, (x - 10, y - 10), (x + w + 10, y + h + 10), color, thickness = 2)
  40. #文字提示是谁
  41. cv2.putText(frame,'kouyongqinag',
  42. (x - 15, y - 30), #坐标
  43. cv2.FONT_HERSHEY_SIMPLEX, #字体
  44. 1, #字号
  45. (255,0,255), #颜色
  46. 2) #字的线宽
  47. else:
  48. pass
  49. cv2.imshow("识别朕", frame)
  50. #等待10毫秒看是否有按键输入
  51. k = cv2.waitKey(10)
  52. #如果输入q则退出循环
  53. if k & 0xFF == ord('q'):
  54. break
  55. #释放摄像头并销毁所有窗口
  56. cap.release()
  57. cv2.destroyAllWindows()

最终实现的结果就是文章开头的时候的效果。希望能帮到你!

下面是一些关于这个项目的常见问题,我列出来了,也有解决方法,有需要的可以参考一下

1. 问题:

TensorFlow报错:AttributeError: module ‘tensorflow_core._api.v2.train’ has no attribute 'Optimizer‘
原因:
TensorFlow版本更新到2.0,Optimizer方法调用方式改变 。
将tf.train.Optimizer,更改为tf.optimizers.Optimizer即可。
解决连接:
https://blog.csdn.net/weixin_42720673/article/details/103066349

2. 问题

  1. AttributeError: module 'tensorflow' has no attribute 'get_default_graph'

解决办法:
使用tf.compat.v1.get_default_graph获取图而不是tf.get_default_graph。
链接:
https://blog.csdn.net/qq_37099552/article/details/102679366

3. 问题

AttributeError: module ‘tensorflow’ has no attribute ‘placeholder’等问题
原因:
查看tf版本。
我的是因为在tf2下使用了tf1的API。
解决方式:
使用

  1. import tensorflow.compat.v1 as tf
  2. tf.disable_v2_behavior()

替换

  1. import tensorflow as tf

链接:
https://blog.csdn.net/flowingfog/article/details/93597697

4. 问题

  1. ImportError: attempted relative import with no known parent package

原因:
出现这个错误的原因主要是由于使用了相对导入包的因素:
首先导入需要区分工作目录
首先可以通过os.getcwd()方法查看当前工作的目录是哪里
通常在python框架开发时候,发现,在项目目录外层嵌套一个工作目录,目录名称通常和工作目录一致。
如果使用解释器打开项目,过多一层或者过少一层打开目录都会导致导入错误,是因为解释器打开那个目录,就将python的工作目录设置那一层,只有上述结构才能实现下面的导入方法
. 和 …导入 相对位置是执行文件的当前目录
因为python的相对导入需要用到父级包作为相对的参考位置
而这个位置是通过__name__属性和__package__属性进行决定的,
当 name 等于 __main__和 package 等于 None的时候导致的问题没有父级包
在这种情况下,相对引用会认为这个模块就是顶级模块,而不管模块在文件系统上的实际位置

解决方法:

在目录下创建一个__init__.py文件转化为一个包
init
python 2是包的标志,只有拥有__init__文件的目录才会叫做包
python 3也是包的标志,但是不强制识别

python2和python3的__init__文件共有功能都是初始化包
链接:
https://blog.csdn.net/z_ipython/article/details/98772556

以上就是本文所有内容,希望能帮到大家!!!

发表评论

表情:
评论列表 (有 0 条评论,435人围观)

还没有评论,来说两句吧...

相关阅读

    相关 基于Python实现人脸识别相似度对比

    随着人工智能技术的不断进步,人脸识别成为了一种广泛应用的技术。人脸相似度对比是其中的一个重要应用场景,可以用于人脸搜索、身份验证等方面。本文将介绍如何使用Python实现...

    相关 基于OpenCV快速实现人脸识别

    以后打算多多关注计算机视觉这一块,涉猎广一些,对今后的毕设也有益处。 做一下人脸识别吧,之前看到一个博主写的一个demo,错误不少,经过修改以及查询资料,现在整理一下思路。