2022年 11月 6日

Python人脸识别考勤打卡系统

Python人脸识别考勤打卡系统

如需安装运行环境或远程调试,可加QQ905733049, 或QQ2945218359由专业技术人员远程协助!

运行结果如下:

 主要代码:

  1. import random
  2. import cv2
  3. import numpy
  4. import datetime
  5. import os
  6. import time
  7. import cv2 as cv
  8. import numpy as np
  9. import threading
  10. from PIL import Image, ImageFont, ImageDraw
  11. database_file_path = './resources/data.db'
  12. picture_dir_path = "./resources/pictures"
  13. trainer_file_path = './resources/Trainer/trainer.yml'
  14. font_file_path = './resources/simsun.ttc'
  15. zsc_circle_file_path = './resources/zsc.jpg'
  16. zsc_rectangle_file_path = './resources/zsc.png'
  17. haarcascade_frontalface_file_path = './resources/haarcascade_frontalface_default.xml'
  18. capture_opt = 0 # 摄像头参数,0,1为本机摄像头
  19. # 继承wx库里面的Frame类来使用
  20. class MainFrame(wx.Frame):
  21. def __init__(self):
  22. # 初始化窗体数据
  23. wx.Frame.__init__(self, None, -1, '人脸识别考勤系统', pos=(100, 100), size=(1337, 600))
  24. panel = wx.Panel(self, -1)
  25. sizer = wx.BoxSizer(wx.HORIZONTAL)
  26. sizer1 = wx.BoxSizer(wx.VERTICAL)
  27. sizer2 = wx.BoxSizer(wx.VERTICAL)
  28. font = wx.Font(15, wx.ROMAN, wx.NORMAL, wx.BOLD)
  29. # 设置窗口以及托盘图标
  30. icon = wx.Icon()
  31. icon.CopyFromBitmap(wx.Bitmap(wx.Image((zsc_circle_file_path), wx.BITMAP_TYPE_JPEG)))
  32. self.SetIcon(icon)
  33. # 设置左边背景学院logo
  34. image = wx.Image(zsc_rectangle_file_path, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
  35. self.background = wx.StaticBitmap(panel, -1, bitmap=image, style=wx.ALIGN_CENTER)
  36. sizer1.Add(self.background, proportion=10, flag=wx.ALIGN_CENTER, border=10)
  37. # 设置采集人脸按钮
  38. self.command1 = wx.Button(panel, -1, '采集人脸')
  39. self.command1.SetFont(font)
  40. self.command1.SetBackgroundColour('#3299CC')
  41. sizer1.Add(self.command1, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
  42. # 设置训练数据按钮
  43. self.command2 = wx.Button(panel, -1, '训练数据')
  44. self.command2.SetFont(font)
  45. self.command2.SetBackgroundColour('#DBDB70')
  46. sizer1.Add(self.command2, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
  47. # 设置人脸识别按钮
  48. self.command3 = wx.Button(panel, -1, '识别打卡')
  49. self.command3.SetFont(font)
  50. self.command3.SetBackgroundColour('#32CC32')
  51. sizer1.Add(self.command3, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
  52. # 设置退出系统按钮
  53. self.command4 = wx.Button(panel, -1, '关闭摄像头')
  54. self.command4.SetFont(font)
  55. self.command4.SetBackgroundColour((random.randint(1, 255), random.randint(0, 255), random.randint(0, 255)))
  56. sizer1.Add(self.command4, proportion=5, flag=wx.ALL | wx.EXPAND, border=10)
  57. # 设置消息提示文本
  58. self.text5 = wx.StaticText(panel, -1, '\n\n', style=wx.ALIGN_CENTER)
  59. self.text5.SetFont(font)
  60. self.text5.SetForegroundColour('Red')
  61. sizer1.Add(self.text5, proportion=15, flag=wx.ALL | wx.EXPAND, border=10)
  62. # 设置个人信息文本
  63. self.text6 = wx.StaticText(panel, -1, '姓名:')
  64. self.text7 = wx.StaticText(panel, -1, '学号:')
  65. self.text8 = wx.StaticText(panel, -1, '学院:')
  66. sizer1.Add(self.text6, proportion=3, flag=wx.LEFT, border=0)
  67. sizer1.Add(self.text7, proportion=3, flag=wx.LEFT, border=0)
  68. sizer1.Add(self.text8, proportion=3, flag=wx.LEFT, border=0)
  69. # 把分布局全部加入整体顶级布局
  70. sizer.Add(sizer1, flag=wx.EXPAND | wx.ALL, border=20)
  71. # 设置右上边消息提示文本
  72. sizer3 = wx.BoxSizer(wx.HORIZONTAL)
  73. font = wx.Font(12, wx.ROMAN, wx.NORMAL, wx.BOLD)
  74. self.text9 = wx.StaticText(panel, -1, '', style=wx.ALIGN_LEFT)
  75. self.text9.SetFont(font)
  76. self.text9.SetForegroundColour('brown')
  77. self.text9.SetLabel(u''+'您好,欢迎使用人脸考勤系统!')
  78. self.text10 = wx.StaticText(panel, -1, '', style=wx.ALIGN_RIGHT)
  79. self.text10.SetFont(font)
  80. self.text10.SetForegroundColour('Blue')
  81. self.data_num = 0
  82. self.updateSumData()
  83. sizer3.Add(self.text9, proportion=1, flag= wx.ALL|wx.EXPAND, border=10)
  84. sizer3.Add(self.text10, proportion=1, flag= wx.ALL|wx.EXPAND, border=10)
  85. sizer2.Add(sizer3, proportion=1, flag=wx.EXPAND | wx.ALL, border=0)
  86. # 封面图片
  87. self.image_cover = wx.Image(zsc_circle_file_path, wx.BITMAP_TYPE_ANY).Scale(575, 460)
  88. self.bmp = wx.StaticBitmap(panel, -1, wx.Bitmap(self.image_cover))
  89. sizer2.Add(self.bmp, proportion=1, flag=wx.ALL|wx.EXPAND ,border=0)
  90. # 加入顶级布局
  91. sizer.Add(sizer2, flag=wx.EXPAND | wx.ALL, border=10)
  92. # 实例化数据库操作对象
  93. self.mySqlDao = MySQLDao(self)
  94. self.grid = MyGrid(panel, self.mySqlDao)
  95. self.grid.updateGrid()
  96. # 打卡记录表
  97. sizer.Add(self.grid, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
  98. panel.SetSizer(sizer)
  99. # 四个按钮对应的事件
  100. self.command1.Bind(wx.EVT_BUTTON, self.command1_event)
  101. self.command4.Bind(wx.EVT_BUTTON, self.command4_event)
  102. self.command3.Bind(wx.EVT_BUTTON, self.command3_event)
  103. self.command2.Bind(wx.EVT_BUTTON, self.command2_event)
  104. # 关闭事件
  105. self.Bind(wx.EVT_CLOSE,self.onClose)
  106. # 窗口居中,显示
  107. self.Center()
  108. self.Show()
  109. # 控制摄像头的开启与关闭
  110. self.recognition = False
  111. self.collected = False
  112. '''
  113. 主窗体关闭事件
  114. '''
  115. def onClose(self,event):
  116. self.command4_event(event)
  117. # 等待子线程完成 再关闭,防止不正常退出
  118. time.sleep(1)
  119. self.Destroy()
  120. '''
  121. 采集数据按钮的响应事件
  122. '''
  123. def command1_event(self, event):
  124. self.text6.SetLabel('姓名:')
  125. self.text7.SetLabel('学号:')
  126. self.text8.SetLabel('学院:')
  127. self.text5.SetLabel(u'\n温馨提示:\n' + '⚪正在进学生信息录入...')
  128. self.text5.Update()
  129. collectFrame = CollectFrame(self,self.mySqlDao)
  130. collectFrame.Show()
  131. '''
  132. 训练数据按钮的响应事件
  133. '''
  134. def command2_event(self, event):
  135. self.trainData()
  136. '''
  137. 识别打卡按钮的响应事件
  138. '''
  139. def command3_event(self, event):
  140. self.text5.SetLabel(u'')
  141. self.recognition = False
  142. t1 = threading.Thread(target=self.recognitionFace)
  143. t1.start()
  144. '''
  145. 关闭摄像头按钮的响应事件
  146. '''
  147. def command4_event(self, event):
  148. if self.collected == False:
  149. self.collected = True
  150. if self.recognition == False:
  151. self.recognition = True
  152. def updateSumData(self):
  153. self.data_num = 0
  154. for list in os.listdir(picture_dir_path):
  155. if len(os.listdir(picture_dir_path + '/' + list)) >= 200:
  156. self.data_num += 1
  157. self.text10.SetLabel(u'当前已采集人脸数据的人数:' + str(self.data_num))
  158. self.text10.Update()
  159. '''
  160. @Author:Himit_ZH
  161. @Function:处理收集人脸每一帧生成图片存入对应文件夹
  162. '''
  163. def collect(self,face_id):
  164. self.text5.SetLabel(u'\n温馨提示:\n' + '请看向摄像头\n准备采集200张人脸图片...')
  165. count = 0 # 统计照片数量
  166. path = picture_dir_path+"/Stu_" + str(face_id) # 人脸图片数据的储存路径
  167. # 读取视频
  168. cap = cv.VideoCapture(capture_opt)
  169. print(cap.isOpened())
  170. if cap.isOpened() == False:
  171. self.text5.SetLabel(u'\n错误提示:\n' + '×采集人脸数据失败!\n原因:未能成功打开摄像头')
  172. return
  173. # 加载特征数据
  174. face_detector = cv.CascadeClassifier(haarcascade_frontalface_file_path)
  175. if not os.path.exists(path): # 如果没有对应文件夹,自动生成
  176. os.makedirs(path)
  177. while self.collected == False:
  178. flag, frame = cap.read()
  179. # print('flag:',flag,'frame.shape:',frame.shape)
  180. if not flag:
  181. break
  182. # 将图片灰度
  183. gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
  184. faces = face_detector.detectMultiScale(gray, 1.1, 3)
  185. if len(faces) > 1: # 一帧出现两张照片丢弃,原因:有人乱入,也有可能人脸识别出现差错
  186. continue
  187. # 框选人脸,for循环保证一个能检测的实时动态视频流
  188. for x, y, w, h in faces:
  189. cv.rectangle(frame, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=2)
  190. count += 1
  191. cv.imwrite(path + '/' + str(count) + '.png', gray[y:y + h, x:x + w])
  192. # # 显示图片
  193. # cv.imshow('Camera', frame)
  194. # 将一帧帧图片显示在UI中
  195. image1 = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  196. image2 = cv2.resize(image1, (575, 460))
  197. height, width = image2.shape[:2]
  198. pic = wx.Bitmap.FromBuffer(width, height, image2)
  199. # 显示图片在panel上
  200. self.bmp.SetBitmap(pic)
  201. self.bmp.Update()
  202. self.text9.SetLabel(u'温馨提示:\n' + '已采集'+ str(count)+'张人脸照片')
  203. if count >= 200: #默认采集200张照片
  204. break
  205. # 关闭资源
  206. if count >=200:
  207. self.text5.SetLabel(u'\n温馨提示:\n' + '✔已成功采集到人脸数据!')
  208. self.updateSumData()
  209. else:
  210. self.text5.SetLabel(u'\n错误提示:\n' + '×采集人脸数据失败!\n未能收集到200张人脸数据!')
  211. # 删除该文件夹下的所有数据
  212. ls = os.listdir(path)
  213. for file_path in ls:
  214. f_path = os.path.join(path, file_path)
  215. os.remove(f_path)
  216. os.rmdir(path)
  217. cv.destroyAllWindows()
  218. cap.release()
  219. self.bmp.SetBitmap(wx.Bitmap(self.image_cover))
  220. '''
  221. @Author:Himit_ZH
  222. @Function:遍历指定文件夹里面的人脸数据,根据文件夹名字,训练对应数据
  223. '''
  224. def trainData(self):
  225. self.text5.SetLabel(u'\n温馨提示:\n' + '⚪正在整合训练的人脸数据\n请稍后...')
  226. # 图片路径
  227. path = picture_dir_path
  228. facesSamples = []
  229. imageFiles = []
  230. ids = []
  231. for root, dirs, files in os.walk(path):
  232. # root 表示当前正在访问的文件夹路径
  233. # dirs 表示该文件夹下的子目录名list
  234. # files 表示该文件夹下的文件list
  235. # 遍历文件
  236. for file in files:
  237. imageFiles.append(os.path.join(root, file))
  238. # 检测人脸的模型数据
  239. face_detector = cv2.CascadeClassifier(haarcascade_frontalface_file_path)
  240. # 遍历列表中的图片
  241. stu_map = self.mySqlDao.getIdfromSql()
  242. for imagefile in imageFiles: # 获得所有文件名字
  243. imagefile = imagefile.replace('\\', '/')
  244. sno = imagefile.split('/')[3].split('_')[1]
  245. if stu_map.get(sno):
  246. PIL_img = Image.open(imagefile).convert('L') # 打开图片并且转为灰度图片
  247. # 将图像转换为数组
  248. img_numpy = np.array(PIL_img, 'uint8')
  249. faces = face_detector.detectMultiScale(img_numpy)
  250. for x, y, w, h in faces:
  251. facesSamples.append(img_numpy[y:y + h, x:x + w])
  252. ids.append(int(stu_map.get(sno)))
  253. if __name__ == '__main__':
  254. app = wx.App()
  255. app.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
  256. frame = MainFrame()
  257. app.MainLoop()

 运行结果如下:

 

Python, C++, PHP语言学习参考实例连接

C++学习参考实例

C++实现图形界面五子棋游戏源码:

https://blog.csdn.net/alicema1111/article/details/90035420

C++实现图形界面五子棋游戏源码2:

https://blog.csdn.net/alicema1111/article/details/106479579

C++ OpenCV相片视频人脸识别统计人数:

https://blog.csdn.net/alicema1111/article/details/105833928

VS2017+PCL开发环境配置:

https://blog.csdn.net/alicema1111/article/details/106877145

VS2017+Qt+PCL点云开发环境配置:

https://blog.csdn.net/alicema1111/article/details/105433636

C++ OpenCV汽车检测障碍物与测距:

https://blog.csdn.net/alicema1111/article/details/105833449

Windows VS2017安装配置PCL点云库:

https://blog.csdn.net/alicema1111/article/details/105111110

VS+VTK+Dicom(dcm)+CT影像切片窗体界面显示源码

https://blog.csdn.net/alicema1111/article/details/106994839

Python学习参考实例

Python相片更换背景颜色qt窗体程序:

https://blog.csdn.net/alicema1111/article/details/106919140

OpenCV汽车识别检测数量统计:

https://blog.csdn.net/alicema1111/article/details/106597260

OpenCV视频识别检测人数跟踪统计:

https://blog.csdn.net/alicema1111/article/details/106113042

OpenCV米粒检测数量统计:

https://blog.csdn.net/alicema1111/article/details/106089697

opencv人脸识别与变形哈哈镜:

https://blog.csdn.net/alicema1111/article/details/105833123

OpenCV人脸检测打卡系统:

https://blog.csdn.net/alicema1111/article/details/105315066

Python+OpenCV摄像头人脸识别:

https://blog.csdn.net/alicema1111/article/details/105107286

Python+Opencv识别视频统计人数:

https://blog.csdn.net/alicema1111/article/details/103804032

Python+OpenCV图像人脸识别人数统计

https://blog.csdn.net/alicema1111/article/details/105378639

python人脸头发身体部位识别人数统计

https://blog.csdn.net/alicema1111/article/details/116424942

VS+QT+VTK三维网格图像显示GUI

https://blog.csdn.net/alicema1111/article/details/117060734

PHP网页框架

PHP Laravel框架安装与配置后台管理前台页面显示:

https://blog.csdn.net/alicema1111/article/details/106686523