目录

案例引入

本节项目


最近有小伙伴们一直在催本项目的进度,好吧,今晚熬夜加班编写,在上一节中,实现了人脸数据的采集,在本节中将对采集的人脸数据进行训练,生成识别模型。

案例引入

首先简要讲解数据集训练生成模型的原理,这里使用的是LBPH算法,在OpenCV模块中已经有内嵌的方法cv2.face.LBPHFaceRecognizer_create(),为了方便小伙伴们读懂之后的代码,在这里先举一个简单的人脸模型训练的小案例。

第一步:采集人脸数据,网络上有许多案例Demo,不再赘述,代码如下:

  1. import cv2
  2. detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
  3. cap = cv2.VideoCapture(0)
  4. sampleNum = 0
  5. #输入人脸图像数据类别
  6. Id = input('enter your id: ')
  7. while True:
  8. ret, img = cap.read()
  9. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  10. faces = detector.detectMultiScale(gray, 1.3, 5)
  11. for (x, y, w, h) in faces:
  12. cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
  13. sampleNum = sampleNum + 1
  14. #命名规则为User.[ID].[SampleNumber].jpg
  15. #如果是2号人的第十张照片,我们可以将它命名为User.2.10.jpg
  16. cv2.imwrite("dataSet/User." + str(Id) + '.' + str(sampleNum) + ".jpg", gray[y:y + h, x:x + w]) #
  17. cv2.imshow('frame', img)
  18. if cv2.waitKey(1) & 0xFF == ord('q'):
  19. break
  20. elif sampleNum > 20:
  21. break
  22. cap.release()
  23. cv2.destroyAllWindows()

采集效果 如下:

第二步:使用OpenCV中LBPH算法的方法建立人脸数据模型,代码如下:

  1. import cv2
  2. import os
  3. import numpy as np
  4. from PIL import Image
  5. #初始化识别器和人脸检测器
  6. '''
  7. 如果face.LBPHFaceRecognizer_create或createLBPHFaceRecognizer显示不存在
  8. 则需要下载opencv-contrib-python pip install opencv-contrib-python
  9. '''
  10. # recognizer = cv2.createLBPHFaceRecognizer()
  11. detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
  12. recognizer = cv2.face.LBPHFaceRecognizer_create()
  13. '''
  14. 遍历图片路径,导入图片和id,添加到list
  15. '''
  16. def get_images_and_labels(path):
  17. image_paths = [os.path.join(path, f) for f in os.listdir(path)]
  18. face_samples = []
  19. ids = []
  20. for image_path in image_paths:
  21. #灰度图片
  22. image = Image.open(image_path).convert('L')
  23. #将图片转换成了Numpy数组
  24. image_np = np.array(image, 'uint8')
  25. #为了获取到id,我们将图片的路径分裂一下并获取相关信息
  26. if os.path.split(image_path)[-1].split(".")[-1] != 'jpg':
  27. continue
  28. image_id = int(os.path.split(image_path)[-1].split(".")[1])
  29. faces = detector.detectMultiScale(image_np)
  30. #将图片和id都添加在list中
  31. for (x, y, w, h) in faces:
  32. face_samples.append(image_np[y:y + h, x:x + w])
  33. ids.append(image_id)
  34. return face_samples, ids
  35. #让LBPH识别器去训练
  36. faces, Ids = get_images_and_labels('dataSet')
  37. recognizer.train(faces, np.array(Ids))
  38. recognizer.save('trainner.yml')

运行程序即可便捷快速生成模型文件“trainner.yml”, 打开模型文件,可以看到人脸数据信息,如下图所示:

本节项目

接下来看看本节训练人脸识别模型小案例吧,只不过是在上面代码的基础添加了图像预处理、数据库操作和GUI操作而已,导入第二节采集到的人脸数据,点击训练即可,当人脸数据类别较多时,可以使用数据库进行查询或者删除操作,效果如下:

