├── IOT_FaceRecogition_Attendance
├── .idea
│ ├── .gitignore
│ ├── IOT人脸识别签到系统.iml
│ ├── inspectionProfiles
│ │ ├── Project_Default.xml
│ │ └── profiles_settings.xml
│ ├── misc.xml
│ └── modules.xml
├── Attendance.csv
├── IOT人脸识别签到系统测试版V0.99说明.md
├── Images
│ ├── EDC.png
│ ├── GodFather.png
│ └── JW.png
├── README.MD
├── icon.png
├── logo.png
├── mainwindow.py
├── mainwindow.spec
├── mainwindow.ui
├── mianwindow.spec
├── out_window.py
├── outputwindow.ui
├── resource.qrc
└── resource_rc.py
└── README.md
/IOT_FaceRecogition_Attendance/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/.idea/IOT人脸识别签到系统.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/Attendance.csv:
--------------------------------------------------------------------------------
1 | BIGBOSS,22/04/20 04:15:23,Clock In
2 | BIGBOSS,22/04/20 04:15:32,Clock Out
3 | BIGBOSS,22/04/20 04:21:42,Clock In
4 | BIGBOSS,22/04/20 04:21:51,Clock Out
5 |
6 | 人脸识别签到系统测试
7 |
8 | BIGBOSS,22/04/20 04:23:32,Clock In
9 | BIGBOSS,22/04/20 04:28:42,Clock Out
10 | BIGBOSS,22/04/20 05:24:35,Clock In
11 | BIGBOSS,22/04/20 05:24:39,Clock Out
12 | BIGBOSS,22/04/20 05:25:38,Clock In
13 | BIGBOSS,22/04/20 05:25:41,Clock Out
14 | BIGBOSS,22/04/20 05:26:00,Clock In
15 | BIGBOSS,22/04/20 05:26:06,Clock Out
16 |
17 | 人脸识别签到系统测试2:
18 |
19 | BIGBOSS,22/04/20 05:28:10,Clock In
20 | BIGBOSS,22/04/20 05:30:52,Clock Out
21 | BIGBOSS,22/04/21 00:51:12,Clock In
22 | BIGBOSS,22/04/21 00:51:16,Clock Out
23 | BIGBOSS,22/04/21 00:57:57,Clock In
24 | BIGBOSS,22/04/21 00:58:08,Clock Out
25 | BIGBOSS,22/04/21 00:59:25,Clock In
26 | BIGBOSS,22/04/21 01:01:38,Clock Out
27 |
28 | 测试3
29 |
30 | GODFATHER,22/04/21 01:42:23,Clock In
31 | GODFATHER,22/04/21 01:43:13,Clock Out
32 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/IOT人脸识别签到系统测试版V0.99说明.md:
--------------------------------------------------------------------------------
1 | # IOT人脸识别签到系统测试版V0.99
2 |
3 | ## 使用注意事项:
4 |
5 | ## 本项目集成项目运行所需的环境,并打包了EXE文件,直接运行mainwindow.exe文件即可
6 |
7 | ### 1.使用中如果报错:
8 |
9 | 
10 |
11 | **则是系统文件中face_recogition_models文件未识别到**
12 |
13 | 将**face-model**压缩包中的文件解压到**mainwindow文件夹**中,进行**替换**
14 |
15 | ### 2.mainwindow文件夹必须是父级目录!!!
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/Images/EDC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BIGBOSS-dedsec/Python-Face-recognition-Attendance/7c7987e9102047f54ba06ba11e232e5c00dcd9b8/IOT_FaceRecogition_Attendance/Images/EDC.png
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/Images/GodFather.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BIGBOSS-dedsec/Python-Face-recognition-Attendance/7c7987e9102047f54ba06ba11e232e5c00dcd9b8/IOT_FaceRecogition_Attendance/Images/GodFather.png
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/Images/JW.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BIGBOSS-dedsec/Python-Face-recognition-Attendance/7c7987e9102047f54ba06ba11e232e5c00dcd9b8/IOT_FaceRecogition_Attendance/Images/JW.png
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/README.MD:
--------------------------------------------------------------------------------
1 | # 前言
2 | 本项目为IOT实验室人员签到考勤设计,系统实现功能:
3 | **1.人员人脸识别并完成签到/签退
4 | 2.考勤时间计算
5 | 3.保存考勤数据为CSV格式(Excel表格)**
6 |
7 | *PS:本系统2D人脸识别,节约了繁琐的人脸识别训练部分,简洁快捷*
8 |
9 | **该项目为测试版,正式版会加入更多的功能,持续更新中.....**
10 | *测试版项目地址我会放到结尾*
11 | ## 项目效果图
12 | **系统初始化登陆界面**
13 | 
14 | **主界面展示图:**
15 | 
16 | **签到功能展示**
17 | 
18 | 
19 | **签退功能展示**
20 | 
21 | **后台签到数据记录**
22 | 
23 | **是否签到/退判断**
24 | 
25 | # 项目需要的环境
26 | *核心环境:*
27 | **OpenCV-Python 4.5.5.64**
28 | **face_recognition 1.30
29 | face_recognition_model 0.3.0
30 | dlib 19.23.1**
31 |
32 | *UI窗体界面:*
33 | **PyQt5 5.15.4
34 | pyqt5-plugins 5.15.4.2.2
35 | PyQt5-Qt5 5.15.2
36 | PyQt5-sip 12.10.1
37 | pyqt5-tools 5.15.4.3.2**
38 |
39 | ## 编译器
40 | **Pycham 2021.1.3**
41 | 
42 | **Python版本 3.9.12**
43 | 
44 | **Anaconda**
45 | 
46 | ### 辅助开发QT-designer
47 | 
48 | 
49 | #### 项目配置
50 | 
51 |
52 | # 代码部分
53 | ## 核心代码
54 | **MainWindow.py**
55 | *UI文件加载:*
56 | ```python
57 | class Ui_Dialog(QDialog):
58 | def __init__(self):
59 | super(Ui_Dialog, self).__init__()
60 | loadUi("mainwindow.ui", self) #加载QTUI文件
61 |
62 | self.runButton.clicked.connect(self.runSlot)
63 |
64 | self._new_window = None
65 | self.Videocapture_ = None
66 | ```
67 | *摄像头调用:*
68 |
69 | ```python
70 | def refreshAll(self):
71 | print("当前调用人俩检测摄像头编号(0为笔记本内置摄像头,1为USB外置摄像头):")
72 | self.Videocapture_ = "0"
73 | ```
74 | **OutWindow.py**
75 | *获取当前系统时间*
76 | ```python
77 | class Ui_OutputDialog(QDialog):
78 | def __init__(self):
79 | super(Ui_OutputDialog, self).__init__()
80 | loadUi("./outputwindow.ui", self) #加载输出窗体UI
81 |
82 | #datetime 时间模块
83 | now = QDate.currentDate()
84 | current_date = now.toString('ddd dd MMMM yyyy') #时间格式
85 | current_time = datetime.datetime.now().strftime("%I:%M %p")
86 | self.Date_Label.setText(current_date)
87 | self.Time_Label.setText(current_time)
88 |
89 | self.image = None
90 | ```
91 | *签到时间计算*
92 |
93 | ```python
94 | def ElapseList(self,name):
95 | with open('Attendance.csv', "r") as csv_file:
96 | csv_reader = csv.reader(csv_file, delimiter=',')
97 | line_count = 2
98 |
99 | Time1 = datetime.datetime.now()
100 | Time2 = datetime.datetime.now()
101 | for row in csv_reader:
102 | for field in row:
103 | if field in row:
104 | if field == 'Clock In':
105 | if row[0] == name:
106 | Time1 = (datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S'))
107 | self.TimeList1.append(Time1)
108 | if field == 'Clock Out':
109 | if row[0] == name:
110 | Time2 = (datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S'))
111 | self.TimeList2.append(Time2)
112 | ```
113 | *人脸识别部分*
114 |
115 | ```python
116 | # 人脸识别部分
117 | faces_cur_frame = face_recognition.face_locations(frame)
118 | encodes_cur_frame = face_recognition.face_encodings(frame, faces_cur_frame)
119 |
120 | for encodeFace, faceLoc in zip(encodes_cur_frame, faces_cur_frame):
121 | match = face_recognition.compare_faces(encode_list_known, encodeFace, tolerance=0.50)
122 | face_dis = face_recognition.face_distance(encode_list_known, encodeFace)
123 | name = "unknown" #未知人脸识别为unknown
124 | best_match_index = np.argmin(face_dis)
125 | if match[best_match_index]:
126 | name = class_names[best_match_index].upper()
127 | y1, x2, y2, x1 = faceLoc
128 | cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
129 | cv2.rectangle(frame, (x1, y2 - 20), (x2, y2), (0, 255, 0), cv2.FILLED)
130 | cv2.putText(frame, name, (x1 + 6, y2 - 6), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
131 | mark_attendance(name)
132 |
133 | return frame
134 | ```
135 | *签到数据保存与判断*
136 |
137 | ```python
138 | # csv表格保存数据
139 | def mark_attendance(name):
140 | """
141 | :param name: 人脸识别部分
142 | :return:
143 | """
144 | if self.ClockInButton.isChecked():
145 | self.ClockInButton.setEnabled(False)
146 | with open('Attendance.csv', 'a') as f:
147 | if (name != 'unknown'): #签到判断:是否为已经识别人脸
148 | buttonReply = QMessageBox.question(self, '欢迎 ' + name, '开始签到' ,
149 | QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
150 | if buttonReply == QMessageBox.Yes:
151 |
152 | date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
153 | f.writelines(f'\n{name},{date_time_string},Clock In')
154 | self.ClockInButton.setChecked(False)
155 |
156 | self.NameLabel.setText(name)
157 | self.StatusLabel.setText('签到')
158 | self.HoursLabel.setText('开始签到计时中')
159 | self.MinLabel.setText('')
160 |
161 | self.Time1 = datetime.datetime.now()
162 | self.ClockInButton.setEnabled(True)
163 | else:
164 | print('签到操作失败')
165 | self.ClockInButton.setEnabled(True)
166 | elif self.ClockOutButton.isChecked():
167 | self.ClockOutButton.setEnabled(False)
168 | with open('Attendance.csv', 'a') as f:
169 | if (name != 'unknown'):
170 | buttonReply = QMessageBox.question(self, '嗨呀 ' + name, '确认签退?',
171 | QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
172 | if buttonReply == QMessageBox.Yes:
173 | date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
174 | f.writelines(f'\n{name},{date_time_string},Clock Out')
175 | self.ClockOutButton.setChecked(False)
176 |
177 | self.NameLabel.setText(name)
178 | self.StatusLabel.setText('签退')
179 | self.Time2 = datetime.datetime.now()
180 |
181 | self.ElapseList(name)
182 | self.TimeList2.append(datetime.datetime.now())
183 | CheckInTime = self.TimeList1[-1]
184 | CheckOutTime = self.TimeList2[-1]
185 | self.ElapseHours = (CheckOutTime - CheckInTime)
186 | self.MinLabel.setText("{:.0f}".format(abs(self.ElapseHours.total_seconds() / 60)%60) + 'm')
187 | self.HoursLabel.setText("{:.0f}".format(abs(self.ElapseHours.total_seconds() / 60**2)) + 'h')
188 | self.ClockOutButton.setEnabled(True)
189 | else:
190 | print('签退操作失败')
191 | self.ClockOutButton.setEnabled(True)
192 | ```
193 |
194 | ### 项目目录结构
195 | 
196 | # 后记
197 | ***因为本系统没有进行人脸训练建立模型,系统误识别率较高,安全性较低
198 | 系统优化较差,摄像头捕捉帧数较低(8-9),后台占有高,CPU利用率较高
199 | 数据保存CSV格式,安全性较低***
200 | ## 正式版改进
201 | **1.加入TensorFlow深度学习,提高系统人脸识别安全性与准确性
202 | 2.加入MySQL数据库,对签到数据进行更安全保护,不易被修改
203 | 3.美化优化UI设计**
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BIGBOSS-dedsec/Python-Face-recognition-Attendance/7c7987e9102047f54ba06ba11e232e5c00dcd9b8/IOT_FaceRecogition_Attendance/icon.png
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BIGBOSS-dedsec/Python-Face-recognition-Attendance/7c7987e9102047f54ba06ba11e232e5c00dcd9b8/IOT_FaceRecogition_Attendance/logo.png
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/mainwindow.py:
--------------------------------------------------------------------------------
1 | # Author BIGBOSS
2 | # April 2022
3 | # IOT人脸识别签到系统
4 | # WX:BIGBOSSyifi
5 | # Mail:bigbossyifi@gmail.com
6 | # *-
7 |
8 | import sys
9 | from PyQt5.uic import loadUi
10 | from PyQt5 import QtWidgets
11 | from PyQt5.QtCore import pyqtSlot
12 | from PyQt5.QtWidgets import QApplication, QDialog
13 | import resource_rc #加载资源文件
14 | # from model import Model
15 | from out_window import Ui_OutputDialog
16 |
17 |
18 | class Ui_Dialog(QDialog):
19 | def __init__(self):
20 | super(Ui_Dialog, self).__init__()
21 | loadUi("mainwindow.ui", self) #加载QTUI文件
22 |
23 | self.runButton.clicked.connect(self.runSlot)
24 |
25 | self._new_window = None
26 | self.Videocapture_ = None
27 |
28 | def refreshAll(self):
29 | print("当前调用人俩检测摄像头编号(0为笔记本内置摄像头,1为USB外置摄像头):")
30 | self.Videocapture_ = "0"
31 |
32 | @pyqtSlot()
33 | def runSlot(self):
34 | print("IOT人脸识别签到系统运行中...")
35 | self.refreshAll()
36 | print(self.Videocapture_)
37 | ui.hide() # UI隐藏
38 | self.outputWindow_() # 创建新的窗体
39 |
40 | def outputWindow_(self):
41 | """
42 | 在GUI中创建人脸识别区域的窗体
43 | """
44 | self._new_window = Ui_OutputDialog()
45 | self._new_window.show()
46 | self._new_window.startVideo(self.Videocapture_)
47 | print("人脸识别功能初始化中....")
48 | print("人脸识别功能初始化完成!")
49 |
50 |
51 | if __name__ == "__main__":
52 | app = QApplication(sys.argv)
53 | ui = Ui_Dialog()
54 | ui.show()
55 | sys.exit(app.exec_())
56 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/mainwindow.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 |
4 | block_cipher = None
5 |
6 |
7 | a = Analysis(
8 | ['mainwindow.py'],
9 | pathex=[],
10 | binaries=[],
11 | datas=[],
12 | hiddenimports=[],
13 | hookspath=[],
14 | hooksconfig={},
15 | runtime_hooks=[],
16 | excludes=[],
17 | win_no_prefer_redirects=False,
18 | win_private_assemblies=False,
19 | cipher=block_cipher,
20 | noarchive=False,
21 | )
22 | pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
23 |
24 | exe = EXE(
25 | pyz,
26 | a.scripts,
27 | a.binaries,
28 | a.zipfiles,
29 | a.datas,
30 | [],
31 | name='mainwindow',
32 | debug=False,
33 | bootloader_ignore_signals=False,
34 | strip=False,
35 | upx=True,
36 | upx_exclude=[],
37 | runtime_tmpdir=None,
38 | console=False,
39 | disable_windowed_traceback=False,
40 | argv_emulation=False,
41 | target_arch=None,
42 | codesign_identity=None,
43 | entitlements_file=None,
44 | )
45 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 |
15 | 800
16 | 600
17 |
18 |
19 |
20 |
21 | 800
22 | 600
23 |
24 |
25 |
26 | IOT人脸识别签到考勤系统-测试版V0.99
27 |
28 |
29 |
30 | :/icon/icon.png:/icon/icon.png
31 |
32 |
33 |
34 |
35 | 0
36 | 500
37 | 801
38 | 101
39 |
40 |
41 |
42 | -
43 |
44 |
45 |
46 | 800
47 | 600
48 |
49 |
50 |
51 |
52 | 黑体
53 | 30
54 |
55 |
56 |
57 | IOT来电
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | 0
67 | 0
68 | 886
69 | 425
70 |
71 |
72 |
73 | -
74 |
75 |
76 |
77 | 884
78 | 432
79 |
80 |
81 |
82 |
83 |
84 |
85 | :/logo/logo.png
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | 230
95 | 440
96 | 331
97 | 61
98 |
99 |
100 |
101 |
102 | 600
103 | 800
104 |
105 |
106 |
107 |
108 | Roboto Condensed
109 | 14
110 | 75
111 | true
112 |
113 |
114 |
115 | IOT人脸识别签到系统—测试版V0.98
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/mianwindow.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 |
4 | block_cipher = None
5 |
6 |
7 | a = Analysis(
8 | ['mianwindow.py'],
9 | pathex=[],
10 | binaries=[],
11 | datas=[],
12 | hiddenimports=[],
13 | hookspath=[],
14 | hooksconfig={},
15 | runtime_hooks=[],
16 | excludes=[],
17 | win_no_prefer_redirects=False,
18 | win_private_assemblies=False,
19 | cipher=block_cipher,
20 | noarchive=False,
21 | )
22 | pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
23 |
24 | exe = EXE(
25 | pyz,
26 | a.scripts,
27 | a.binaries,
28 | a.zipfiles,
29 | a.datas,
30 | [],
31 | name='mianwindow',
32 | debug=False,
33 | bootloader_ignore_signals=False,
34 | strip=False,
35 | upx=True,
36 | upx_exclude=[],
37 | runtime_tmpdir=None,
38 | console=False,
39 | disable_windowed_traceback=False,
40 | argv_emulation=False,
41 | target_arch=None,
42 | codesign_identity=None,
43 | entitlements_file=None,
44 | )
45 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/out_window.py:
--------------------------------------------------------------------------------
1 | # Author BIGBOSS
2 | # April 2022
3 | # IOT人脸识别签到系统
4 | # WX:BIGBOSSyifi
5 | # Mail:bigbossyifi@gmail.com
6 | # *-
7 |
8 | from PyQt5.QtGui import QImage, QPixmap
9 | from PyQt5.uic import loadUi
10 | from PyQt5.QtCore import pyqtSlot, QTimer, QDate, Qt
11 | from PyQt5.QtWidgets import QDialog,QMessageBox
12 | import cv2
13 | import face_recognition
14 | import numpy as np
15 | import datetime
16 | import os
17 | import csv
18 |
19 | class Ui_OutputDialog(QDialog):
20 | def __init__(self):
21 | super(Ui_OutputDialog, self).__init__()
22 | loadUi("./outputwindow.ui", self) #加载输出窗体UI
23 |
24 | #datetime 时间模块
25 | now = QDate.currentDate()
26 | current_date = now.toString('ddd dd MMMM yyyy') #时间格式
27 | current_time = datetime.datetime.now().strftime("%I:%M %p")
28 | self.Date_Label.setText(current_date)
29 | self.Time_Label.setText(current_time)
30 |
31 | self.image = None
32 |
33 | @pyqtSlot()
34 | def startVideo(self, camera_name):
35 | """
36 | :param camera_name: 摄像头或usb摄像头的链接
37 | :return:
38 | """
39 | if len(camera_name) == 1:
40 | self.capture = cv2.VideoCapture(int(camera_name))
41 | else:
42 | self.capture = cv2.VideoCapture(camera_name)
43 | self.timer = QTimer(self) # 创建 Timer
44 | path = 'Images' #读取人脸识别图片的路径
45 | if not os.path.exists(path):
46 | os.mkdir(path)
47 | # 路径下人脸编码和人脸名称列表
48 | images = []
49 | self.class_names = []
50 | self.encode_list = []
51 | self.TimeList1 = []
52 | self.TimeList2 = []
53 | attendance_list = os.listdir(path)
54 |
55 | for cl in attendance_list:
56 | cur_img = cv2.imread(f'{path}/{cl}')
57 | images.append(cur_img)
58 | self.class_names.append(os.path.splitext(cl)[0])
59 | for img in images:
60 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
61 | boxes = face_recognition.face_locations(img)
62 | encodes_cur_frame = face_recognition.face_encodings(img, boxes)[0]
63 | self.encode_list.append(encodes_cur_frame)
64 | self.timer.timeout.connect(self.update_frame) # 超时连接输出
65 | self.timer.start(10)
66 |
67 | def face_rec_(self, frame, encode_list_known, class_names):
68 | """
69 | :param frame: 摄像头捕捉
70 | :param encode_list_known: 已录入的人脸编码
71 | :param class_names: 已录入的人脸姓名
72 | :return:
73 | """
74 | # csv表格保存数据
75 | def mark_attendance(name):
76 | """
77 | :param name: 人脸识别部分
78 | :return:
79 | """
80 | if self.ClockInButton.isChecked():
81 | self.ClockInButton.setEnabled(False)
82 | with open('Attendance.csv', 'a') as f:
83 | if (name != 'unknown'): #签到判断:是否为已经识别人脸
84 | buttonReply = QMessageBox.question(self, '欢迎 ' + name, '开始签到' ,
85 | QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
86 | if buttonReply == QMessageBox.Yes:
87 |
88 | date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
89 | f.writelines(f'\n{name},{date_time_string},Clock In')
90 | self.ClockInButton.setChecked(False)
91 |
92 | self.NameLabel.setText(name)
93 | self.StatusLabel.setText('签到')
94 | self.HoursLabel.setText('开始签到计时中')
95 | self.MinLabel.setText('')
96 |
97 | self.Time1 = datetime.datetime.now()
98 | self.ClockInButton.setEnabled(True)
99 | else:
100 | print('签到操作失败')
101 | self.ClockInButton.setEnabled(True)
102 | elif self.ClockOutButton.isChecked():
103 | self.ClockOutButton.setEnabled(False)
104 | with open('Attendance.csv', 'a') as f:
105 | if (name != 'unknown'):
106 | buttonReply = QMessageBox.question(self, '嗨呀 ' + name, '确认签退?',
107 | QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
108 | if buttonReply == QMessageBox.Yes:
109 | date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
110 | f.writelines(f'\n{name},{date_time_string},Clock Out')
111 | self.ClockOutButton.setChecked(False)
112 |
113 | self.NameLabel.setText(name)
114 | self.StatusLabel.setText('签退')
115 | self.Time2 = datetime.datetime.now()
116 |
117 | self.ElapseList(name)
118 | self.TimeList2.append(datetime.datetime.now())
119 | CheckInTime = self.TimeList1[-1]
120 | CheckOutTime = self.TimeList2[-1]
121 | self.ElapseHours = (CheckOutTime - CheckInTime)
122 | self.MinLabel.setText("{:.0f}".format(abs(self.ElapseHours.total_seconds() / 60)%60) + 'm')
123 | self.HoursLabel.setText("{:.0f}".format(abs(self.ElapseHours.total_seconds() / 60**2)) + 'h')
124 | self.ClockOutButton.setEnabled(True)
125 | else:
126 | print('签退操作失败')
127 | self.ClockOutButton.setEnabled(True)
128 |
129 | # 人脸识别部分
130 | faces_cur_frame = face_recognition.face_locations(frame)
131 | encodes_cur_frame = face_recognition.face_encodings(frame, faces_cur_frame)
132 |
133 | for encodeFace, faceLoc in zip(encodes_cur_frame, faces_cur_frame):
134 | match = face_recognition.compare_faces(encode_list_known, encodeFace, tolerance=0.50)
135 | face_dis = face_recognition.face_distance(encode_list_known, encodeFace)
136 | name = "unknown" #未知人脸识别为unknown
137 | best_match_index = np.argmin(face_dis)
138 | if match[best_match_index]:
139 | name = class_names[best_match_index].upper()
140 | y1, x2, y2, x1 = faceLoc
141 | cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
142 | cv2.rectangle(frame, (x1, y2 - 20), (x2, y2), (0, 255, 0), cv2.FILLED)
143 | cv2.putText(frame, name, (x1 + 6, y2 - 6), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
144 | mark_attendance(name)
145 |
146 | return frame
147 |
148 | def showdialog(self):
149 | msg = QMessageBox()
150 | msg.setIcon(QMessageBox.Information)
151 |
152 | msg.setText("提示")
153 | msg.setInformativeText("消息附加")
154 | msg.setWindowTitle("消息提示")
155 | msg.setDetailedText("内容如下:")
156 | msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
157 |
158 |
159 | def ElapseList(self,name):
160 | with open('Attendance.csv', "r") as csv_file:
161 | csv_reader = csv.reader(csv_file, delimiter=',')
162 | line_count = 2
163 |
164 | Time1 = datetime.datetime.now()
165 | Time2 = datetime.datetime.now()
166 | for row in csv_reader:
167 | for field in row:
168 | if field in row:
169 | if field == 'Clock In':
170 | if row[0] == name:
171 | Time1 = (datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S'))
172 | self.TimeList1.append(Time1)
173 | if field == 'Clock Out':
174 | if row[0] == name:
175 | Time2 = (datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S'))
176 | self.TimeList2.append(Time2)
177 |
178 | def update_frame(self):
179 | ret, self.image = self.capture.read()
180 | self.displayImage(self.image, self.encode_list, self.class_names, 1)
181 |
182 | def displayImage(self, image, encode_list, class_names, window=1):
183 | """
184 | :param image: 从摄像头捕捉的图像
185 | :param encode_list: 已识别人脸识别编码
186 | :param class_names: 已识别人脸人员姓名
187 | :param window: 窗体
188 | :return:
189 | """
190 | image = cv2.resize(image, (640, 480)) #定义识别区域大小
191 | try:
192 | image = self.face_rec_(image, encode_list, class_names)
193 | except Exception as e:
194 | print(e)
195 | qformat = QImage.Format_Indexed8
196 | if len(image.shape) == 3:
197 | if image.shape[2] == 4:
198 | qformat = QImage.Format_RGBA8888
199 | else:
200 | qformat = QImage.Format_RGB888
201 | outImage = QImage(image, image.shape[1], image.shape[0], image.strides[0], qformat)
202 | outImage = outImage.rgbSwapped()
203 |
204 | if window == 1:
205 | self.imgLabel.setPixmap(QPixmap.fromImage(outImage))
206 | self.imgLabel.setScaledContents(True)
207 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/outputwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | OutputDialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 951
10 | 591
11 |
12 |
13 |
14 |
15 | 0
16 | 0
17 |
18 |
19 |
20 |
21 | 1280
22 | 720
23 |
24 |
25 |
26 |
27 | Calibri
28 | 75
29 | true
30 |
31 |
32 |
33 | IOT人脸识别签到系统测试版V0.99
34 |
35 |
36 |
37 | :/icon/icon.png:/icon/icon.png
38 |
39 |
40 |
41 |
42 | 10
43 | 10
44 | 640
45 | 480
46 |
47 |
48 |
49 |
50 | 4
51 | 0
52 |
53 |
54 |
55 |
56 | 640
57 | 480
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 10
68 | 500
69 | 641
70 | 80
71 |
72 |
73 |
74 | -
75 |
76 |
77 |
78 | 400
79 | 600
80 |
81 |
82 |
83 |
84 | Roboto Condensed Light
85 | 30
86 | 75
87 | true
88 |
89 |
90 |
91 | 签到
92 |
93 |
94 | true
95 |
96 |
97 | 100
98 |
99 |
100 |
101 | -
102 |
103 |
104 |
105 | 400
106 | 600
107 |
108 |
109 |
110 |
111 | Roboto Condensed Light
112 | 30
113 | 75
114 | true
115 |
116 |
117 |
118 | 签退
119 |
120 |
121 | true
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | 660
131 | 40
132 | 281
133 | 121
134 |
135 |
136 |
137 | -
138 |
139 |
140 |
141 | Roboto Condensed Light
142 | 15
143 | 75
144 | true
145 |
146 |
147 |
148 | -
149 |
150 |
151 |
152 | -
153 |
154 |
155 |
156 | Roboto Condensed Light
157 | 15
158 | 75
159 | true
160 |
161 |
162 |
163 | -
164 |
165 |
166 |
167 | -
168 |
169 |
170 |
171 | Roboto Condensed Light
172 | 16
173 | 75
174 | true
175 |
176 |
177 |
178 | 日期 :
179 |
180 |
181 |
182 | -
183 |
184 |
185 |
186 | Roboto Condensed Light
187 | 16
188 | 75
189 | true
190 |
191 |
192 |
193 | 时间 :
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | 660
203 | 200
204 | 271
205 | 291
206 |
207 |
208 |
209 | 签到详细
210 |
211 |
212 |
213 |
214 | 30
215 | 30
216 | 110
217 | 211
218 |
219 |
220 |
221 | -
222 |
223 |
224 |
225 | Roboto Condensed Light
226 | 12
227 | 50
228 | false
229 |
230 |
231 |
232 | 姓名 :
233 |
234 |
235 |
236 | -
237 |
238 |
239 |
240 | Roboto Condensed Light
241 | 12
242 | 50
243 | false
244 |
245 |
246 |
247 | 状态 :
248 |
249 |
250 |
251 | -
252 |
253 |
254 |
255 | Roboto Condensed Light
256 | 12
257 | 50
258 | false
259 |
260 |
261 |
262 | 时间 :
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 | 120
272 | 30
273 | 131
274 | 211
275 |
276 |
277 |
278 | -
279 |
280 |
281 |
282 | Roboto Condensed Light
283 | 12
284 | 50
285 | false
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 | -
294 |
295 |
296 |
297 | Roboto Condensed Light
298 | 12
299 | 50
300 | false
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 | -
309 |
310 |
-
311 |
312 |
313 |
314 | Roboto Condensed Light
315 | 12
316 | 50
317 | false
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 | -
326 |
327 |
328 |
329 | Roboto Condensed Light
330 | 12
331 | 50
332 | false
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
--------------------------------------------------------------------------------
/IOT_FaceRecogition_Attendance/resource.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | logo.png
4 |
5 |
6 | icon.png
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | This project is designed for IOT laboratory personnel check-in and attendance, and the system implements the following functions:
4 | **1. Personnel face recognition and complete check-in/check-out
5 | 2. Calculation of attendance time
6 | 3. Save the attendance data in CSV format (Excel) **
7 |
8 | PS: This system 2D face recognition, saving the tedious face recognition training part, simple and fast
9 |
10 | This project is a beta version, the official version will add more features, continue to update.....
11 | I'll put the beta project address at the end
12 |
13 | ## Project renderings
14 |
15 | **System initialization login interface**
16 | 
17 | **Main interface display picture:**
18 | 
19 | **Sign in function display **
20 | 
21 | 
22 | **Sign out function display**
23 | 
24 | **Background check-in data recording**
25 | 
26 | **Check in/check out**
27 | 
28 |
29 | # The environment required for the project
30 |
31 | **OpenCV-Python 4.5.5.64**
32 | **face_recognition 1.30
33 | face_recognition_model 0.3.0
34 | dlib 19.23.1**
35 |
36 |
37 | **PyQt5 5.15.4
38 | pyqt5-plugins 5.15.4.2.2
39 | PyQt5-Qt5 5.15.2
40 | PyQt5-sip 12.10.1
41 | pyqt5-tools 5.15.4.3.2**
42 |
43 | ```
44 | **PythonVersion 3.9.12**
45 | ```
46 | ### QT-designer
47 |
48 | 
49 | 
50 |
51 |
52 | # Code
53 |
54 | ## CoreCode
55 |
56 | **MainWindow.py**
57 | *UI File:*
58 |
59 | ```python
60 | class Ui_Dialog(QDialog):
61 | def __init__(self):
62 | super(Ui_Dialog, self).__init__()
63 | loadUi("mainwindow.ui", self) #加载QTUI文件
64 |
65 | self.runButton.clicked.connect(self.runSlot)
66 |
67 | self._new_window = None
68 | self.Videocapture_ = None
69 | ```
70 |
71 | *Camera:*
72 |
73 | ```python
74 | def refreshAll(self):
75 | print("当前调用人俩检测摄像头编号(0为笔记本内置摄像头,1为USB外置摄像头):")
76 | self.Videocapture_ = "0"
77 | ```
78 |
79 | **OutWindow.py**
80 | *request Time*
81 |
82 | ```python
83 | class Ui_OutputDialog(QDialog):
84 | def __init__(self):
85 | super(Ui_OutputDialog, self).__init__()
86 | loadUi("./outputwindow.ui", self) #加载输出窗体UI
87 |
88 | #datetime 时间模块
89 | now = QDate.currentDate()
90 | current_date = now.toString('ddd dd MMMM yyyy') #时间格式
91 | current_time = datetime.datetime.now().strftime("%I:%M %p")
92 | self.Date_Label.setText(current_date)
93 | self.Time_Label.setText(current_time)
94 |
95 | self.image = None
96 | ```
97 |
98 | *Check in time*
99 |
100 | ```python
101 | def ElapseList(self,name):
102 | with open('Attendance.csv', "r") as csv_file:
103 | csv_reader = csv.reader(csv_file, delimiter=',')
104 | line_count = 2
105 |
106 | Time1 = datetime.datetime.now()
107 | Time2 = datetime.datetime.now()
108 | for row in csv_reader:
109 | for field in row:
110 | if field in row:
111 | if field == 'Clock In':
112 | if row[0] == name:
113 | Time1 = (datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S'))
114 | self.TimeList1.append(Time1)
115 | if field == 'Clock Out':
116 | if row[0] == name:
117 | Time2 = (datetime.datetime.strptime(row[1], '%y/%m/%d %H:%M:%S'))
118 | self.TimeList2.append(Time2)
119 | ```
120 |
121 | *FaceRecognition*
122 |
123 | ```python
124 | # 人脸识别部分
125 | faces_cur_frame = face_recognition.face_locations(frame)
126 | encodes_cur_frame = face_recognition.face_encodings(frame, faces_cur_frame)
127 |
128 | for encodeFace, faceLoc in zip(encodes_cur_frame, faces_cur_frame):
129 | match = face_recognition.compare_faces(encode_list_known, encodeFace, tolerance=0.50)
130 | face_dis = face_recognition.face_distance(encode_list_known, encodeFace)
131 | name = "unknown" #未知人脸识别为unknown
132 | best_match_index = np.argmin(face_dis)
133 | if match[best_match_index]:
134 | name = class_names[best_match_index].upper()
135 | y1, x2, y2, x1 = faceLoc
136 | cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
137 | cv2.rectangle(frame, (x1, y2 - 20), (x2, y2), (0, 255, 0), cv2.FILLED)
138 | cv2.putText(frame, name, (x1 + 6, y2 - 6), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
139 | mark_attendance(name)
140 |
141 | return frame
142 | ```
143 |
144 | *CheckData*
145 |
146 | ```python
147 | # csv表格保存数据
148 | def mark_attendance(name):
149 | """
150 | :param name: 人脸识别部分
151 | :return:
152 | """
153 | if self.ClockInButton.isChecked():
154 | self.ClockInButton.setEnabled(False)
155 | with open('Attendance.csv', 'a') as f:
156 | if (name != 'unknown'): #签到判断:是否为已经识别人脸
157 | buttonReply = QMessageBox.question(self, '欢迎 ' + name, '开始签到' ,
158 | QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
159 | if buttonReply == QMessageBox.Yes:
160 |
161 | date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
162 | f.writelines(f'\n{name},{date_time_string},Clock In')
163 | self.ClockInButton.setChecked(False)
164 |
165 | self.NameLabel.setText(name)
166 | self.StatusLabel.setText('签到')
167 | self.HoursLabel.setText('开始签到计时中')
168 | self.MinLabel.setText('')
169 |
170 | self.Time1 = datetime.datetime.now()
171 | self.ClockInButton.setEnabled(True)
172 | else:
173 | print('签到操作失败')
174 | self.ClockInButton.setEnabled(True)
175 | elif self.ClockOutButton.isChecked():
176 | self.ClockOutButton.setEnabled(False)
177 | with open('Attendance.csv', 'a') as f:
178 | if (name != 'unknown'):
179 | buttonReply = QMessageBox.question(self, '嗨呀 ' + name, '确认签退?',
180 | QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
181 | if buttonReply == QMessageBox.Yes:
182 | date_time_string = datetime.datetime.now().strftime("%y/%m/%d %H:%M:%S")
183 | f.writelines(f'\n{name},{date_time_string},Clock Out')
184 | self.ClockOutButton.setChecked(False)
185 |
186 | self.NameLabel.setText(name)
187 | self.StatusLabel.setText('签退')
188 | self.Time2 = datetime.datetime.now()
189 |
190 | self.ElapseList(name)
191 | self.TimeList2.append(datetime.datetime.now())
192 | CheckInTime = self.TimeList1[-1]
193 | CheckOutTime = self.TimeList2[-1]
194 | self.ElapseHours = (CheckOutTime - CheckInTime)
195 | self.MinLabel.setText("{:.0f}".format(abs(self.ElapseHours.total_seconds() / 60)%60) + 'm')
196 | self.HoursLabel.setText("{:.0f}".format(abs(self.ElapseHours.total_seconds() / 60**2)) + 'h')
197 | self.ClockOutButton.setEnabled(True)
198 | else:
199 | print('签退操作失败')
200 | self.ClockOutButton.setEnabled(True)
201 | ```
202 |
203 | ### Project directory structure
204 |
205 | 
206 |
207 | # At Last
208 |
209 | ***Because there is no face training model in this system, the system misrecognition rate is high and the security is low
210 | The system optimization is poor, the camera captures a low number of frames (8-9), the background occupies a high, and the CPU utilization is high
211 | Data is saved in CSV format, which has low security***
212 |
213 |
--------------------------------------------------------------------------------