确定无误后即可训练模型,效果如下:

训练仅需几秒即可,训练过程中程序会暂停响应,训练成功后就会生成所需模型,大功告成~

最后分享本节实现代码~

  1. #!/usr/bin/env python3
  2. # Author: winterssy <winterssy@foxmail.com>
  3. import cv2
  4. import numpy as np
  5. from PyQt5.QtCore import pyqtSignal
  6. from PyQt5.QtGui import QIcon, QTextCursor
  7. from PyQt5.QtWidgets import QApplication, QWidget, QMessageBox, QTableWidgetItem, QAbstractItemView
  8. from PyQt5.uic import loadUi
  9. import logging
  10. import logging.config
  11. import os
  12. import shutil
  13. import sqlite3
  14. import sys
  15. import threading
  16. import multiprocessing
  17. from datetime import datetime
  18. # 自定义数据库记录不存在异常
  19. class RecordNotFound(Exception):
  20. pass
  21. class DataManageUI(QWidget):
  22. logQueue = multiprocessing.Queue() # 日志队列
  23. receiveLogSignal = pyqtSignal(str) # 日志信号
  24. def __init__(self):
  25. super(DataManageUI, self).__init__()
  26. loadUi('./ui/DataManage.ui', self)
  27. self.setWindowIcon(QIcon('./icons/icon.png'))
  28. self.setFixedSize(931, 577)
  29. # 设置tableWidget只读,不允许修改
  30. self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
  31. # 数据库
  32. self.database = './FaceBase.db'
  33. self.datasets = './datasets'
  34. self.isDbReady = False
  35. self.initDbButton.clicked.connect(self.initDb)
  36. # 用户管理
  37. self.queryUserButton.clicked.connect(self.queryUser)
  38. self.deleteUserButton.clicked.connect(self.deleteUser)
  39. # 直方图均衡化
  40. self.isEqualizeHistEnabled = False
  41. self.equalizeHistCheckBox.stateChanged.connect(
  42. lambda: self.enableEqualizeHist(self.equalizeHistCheckBox))
  43. # 训练人脸数据
  44. self.trainButton.clicked.connect(self.train)
  45. # 系统日志
  46. self.receiveLogSignal.connect(lambda log: self.logOutput(log))
  47. self.logOutputThread = threading.Thread(target=self.receiveLog, daemon=True)
  48. self.logOutputThread.start()
  49. # 是否执行直方图均衡化
  50. def enableEqualizeHist(self, equalizeHistCheckBox):
  51. if equalizeHistCheckBox.isChecked():
  52. self.isEqualizeHistEnabled = True
  53. else:
  54. self.isEqualizeHistEnabled = False
  55. # 初始化/刷新数据库
  56. def initDb(self):
  57. # 刷新前重置tableWidget
  58. while self.tableWidget.rowCount() > 0:
  59. self.tableWidget.removeRow(0)
  60. try:
  61. if not os.path.isfile(self.database):
  62. raise FileNotFoundError
  63. conn = sqlite3.connect(self.database)
  64. cursor = conn.cursor()
  65. res = cursor.execute('SELECT * FROM users')
  66. for row_index, row_data in enumerate(res):
  67. self.tableWidget.insertRow(row_index)
  68. for col_index, col_data in enumerate(row_data):
  69. self.tableWidget.setItem(row_index, col_index, QTableWidgetItem(str(col_data)))
  70. cursor.execute('SELECT Count(*) FROM users')
  71. result = cursor.fetchone()
  72. dbUserCount = result[0]
  73. except FileNotFoundError:
  74. logging.error('系统找不到数据库文件{}'.format(self.database))
  75. self.isDbReady = False
  76. self.initDbButton.setIcon(QIcon('./icons/error.png'))
  77. self.logQueue.put('Error:未发现数据库文件,你可能未进行人脸采集')
  78. except Exception:
  79. logging.error('读取数据库异常,无法完成数据库初始化')
  80. self.isDbReady = False
  81. self.initDbButton.setIcon(QIcon('./icons/error.png'))
  82. self.logQueue.put('Error:读取数据库异常,初始化/刷新数据库失败')
  83. else:
  84. cursor.close()
  85. conn.close()
  86. self.dbUserCountLcdNum.display(dbUserCount)
  87. if not self.isDbReady:
  88. self.isDbReady = True
  89. self.logQueue.put('Success:数据库初始化完成,发现用户数:{}'.format(dbUserCount))
  90. self.initDbButton.setText('刷新数据库')
  91. self.initDbButton.setIcon(QIcon('./icons/success.png'))
  92. self.trainButton.setToolTip('')
  93. self.trainButton.setEnabled(True)
  94. self.queryUserButton.setToolTip('')
  95. self.queryUserButton.setEnabled(True)
  96. else:
  97. self.logQueue.put('Success:刷新数据库成功,发现用户数:{}'.format(dbUserCount))
  98. # 查询用户
  99. def queryUser(self):
  100. stu_id = self.queryUserLineEdit.text().strip()
  101. conn = sqlite3.connect(self.database)
  102. cursor = conn.cursor()
  103. try:
  104. cursor.execute('SELECT * FROM users WHERE stu_id=?', (stu_id,))
  105. ret = cursor.fetchall()
  106. if not ret:
  107. raise RecordNotFound
  108. face_id = ret[0][1]
  109. cn_name = ret[0][2]
  110. except RecordNotFound:
  111. self.queryUserButton.setIcon(QIcon('./icons/error.png'))
  112. self.queryResultLabel.setText('<font color=red>Error:此用户不存在</font>')
  113. except Exception as e:
  114. logging.error('读取数据库异常,无法查询到{}的用户信息'.format(stu_id))
  115. self.queryResultLabel.clear()
  116. self.queryUserButton.setIcon(QIcon('./icons/error.png'))
  117. self.logQueue.put('Error:读取数据库异常,查询失败')
  118. else:
  119. self.queryResultLabel.clear()
  120. self.queryUserButton.setIcon(QIcon('./icons/success.png'))
  121. self.stuIDLineEdit.setText(stu_id)
  122. self.cnNameLineEdit.setText(cn_name)
  123. self.faceIDLineEdit.setText(str(face_id))
  124. self.deleteUserButton.setEnabled(True)
  125. finally:
  126. cursor.close()
  127. conn.close()
  128. # 删除用户
  129. def deleteUser(self):
  130. text = '从数据库中删除该用户,同时删除相应人脸数据,<font color=red>该操作不可逆!</font>'
  131. informativeText = '<b>是否继续?</b>'
  132. ret = DataManageUI.callDialog(QMessageBox.Warning, text, informativeText, QMessageBox.Yes | QMessageBox.No,
  133. QMessageBox.No)
  134. if ret == QMessageBox.Yes:
  135. stu_id = self.stuIDLineEdit.text()
  136. conn = sqlite3.connect(self.database)
  137. cursor = conn.cursor()
  138. try:
  139. cursor.execute('DELETE FROM users WHERE stu_id=?', (stu_id,))
  140. except Exception as e:
  141. cursor.close()
  142. logging.error('无法从数据库中删除{}'.format(stu_id))
  143. self.deleteUserButton.setIcon(QIcon('./icons/error.png'))
  144. self.logQueue.put('Error:读写数据库异常,删除失败')
  145. else:
  146. cursor.close()
  147. conn.commit()
  148. if os.path.exists('{}/stu_{}'.format(self.datasets, stu_id)):
  149. try:
  150. shutil.rmtree('{}/stu_{}'.format(self.datasets, stu_id))
  151. except Exception as e:
  152. logging.error('系统无法删除删除{}/stu_{}'.format(self.datasets, stu_id))
  153. self.logQueue.put('Error:删除人脸数据失败,请手动删除{}/stu_{}目录'.format(self.datasets, stu_id))
  154. text = '你已成功删除学号为 <font color=blue>{}</font> 的用户记录。'.format(stu_id)
  155. informativeText = '<b>请在右侧菜单重新训练人脸数据。</b>'
  156. DataManageUI.callDialog(QMessageBox.Information, text, informativeText, QMessageBox.Ok)
  157. self.stuIDLineEdit.clear()
  158. self.cnNameLineEdit.clear()
  159. self.faceIDLineEdit.clear()
  160. self.initDb()
  161. self.deleteUserButton.setIcon(QIcon('./icons/success.png'))
  162. self.deleteUserButton.setEnabled(False)
  163. self.queryUserButton.setIcon(QIcon())
  164. finally:
  165. conn.close()
  166. # 检测人脸
  167. def detectFace(self, img):
  168. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  169. if self.isEqualizeHistEnabled:
  170. gray = cv2.equalizeHist(gray)
  171. face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')
  172. faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(90, 90))
  173. if (len(faces) == 0):
  174. return None, None
  175. (x, y, w, h) = faces[0]
  176. return gray[y:y + w, x:x + h], faces[0]
  177. # 准备图片数据
  178. def prepareTrainingData(self, data_folder_path):
  179. dirs = os.listdir(data_folder_path)
  180. faces = []
  181. labels = []
  182. face_id = 1
  183. conn = sqlite3.connect(self.database)
  184. cursor = conn.cursor()
  185. # 遍历人脸库
  186. for dir_name in dirs:
  187. if not dir_name.startswith('stu_'):
  188. continue
  189. stu_id = dir_name.replace('stu_', '')
  190. try:
  191. cursor.execute('SELECT * FROM users WHERE stu_id=?', (stu_id,))
  192. ret = cursor.fetchall()
  193. if not ret:
  194. raise RecordNotFound
  195. cursor.execute('UPDATE users SET face_id=? WHERE stu_id=?', (face_id, stu_id,))
  196. except RecordNotFound:
  197. logging.warning('数据库中找不到学号为{}的用户记录'.format(stu_id))
  198. self.logQueue.put('发现学号为{}的人脸数据,但数据库中找不到相应记录,已忽略'.format(stu_id))
  199. continue
  200. subject_dir_path = data_folder_path + '/' + dir_name
  201. subject_images_names = os.listdir(subject_dir_path)
  202. for image_name in subject_images_names:
  203. if image_name.startswith('.'):
  204. continue
  205. image_path = subject_dir_path + '/' + image_name
  206. image = cv2.imread(image_path)
  207. face, rect = self.detectFace(image)
  208. if face is not None:
  209. faces.append(face)
  210. labels.append(face_id)
  211. face_id = face_id + 1
  212. cursor.close()
  213. conn.commit()
  214. conn.close()
  215. return faces, labels
  216. # 训练人脸数据
  217. def train(self):
  218. try:
  219. if not os.path.isdir(self.datasets):
  220. raise FileNotFoundError
  221. text = '系统将开始训练人脸数据,界面会暂停响应一段时间,完成后会弹出提示。'
  222. informativeText = '<b>训练过程请勿进行其它操作,是否继续?</b>'
  223. ret = DataManageUI.callDialog(QMessageBox.Question, text, informativeText,
  224. QMessageBox.Yes | QMessageBox.No,
  225. QMessageBox.No)
  226. if ret == QMessageBox.Yes:
  227. face_recognizer = cv2.face.LBPHFaceRecognizer_create()
  228. if not os.path.exists('./recognizer'):
  229. os.makedirs('./recognizer')
  230. faces, labels = self.prepareTrainingData(self.datasets)
  231. face_recognizer.train(faces, np.array(labels))
  232. face_recognizer.save('./recognizer/trainingData.yml')
  233. except FileNotFoundError:
  234. logging.error('系统找不到人脸数据目录{}'.format(self.datasets))
  235. self.trainButton.setIcon(QIcon('./icons/error.png'))
  236. self.logQueue.put('未发现人脸数据目录{},你可能未进行人脸采集'.format(self.datasets))
  237. except Exception as e:
  238. logging.error('遍历人脸库出现异常,训练人脸数据失败')
  239. self.trainButton.setIcon(QIcon('./icons/error.png'))
  240. self.logQueue.put('Error:遍历人脸库出现异常,训练失败')
  241. else:
  242. text = '<font color=green><b>Success!</b></font> 系统已生成./recognizer/trainingData.yml'
  243. informativeText = '<b>人脸数据训练完成!</b>'
  244. DataManageUI.callDialog(QMessageBox.Information, text, informativeText, QMessageBox.Ok)
  245. self.trainButton.setIcon(QIcon('./icons/success.png'))
  246. self.logQueue.put('Success:人脸数据训练完成')
  247. self.initDb()
  248. # 系统日志服务常驻,接收并处理系统日志
  249. def receiveLog(self):
  250. while True:
  251. data = self.logQueue.get()
  252. if data:
  253. self.receiveLogSignal.emit(data)
  254. else:
  255. continue
  256. # LOG输出
  257. def logOutput(self, log):
  258. time = datetime.now().strftime('[%Y/%m/%d %H:%M:%S]')
  259. log = time + ' ' + log + '\n'
  260. self.logTextEdit.moveCursor(QTextCursor.End)
  261. self.logTextEdit.insertPlainText(log)
  262. self.logTextEdit.ensureCursorVisible() # 自动滚屏
  263. # 系统对话框
  264. @staticmethod
  265. def callDialog(icon, text, informativeText, standardButtons, defaultButton=None):
  266. msg = QMessageBox()
  267. msg.setWindowIcon(QIcon('./icons/icon.png'))
  268. msg.setWindowTitle('OpenCV Face Recognition System - DataManage')
  269. msg.setIcon(icon)
  270. msg.setText(text)
  271. msg.setInformativeText(informativeText)
  272. msg.setStandardButtons(standardButtons)
  273. if defaultButton:
  274. msg.setDefaultButton(defaultButton)
  275. return msg.exec()
  276. if __name__ == '__main__':
  277. logging.config.fileConfig('./config/logging.cfg')
  278. app = QApplication(sys.argv)
  279. window = DataManageUI()
  280. window.show()
  281. sys.exit(app.exec())

本项目资源下载地址:https://download.csdn.net/download/m0_38106923/11072010

Python+OpenCv实现AI人脸识别身份认证系统(1)——人脸识别原理:

https://blog.csdn.net/m0_38106923/article/details/86489773

Python+OpenCv实现AI人脸识别身份认证系统(3)——训练人脸识别模型相关推荐

  1. Python+OpenCV实现AI人脸识别身份认证系统(3)—训练人脸识别模型

    目录 案例引入 本节项目 最近有小伙伴们一直在催本项目的进度,好吧,今晚熬夜加班编写,在上一节中,实现了人脸数据的采集,在本节中将对采集的人脸数据进行训练,生成识别模型. 案例引入 首先简要讲解数据集 ...

  2. Python+OpenCv实现AI人脸识别身份认证系统(2)——人脸数据采集、存储

    原 Python+OpenCv实现AI人脸识别身份认证系统(2)--人脸数据采集.存储 2019年07月02日 08:47:52 不脱发的程序猿 阅读数 602更多 所属专栏: 人脸识别身份认证系统设 ...

  3. Python+OpenCV实现AI人脸识别身份认证系统(4)—人脸识别

    本篇博文是Python+OpenCV实现AI人脸识别身份认证系统的收官之作,在人脸识别原理到数据采集.存储和训练识别模型基础上,实现人脸识别,废话少说,上效果图: 案例引入 在Python+OpenC ...

  4. Python+OpenCv实现AI人脸识别身份认证系统(1)——人脸识别原理

    原 Python+OpenCv实现AI人脸识别身份认证系统(1)--人脸识别原理 置顶 2019年07月02日 08:47:40 不脱发的程序猿 阅读数 1255更多 所属专栏: 人脸识别身份认证系统 ...

  5. PyQt5 + Python3.7 + OpenCV人脸识别身份认证系统(附源码)

    基于PyQt5 + Python3.7 + OpenCV实现的人脸识别身份认证系统,附源码. 技术选型 PyQt5 + Python3.7 + OpenCV 功能概述 实现人员注册,信息修改,人脸识别 ...

  6. Python+OpenCV实现AI人脸识别身份认证系统(2)—人脸数据采集、存储

    目录 实现原理 实施步骤 实现程序 了解人脸检测.识别的原理后,让我们开始人脸识别系统的设计吧~ 首先展示下数据采集.存储的界面设计: 实现原理

  7. Python+OpenCV实现AI人脸识别身份认证系统(1)—人脸识别原理

    目录 人脸识别流程 第一步:人脸检测,找出所有的面孔 第二步:脸部的不同姿势

  8. Python+OpenCV人脸识别身份认证系统设计:专栏总述

    本专栏依托于Python编程语言,在内容上尽可能涵盖了人脸识别的各个技术模块,从人脸数据采集.数据预处理.数据分析.人脸识别模型的训练到最后的人脸识别,均有详细的操作步骤和注释代码,能帮助学习者从零开 ...

  9. Django的身份认证系统

    1 . 在Django中使用身份认证系统 Django的身份认证系统实际上是一个app,该app叫做django.contrib.auth,它在django contrib模块下 使用时只需要在set ...

最新文章

  1. 博士一次性最高给140万安家费!还享副教授待遇,这所高校为了引进人才!拼了...
  2. .NET 通用权限设计
  3. TabActivity 切换到后台遇到的问题
  4. JZOJ 4421. aplusb
  5. maven集成spring_Maven集成测试和Spring Restful Services
  6. server sql 众数_sql 语句系列(众数中位数与百分比)[八百章之第十五章]
  7. linux下安装mysql5.7方法与常见问题
  8. centos删除gnome_自定义你的 GNOME 桌面主题 | Linux 中国
  9. html5好看的大方框,这个样式导致HTML5的视频中的按钮变成一个方框。求解决…...
  10. linux下mysql允许远程连接
  11. PostgreSQL 10 新特性, 流式接收端在线压缩redo
  12. 从入门到狂热,特征工程必学的几项资源
  13. mysql数据库导出txt文件_mysql数据库导出表数据 为.txt文件
  14. i.MX6UL IO分析
  15. HTTP协议-get与post请求
  16. 编辑器生成静态网页_使用静态网站生成器的7个理由
  17. 写出HTML的基本结构 做简要说明,北京市顺义区2017年--2018年届高三二模语文试题(卷)与答案解析.doc...
  18. 木兰天池全新景观2013闪亮登场
  19. 「订单」业务的设计与实现
  20. 广州小学计算机教师待遇,给大家详细的分享一下广州市各区在编教师的待遇到底有多少?一个月的工资大概有多少,到底高不高?...

热门文章

  1. 苏格拉底与柏拉图麦穗的故事
  2. android适配和新文件及作用
  3. npm ERR! cb() never called! 解决办法
  4. 5G千兆网关助力重工业能耗监测系统
  5. Android模拟器模拟打电话,发短信
  6. ARCore⭐二、从零到放置物体
  7. 金融量化ushare模块
  8. Java file outside of soure root 导入项目时idea无法识别为java文件
  9. Spark2.X管理与开发
  10. 计算思维就是指计算机程序 即计算机的思维,[数学思维在计算机程序设计中的体现]计算机思维的本质是指...