├── align
├── __init__.py
├── text.txt
├── det1.npy
├── det2.npy
└── det3.npy
├── src
├── __init__.py
├── take_photo.py
├── get_face.py
├── SetUpMainWindow.py
├── face_recognition.py
├── Sqlite_UI.py
└── facenet.py
├── tools
├── __init__.py
└── sqlite_func.py
├── 20170512-110547
└── test.txt
├── DB
├── DB_File.txt
├── StudentFaceDB.db
└── StudentCheckWorkDB.db
├── markdown_imgs
├── 1.png
├── 2.png
└── 3.png
├── ui_src
├── __pycache__
│ ├── help.cpython-36.pyc
│ ├── delwin_ui.cpython-36.pyc
│ ├── addStudent.cpython-36.pyc
│ ├── checkTable.cpython-36.pyc
│ ├── addClassTable.cpython-36.pyc
│ ├── delCheckTable.cpython-36.pyc
│ └── deleteClassTable.cpython-36.pyc
├── Add_Data.ui
├── Add_Table.ui
├── Add_Data.py
├── Add_Table.py
├── prompt.ui
├── prompt.py
├── help.py
├── help.ui
├── delwin_ui.ui
├── delwin_ui.py
├── checkTable.ui
├── deleteClassTable.ui
├── delCheckTable.ui
├── checkTable.py
├── deleteClassTable.py
├── delCheckTable.py
├── addClassTable.ui
├── addClassTable.py
├── sqlite_main_window.ui
├── sqlite_main_window.py
├── MainUI.ui
├── MainUI.py
├── addStudent.ui
└── addStudent.py
├── .gitignore
└── README.md
/align/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tools/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/align/text.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/20170512-110547/test.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/DB/DB_File.txt:
--------------------------------------------------------------------------------
1 | StudentFaceDB.db:人脸数据库
2 | StudentCheckWorkDB.db:考勤数据库
--------------------------------------------------------------------------------
/align/det1.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/align/det1.npy
--------------------------------------------------------------------------------
/align/det2.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/align/det2.npy
--------------------------------------------------------------------------------
/align/det3.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/align/det3.npy
--------------------------------------------------------------------------------
/DB/StudentFaceDB.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/DB/StudentFaceDB.db
--------------------------------------------------------------------------------
/markdown_imgs/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/markdown_imgs/1.png
--------------------------------------------------------------------------------
/markdown_imgs/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/markdown_imgs/2.png
--------------------------------------------------------------------------------
/markdown_imgs/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/markdown_imgs/3.png
--------------------------------------------------------------------------------
/DB/StudentCheckWorkDB.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/DB/StudentCheckWorkDB.db
--------------------------------------------------------------------------------
/ui_src/__pycache__/help.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/help.cpython-36.pyc
--------------------------------------------------------------------------------
/ui_src/__pycache__/delwin_ui.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/delwin_ui.cpython-36.pyc
--------------------------------------------------------------------------------
/ui_src/__pycache__/addStudent.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/addStudent.cpython-36.pyc
--------------------------------------------------------------------------------
/ui_src/__pycache__/checkTable.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/checkTable.cpython-36.pyc
--------------------------------------------------------------------------------
/ui_src/__pycache__/addClassTable.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/addClassTable.cpython-36.pyc
--------------------------------------------------------------------------------
/ui_src/__pycache__/delCheckTable.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/delCheckTable.cpython-36.pyc
--------------------------------------------------------------------------------
/ui_src/__pycache__/deleteClassTable.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akira4O4/PyQt5_Face_Recognition/HEAD/ui_src/__pycache__/deleteClassTable.cpython-36.pyc
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
3 | 20170512-110547/
4 |
5 | align/__pycache__/
6 |
7 | src/__pycache__/
8 |
9 | ui_src/__pycache__/
10 |
11 | tools/__pycache__/
12 |
13 | test/
14 |
15 |
16 | ui_src/__pycache__/MainUI.cpython-36.pyc
17 |
18 | src_img/
19 | emb_img/
20 |
21 | src/file_op.py
22 | src/sqlite3_op.py
23 |
--------------------------------------------------------------------------------
/ui_src/Add_Data.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dialog_Add_Data
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Add_Data
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ui_src/Add_Table.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dialog_Add_Table
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Add Table
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ui_src/Add_Data.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'Add_Data.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Dialog_Add_Data(object):
12 | def setupUi(self, Dialog_Add_Data):
13 | Dialog_Add_Data.setObjectName("Dialog_Add_Data")
14 | Dialog_Add_Data.resize(400, 300)
15 |
16 | self.retranslateUi(Dialog_Add_Data)
17 | QtCore.QMetaObject.connectSlotsByName(Dialog_Add_Data)
18 |
19 | def retranslateUi(self, Dialog_Add_Data):
20 | _translate = QtCore.QCoreApplication.translate
21 | Dialog_Add_Data.setWindowTitle(_translate("Dialog_Add_Data", "Add_Data"))
22 |
23 |
--------------------------------------------------------------------------------
/ui_src/Add_Table.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'Add_Table.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Dialog_Add_Table(object):
12 | def setupUi(self, Dialog_Add_Table):
13 | Dialog_Add_Table.setObjectName("Dialog_Add_Table")
14 | Dialog_Add_Table.resize(400, 300)
15 |
16 | self.retranslateUi(Dialog_Add_Table)
17 | QtCore.QMetaObject.connectSlotsByName(Dialog_Add_Table)
18 |
19 | def retranslateUi(self, Dialog_Add_Table):
20 | _translate = QtCore.QCoreApplication.translate
21 | Dialog_Add_Table.setWindowTitle(_translate("Dialog_Add_Table", "Add Table"))
22 |
23 |
--------------------------------------------------------------------------------
/ui_src/prompt.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 | true
19 |
20 |
21 |
22 | 120
23 | 100
24 | 211
25 | 71
26 |
27 |
28 |
29 |
30 | 20
31 |
32 |
33 |
34 | 正在训练...
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/ui_src/prompt.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'prompt.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_For_prompt(object):
12 | def setupUi(self, Form):
13 | Form.setObjectName("prompt")
14 | Form.resize(400, 300)
15 | self.label = QtWidgets.QLabel(Form)
16 | self.label.setEnabled(True)
17 | self.label.setGeometry(QtCore.QRect(120, 100, 211, 71))
18 | font = QtGui.QFont()
19 | font.setPointSize(20)
20 | self.label.setFont(font)
21 | self.label.setObjectName("label")
22 |
23 | self.retranslateUi(Form)
24 | QtCore.QMetaObject.connectSlotsByName(Form)
25 |
26 | def retranslateUi(self, Form):
27 | _translate = QtCore.QCoreApplication.translate
28 | Form.setWindowTitle(_translate("Form", "提示"))
29 | self.label.setText(_translate("Form", "正在训练..."))
30 |
31 |
--------------------------------------------------------------------------------
/src/take_photo.py:
--------------------------------------------------------------------------------
1 | import cv2
2 |
3 |
4 | class Camera:
5 | global cap
6 | cap = cv2.VideoCapture(0)
7 | num = 1 # 照片计数器
8 |
9 | def __init__(self):
10 | pass
11 |
12 | def openCamera(self):
13 | cap.open()
14 | ret, frame = cap.read()
15 | frame = cv2.flip(frame, 1)
16 | frame = cv2.resize(frame, (640, 480))
17 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
18 | lable = cv2.putText(frame, '-->Camera OK', (10, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 0),
19 | thickness=1, lineType=1)
20 | return frame
21 |
22 | def takePhoto(self):
23 | ret, frame = cap.read()
24 | frame = cv2.flip(frame, 1)
25 | frame = cv2.resize(self.frame, (640, 480))
26 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
27 | lable = cv2.putText(frame, '-->Press the space to take a photo', (10, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,
28 | (0, 255, 0),
29 | thickness=1, lineType=1)
30 |
31 |
32 | if __name__ == "__main__":
33 | # cap=Camera()
34 | # cap.openCamera()
35 | selectFName = 'ff'
36 | fPaht = '../faces/' + selectFName
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # 基于卷积神经网络的学生人脸识别考勤系统
3 | ## 上传前已经通过测试,希望各位认真查阅README,README中写了许多细节,不熟悉TensorFlow和python的请提前学习。欢迎给小星星。
4 |
5 | **gitee:https://gitee.com/omegalee/PyQt5_Face_Recognition**
6 |
7 | ## 测试环境:
8 | >**1.Windows 10 Ubuntu 20.04**
9 | >**2.TensorFlow1.15 GPU版本(没有GPU也可以,CPU版本会慢一些)**
10 | >**3.PyQt5**
11 | >**4.Sqlite3**
12 |
13 | ## 使用的模型:
14 | ### MTCNN->人脸检测
15 | ### FaceNet->人脸识别
16 |
17 | ## 程序目录如下:
18 | >**20170512-11-547下为FaceNet数据 这个数据太大无法上传,请到百度云下载**
19 | >**链接:https://**
20 | >**pan.baidu.**
21 | >**com/s/1nMwbahnZ0ZgeIOO6UrATdw(请去掉空格)**
22 | >**提取码:w3it **
23 | >**align文件夹下为MTCNN模型数据**
24 | >**src文件夹下为所有主程序文件 SetUpMainWindow.py为启动文件**
25 | >**DB文件夹下为sqlite3数据库(文件夹里面是空的,运行主程序会自动创建,也可以手动创建,但是名字必须和DB_File里面写的一样)**
26 | >**ui_src文件夹下为ui设计文件和转码py文件**
27 | >**emb_img和src_img文件夹在程序运行时会自动创建(或者可以直接手动创建,两个都是空文件夹)**
28 |
29 |
30 | ## 目录结构
31 | 
32 |
33 |
34 | ## DB目录讲解
35 | >**StudentCheckWorkDB.db 为学生考勤数据表**
36 | >**StudentFaceDB.db 为学生人脸数据**
37 |
38 |
39 | ## 操作步骤
40 | 0、SetUpMainWindow.py是主界面启动文件
41 | 1、在数据库管理中添加用户,主要不要修改主键内容,修改主键内容会导致更新错误
42 | 2、在主界面点击刷新,更新数据表
43 | 3、选择学号ID
44 | 4、打开摄像头->录入人脸
45 | 5、点击生成模型(人脸模型生成过程线程会被阻塞,但是训练完成就没事了)
46 | 5、开始检测
47 |
48 | ## 软件界面细节
49 |
50 | 
51 |
52 | 
53 |
54 |
--------------------------------------------------------------------------------
/ui_src/help.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'help.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_help(object):
12 | def setupUi(self, help):
13 | help.setObjectName("help")
14 | help.resize(792, 240)
15 | self.horizontalLayout = QtWidgets.QHBoxLayout(help)
16 | self.horizontalLayout.setObjectName("horizontalLayout")
17 | self.textEdit = QtWidgets.QTextEdit(help)
18 | self.textEdit.setEnabled(False)
19 | self.textEdit.setObjectName("textEdit")
20 | self.horizontalLayout.addWidget(self.textEdit)
21 |
22 | self.retranslateUi(help)
23 | QtCore.QMetaObject.connectSlotsByName(help)
24 |
25 | def retranslateUi(self, help):
26 | _translate = QtCore.QCoreApplication.translate
27 | help.setWindowTitle(_translate("help", "帮助"))
28 | self.textEdit.setHtml(_translate("help", "\n"
29 | "
\n"
32 | "一:运行环境:TensorFlow-gpu,win10,python3.7
\n"
33 | "
\n"
34 | "二、使用方法:
\n"
35 | "1、单击打开摄像头按钮,检测摄像头是否正常。
\n"
36 | "2、单击添加标签按钮,添加一个新用户标签。
\n"
37 | "3、在打开摄像头的情况下,单击录入人脸按钮,尽可能的确保正脸面对摄像头。
\n"
38 | "4、单击提取特征按钮,在训练过程中,程序将保持忙碌状态直到提取结束。
\n"
39 | "5、单击开始检测按钮,程序开启时间根据机器性能而定,在检测过程中,按下esc退出识别。
\n"
40 | "6、单击删除按钮,输入需要删除的标签,完成删除操作。
"))
41 |
42 |
--------------------------------------------------------------------------------
/ui_src/help.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | help
4 |
5 |
6 |
7 | 0
8 | 0
9 | 792
10 | 240
11 |
12 |
13 |
14 | 帮助
15 |
16 |
17 | -
18 |
19 |
20 | false
21 |
22 |
23 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
24 | <html><head><meta name="qrichtext" content="1" /><style type="text/css">
25 | p, li { white-space: pre-wrap; }
26 | </style></head><body style=" font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;">
27 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">一:运行环境</span>:<span style=" font-weight:600;">TensorFlow-gpu,win10,python3.7</span></p>
28 | <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"><br /></p>
29 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt; font-weight:600;">二、使用方法:</span></p>
30 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">1、单击打开摄像头按钮,检测摄像头是否正常。</span></p>
31 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">2、单击添加标签按钮,添加一个新用户标签。</span></p>
32 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">3、在打开摄像头的情况下,单击录入人脸按钮,尽可能的确保正脸面对摄像头。</span></p>
33 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">4、单击提取特征按钮,在训练过程中,程序将保持忙碌状态直到提取结束。</span></p>
34 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">5、单击开始检测按钮,程序开启时间根据机器性能而定,在检测过程中,按下esc退出识别。</span></p>
35 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">6、单击删除按钮,输入需要删除的标签,完成删除操作。</span></p></body></html>
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/ui_src/delwin_ui.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form_Del
4 |
5 |
6 |
7 | 0
8 | 0
9 | 401
10 | 252
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 50
20 | 50
21 | 299
22 | 138
23 |
24 |
25 |
26 | -
27 |
28 |
29 |
30 | 16
31 |
32 |
33 |
34 | Qt::LeftToRight
35 |
36 |
37 | 选择需要删除的班级学号
38 |
39 |
40 | Qt::AlignCenter
41 |
42 |
43 |
44 | -
45 |
46 |
-
47 |
48 |
-
49 |
50 |
-
51 |
52 |
53 |
54 | 16
55 |
56 |
57 |
58 | 选择班级
59 |
60 |
61 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
62 |
63 |
64 |
65 | -
66 |
67 |
68 |
69 |
70 | -
71 |
72 |
-
73 |
74 |
75 |
76 | 16
77 |
78 |
79 |
80 | 选择学号
81 |
82 |
83 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
84 |
85 |
86 |
87 | -
88 |
89 |
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 | 200
99 | 60
100 |
101 |
102 |
103 |
104 | 16
105 | 50
106 | false
107 |
108 |
109 |
110 | 查询
111 |
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
-
119 |
120 |
121 |
122 | 200
123 | 60
124 |
125 |
126 |
127 |
128 | 16
129 | 50
130 | false
131 |
132 |
133 |
134 | 确定
135 |
136 |
137 |
138 | -
139 |
140 |
141 |
142 | 200
143 | 60
144 |
145 |
146 |
147 |
148 | 16
149 | 50
150 | false
151 |
152 |
153 |
154 | 取消
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/ui_src/delwin_ui.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'delwin_ui.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Form_Del(object):
12 | def setupUi(self, Form_Del):
13 | Form_Del.setObjectName("Form_Del")
14 | Form_Del.resize(401, 252)
15 | self.widget = QtWidgets.QWidget(Form_Del)
16 | self.widget.setGeometry(QtCore.QRect(50, 50, 299, 138))
17 | self.widget.setObjectName("widget")
18 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.widget)
19 | self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
20 | self.verticalLayout_2.setObjectName("verticalLayout_2")
21 | self.lab_delTest = QtWidgets.QLabel(self.widget)
22 | font = QtGui.QFont()
23 | font.setPointSize(16)
24 | self.lab_delTest.setFont(font)
25 | self.lab_delTest.setLayoutDirection(QtCore.Qt.LeftToRight)
26 | self.lab_delTest.setAlignment(QtCore.Qt.AlignCenter)
27 | self.lab_delTest.setObjectName("lab_delTest")
28 | self.verticalLayout_2.addWidget(self.lab_delTest)
29 | self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
30 | self.horizontalLayout_4.setObjectName("horizontalLayout_4")
31 | self.verticalLayout = QtWidgets.QVBoxLayout()
32 | self.verticalLayout.setObjectName("verticalLayout")
33 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
34 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
35 | self.lab_selecCalss = QtWidgets.QLabel(self.widget)
36 | font = QtGui.QFont()
37 | font.setPointSize(16)
38 | self.lab_selecCalss.setFont(font)
39 | self.lab_selecCalss.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
40 | self.lab_selecCalss.setObjectName("lab_selecCalss")
41 | self.horizontalLayout_2.addWidget(self.lab_selecCalss)
42 | self.comboBox_selectClass = QtWidgets.QComboBox(self.widget)
43 | self.comboBox_selectClass.setObjectName("comboBox_selectClass")
44 | self.horizontalLayout_2.addWidget(self.comboBox_selectClass)
45 | self.verticalLayout.addLayout(self.horizontalLayout_2)
46 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
47 | self.horizontalLayout_3.setObjectName("horizontalLayout_3")
48 | self.lab_selecLable = QtWidgets.QLabel(self.widget)
49 | font = QtGui.QFont()
50 | font.setPointSize(16)
51 | self.lab_selecLable.setFont(font)
52 | self.lab_selecLable.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
53 | self.lab_selecLable.setObjectName("lab_selecLable")
54 | self.horizontalLayout_3.addWidget(self.lab_selecLable)
55 | self.comboBox_selectId = QtWidgets.QComboBox(self.widget)
56 | self.comboBox_selectId.setObjectName("comboBox_selectId")
57 | self.horizontalLayout_3.addWidget(self.comboBox_selectId)
58 | self.verticalLayout.addLayout(self.horizontalLayout_3)
59 | self.horizontalLayout_4.addLayout(self.verticalLayout)
60 | self.btn_Refresh = QtWidgets.QPushButton(self.widget)
61 | self.btn_Refresh.setMaximumSize(QtCore.QSize(200, 60))
62 | font = QtGui.QFont()
63 | font.setPointSize(16)
64 | font.setBold(False)
65 | font.setWeight(50)
66 | self.btn_Refresh.setFont(font)
67 | self.btn_Refresh.setObjectName("btn_Refresh")
68 | self.horizontalLayout_4.addWidget(self.btn_Refresh)
69 | self.verticalLayout_2.addLayout(self.horizontalLayout_4)
70 | self.horizontalLayout = QtWidgets.QHBoxLayout()
71 | self.horizontalLayout.setObjectName("horizontalLayout")
72 | self.btn_Enter = QtWidgets.QPushButton(self.widget)
73 | self.btn_Enter.setMaximumSize(QtCore.QSize(200, 60))
74 | font = QtGui.QFont()
75 | font.setPointSize(16)
76 | font.setBold(False)
77 | font.setWeight(50)
78 | self.btn_Enter.setFont(font)
79 | self.btn_Enter.setObjectName("btn_Enter")
80 | self.horizontalLayout.addWidget(self.btn_Enter)
81 | self.btn_Cancel = QtWidgets.QPushButton(self.widget)
82 | self.btn_Cancel.setMaximumSize(QtCore.QSize(200, 60))
83 | font = QtGui.QFont()
84 | font.setPointSize(16)
85 | font.setBold(False)
86 | font.setWeight(50)
87 | self.btn_Cancel.setFont(font)
88 | self.btn_Cancel.setObjectName("btn_Cancel")
89 | self.horizontalLayout.addWidget(self.btn_Cancel)
90 | self.verticalLayout_2.addLayout(self.horizontalLayout)
91 |
92 | self.retranslateUi(Form_Del)
93 | QtCore.QMetaObject.connectSlotsByName(Form_Del)
94 |
95 | def retranslateUi(self, Form_Del):
96 | _translate = QtCore.QCoreApplication.translate
97 | Form_Del.setWindowTitle(_translate("Form_Del", "Form"))
98 | self.lab_delTest.setText(_translate("Form_Del", "选择需要删除的班级学号"))
99 | self.lab_selecCalss.setText(_translate("Form_Del", "选择班级"))
100 | self.lab_selecLable.setText(_translate("Form_Del", "选择学号"))
101 | self.btn_Refresh.setText(_translate("Form_Del", "查询"))
102 | self.btn_Enter.setText(_translate("Form_Del", "确定"))
103 | self.btn_Cancel.setText(_translate("Form_Del", "取消"))
104 |
105 |
--------------------------------------------------------------------------------
/ui_src/checkTable.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form_checkTable
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 30
20 | 60
21 | 344
22 | 164
23 |
24 |
25 |
26 | -
27 |
28 |
-
29 |
30 |
31 |
32 | 0
33 | 0
34 |
35 |
36 |
37 |
38 | 16
39 |
40 |
41 |
42 | Qt::LeftToRight
43 |
44 |
45 | 添加考勤表
46 |
47 |
48 | Qt::AlignCenter
49 |
50 |
51 |
52 | -
53 |
54 |
-
55 |
56 |
-
57 |
58 |
59 |
60 | 0
61 | 0
62 |
63 |
64 |
65 |
66 | 16
67 |
68 |
69 |
70 | Qt::LeftToRight
71 |
72 |
73 | 考勤表名称:
74 |
75 |
76 | Qt::AlignCenter
77 |
78 |
79 |
80 |
81 |
82 | -
83 |
84 |
-
85 |
86 |
87 | true
88 |
89 |
90 |
91 | 0
92 | 0
93 |
94 |
95 |
96 |
97 | 16
98 |
99 |
100 |
101 | Qt::LeftToRight
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | -
112 |
113 |
-
114 |
115 |
116 |
117 | 0
118 | 0
119 |
120 |
121 |
122 |
123 | 200
124 | 60
125 |
126 |
127 |
128 |
129 | 16
130 | 50
131 | false
132 |
133 |
134 |
135 | Qt::LeftToRight
136 |
137 |
138 | 确定
139 |
140 |
141 |
142 | -
143 |
144 |
145 |
146 | 0
147 | 0
148 |
149 |
150 |
151 |
152 | 200
153 | 60
154 |
155 |
156 |
157 |
158 | 16
159 | 50
160 | false
161 |
162 |
163 |
164 | Qt::LeftToRight
165 |
166 |
167 | 取消
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/src/get_face.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import numpy as np
3 | import os
4 | from scipy import misc
5 | from skimage import transform
6 | import copy
7 | import facenet
8 | import align.detect_face
9 | import argparse
10 | import sys
11 | # import sqlite3_op
12 | from tools.sqlite_func import Sqlite_Func
13 | import cv2
14 | import imageio
15 |
16 |
17 | # MTCNN人脸检测
18 | def align_data(image_path, imgae_size, gpu_memory_faction):
19 | minsize = 20
20 | threshhold = [0.6, 0.7, 0.7]
21 | factor = 0.709
22 |
23 | with tf.Graph().as_default():
24 | # per_process_gpu_memory_fraction指定了每个GPU进程中使用显存的上限,但它只能均匀地作用于所有GPU,无法对不同GPU设置不同的上限。
25 | gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_memory_faction, allow_growth=True)
26 | sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
27 | # 加载mtcnn
28 | with sess.as_default():
29 | pnet, onet, rnet = align.detect_face.create_mtcnn(sess, None)
30 |
31 | temp_image_path = copy.copy(image_path) # 浅拷贝文件目录
32 | image_list = [] # 图片列表
33 | for path in temp_image_path:
34 |
35 | print('读取:', path)
36 | # os.path.expanduser:展开目录
37 | img = imageio.imread(os.path.expanduser(path)) # 这样读出来的图片格式为numpy类型,后面就不需要再转换了
38 | # img_size = np.asarray(img.shape)[0:2] # 获取数据尺寸类型为ndarray
39 |
40 | bounding_boxes, _ = align.detect_face.detect_face(img, minsize, pnet, onet, rnet, threshhold, factor)
41 | if len(bounding_boxes) < 1:
42 | image_path.remove(path)
43 | print("无法检测到脸部,删除", path)
44 | continue
45 |
46 | det = np.squeeze(bounding_boxes[0, 0:4]) # 从数组的形状中删除单维度条目,即把shape中为1的维度去掉,数据降维
47 |
48 | # 切片操作需要整数类型
49 | bb = np.zeros(4, dtype=np.int32)
50 | bb[0] = det[0]
51 | bb[1] = det[1]
52 | bb[2] = det[2]
53 | bb[3] = det[3]
54 | cropped = img[bb[1]:bb[3], bb[0]:bb[2], :] # 对角坐标
55 | cropped = cv2.resize(cropped, (imgae_size, imgae_size), interpolation=cv2.INTER_AREA) # 默认双三线性插值
56 |
57 | prewhitened = facenet.prewhiten(cropped) # 白化,取出冗余数据
58 | image_list.append(prewhitened)
59 |
60 | images = np.stack(image_list)
61 |
62 | return images
63 |
64 |
65 | # 文件夹人脸检测
66 | def detection():
67 | src_img = '../src_img/' # 原图片
68 | emb_img = '../emb_img' # 人脸目录
69 |
70 | # 如果不存在这个目录就新建一个
71 | if os.path.exists(emb_img) is False:
72 | os.mkdir(emb_img)
73 | if os.path.exists(src_img) is False:
74 | os.mkdir(src_img)
75 |
76 | img_path_set = []
77 | # 查看src_img下所有文件
78 | for f in os.listdir(src_img):
79 | # 拼接图片目录
80 | one_img = os.path.join(src_img, f)
81 | img_path_set.append(one_img)
82 |
83 | print(img_path_set)
84 | if len(img_path_set) != 0:
85 | # 提取人脸
86 | images_align = align_data(img_path_set, 160, 1.0)
87 |
88 | # 保存切割好的图片
89 | count = 0
90 | for f in os.listdir(src_img):
91 | # param:path,img
92 | imageio.imwrite(os.path.join(emb_img, f), images_align[count])
93 | count = count + 1
94 |
95 | # 删除已经被剪裁的图片
96 | os.remove(os.path.join(src_img, f))
97 |
98 | # 计算特征值
99 | computing_emb()
100 | return True
101 |
102 |
103 | # Facenet计算embadding并存入数据库
104 | def computing_emb():
105 | with tf.Graph().as_default():
106 | with tf.Session() as sess:
107 |
108 | # opsql = sqlite3_op.Operate_Sql()
109 | sqlite = Sqlite_Func()
110 |
111 | model = '../20170512-110547/'
112 | emb_img = '../emb_img'
113 | # 加载facenet模型
114 | facenet.load_model(model)
115 | images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
116 | embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
117 | phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
118 | image = []
119 | nrof_images = 0
120 | global compare_emb, compare_num, all_obj_name
121 |
122 | all_obj_name = []
123 | for i in os.listdir(emb_img):
124 | all_obj_name.append(i)
125 | img = imageio.imread(os.path.join(emb_img, i))
126 | prewhitened = facenet.prewhiten(img) # 预白化去除冗余信息
127 | image.append(prewhitened)
128 | nrof_images = nrof_images + 1
129 |
130 | images = np.stack(image) # 沿着新轴连接数组的序列。
131 | # 计算对比图片embadding,embdadding是一个128维的张量
132 | compare_emb = sess.run(embeddings, feed_dict={images_placeholder: images, phase_train_placeholder: False})
133 | compare_num = len(compare_emb)
134 | print('compare_emb len:', len(compare_emb[0]))
135 | print("pre_embadding计算完成")
136 |
137 | for i in os.listdir(emb_img):
138 | #拆分表名和id号
139 | index = 0
140 | info = i.split("#")
141 | print("info:{}".format(info))
142 | table_name=info[0]
143 | id = info[1].split(".")
144 | ID=id[0]
145 |
146 | # opsql.insert_emb(info[0], id[0], compare_emb[index])
147 | sqlite.update_face_emb(sqlite.DB_STUDENTFACE_PATH, table_name, ID, compare_emb[index])
148 | index += 1
149 |
150 | # 移除已经计算过的image
151 | for f in os.listdir(emb_img):
152 | pass
153 | os.remove(os.path.join(emb_img, f))
154 |
155 |
156 | def parse_arguments(argv):
157 | parser = argparse.ArgumentParser()
158 | parser.add_argument('--img_size', type=int, default=160)
159 | return parser.parse_args(argv)
160 |
161 |
162 | def main(args):
163 | detection()
164 |
165 |
166 | if __name__ == "__main__":
167 | # main(parse_arguments(sys.argv[1:]))
168 | detection()
169 |
--------------------------------------------------------------------------------
/ui_src/deleteClassTable.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 498
10 | 250
11 |
12 |
13 |
14 | 删除班级表
15 |
16 |
17 |
18 |
19 | 30
20 | 30
21 | 436
22 | 166
23 |
24 |
25 |
26 | -
27 |
28 |
-
29 |
30 |
31 |
32 | 0
33 | 0
34 |
35 |
36 |
37 |
38 | 16
39 |
40 |
41 |
42 | Qt::LeftToRight
43 |
44 |
45 | 删除人脸数据表
46 |
47 |
48 | Qt::AlignCenter
49 |
50 |
51 |
52 | -
53 |
54 |
-
55 |
56 |
-
57 |
58 |
59 |
60 | 0
61 | 0
62 |
63 |
64 |
65 |
66 | 16
67 |
68 |
69 |
70 | Qt::LeftToRight
71 |
72 |
73 | 人脸数据表名:
74 |
75 |
76 | Qt::AlignCenter
77 |
78 |
79 |
80 | -
81 |
82 |
83 |
84 |
85 | -
86 |
87 |
88 |
89 |
90 |
91 |
92 | -
93 |
94 |
-
95 |
96 |
97 |
98 | 0
99 | 0
100 |
101 |
102 |
103 |
104 | 200
105 | 60
106 |
107 |
108 |
109 |
110 | 16
111 | 50
112 | false
113 |
114 |
115 |
116 | Qt::LeftToRight
117 |
118 |
119 | 确定
120 |
121 |
122 |
123 | -
124 |
125 |
126 |
127 | 0
128 | 0
129 |
130 |
131 |
132 |
133 | 200
134 | 60
135 |
136 |
137 |
138 |
139 | 16
140 | 50
141 | false
142 |
143 |
144 |
145 | Qt::LeftToRight
146 |
147 |
148 | 刷新
149 |
150 |
151 |
152 | -
153 |
154 |
155 |
156 | 0
157 | 0
158 |
159 |
160 |
161 |
162 | 200
163 | 60
164 |
165 |
166 |
167 |
168 | 16
169 | 50
170 | false
171 |
172 |
173 |
174 | Qt::LeftToRight
175 |
176 |
177 | 取消
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/ui_src/delCheckTable.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form_delCheckTable
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 |
19 | 30
20 | 60
21 | 344
22 | 164
23 |
24 |
25 |
26 | -
27 |
28 |
-
29 |
30 |
31 |
32 | 0
33 | 0
34 |
35 |
36 |
37 |
38 | 16
39 |
40 |
41 |
42 | Qt::LeftToRight
43 |
44 |
45 | 删除考勤表
46 |
47 |
48 | Qt::AlignCenter
49 |
50 |
51 |
52 | -
53 |
54 |
-
55 |
56 |
-
57 |
58 |
59 |
60 | 0
61 | 0
62 |
63 |
64 |
65 |
66 | 16
67 |
68 |
69 |
70 | Qt::LeftToRight
71 |
72 |
73 | 考勤表名称:
74 |
75 |
76 | Qt::AlignCenter
77 |
78 |
79 |
80 |
81 |
82 | -
83 |
84 |
-
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | -
94 |
95 |
-
96 |
97 |
98 |
99 | 0
100 | 0
101 |
102 |
103 |
104 |
105 | 200
106 | 60
107 |
108 |
109 |
110 |
111 | 16
112 | 50
113 | false
114 |
115 |
116 |
117 | Qt::LeftToRight
118 |
119 |
120 | 确定
121 |
122 |
123 |
124 | -
125 |
126 |
127 |
128 | 0
129 | 0
130 |
131 |
132 |
133 |
134 | 200
135 | 60
136 |
137 |
138 |
139 |
140 | 16
141 | 50
142 | false
143 |
144 |
145 |
146 | Qt::LeftToRight
147 |
148 |
149 | 刷新
150 |
151 |
152 |
153 | -
154 |
155 |
156 |
157 | 0
158 | 0
159 |
160 |
161 |
162 |
163 | 200
164 | 60
165 |
166 |
167 |
168 |
169 | 16
170 | 50
171 | false
172 |
173 |
174 |
175 | Qt::LeftToRight
176 |
177 |
178 | 取消
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/ui_src/checkTable.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'checkTable.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Form_checkTable(object):
12 | def setupUi(self, Form_checkTable):
13 | Form_checkTable.setObjectName("Form_checkTable")
14 | Form_checkTable.resize(400, 300)
15 | self.layoutWidget = QtWidgets.QWidget(Form_checkTable)
16 | self.layoutWidget.setGeometry(QtCore.QRect(30, 60, 344, 164))
17 | self.layoutWidget.setObjectName("layoutWidget")
18 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.layoutWidget)
19 | self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
20 | self.verticalLayout_4.setObjectName("verticalLayout_4")
21 | self.verticalLayout_3 = QtWidgets.QVBoxLayout()
22 | self.verticalLayout_3.setObjectName("verticalLayout_3")
23 | self.lab_addTest_8 = QtWidgets.QLabel(self.layoutWidget)
24 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
25 | sizePolicy.setHorizontalStretch(0)
26 | sizePolicy.setVerticalStretch(0)
27 | sizePolicy.setHeightForWidth(self.lab_addTest_8.sizePolicy().hasHeightForWidth())
28 | self.lab_addTest_8.setSizePolicy(sizePolicy)
29 | font = QtGui.QFont()
30 | font.setPointSize(16)
31 | self.lab_addTest_8.setFont(font)
32 | self.lab_addTest_8.setLayoutDirection(QtCore.Qt.LeftToRight)
33 | self.lab_addTest_8.setAlignment(QtCore.Qt.AlignCenter)
34 | self.lab_addTest_8.setObjectName("lab_addTest_8")
35 | self.verticalLayout_3.addWidget(self.lab_addTest_8)
36 | self.horizontalLayout = QtWidgets.QHBoxLayout()
37 | self.horizontalLayout.setObjectName("horizontalLayout")
38 | self.verticalLayout = QtWidgets.QVBoxLayout()
39 | self.verticalLayout.setObjectName("verticalLayout")
40 | self.lab_addTest_6 = QtWidgets.QLabel(self.layoutWidget)
41 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
42 | sizePolicy.setHorizontalStretch(0)
43 | sizePolicy.setVerticalStretch(0)
44 | sizePolicy.setHeightForWidth(self.lab_addTest_6.sizePolicy().hasHeightForWidth())
45 | self.lab_addTest_6.setSizePolicy(sizePolicy)
46 | font = QtGui.QFont()
47 | font.setPointSize(16)
48 | self.lab_addTest_6.setFont(font)
49 | self.lab_addTest_6.setLayoutDirection(QtCore.Qt.LeftToRight)
50 | self.lab_addTest_6.setAlignment(QtCore.Qt.AlignCenter)
51 | self.lab_addTest_6.setObjectName("lab_addTest_6")
52 | self.verticalLayout.addWidget(self.lab_addTest_6)
53 | self.horizontalLayout.addLayout(self.verticalLayout)
54 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
55 | self.verticalLayout_2.setObjectName("verticalLayout_2")
56 | self.line_addCheckTable = QtWidgets.QLineEdit(self.layoutWidget)
57 | self.line_addCheckTable.setEnabled(True)
58 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
59 | sizePolicy.setHorizontalStretch(0)
60 | sizePolicy.setVerticalStretch(0)
61 | sizePolicy.setHeightForWidth(self.line_addCheckTable.sizePolicy().hasHeightForWidth())
62 | self.line_addCheckTable.setSizePolicy(sizePolicy)
63 | font = QtGui.QFont()
64 | font.setPointSize(16)
65 | self.line_addCheckTable.setFont(font)
66 | self.line_addCheckTable.setLayoutDirection(QtCore.Qt.LeftToRight)
67 | self.line_addCheckTable.setObjectName("line_addCheckTable")
68 | self.verticalLayout_2.addWidget(self.line_addCheckTable)
69 | self.horizontalLayout.addLayout(self.verticalLayout_2)
70 | self.verticalLayout_3.addLayout(self.horizontalLayout)
71 | self.verticalLayout_4.addLayout(self.verticalLayout_3)
72 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
73 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
74 | self.btn_confirm = QtWidgets.QPushButton(self.layoutWidget)
75 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
76 | sizePolicy.setHorizontalStretch(0)
77 | sizePolicy.setVerticalStretch(0)
78 | sizePolicy.setHeightForWidth(self.btn_confirm.sizePolicy().hasHeightForWidth())
79 | self.btn_confirm.setSizePolicy(sizePolicy)
80 | self.btn_confirm.setMaximumSize(QtCore.QSize(200, 60))
81 | font = QtGui.QFont()
82 | font.setPointSize(16)
83 | font.setBold(False)
84 | font.setWeight(50)
85 | self.btn_confirm.setFont(font)
86 | self.btn_confirm.setLayoutDirection(QtCore.Qt.LeftToRight)
87 | self.btn_confirm.setObjectName("btn_confirm")
88 | self.horizontalLayout_2.addWidget(self.btn_confirm)
89 | self.btn_cancel = QtWidgets.QPushButton(self.layoutWidget)
90 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
91 | sizePolicy.setHorizontalStretch(0)
92 | sizePolicy.setVerticalStretch(0)
93 | sizePolicy.setHeightForWidth(self.btn_cancel.sizePolicy().hasHeightForWidth())
94 | self.btn_cancel.setSizePolicy(sizePolicy)
95 | self.btn_cancel.setMaximumSize(QtCore.QSize(200, 60))
96 | font = QtGui.QFont()
97 | font.setPointSize(16)
98 | font.setBold(False)
99 | font.setWeight(50)
100 | self.btn_cancel.setFont(font)
101 | self.btn_cancel.setLayoutDirection(QtCore.Qt.LeftToRight)
102 | self.btn_cancel.setObjectName("btn_cancel")
103 | self.horizontalLayout_2.addWidget(self.btn_cancel)
104 | self.verticalLayout_4.addLayout(self.horizontalLayout_2)
105 |
106 | self.retranslateUi(Form_checkTable)
107 | QtCore.QMetaObject.connectSlotsByName(Form_checkTable)
108 |
109 | def retranslateUi(self, Form_checkTable):
110 | _translate = QtCore.QCoreApplication.translate
111 | Form_checkTable.setWindowTitle(_translate("Form_checkTable", "Form"))
112 | self.lab_addTest_8.setText(_translate("Form_checkTable", "添加考勤表"))
113 | self.lab_addTest_6.setText(_translate("Form_checkTable", "考勤表名称:"))
114 | self.btn_confirm.setText(_translate("Form_checkTable", "确定"))
115 | self.btn_cancel.setText(_translate("Form_checkTable", "取消"))
116 |
117 |
--------------------------------------------------------------------------------
/ui_src/deleteClassTable.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'deleteClassTable.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_DelClassTable(object):
12 | def setupUi(self, Form):
13 | Form.setObjectName("Form")
14 | Form.resize(498, 250)
15 | self.layoutWidget = QtWidgets.QWidget(Form)
16 | self.layoutWidget.setGeometry(QtCore.QRect(30, 30, 436, 166))
17 | self.layoutWidget.setObjectName("layoutWidget")
18 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget)
19 | self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
20 | self.verticalLayout_3.setObjectName("verticalLayout_3")
21 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
22 | self.verticalLayout_2.setObjectName("verticalLayout_2")
23 | self.lab_addTest_8 = QtWidgets.QLabel(self.layoutWidget)
24 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
25 | sizePolicy.setHorizontalStretch(0)
26 | sizePolicy.setVerticalStretch(0)
27 | sizePolicy.setHeightForWidth(self.lab_addTest_8.sizePolicy().hasHeightForWidth())
28 | self.lab_addTest_8.setSizePolicy(sizePolicy)
29 | font = QtGui.QFont()
30 | font.setPointSize(16)
31 | self.lab_addTest_8.setFont(font)
32 | self.lab_addTest_8.setLayoutDirection(QtCore.Qt.LeftToRight)
33 | self.lab_addTest_8.setAlignment(QtCore.Qt.AlignCenter)
34 | self.lab_addTest_8.setObjectName("lab_addTest_8")
35 | self.verticalLayout_2.addWidget(self.lab_addTest_8)
36 | self.verticalLayout = QtWidgets.QVBoxLayout()
37 | self.verticalLayout.setObjectName("verticalLayout")
38 | self.horizontalLayout = QtWidgets.QHBoxLayout()
39 | self.horizontalLayout.setObjectName("horizontalLayout")
40 | self.lab_addTest_6 = QtWidgets.QLabel(self.layoutWidget)
41 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
42 | sizePolicy.setHorizontalStretch(0)
43 | sizePolicy.setVerticalStretch(0)
44 | sizePolicy.setHeightForWidth(self.lab_addTest_6.sizePolicy().hasHeightForWidth())
45 | self.lab_addTest_6.setSizePolicy(sizePolicy)
46 | font = QtGui.QFont()
47 | font.setPointSize(16)
48 | self.lab_addTest_6.setFont(font)
49 | self.lab_addTest_6.setLayoutDirection(QtCore.Qt.LeftToRight)
50 | self.lab_addTest_6.setAlignment(QtCore.Qt.AlignCenter)
51 | self.lab_addTest_6.setObjectName("lab_addTest_6")
52 | self.horizontalLayout.addWidget(self.lab_addTest_6)
53 | self.comboBox_del_facedata_table = QtWidgets.QComboBox(self.layoutWidget)
54 | self.comboBox_del_facedata_table.setObjectName("comboBox_del_facedata_table")
55 | self.horizontalLayout.addWidget(self.comboBox_del_facedata_table)
56 | self.verticalLayout.addLayout(self.horizontalLayout)
57 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
58 | self.horizontalLayout_3.setObjectName("horizontalLayout_3")
59 | self.verticalLayout.addLayout(self.horizontalLayout_3)
60 | self.verticalLayout_2.addLayout(self.verticalLayout)
61 | self.verticalLayout_3.addLayout(self.verticalLayout_2)
62 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
63 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
64 | self.btn_confirm = QtWidgets.QPushButton(self.layoutWidget)
65 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
66 | sizePolicy.setHorizontalStretch(0)
67 | sizePolicy.setVerticalStretch(0)
68 | sizePolicy.setHeightForWidth(self.btn_confirm.sizePolicy().hasHeightForWidth())
69 | self.btn_confirm.setSizePolicy(sizePolicy)
70 | self.btn_confirm.setMaximumSize(QtCore.QSize(200, 60))
71 | font = QtGui.QFont()
72 | font.setPointSize(16)
73 | font.setBold(False)
74 | font.setWeight(50)
75 | self.btn_confirm.setFont(font)
76 | self.btn_confirm.setLayoutDirection(QtCore.Qt.LeftToRight)
77 | self.btn_confirm.setObjectName("btn_confirm")
78 | self.horizontalLayout_2.addWidget(self.btn_confirm)
79 | self.btn_refresh = QtWidgets.QPushButton(self.layoutWidget)
80 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
81 | sizePolicy.setHorizontalStretch(0)
82 | sizePolicy.setVerticalStretch(0)
83 | sizePolicy.setHeightForWidth(self.btn_refresh.sizePolicy().hasHeightForWidth())
84 | self.btn_refresh.setSizePolicy(sizePolicy)
85 | self.btn_refresh.setMaximumSize(QtCore.QSize(200, 60))
86 | font = QtGui.QFont()
87 | font.setPointSize(16)
88 | font.setBold(False)
89 | font.setWeight(50)
90 | self.btn_refresh.setFont(font)
91 | self.btn_refresh.setLayoutDirection(QtCore.Qt.LeftToRight)
92 | self.btn_refresh.setObjectName("btn_refresh")
93 | self.horizontalLayout_2.addWidget(self.btn_refresh)
94 | self.btn_cancel = QtWidgets.QPushButton(self.layoutWidget)
95 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
96 | sizePolicy.setHorizontalStretch(0)
97 | sizePolicy.setVerticalStretch(0)
98 | sizePolicy.setHeightForWidth(self.btn_cancel.sizePolicy().hasHeightForWidth())
99 | self.btn_cancel.setSizePolicy(sizePolicy)
100 | self.btn_cancel.setMaximumSize(QtCore.QSize(200, 60))
101 | font = QtGui.QFont()
102 | font.setPointSize(16)
103 | font.setBold(False)
104 | font.setWeight(50)
105 | self.btn_cancel.setFont(font)
106 | self.btn_cancel.setLayoutDirection(QtCore.Qt.LeftToRight)
107 | self.btn_cancel.setObjectName("btn_cancel")
108 | self.horizontalLayout_2.addWidget(self.btn_cancel)
109 | self.verticalLayout_3.addLayout(self.horizontalLayout_2)
110 |
111 | self.retranslateUi(Form)
112 | QtCore.QMetaObject.connectSlotsByName(Form)
113 |
114 | def retranslateUi(self, Form):
115 | _translate = QtCore.QCoreApplication.translate
116 | Form.setWindowTitle(_translate("Form", "删除班级表"))
117 | self.lab_addTest_8.setText(_translate("Form", "删除人脸数据表"))
118 | self.lab_addTest_6.setText(_translate("Form", "人脸数据表名:"))
119 | self.btn_confirm.setText(_translate("Form", "确定"))
120 | self.btn_refresh.setText(_translate("Form", "刷新"))
121 | self.btn_cancel.setText(_translate("Form", "取消"))
122 |
123 |
--------------------------------------------------------------------------------
/ui_src/delCheckTable.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'delCheckTable.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Form_delCheckTable(object):
12 | def setupUi(self, Form_delCheckTable):
13 | Form_delCheckTable.setObjectName("Form_delCheckTable")
14 | Form_delCheckTable.resize(400, 300)
15 | self.layoutWidget = QtWidgets.QWidget(Form_delCheckTable)
16 | self.layoutWidget.setGeometry(QtCore.QRect(30, 60, 344, 164))
17 | self.layoutWidget.setObjectName("layoutWidget")
18 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.layoutWidget)
19 | self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
20 | self.verticalLayout_4.setObjectName("verticalLayout_4")
21 | self.verticalLayout_3 = QtWidgets.QVBoxLayout()
22 | self.verticalLayout_3.setObjectName("verticalLayout_3")
23 | self.lab_addTest_8 = QtWidgets.QLabel(self.layoutWidget)
24 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
25 | sizePolicy.setHorizontalStretch(0)
26 | sizePolicy.setVerticalStretch(0)
27 | sizePolicy.setHeightForWidth(self.lab_addTest_8.sizePolicy().hasHeightForWidth())
28 | self.lab_addTest_8.setSizePolicy(sizePolicy)
29 | font = QtGui.QFont()
30 | font.setPointSize(16)
31 | self.lab_addTest_8.setFont(font)
32 | self.lab_addTest_8.setLayoutDirection(QtCore.Qt.LeftToRight)
33 | self.lab_addTest_8.setAlignment(QtCore.Qt.AlignCenter)
34 | self.lab_addTest_8.setObjectName("lab_addTest_8")
35 | self.verticalLayout_3.addWidget(self.lab_addTest_8)
36 | self.horizontalLayout = QtWidgets.QHBoxLayout()
37 | self.horizontalLayout.setObjectName("horizontalLayout")
38 | self.verticalLayout = QtWidgets.QVBoxLayout()
39 | self.verticalLayout.setObjectName("verticalLayout")
40 | self.lab_addTest_6 = QtWidgets.QLabel(self.layoutWidget)
41 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
42 | sizePolicy.setHorizontalStretch(0)
43 | sizePolicy.setVerticalStretch(0)
44 | sizePolicy.setHeightForWidth(self.lab_addTest_6.sizePolicy().hasHeightForWidth())
45 | self.lab_addTest_6.setSizePolicy(sizePolicy)
46 | font = QtGui.QFont()
47 | font.setPointSize(16)
48 | self.lab_addTest_6.setFont(font)
49 | self.lab_addTest_6.setLayoutDirection(QtCore.Qt.LeftToRight)
50 | self.lab_addTest_6.setAlignment(QtCore.Qt.AlignCenter)
51 | self.lab_addTest_6.setObjectName("lab_addTest_6")
52 | self.verticalLayout.addWidget(self.lab_addTest_6)
53 | self.horizontalLayout.addLayout(self.verticalLayout)
54 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
55 | self.verticalLayout_2.setObjectName("verticalLayout_2")
56 | self.comboBox_delCheckTable = QtWidgets.QComboBox(self.layoutWidget)
57 | self.comboBox_delCheckTable.setObjectName("comboBox_delCheckTable")
58 | self.verticalLayout_2.addWidget(self.comboBox_delCheckTable)
59 | self.horizontalLayout.addLayout(self.verticalLayout_2)
60 | self.verticalLayout_3.addLayout(self.horizontalLayout)
61 | self.verticalLayout_4.addLayout(self.verticalLayout_3)
62 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
63 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
64 | self.btn_confirm = QtWidgets.QPushButton(self.layoutWidget)
65 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
66 | sizePolicy.setHorizontalStretch(0)
67 | sizePolicy.setVerticalStretch(0)
68 | sizePolicy.setHeightForWidth(self.btn_confirm.sizePolicy().hasHeightForWidth())
69 | self.btn_confirm.setSizePolicy(sizePolicy)
70 | self.btn_confirm.setMaximumSize(QtCore.QSize(200, 60))
71 | font = QtGui.QFont()
72 | font.setPointSize(16)
73 | font.setBold(False)
74 | font.setWeight(50)
75 | self.btn_confirm.setFont(font)
76 | self.btn_confirm.setLayoutDirection(QtCore.Qt.LeftToRight)
77 | self.btn_confirm.setObjectName("btn_confirm")
78 | self.horizontalLayout_2.addWidget(self.btn_confirm)
79 | self.btn_refresh = QtWidgets.QPushButton(self.layoutWidget)
80 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
81 | sizePolicy.setHorizontalStretch(0)
82 | sizePolicy.setVerticalStretch(0)
83 | sizePolicy.setHeightForWidth(self.btn_refresh.sizePolicy().hasHeightForWidth())
84 | self.btn_refresh.setSizePolicy(sizePolicy)
85 | self.btn_refresh.setMaximumSize(QtCore.QSize(200, 60))
86 | font = QtGui.QFont()
87 | font.setPointSize(16)
88 | font.setBold(False)
89 | font.setWeight(50)
90 | self.btn_refresh.setFont(font)
91 | self.btn_refresh.setLayoutDirection(QtCore.Qt.LeftToRight)
92 | self.btn_refresh.setObjectName("btn_refresh")
93 | self.horizontalLayout_2.addWidget(self.btn_refresh)
94 | self.btn_cancel = QtWidgets.QPushButton(self.layoutWidget)
95 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
96 | sizePolicy.setHorizontalStretch(0)
97 | sizePolicy.setVerticalStretch(0)
98 | sizePolicy.setHeightForWidth(self.btn_cancel.sizePolicy().hasHeightForWidth())
99 | self.btn_cancel.setSizePolicy(sizePolicy)
100 | self.btn_cancel.setMaximumSize(QtCore.QSize(200, 60))
101 | font = QtGui.QFont()
102 | font.setPointSize(16)
103 | font.setBold(False)
104 | font.setWeight(50)
105 | self.btn_cancel.setFont(font)
106 | self.btn_cancel.setLayoutDirection(QtCore.Qt.LeftToRight)
107 | self.btn_cancel.setObjectName("btn_cancel")
108 | self.horizontalLayout_2.addWidget(self.btn_cancel)
109 | self.verticalLayout_4.addLayout(self.horizontalLayout_2)
110 |
111 | self.retranslateUi(Form_delCheckTable)
112 | QtCore.QMetaObject.connectSlotsByName(Form_delCheckTable)
113 |
114 | def retranslateUi(self, Form_delCheckTable):
115 | _translate = QtCore.QCoreApplication.translate
116 | Form_delCheckTable.setWindowTitle(_translate("Form_delCheckTable", "Form"))
117 | self.lab_addTest_8.setText(_translate("Form_delCheckTable", "删除考勤表"))
118 | self.lab_addTest_6.setText(_translate("Form_delCheckTable", "考勤表名称:"))
119 | self.btn_confirm.setText(_translate("Form_delCheckTable", "确定"))
120 | self.btn_refresh.setText(_translate("Form_delCheckTable", "刷新"))
121 | self.btn_cancel.setText(_translate("Form_delCheckTable", "取消"))
122 |
123 |
--------------------------------------------------------------------------------
/ui_src/addClassTable.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 496
10 | 255
11 |
12 |
13 |
14 | 添加班级表
15 |
16 |
17 |
18 |
19 | 70
20 | 50
21 | 344
22 | 164
23 |
24 |
25 |
26 | -
27 |
28 |
-
29 |
30 |
31 |
32 | 0
33 | 0
34 |
35 |
36 |
37 |
38 | 16
39 |
40 |
41 |
42 | Qt::LeftToRight
43 |
44 |
45 | 添加人脸数据表
46 |
47 |
48 | Qt::AlignCenter
49 |
50 |
51 |
52 | -
53 |
54 |
-
55 |
56 |
-
57 |
58 |
59 |
60 | 0
61 | 0
62 |
63 |
64 |
65 |
66 | 16
67 |
68 |
69 |
70 | Qt::LeftToRight
71 |
72 |
73 | 院系
74 |
75 |
76 | Qt::AlignCenter
77 |
78 |
79 |
80 | -
81 |
82 |
83 |
84 | 0
85 | 0
86 |
87 |
88 |
89 |
90 | 16
91 |
92 |
93 |
94 | Qt::LeftToRight
95 |
96 |
97 | 班级
98 |
99 |
100 | Qt::AlignCenter
101 |
102 |
103 |
104 |
105 |
106 | -
107 |
108 |
-
109 |
110 |
111 | true
112 |
113 |
114 |
115 | 0
116 | 0
117 |
118 |
119 |
120 |
121 | 16
122 |
123 |
124 |
125 | Qt::LeftToRight
126 |
127 |
128 |
129 | -
130 |
131 |
132 | true
133 |
134 |
135 |
136 | 0
137 | 0
138 |
139 |
140 |
141 |
142 | 16
143 |
144 |
145 |
146 | Qt::LeftToRight
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | -
157 |
158 |
-
159 |
160 |
161 |
162 | 0
163 | 0
164 |
165 |
166 |
167 |
168 | 200
169 | 60
170 |
171 |
172 |
173 |
174 | 16
175 | 50
176 | false
177 |
178 |
179 |
180 | Qt::LeftToRight
181 |
182 |
183 | 确定
184 |
185 |
186 |
187 | -
188 |
189 |
190 |
191 | 0
192 | 0
193 |
194 |
195 |
196 |
197 | 200
198 | 60
199 |
200 |
201 |
202 |
203 | 16
204 | 50
205 | false
206 |
207 |
208 |
209 | Qt::LeftToRight
210 |
211 |
212 | 取消
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
--------------------------------------------------------------------------------
/tools/sqlite_func.py:
--------------------------------------------------------------------------------
1 | import sqlite3 as db
2 |
3 | test_db_path = "/home/lee/pyCode/PyQt5_Face_Recognition/DB/StudentFaceDB.db"
4 |
5 |
6 | class Sqlite_Func:
7 | def __init__(self):
8 |
9 | # 数据库数据库地址
10 | self.DB_STUDENTFACE_PATH = '../DB/StudentFaceDB.db'
11 | self.DB_STUDENTCHECKWORK_PATH = '../DB/StudentCheckWorkDB.db'
12 |
13 | # 数据库类型
14 | self.DB_TYPE_FACE = "studentfacedb.db".upper()
15 | self.DB_TYPE_CHECKWORK = "studentcheckworkdb.db".upper()
16 |
17 | self.dict_cmd = {}
18 |
19 | self.init_cmd()
20 |
21 | def init_cmd(self):
22 |
23 | # 创建人脸数据表
24 | self.dict_cmd[self.DB_TYPE_FACE] = "CREATE TABLE {}(" \
25 | "lable text not null," \
26 | "name text not null," \
27 | "sex text not null," \
28 | "id text primary key not null," \
29 | "profession text not null," \
30 | "features text not null);"
31 | # 创建学生考勤表
32 | self.dict_cmd[self.DB_TYPE_CHECKWORK] = "CREATE TABLE {}(" \
33 | "id text primary key not null," \
34 | "name text not null," \
35 | "flag text not null);"
36 |
37 | # 执行语句
38 | def executeCMD(self, db_path, cmd):
39 | if cmd == "":
40 | assert "func executeCMD error"
41 | conn = db.connect(db_path) # 该 API 打开一个到 SQLite 数据库文件 database 的链接,如果数据库成功打开,则返回一个连接对象
42 | if conn == None:
43 | return None
44 | cursor = conn.cursor() # 该例程创建一个 cursor,将在 Python 数据库编程中用到。
45 | conn.row_factory = db.Row # 可访问列信息
46 | print("cmd:",cmd)
47 | cursor.execute(cmd) # 该例程执行一个 SQL 语句
48 | rows = cursor.fetchall() # 该例程获取查询结果集中所有(剩余)的行,返回一个列表。当没有可用的行时,则返回一个空的列表。
49 | conn.commit()
50 | conn.close()
51 | return rows
52 |
53 | # 返回当前当前数据库所有表
54 | def check_table(self, db_path):
55 | print("返回当前当前数据库:{}所有表".format(db_path))
56 | self._table = "select name from sqlite_master where type='table' order by name"
57 | ret = self.executeCMD(db_path, self._table)
58 | self.table_list = []
59 | for i in ret:
60 | self.table_list.append(i[0])
61 | return self.table_list
62 |
63 | # 查看表结构
64 | def check_field(self, db_path, t):
65 | self.field_list = []
66 | self._schema = lambda t: "PRAGMA table_info({})".format(t)
67 | ret = self.executeCMD(db_path, self._schema(t))
68 | for i in ret:
69 | self.field_list.append(i[1])
70 | return self.field_list
71 |
72 | # 构建普通查询语句
73 | def auto_select(self, table, fields="*"):
74 |
75 | cmd = "select * from {};".format(table)
76 |
77 | if fields != "*":
78 | f = ', '.join(list(map(lambda x: x, fields)))
79 | cmd = "select {} from {};".format(f, table)
80 | return cmd
81 |
82 | # 插入emb
83 | def update_face_emb(self, db_path, table, id, data):
84 | print(data)
85 | emb_str = ''
86 | for i in range(len(data)):
87 | emb_str += str(data[i]) + ' '
88 | print(emb_str)
89 | cmd = 'UPDATE {table_name} SET features = "{emb}" WHERE id = {id};'.format(table_name=table,
90 | emb=emb_str, id=id)
91 | self.executeCMD(db_path, cmd)
92 |
93 | # 更新考勤
94 | def update_checkwork(self, db_path, table, id):
95 | cmd = 'UPDATE {table_name} SET flag = "{f}" WHERE id = {id};'.format(table_name=table,
96 | f="1", id=id)
97 | self.executeCMD(db_path, cmd)
98 | print("update checkwork done")
99 |
100 | # 更新
101 | def update(self, db_path, table, field, data, primary_key_index):
102 | print("upate new date...")
103 |
104 | for info in data:
105 | # 检查id是否被修改
106 | cmd = "select * from {} where {}='{}'".format(table,field[primary_key_index], info[primary_key_index])
107 | print("cmd->",cmd)
108 | ret = self.executeCMD(db_path, cmd)
109 | if ret == []:
110 | # 主键被修改
111 | return -3
112 |
113 | print("new data->", data)
114 | for info in data:
115 | for i in range(len(info)):
116 | if info == "":
117 | print("数据为空")
118 | return -1
119 |
120 | # 删除修改的数据项
121 | # DELETE FROM table_name WHERE primary key=val;
122 | print("删除旧数据")
123 | for i in range(len(data)):
124 | cmd = "delete from {} where {}='{}';".format(str(table), field[primary_key_index],
125 | data[i][primary_key_index])
126 | print("execute cmd={}".format(cmd))
127 | ret = self.executeCMD(db_path, cmd)
128 | if ret == []:
129 | print("delete success")
130 |
131 | # 插入新数据
132 | # INSERT INTO TABLE_NAME VALUES (value1,value2,value3,...valueN);
133 | print("插入新数据")
134 | for info in data:
135 | print("new data:", info)
136 | ret = self.insert(db_path, table, info)
137 | print("ret:", ret)
138 | return ret
139 |
140 | # 查找一个表中的主键位置
141 | # para:db路径,表名
142 | # return primary_key_index,primary_key
143 | def find_primary_key(self, db_path, table):
144 | cmd = "pragma table_info ({});".format(str(table))
145 | ret = self.executeCMD(db_path, cmd)
146 | print(ret)
147 | num = len(ret[0]) - 1
148 | for i in range(len(ret)):
149 | if ret[i][num] == 1:
150 | print("{}:{}是主键".format(i, ret[i][1]))
151 | return i, ret[i][1]
152 |
153 | # 删除
154 | # param:表,主键,参数
155 | def delete(self, db_path, table_name, primary_key, primary_key_index, data):
156 | # DELETE FROM table_name WHERE [condition];
157 | cmd = "DELETE FROM {} WHERE {}='{}';".format(table_name, primary_key, data[primary_key_index])
158 | print("del cmd:", cmd)
159 | self.executeCMD(db_path, cmd)
160 |
161 | def insert(self, db_path, table, data):
162 | # INSERT INTO TABLE_NAME VALUES (value1,value2,value3,...valueN);
163 | for i in data:
164 | if i == "":
165 | print("数据为空")
166 | return -1
167 | cmd = ', '.join(list(map(lambda x: "'" + x + "'", data)))
168 | cmd = "INSERT INTO {} VALUES ({});".format(table, cmd)
169 | print("execute cmd={}\n".format(cmd))
170 | try:
171 | ret = self.executeCMD(db_path, cmd)
172 | except:
173 | return -2
174 | return 0
175 |
176 | def delete_table(self, db_path, table_name):
177 | cmd = "DROP TABLE {};".format(table_name)
178 | print(cmd)
179 | self.executeCMD(db_path, cmd)
180 |
181 | # param->table_type:
182 | def create_table(self, db_path, table_name, db_type):
183 |
184 | print("create_table")
185 | cmd = self.dict_cmd[db_type].format(table_name)
186 | print(cmd)
187 |
188 | # 检查表名是否重复
189 | table_list = self.check_table(db_path)
190 | for i in table_list:
191 | if i == table_name:
192 | print("表名重复")
193 | return
194 |
195 | # 检查类型是否正确
196 | self.executeCMD(db_path, cmd)
197 |
198 |
199 | #
200 |
201 | if __name__ == "__main__":
202 | t = Sqlite_Func()
203 | print(t.dict_cmd)
204 |
--------------------------------------------------------------------------------
/ui_src/addClassTable.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'addClassTable.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_AddClassTable(object):
12 | def setupUi(self, Form):
13 | Form.setObjectName("Form")
14 | Form.resize(496, 255)
15 | self.layoutWidget = QtWidgets.QWidget(Form)
16 | self.layoutWidget.setGeometry(QtCore.QRect(70, 50, 344, 164))
17 | self.layoutWidget.setObjectName("layoutWidget")
18 | self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.layoutWidget)
19 | self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
20 | self.verticalLayout_4.setObjectName("verticalLayout_4")
21 | self.verticalLayout_3 = QtWidgets.QVBoxLayout()
22 | self.verticalLayout_3.setObjectName("verticalLayout_3")
23 | self.lab_addTest_8 = QtWidgets.QLabel(self.layoutWidget)
24 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
25 | sizePolicy.setHorizontalStretch(0)
26 | sizePolicy.setVerticalStretch(0)
27 | sizePolicy.setHeightForWidth(self.lab_addTest_8.sizePolicy().hasHeightForWidth())
28 | self.lab_addTest_8.setSizePolicy(sizePolicy)
29 | font = QtGui.QFont()
30 | font.setPointSize(16)
31 | self.lab_addTest_8.setFont(font)
32 | self.lab_addTest_8.setLayoutDirection(QtCore.Qt.LeftToRight)
33 | self.lab_addTest_8.setAlignment(QtCore.Qt.AlignCenter)
34 | self.lab_addTest_8.setObjectName("lab_addTest_8")
35 | self.verticalLayout_3.addWidget(self.lab_addTest_8)
36 | self.horizontalLayout = QtWidgets.QHBoxLayout()
37 | self.horizontalLayout.setObjectName("horizontalLayout")
38 | self.verticalLayout = QtWidgets.QVBoxLayout()
39 | self.verticalLayout.setObjectName("verticalLayout")
40 | self.lab_addTest_6 = QtWidgets.QLabel(self.layoutWidget)
41 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
42 | sizePolicy.setHorizontalStretch(0)
43 | sizePolicy.setVerticalStretch(0)
44 | sizePolicy.setHeightForWidth(self.lab_addTest_6.sizePolicy().hasHeightForWidth())
45 | self.lab_addTest_6.setSizePolicy(sizePolicy)
46 | font = QtGui.QFont()
47 | font.setPointSize(16)
48 | self.lab_addTest_6.setFont(font)
49 | self.lab_addTest_6.setLayoutDirection(QtCore.Qt.LeftToRight)
50 | self.lab_addTest_6.setAlignment(QtCore.Qt.AlignCenter)
51 | self.lab_addTest_6.setObjectName("lab_addTest_6")
52 | self.verticalLayout.addWidget(self.lab_addTest_6)
53 | self.lab_addTest_7 = QtWidgets.QLabel(self.layoutWidget)
54 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
55 | sizePolicy.setHorizontalStretch(0)
56 | sizePolicy.setVerticalStretch(0)
57 | sizePolicy.setHeightForWidth(self.lab_addTest_7.sizePolicy().hasHeightForWidth())
58 | self.lab_addTest_7.setSizePolicy(sizePolicy)
59 | font = QtGui.QFont()
60 | font.setPointSize(16)
61 | self.lab_addTest_7.setFont(font)
62 | self.lab_addTest_7.setLayoutDirection(QtCore.Qt.LeftToRight)
63 | self.lab_addTest_7.setAlignment(QtCore.Qt.AlignCenter)
64 | self.lab_addTest_7.setObjectName("lab_addTest_7")
65 | self.verticalLayout.addWidget(self.lab_addTest_7)
66 | self.horizontalLayout.addLayout(self.verticalLayout)
67 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
68 | self.verticalLayout_2.setObjectName("verticalLayout_2")
69 | self.line_profession = QtWidgets.QLineEdit(self.layoutWidget)
70 | self.line_profession.setEnabled(True)
71 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
72 | sizePolicy.setHorizontalStretch(0)
73 | sizePolicy.setVerticalStretch(0)
74 | sizePolicy.setHeightForWidth(self.line_profession.sizePolicy().hasHeightForWidth())
75 | self.line_profession.setSizePolicy(sizePolicy)
76 | font = QtGui.QFont()
77 | font.setPointSize(16)
78 | self.line_profession.setFont(font)
79 | self.line_profession.setLayoutDirection(QtCore.Qt.LeftToRight)
80 | self.line_profession.setObjectName("line_profession")
81 | self.verticalLayout_2.addWidget(self.line_profession)
82 | self.line_class = QtWidgets.QLineEdit(self.layoutWidget)
83 | self.line_class.setEnabled(True)
84 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
85 | sizePolicy.setHorizontalStretch(0)
86 | sizePolicy.setVerticalStretch(0)
87 | sizePolicy.setHeightForWidth(self.line_class.sizePolicy().hasHeightForWidth())
88 | self.line_class.setSizePolicy(sizePolicy)
89 | font = QtGui.QFont()
90 | font.setPointSize(16)
91 | self.line_class.setFont(font)
92 | self.line_class.setLayoutDirection(QtCore.Qt.LeftToRight)
93 | self.line_class.setObjectName("line_class")
94 | self.verticalLayout_2.addWidget(self.line_class)
95 | self.horizontalLayout.addLayout(self.verticalLayout_2)
96 | self.verticalLayout_3.addLayout(self.horizontalLayout)
97 | self.verticalLayout_4.addLayout(self.verticalLayout_3)
98 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
99 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
100 | self.btn_confirm = QtWidgets.QPushButton(self.layoutWidget)
101 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
102 | sizePolicy.setHorizontalStretch(0)
103 | sizePolicy.setVerticalStretch(0)
104 | sizePolicy.setHeightForWidth(self.btn_confirm.sizePolicy().hasHeightForWidth())
105 | self.btn_confirm.setSizePolicy(sizePolicy)
106 | self.btn_confirm.setMaximumSize(QtCore.QSize(200, 60))
107 | font = QtGui.QFont()
108 | font.setPointSize(16)
109 | font.setBold(False)
110 | font.setWeight(50)
111 | self.btn_confirm.setFont(font)
112 | self.btn_confirm.setLayoutDirection(QtCore.Qt.LeftToRight)
113 | self.btn_confirm.setObjectName("btn_confirm")
114 | self.horizontalLayout_2.addWidget(self.btn_confirm)
115 | self.btn_cancel = QtWidgets.QPushButton(self.layoutWidget)
116 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
117 | sizePolicy.setHorizontalStretch(0)
118 | sizePolicy.setVerticalStretch(0)
119 | sizePolicy.setHeightForWidth(self.btn_cancel.sizePolicy().hasHeightForWidth())
120 | self.btn_cancel.setSizePolicy(sizePolicy)
121 | self.btn_cancel.setMaximumSize(QtCore.QSize(200, 60))
122 | font = QtGui.QFont()
123 | font.setPointSize(16)
124 | font.setBold(False)
125 | font.setWeight(50)
126 | self.btn_cancel.setFont(font)
127 | self.btn_cancel.setLayoutDirection(QtCore.Qt.LeftToRight)
128 | self.btn_cancel.setObjectName("btn_cancel")
129 | self.horizontalLayout_2.addWidget(self.btn_cancel)
130 | self.verticalLayout_4.addLayout(self.horizontalLayout_2)
131 |
132 | self.retranslateUi(Form)
133 | QtCore.QMetaObject.connectSlotsByName(Form)
134 |
135 | def retranslateUi(self, Form):
136 | _translate = QtCore.QCoreApplication.translate
137 | Form.setWindowTitle(_translate("Form", "添加班级表"))
138 | self.lab_addTest_8.setText(_translate("Form", "添加人脸数据表"))
139 | self.lab_addTest_6.setText(_translate("Form", "院系"))
140 | self.lab_addTest_7.setText(_translate("Form", "班级"))
141 | self.btn_confirm.setText(_translate("Form", "确定"))
142 | self.btn_cancel.setText(_translate("Form", "取消"))
143 |
144 |
--------------------------------------------------------------------------------
/ui_src/sqlite_main_window.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | SqliteMainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 922
10 | 688
11 |
12 |
13 |
14 | Sqlite Main Window
15 |
16 |
17 |
18 | -
19 |
20 |
21 | 选择一个表和若干字段
22 |
23 |
24 |
-
25 |
26 |
-
27 |
28 |
-
29 |
30 |
31 |
32 | 16
33 |
34 |
35 |
36 | 表
37 |
38 |
39 | Qt::AlignCenter
40 |
41 |
42 |
43 | -
44 |
45 |
46 | true
47 |
48 |
49 |
50 |
51 | 0
52 | 0
53 | 182
54 | 497
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | -
63 |
64 |
-
65 |
66 |
-
67 |
68 |
69 |
70 | 16
71 |
72 |
73 |
74 | 字段
75 |
76 |
77 | Qt::AlignCenter
78 |
79 |
80 |
81 | -
82 |
83 |
84 | true
85 |
86 |
87 |
88 |
89 | 0
90 | 0
91 | 180
92 | 412
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | -
101 |
102 |
103 |
104 |
105 |
106 |
-
107 |
108 |
-
109 |
110 |
111 |
112 | 12
113 |
114 |
115 |
116 | 全不选
117 |
118 |
119 |
120 | -
121 |
122 |
123 |
124 | 12
125 |
126 |
127 |
128 | 全选
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | -
145 |
146 |
147 | -
148 |
149 |
-
150 |
151 |
-
152 |
153 |
154 | 创建新表
155 |
156 |
157 |
158 | -
159 |
160 |
161 | 删除表
162 |
163 |
164 |
165 |
166 |
167 | -
168 |
169 |
-
170 |
171 |
172 | 添加数据
173 |
174 |
175 |
176 | -
177 |
178 |
179 | 删除数据
180 |
181 |
182 |
183 |
184 |
185 | -
186 |
187 |
-
188 |
189 |
190 | 更新数据
191 |
192 |
193 |
194 | -
195 |
196 |
197 | 查询数据
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | -
206 |
207 |
208 |
209 | 16
210 |
211 |
212 |
213 | 命令
214 |
215 |
216 | Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
217 |
218 |
219 |
220 | -
221 |
222 |
223 |
224 |
225 |
242 |
243 |
244 |
245 | Open File
246 |
247 |
248 |
249 |
250 |
251 |
252 |
--------------------------------------------------------------------------------
/src/SetUpMainWindow.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import sys
3 | import time
4 | import os
5 |
6 | from PyQt5.QtWidgets import *
7 | from PyQt5 import QtCore, QtGui, QtWidgets
8 | from PyQt5.QtWidgets import QMainWindow, QApplication
9 |
10 | import get_face
11 | import face_recognition
12 | # from file_op import File_Operate
13 | # from sqlite3_op import Operate_Sql
14 | from tools.sqlite_func import Sqlite_Func
15 |
16 | from ui_src.MainUI import Ui_Face_Recognition_window
17 | from Sqlite_UI import Sqlite_UI
18 |
19 |
20 | # 主窗口类
21 | class MainWindow(QMainWindow, Ui_Face_Recognition_window):
22 | # 构造函数
23 | def __init__(self, parent=None):
24 | super(MainWindow, self).__init__(parent)
25 | self.setupUi(self)
26 |
27 | self.sf = Sqlite_Func()
28 |
29 | # self.opsql = Operate_Sql()
30 |
31 | self.timer_camera_test = QtCore.QTimer() # qt计数器
32 | self.timer_camera_face = QtCore.QTimer() # qt计数器
33 |
34 | self.openSqlite = Sqlite_UI() # 数据库对象
35 | self.slot_init()
36 |
37 | self.combobox_face_init() # 初始化下拉列表:人脸数据表
38 | self.combobox_checkWork_init() # 初始化下拉列表:考勤数据表
39 |
40 | self.photoNum = 0 # 照片计数
41 | self.CAM_NUM = 0
42 | self.pNum = 0 # 照片计数器
43 | self.photo_transmission = 0 # 图片传输变量
44 | self.frame_out = 0
45 |
46 | # 启动Facenet模块
47 | self.face = face_recognition.face()
48 | self.init_db()
49 |
50 | def init_db(self):
51 | if os.path.exists("../DB/StudentFaceDB.db") is False:
52 | os.mkdir("../DB/StudentFaceDB.db")
53 | if os.path.exists("../DB/StudentCheckWorkDB.db.db") is False:
54 | os.mkdir("../DB/StudentCheckWorkDB.db.db")
55 |
56 | # 槽初始化
57 | def slot_init(self):
58 |
59 | self.timer_camera_test.timeout.connect(self.show_frame)
60 |
61 | self.btn_openCamera.clicked.connect(self.opencamera)
62 | self.btn_takePhoto.clicked.connect(self.take_photo)
63 |
64 | self.btn_refresh.clicked.connect(self.refresh)
65 |
66 | self.btn_train.clicked.connect(self.train)
67 | self.btn_recogniton.clicked.connect(self.open_recognition_camera)
68 | self.btn_sqlite.clicked.connect(self.open_sqlite)
69 |
70 | def open_sqlite(self):
71 | self.openSqlite.show()
72 |
73 | def opencamera(self):
74 | if self.timer_camera_test.isActive() == False:
75 | self.cap = cv2.VideoCapture(0)
76 | flag = self.cap.open(self.CAM_NUM)
77 | if flag is None:
78 | msg = QtWidgets.QMessageBox.warning(self, u"Warning", u"摄像头无法打开!",
79 | buttons=QtWidgets.QMessageBox.Ok,
80 | defaultButton=QtWidgets.QMessageBox.Ok)
81 | self.btn_openCamera.setText("关闭摄像头")
82 | self.timer_camera_test.start(25)
83 | else:
84 | self.btn_openCamera.setText(u"打开摄像头")
85 | self.timer_camera_test.stop()
86 | self.lab_frame.setText(u"无图像输入")
87 | self.cap.release()
88 |
89 | def show_frame(self):
90 | ret, frame = self.cap.read()
91 | if frame is None:
92 | return
93 | frame = cv2.flip(frame, 1)
94 | frame = cv2.resize(frame, (640, 480))
95 | self.photo_transmission = frame
96 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
97 | lable = cv2.putText(frame, '-->Camera OK', (10, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 0),
98 | thickness=1, lineType=1)
99 | showFrame = QtGui.QImage(frame.data, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
100 | self.lab_frame.setPixmap(QtGui.QPixmap.fromImage(showFrame))
101 |
102 | # 拍照
103 | def take_photo(self):
104 | '''
105 | 1、从数据库中读取所有文件名
106 | 2、从文件名中选择文件目录作为照片存储地址
107 | 3、调用拍照程序对当前画面进行拍照
108 | 4、更新拍照数量
109 | '''
110 |
111 | # 如果摄像头没有打开
112 | if self.btn_openCamera.text() != '关闭摄像头':
113 | msg = QtWidgets.QMessageBox.warning(self, u"Warning", u"请打开摄像头!",
114 | buttons=QtWidgets.QMessageBox.Ok,
115 | defaultButton=QtWidgets.QMessageBox.Ok)
116 | else:
117 | face = self.comboBox_face.currentText()
118 | id = self.comboBox_id.currentText()
119 | if id == '' or id is None:
120 | msg = QtWidgets.QMessageBox.warning(self, u"Warning", u"请选择学号!",
121 | buttons=QtWidgets.QMessageBox.Ok,
122 | defaultButton=QtWidgets.QMessageBox.Ok)
123 | else:
124 | name = '{CLASS}#{id}'.format(CLASS=face, id=id)
125 | name = '../src_img/{name}.jpg'.format(name=name)
126 | print(name)
127 | cv2.imwrite(name, self.photo_transmission)
128 |
129 | # 考勤表初始化
130 | def combobox_checkWork_init(self, checktable=None):
131 | self.comboBox_checkWork.clear()
132 |
133 | ret = self.sf.check_table(self.sf.DB_STUDENTCHECKWORK_PATH)
134 | print("DB:{}\ntables:{}\ntable_nmu:{}".format(self.sf.DB_STUDENTCHECKWORK_PATH, ret, len(ret)))
135 |
136 | readlines = len(ret)
137 | lineindex = 0
138 |
139 | while lineindex < readlines:
140 | self.comboBox_checkWork.addItem(ret[lineindex])
141 | lineindex += 1
142 | if checktable != '' or checktable is None:
143 | self.comboBox_checkWork.setCurrentText(checktable)
144 | print('combobox_checkWork_init done\n')
145 |
146 | # 获取人脸数据表
147 | def combobox_face_init(self, checked_table=None):
148 | self.comboBox_face.clear()
149 | ret = self.sf.check_table(self.sf.DB_STUDENTFACE_PATH)
150 | table_nmu = len(ret)
151 | print("DB:{}\ntables:{}\ntable_nmu:{}".format(self.sf.DB_STUDENTFACE_PATH, ret, len(ret)))
152 | readlines = table_nmu
153 | lineindex = 0
154 |
155 | while lineindex < readlines:
156 | self.comboBox_face.addItem(ret[lineindex])
157 | lineindex += 1
158 | if checked_table != '' or checked_table is None:
159 | self.comboBox_face.setCurrentText(checked_table)
160 | print('combobox_face_init done\n')
161 |
162 | # 初始化id列表
163 | self.combobox_id_init(self.comboBox_face.currentText())
164 |
165 | def combobox_id_init(self, table):
166 | # if table == "":
167 | # return
168 | # 读取人脸数据库中所有id
169 | field = []
170 | field.append("id")
171 | print('====', table)
172 | cmd = self.sf.auto_select(table, field)
173 | print("cmd-->", cmd)
174 | ret = self.sf.executeCMD(self.sf.DB_STUDENTFACE_PATH, cmd)
175 | print("ret:", ret)
176 |
177 | self.comboBox_id.clear()
178 | print(len(ret))
179 | for i in range(len(ret)):
180 | self.comboBox_id.addItem(str(ret[i][0]))
181 |
182 | # 刷新显示数据库并且显示id号
183 | def refresh(self):
184 |
185 | # 获取当前选中表明
186 | checked_face = self.comboBox_face.currentText()
187 | checked_cw = self.comboBox_checkWork.currentText()
188 |
189 | print("当前选中:{},{}".format(checked_face, checked_cw))
190 |
191 | self.combobox_face_init(checked_table=checked_face)
192 | self.combobox_checkWork_init(checktable=checked_cw)
193 |
194 | def train(self):
195 |
196 | ret = QMessageBox.question(self, "Train", "训练过程中,画面无法更新,训练时间随机器性能决定", QMessageBox.Yes | QMessageBox.No,
197 | QMessageBox.No)
198 | if ret == QMessageBox.Yes:
199 | get_face.detection()
200 |
201 | # 打开识别摄像头
202 | def open_recognition_camera(self):
203 |
204 | if self.btn_openCamera.text() == '关闭摄像头':
205 | msg = QtWidgets.QMessageBox.warning(self, u"警告", u"请先关闭摄像头!",
206 | buttons=QtWidgets.QMessageBox.Ok,
207 | defaultButton=QtWidgets.QMessageBox.Ok)
208 | else:
209 | ret = QMessageBox.question(self, "Train", "1、启动时间根据设备性能强弱决定\n\n2、程序启动后按下esc退出检测窗口",
210 | QMessageBox.Yes | QMessageBox.No,
211 | QMessageBox.No)
212 | if ret == QMessageBox.Yes:
213 | print('开启摄像头')
214 | face = self.comboBox_face.currentText()
215 | cw = self.comboBox_checkWork.currentText()
216 | self.face.main(face, cw)
217 |
218 |
219 | if __name__ == "__main__":
220 | app = QApplication(sys.argv)
221 | ui = MainWindow()
222 | ui.show()
223 | sys.exit((app.exec_()))
224 |
--------------------------------------------------------------------------------
/ui_src/sqlite_main_window.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'sqlite_main_window.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_SqliteMainWindow(object):
12 | def setupUi(self, SqliteMainWindow):
13 | SqliteMainWindow.setObjectName("SqliteMainWindow")
14 | SqliteMainWindow.resize(922, 688)
15 | self.centralwidget = QtWidgets.QWidget(SqliteMainWindow)
16 | self.centralwidget.setObjectName("centralwidget")
17 | self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
18 | self.gridLayout.setObjectName("gridLayout")
19 | self.groupBox_table_field = QtWidgets.QGroupBox(self.centralwidget)
20 | self.groupBox_table_field.setObjectName("groupBox_table_field")
21 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_table_field)
22 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
23 | self.horizontalLayout = QtWidgets.QHBoxLayout()
24 | self.horizontalLayout.setObjectName("horizontalLayout")
25 | self.verticalLayout_6 = QtWidgets.QVBoxLayout()
26 | self.verticalLayout_6.setObjectName("verticalLayout_6")
27 | self.label_table = QtWidgets.QLabel(self.groupBox_table_field)
28 | font = QtGui.QFont()
29 | font.setPointSize(16)
30 | self.label_table.setFont(font)
31 | self.label_table.setAlignment(QtCore.Qt.AlignCenter)
32 | self.label_table.setObjectName("label_table")
33 | self.verticalLayout_6.addWidget(self.label_table)
34 | self.scrollArea_table = QtWidgets.QScrollArea(self.groupBox_table_field)
35 | self.scrollArea_table.setWidgetResizable(True)
36 | self.scrollArea_table.setObjectName("scrollArea_table")
37 | self.scrollAreaWidgetContents = QtWidgets.QWidget()
38 | self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 182, 497))
39 | self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
40 | self.scrollArea_table.setWidget(self.scrollAreaWidgetContents)
41 | self.verticalLayout_6.addWidget(self.scrollArea_table)
42 | self.horizontalLayout.addLayout(self.verticalLayout_6)
43 | self.verticalLayout_5 = QtWidgets.QVBoxLayout()
44 | self.verticalLayout_5.setObjectName("verticalLayout_5")
45 | self.verticalLayout_4 = QtWidgets.QVBoxLayout()
46 | self.verticalLayout_4.setObjectName("verticalLayout_4")
47 | self.label_field = QtWidgets.QLabel(self.groupBox_table_field)
48 | font = QtGui.QFont()
49 | font.setPointSize(16)
50 | self.label_field.setFont(font)
51 | self.label_field.setAlignment(QtCore.Qt.AlignCenter)
52 | self.label_field.setObjectName("label_field")
53 | self.verticalLayout_4.addWidget(self.label_field)
54 | self.scrollArea_field = QtWidgets.QScrollArea(self.groupBox_table_field)
55 | self.scrollArea_field.setWidgetResizable(True)
56 | self.scrollArea_field.setObjectName("scrollArea_field")
57 | self.scrollAreaWidgetContents_2 = QtWidgets.QWidget()
58 | self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 180, 412))
59 | self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2")
60 | self.scrollArea_field.setWidget(self.scrollAreaWidgetContents_2)
61 | self.verticalLayout_4.addWidget(self.scrollArea_field)
62 | self.verticalLayout_5.addLayout(self.verticalLayout_4)
63 | self.groupBox = QtWidgets.QGroupBox(self.groupBox_table_field)
64 | self.groupBox.setTitle("")
65 | self.groupBox.setObjectName("groupBox")
66 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox)
67 | self.verticalLayout_3.setObjectName("verticalLayout_3")
68 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
69 | self.horizontalLayout_3.setObjectName("horizontalLayout_3")
70 | self.radioButton_notall = QtWidgets.QRadioButton(self.groupBox)
71 | font = QtGui.QFont()
72 | font.setPointSize(12)
73 | self.radioButton_notall.setFont(font)
74 | self.radioButton_notall.setObjectName("radioButton_notall")
75 | self.horizontalLayout_3.addWidget(self.radioButton_notall)
76 | self.radioButton_all = QtWidgets.QRadioButton(self.groupBox)
77 | font = QtGui.QFont()
78 | font.setPointSize(12)
79 | self.radioButton_all.setFont(font)
80 | self.radioButton_all.setObjectName("radioButton_all")
81 | self.horizontalLayout_3.addWidget(self.radioButton_all)
82 | self.verticalLayout_3.addLayout(self.horizontalLayout_3)
83 | self.verticalLayout_5.addWidget(self.groupBox)
84 | self.horizontalLayout.addLayout(self.verticalLayout_5)
85 | self.horizontalLayout_2.addLayout(self.horizontalLayout)
86 | self.gridLayout.addWidget(self.groupBox_table_field, 0, 0, 1, 1)
87 | self.tableView_content = QtWidgets.QTableView(self.centralwidget)
88 | self.tableView_content.setObjectName("tableView_content")
89 | self.gridLayout.addWidget(self.tableView_content, 0, 1, 1, 1)
90 | self.verticalLayout_8 = QtWidgets.QVBoxLayout()
91 | self.verticalLayout_8.setObjectName("verticalLayout_8")
92 | self.verticalLayout = QtWidgets.QVBoxLayout()
93 | self.verticalLayout.setObjectName("verticalLayout")
94 | self.pushButton_newTable = QtWidgets.QPushButton(self.centralwidget)
95 | self.pushButton_newTable.setObjectName("pushButton_newTable")
96 | self.verticalLayout.addWidget(self.pushButton_newTable)
97 | self.pushButton_delTable = QtWidgets.QPushButton(self.centralwidget)
98 | self.pushButton_delTable.setObjectName("pushButton_delTable")
99 | self.verticalLayout.addWidget(self.pushButton_delTable)
100 | self.verticalLayout_8.addLayout(self.verticalLayout)
101 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
102 | self.verticalLayout_2.setObjectName("verticalLayout_2")
103 | self.pushButton_add = QtWidgets.QPushButton(self.centralwidget)
104 | self.pushButton_add.setObjectName("pushButton_add")
105 | self.verticalLayout_2.addWidget(self.pushButton_add)
106 | self.pushButton_del = QtWidgets.QPushButton(self.centralwidget)
107 | self.pushButton_del.setObjectName("pushButton_del")
108 | self.verticalLayout_2.addWidget(self.pushButton_del)
109 | self.verticalLayout_8.addLayout(self.verticalLayout_2)
110 | self.verticalLayout_7 = QtWidgets.QVBoxLayout()
111 | self.verticalLayout_7.setObjectName("verticalLayout_7")
112 | self.pushButton_update = QtWidgets.QPushButton(self.centralwidget)
113 | self.pushButton_update.setObjectName("pushButton_update")
114 | self.verticalLayout_7.addWidget(self.pushButton_update)
115 | self.pushButton_query = QtWidgets.QPushButton(self.centralwidget)
116 | self.pushButton_query.setObjectName("pushButton_query")
117 | self.verticalLayout_7.addWidget(self.pushButton_query)
118 | self.verticalLayout_8.addLayout(self.verticalLayout_7)
119 | self.gridLayout.addLayout(self.verticalLayout_8, 0, 2, 1, 1)
120 | self.label_cmd = QtWidgets.QLabel(self.centralwidget)
121 | font = QtGui.QFont()
122 | font.setPointSize(16)
123 | self.label_cmd.setFont(font)
124 | self.label_cmd.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
125 | self.label_cmd.setObjectName("label_cmd")
126 | self.gridLayout.addWidget(self.label_cmd, 1, 0, 1, 1)
127 | self.lineEdit_cmd = QtWidgets.QLineEdit(self.centralwidget)
128 | self.lineEdit_cmd.setObjectName("lineEdit_cmd")
129 | self.gridLayout.addWidget(self.lineEdit_cmd, 1, 1, 1, 1)
130 | SqliteMainWindow.setCentralWidget(self.centralwidget)
131 | self.menubar = QtWidgets.QMenuBar(SqliteMainWindow)
132 | self.menubar.setGeometry(QtCore.QRect(0, 0, 922, 23))
133 | self.menubar.setObjectName("menubar")
134 | self.menuFile = QtWidgets.QMenu(self.menubar)
135 | self.menuFile.setObjectName("menuFile")
136 | SqliteMainWindow.setMenuBar(self.menubar)
137 | self.statusbar = QtWidgets.QStatusBar(SqliteMainWindow)
138 | self.statusbar.setObjectName("statusbar")
139 | SqliteMainWindow.setStatusBar(self.statusbar)
140 | self.actionOpen_File = QtWidgets.QAction(SqliteMainWindow)
141 | self.actionOpen_File.setObjectName("actionOpen_File")
142 | self.menuFile.addAction(self.actionOpen_File)
143 | self.menubar.addAction(self.menuFile.menuAction())
144 |
145 | self.retranslateUi(SqliteMainWindow)
146 | QtCore.QMetaObject.connectSlotsByName(SqliteMainWindow)
147 |
148 | def retranslateUi(self, SqliteMainWindow):
149 | _translate = QtCore.QCoreApplication.translate
150 | SqliteMainWindow.setWindowTitle(_translate("SqliteMainWindow", "Sqlite Main Window"))
151 | self.groupBox_table_field.setTitle(_translate("SqliteMainWindow", "选择一个表和若干字段"))
152 | self.label_table.setText(_translate("SqliteMainWindow", "表"))
153 | self.label_field.setText(_translate("SqliteMainWindow", "字段"))
154 | self.radioButton_notall.setText(_translate("SqliteMainWindow", "全不选"))
155 | self.radioButton_all.setText(_translate("SqliteMainWindow", "全选"))
156 | self.pushButton_newTable.setText(_translate("SqliteMainWindow", "创建新表"))
157 | self.pushButton_delTable.setText(_translate("SqliteMainWindow", " 删除表"))
158 | self.pushButton_add.setText(_translate("SqliteMainWindow", "添加数据"))
159 | self.pushButton_del.setText(_translate("SqliteMainWindow", "删除数据"))
160 | self.pushButton_update.setText(_translate("SqliteMainWindow", "更新数据"))
161 | self.pushButton_query.setText(_translate("SqliteMainWindow", "查询数据"))
162 | self.label_cmd.setText(_translate("SqliteMainWindow", "命令"))
163 | self.menuFile.setTitle(_translate("SqliteMainWindow", "File"))
164 | self.actionOpen_File.setText(_translate("SqliteMainWindow", "Open File"))
165 |
166 |
--------------------------------------------------------------------------------
/ui_src/MainUI.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Face_Recognition_window
4 |
5 |
6 |
7 | 0
8 | 0
9 | 843
10 | 694
11 |
12 |
13 |
14 |
15 | 843
16 | 694
17 |
18 |
19 |
20 |
21 | 843
22 | 694
23 |
24 |
25 |
26 | ArrowCursor
27 |
28 |
29 | 人脸识别1.0
30 |
31 |
32 |
33 |
34 |
35 | 30
36 | 40
37 | 798
38 | 603
39 |
40 |
41 |
42 | -
43 |
44 |
-
45 |
46 |
47 | true
48 |
49 |
50 |
51 | 641
52 | 481
53 |
54 |
55 |
56 |
57 | 641
58 | 481
59 |
60 |
61 |
62 |
63 | 30
64 | 50
65 | false
66 |
67 |
68 |
69 |
70 |
71 |
72 | 没有图像输入
73 |
74 |
75 | Qt::RichText
76 |
77 |
78 | Qt::AlignCenter
79 |
80 |
81 |
82 | -
83 |
84 |
-
85 |
86 |
-
87 |
88 |
89 |
90 | 16
91 |
92 |
93 |
94 | 选择人脸数据表(Face)
95 |
96 |
97 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
98 |
99 |
100 |
101 | -
102 |
103 |
104 |
105 | 16
106 |
107 |
108 |
109 | 选择学号(Face)
110 |
111 |
112 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
113 |
114 |
115 |
116 | -
117 |
118 |
119 |
120 | 16
121 |
122 |
123 |
124 | 选择考勤表(CheckWork)
125 |
126 |
127 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
128 |
129 |
130 |
131 |
132 |
133 | -
134 |
135 |
-
136 |
137 |
138 | -
139 |
140 |
141 | -
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | -
151 |
152 |
-
153 |
154 |
155 |
156 | 200
157 | 60
158 |
159 |
160 |
161 |
162 | 16
163 | 50
164 | false
165 |
166 |
167 |
168 | 打开摄像头
169 |
170 |
171 |
172 | -
173 |
174 |
175 |
176 | 50
177 | 50
178 |
179 |
180 |
181 |
182 | 200
183 | 60
184 |
185 |
186 |
187 |
188 | 16
189 | 50
190 | false
191 |
192 |
193 |
194 | 数据库管理
195 |
196 |
197 | 100
198 |
199 |
200 |
201 | -
202 |
203 |
204 |
205 | 200
206 | 60
207 |
208 |
209 |
210 |
211 | 16
212 | 50
213 | false
214 |
215 |
216 |
217 | 录入人脸
218 |
219 |
220 |
221 | -
222 |
223 |
224 |
225 | 100
226 | 50
227 |
228 |
229 |
230 |
231 | 200
232 | 60
233 |
234 |
235 |
236 |
237 | 16
238 | 50
239 | false
240 |
241 |
242 |
243 | 生成模型
244 |
245 |
246 |
247 | -
248 |
249 |
250 |
251 | 100
252 | 50
253 |
254 |
255 |
256 |
257 | 200
258 | 60
259 |
260 |
261 |
262 |
263 | 16
264 | 50
265 | false
266 |
267 |
268 |
269 | 开始检测
270 |
271 |
272 |
273 | -
274 |
275 |
276 |
277 | 100
278 | 50
279 |
280 |
281 |
282 |
283 | 200
284 | 60
285 |
286 |
287 |
288 |
289 | 16
290 | 50
291 | false
292 |
293 |
294 |
295 | 刷新
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
314 |
315 |
316 |
317 | 添加人脸
318 |
319 |
320 |
321 |
322 | 删除人脸
323 |
324 |
325 |
326 |
327 | 操作细节
328 |
329 |
330 |
331 |
332 | 退出
333 |
334 |
335 |
336 |
337 | 关于作者
338 |
339 |
340 |
341 |
342 | 添加人脸数据表
343 |
344 |
345 |
346 |
347 | 删除人脸数据表
348 |
349 |
350 |
351 |
352 | 添加考勤表
353 |
354 |
355 |
356 |
357 | 删除考勤表
358 |
359 |
360 |
361 |
362 |
363 |
364 |
--------------------------------------------------------------------------------
/ui_src/MainUI.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'MainUI.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Face_Recognition_window(object):
12 | def setupUi(self, Face_Recognition_window):
13 | Face_Recognition_window.setObjectName("Face_Recognition_window")
14 | Face_Recognition_window.resize(843, 694)
15 | Face_Recognition_window.setMinimumSize(QtCore.QSize(843, 694))
16 | Face_Recognition_window.setMaximumSize(QtCore.QSize(843, 694))
17 | Face_Recognition_window.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
18 | self.centralwidget = QtWidgets.QWidget(Face_Recognition_window)
19 | self.centralwidget.setObjectName("centralwidget")
20 | self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
21 | self.layoutWidget.setGeometry(QtCore.QRect(30, 40, 798, 603))
22 | self.layoutWidget.setObjectName("layoutWidget")
23 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
24 | self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
25 | self.horizontalLayout.setObjectName("horizontalLayout")
26 | self.verticalLayout = QtWidgets.QVBoxLayout()
27 | self.verticalLayout.setObjectName("verticalLayout")
28 | self.lab_frame = QtWidgets.QLabel(self.layoutWidget)
29 | self.lab_frame.setEnabled(True)
30 | self.lab_frame.setMinimumSize(QtCore.QSize(641, 481))
31 | self.lab_frame.setMaximumSize(QtCore.QSize(641, 481))
32 | font = QtGui.QFont()
33 | font.setPointSize(30)
34 | font.setBold(False)
35 | font.setWeight(50)
36 | self.lab_frame.setFont(font)
37 | self.lab_frame.setToolTip("")
38 | self.lab_frame.setTextFormat(QtCore.Qt.RichText)
39 | self.lab_frame.setAlignment(QtCore.Qt.AlignCenter)
40 | self.lab_frame.setObjectName("lab_frame")
41 | self.verticalLayout.addWidget(self.lab_frame)
42 | self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
43 | self.horizontalLayout_3.setObjectName("horizontalLayout_3")
44 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
45 | self.verticalLayout_2.setObjectName("verticalLayout_2")
46 | self.lab_selecCalss = QtWidgets.QLabel(self.layoutWidget)
47 | font = QtGui.QFont()
48 | font.setPointSize(16)
49 | self.lab_selecCalss.setFont(font)
50 | self.lab_selecCalss.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
51 | self.lab_selecCalss.setObjectName("lab_selecCalss")
52 | self.verticalLayout_2.addWidget(self.lab_selecCalss)
53 | self.lab_selecLable = QtWidgets.QLabel(self.layoutWidget)
54 | font = QtGui.QFont()
55 | font.setPointSize(16)
56 | self.lab_selecLable.setFont(font)
57 | self.lab_selecLable.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
58 | self.lab_selecLable.setObjectName("lab_selecLable")
59 | self.verticalLayout_2.addWidget(self.lab_selecLable)
60 | self.lab_selecLable_2 = QtWidgets.QLabel(self.layoutWidget)
61 | font = QtGui.QFont()
62 | font.setPointSize(16)
63 | self.lab_selecLable_2.setFont(font)
64 | self.lab_selecLable_2.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
65 | self.lab_selecLable_2.setObjectName("lab_selecLable_2")
66 | self.verticalLayout_2.addWidget(self.lab_selecLable_2)
67 | self.horizontalLayout_3.addLayout(self.verticalLayout_2)
68 | self.verticalLayout_3 = QtWidgets.QVBoxLayout()
69 | self.verticalLayout_3.setObjectName("verticalLayout_3")
70 | self.comboBox_face = QtWidgets.QComboBox(self.layoutWidget)
71 | self.comboBox_face.setObjectName("comboBox_face")
72 | self.verticalLayout_3.addWidget(self.comboBox_face)
73 | self.comboBox_id = QtWidgets.QComboBox(self.layoutWidget)
74 | self.comboBox_id.setObjectName("comboBox_id")
75 | self.verticalLayout_3.addWidget(self.comboBox_id)
76 | self.comboBox_checkWork = QtWidgets.QComboBox(self.layoutWidget)
77 | self.comboBox_checkWork.setObjectName("comboBox_checkWork")
78 | self.verticalLayout_3.addWidget(self.comboBox_checkWork)
79 | self.horizontalLayout_3.addLayout(self.verticalLayout_3)
80 | self.verticalLayout.addLayout(self.horizontalLayout_3)
81 | self.horizontalLayout.addLayout(self.verticalLayout)
82 | self.verticalLayout_4 = QtWidgets.QVBoxLayout()
83 | self.verticalLayout_4.setObjectName("verticalLayout_4")
84 | self.btn_openCamera = QtWidgets.QPushButton(self.layoutWidget)
85 | self.btn_openCamera.setMaximumSize(QtCore.QSize(200, 60))
86 | font = QtGui.QFont()
87 | font.setPointSize(16)
88 | font.setBold(False)
89 | font.setWeight(50)
90 | self.btn_openCamera.setFont(font)
91 | self.btn_openCamera.setObjectName("btn_openCamera")
92 | self.verticalLayout_4.addWidget(self.btn_openCamera)
93 | self.btn_sqlite = QtWidgets.QPushButton(self.layoutWidget)
94 | self.btn_sqlite.setMinimumSize(QtCore.QSize(50, 50))
95 | self.btn_sqlite.setMaximumSize(QtCore.QSize(200, 60))
96 | font = QtGui.QFont()
97 | font.setPointSize(16)
98 | font.setBold(False)
99 | font.setWeight(50)
100 | self.btn_sqlite.setFont(font)
101 | self.btn_sqlite.setAutoRepeatInterval(100)
102 | self.btn_sqlite.setObjectName("btn_sqlite")
103 | self.verticalLayout_4.addWidget(self.btn_sqlite)
104 | self.btn_takePhoto = QtWidgets.QPushButton(self.layoutWidget)
105 | self.btn_takePhoto.setMaximumSize(QtCore.QSize(200, 60))
106 | font = QtGui.QFont()
107 | font.setPointSize(16)
108 | font.setBold(False)
109 | font.setWeight(50)
110 | self.btn_takePhoto.setFont(font)
111 | self.btn_takePhoto.setObjectName("btn_takePhoto")
112 | self.verticalLayout_4.addWidget(self.btn_takePhoto)
113 | self.btn_train = QtWidgets.QPushButton(self.layoutWidget)
114 | self.btn_train.setMinimumSize(QtCore.QSize(100, 50))
115 | self.btn_train.setMaximumSize(QtCore.QSize(200, 60))
116 | font = QtGui.QFont()
117 | font.setPointSize(16)
118 | font.setBold(False)
119 | font.setWeight(50)
120 | self.btn_train.setFont(font)
121 | self.btn_train.setObjectName("btn_train")
122 | self.verticalLayout_4.addWidget(self.btn_train)
123 | self.btn_recogniton = QtWidgets.QPushButton(self.layoutWidget)
124 | self.btn_recogniton.setMinimumSize(QtCore.QSize(100, 50))
125 | self.btn_recogniton.setMaximumSize(QtCore.QSize(200, 60))
126 | font = QtGui.QFont()
127 | font.setPointSize(16)
128 | font.setBold(False)
129 | font.setWeight(50)
130 | self.btn_recogniton.setFont(font)
131 | self.btn_recogniton.setObjectName("btn_recogniton")
132 | self.verticalLayout_4.addWidget(self.btn_recogniton)
133 | self.btn_refresh = QtWidgets.QPushButton(self.layoutWidget)
134 | self.btn_refresh.setMinimumSize(QtCore.QSize(100, 50))
135 | self.btn_refresh.setMaximumSize(QtCore.QSize(200, 60))
136 | font = QtGui.QFont()
137 | font.setPointSize(16)
138 | font.setBold(False)
139 | font.setWeight(50)
140 | self.btn_refresh.setFont(font)
141 | self.btn_refresh.setObjectName("btn_refresh")
142 | self.verticalLayout_4.addWidget(self.btn_refresh)
143 | self.horizontalLayout.addLayout(self.verticalLayout_4)
144 | Face_Recognition_window.setCentralWidget(self.centralwidget)
145 | self.menubar = QtWidgets.QMenuBar(Face_Recognition_window)
146 | self.menubar.setGeometry(QtCore.QRect(0, 0, 843, 23))
147 | self.menubar.setObjectName("menubar")
148 | Face_Recognition_window.setMenuBar(self.menubar)
149 | self.statusbar = QtWidgets.QStatusBar(Face_Recognition_window)
150 | self.statusbar.setObjectName("statusbar")
151 | Face_Recognition_window.setStatusBar(self.statusbar)
152 | self.actionAdd_Person = QtWidgets.QAction(Face_Recognition_window)
153 | self.actionAdd_Person.setObjectName("actionAdd_Person")
154 | self.actionDelete_Person = QtWidgets.QAction(Face_Recognition_window)
155 | self.actionDelete_Person.setObjectName("actionDelete_Person")
156 | self.actionHelp = QtWidgets.QAction(Face_Recognition_window)
157 | self.actionHelp.setObjectName("actionHelp")
158 | self.actionExit = QtWidgets.QAction(Face_Recognition_window)
159 | self.actionExit.setObjectName("actionExit")
160 | self.actionauthor = QtWidgets.QAction(Face_Recognition_window)
161 | self.actionauthor.setObjectName("actionauthor")
162 | self.actionAddClass = QtWidgets.QAction(Face_Recognition_window)
163 | self.actionAddClass.setObjectName("actionAddClass")
164 | self.actionDelClass = QtWidgets.QAction(Face_Recognition_window)
165 | self.actionDelClass.setObjectName("actionDelClass")
166 | self.actionAddCheck = QtWidgets.QAction(Face_Recognition_window)
167 | self.actionAddCheck.setObjectName("actionAddCheck")
168 | self.actionDelCheck = QtWidgets.QAction(Face_Recognition_window)
169 | self.actionDelCheck.setObjectName("actionDelCheck")
170 |
171 | self.retranslateUi(Face_Recognition_window)
172 | QtCore.QMetaObject.connectSlotsByName(Face_Recognition_window)
173 |
174 | def retranslateUi(self, Face_Recognition_window):
175 | _translate = QtCore.QCoreApplication.translate
176 | Face_Recognition_window.setWindowTitle(_translate("Face_Recognition_window", "人脸识别1.0"))
177 | self.lab_frame.setText(_translate("Face_Recognition_window", "没有图像输入"))
178 | self.lab_selecCalss.setText(_translate("Face_Recognition_window", "选择人脸数据表(Face)"))
179 | self.lab_selecLable.setText(_translate("Face_Recognition_window", "选择学号(Face)"))
180 | self.lab_selecLable_2.setText(_translate("Face_Recognition_window", "选择考勤表(CheckWork)"))
181 | self.btn_openCamera.setText(_translate("Face_Recognition_window", "打开摄像头"))
182 | self.btn_sqlite.setText(_translate("Face_Recognition_window", "数据库管理"))
183 | self.btn_takePhoto.setText(_translate("Face_Recognition_window", "录入人脸"))
184 | self.btn_train.setText(_translate("Face_Recognition_window", "生成模型"))
185 | self.btn_recogniton.setText(_translate("Face_Recognition_window", "开始检测"))
186 | self.btn_refresh.setText(_translate("Face_Recognition_window", "刷新"))
187 | self.actionAdd_Person.setText(_translate("Face_Recognition_window", "添加人脸"))
188 | self.actionDelete_Person.setText(_translate("Face_Recognition_window", "删除人脸"))
189 | self.actionHelp.setText(_translate("Face_Recognition_window", "操作细节"))
190 | self.actionExit.setText(_translate("Face_Recognition_window", "退出"))
191 | self.actionauthor.setText(_translate("Face_Recognition_window", "关于作者"))
192 | self.actionAddClass.setText(_translate("Face_Recognition_window", "添加人脸数据表"))
193 | self.actionDelClass.setText(_translate("Face_Recognition_window", "删除人脸数据表"))
194 | self.actionAddCheck.setText(_translate("Face_Recognition_window", "添加考勤表"))
195 | self.actionDelCheck.setText(_translate("Face_Recognition_window", "删除考勤表"))
196 |
197 |
--------------------------------------------------------------------------------
/ui_src/addStudent.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Form
4 |
5 |
6 |
7 | 0
8 | 0
9 | 730
10 | 379
11 |
12 |
13 |
14 | 添加新用户
15 |
16 |
17 |
18 |
19 | 50
20 | 50
21 | 639
22 | 282
23 |
24 |
25 |
26 |
27 | 0
28 | 0
29 |
30 |
31 |
32 | -
33 |
34 |
-
35 |
36 |
-
37 |
38 |
39 |
40 | 0
41 | 0
42 |
43 |
44 |
45 |
46 | 16
47 |
48 |
49 |
50 | Qt::LeftToRight
51 |
52 |
53 | 选择人脸数据表
54 |
55 |
56 | Qt::AlignCenter
57 |
58 |
59 |
60 | -
61 |
62 |
63 |
64 | 0
65 | 0
66 |
67 |
68 |
69 |
70 | 16
71 |
72 |
73 |
74 | Qt::LeftToRight
75 |
76 |
77 | 添加用户标签(姓名拼音)
78 |
79 |
80 | Qt::AlignCenter
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 | 0
89 | 0
90 |
91 |
92 |
93 |
94 | 16
95 |
96 |
97 |
98 | Qt::LeftToRight
99 |
100 |
101 | 添加用户姓名
102 |
103 |
104 | Qt::AlignCenter
105 |
106 |
107 |
108 | -
109 |
110 |
111 |
112 | 0
113 | 0
114 |
115 |
116 |
117 |
118 | 16
119 |
120 |
121 |
122 | Qt::LeftToRight
123 |
124 |
125 | 添加用户性别
126 |
127 |
128 | Qt::AlignCenter
129 |
130 |
131 |
132 | -
133 |
134 |
135 |
136 | 0
137 | 0
138 |
139 |
140 |
141 |
142 | 16
143 |
144 |
145 |
146 | Qt::LeftToRight
147 |
148 |
149 | 添加用户学号
150 |
151 |
152 | Qt::AlignCenter
153 |
154 |
155 |
156 |
157 |
158 | -
159 |
160 |
-
161 |
162 |
163 |
164 | 0
165 | 0
166 |
167 |
168 |
169 |
170 | -
171 |
172 |
173 | true
174 |
175 |
176 |
177 | 0
178 | 0
179 |
180 |
181 |
182 |
183 | 16
184 |
185 |
186 |
187 | Qt::LeftToRight
188 |
189 |
190 |
191 | -
192 |
193 |
194 | true
195 |
196 |
197 |
198 | 0
199 | 0
200 |
201 |
202 |
203 |
204 | 16
205 |
206 |
207 |
208 | Qt::LeftToRight
209 |
210 |
211 |
212 | -
213 |
214 |
215 | true
216 |
217 |
218 |
219 | 0
220 | 0
221 |
222 |
223 |
224 |
225 | 16
226 |
227 |
228 |
229 | Qt::LeftToRight
230 |
231 |
232 |
233 | -
234 |
235 |
236 | true
237 |
238 |
239 |
240 | 0
241 | 0
242 |
243 |
244 |
245 |
246 | 16
247 |
248 |
249 |
250 | Qt::LeftToRight
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 | -
259 |
260 |
-
261 |
262 |
263 |
264 | 0
265 | 0
266 |
267 |
268 |
269 |
270 | 200
271 | 60
272 |
273 |
274 |
275 |
276 | 16
277 | 50
278 | false
279 |
280 |
281 |
282 | Qt::LeftToRight
283 |
284 |
285 | 确定
286 |
287 |
288 |
289 | -
290 |
291 |
292 |
293 | 0
294 | 0
295 |
296 |
297 |
298 |
299 | 200
300 | 60
301 |
302 |
303 |
304 |
305 | 16
306 | 50
307 | false
308 |
309 |
310 |
311 | Qt::LeftToRight
312 |
313 |
314 | 刷新
315 |
316 |
317 |
318 | -
319 |
320 |
321 |
322 | 0
323 | 0
324 |
325 |
326 |
327 |
328 | 200
329 | 60
330 |
331 |
332 |
333 |
334 | 16
335 | 50
336 | false
337 |
338 |
339 |
340 | Qt::LeftToRight
341 |
342 |
343 | 取消
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
--------------------------------------------------------------------------------
/src/face_recognition.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import imageio
6 | import cv2
7 | import tensorflow as tf
8 | import numpy as np
9 | import os
10 |
11 | import facenet
12 | import align.detect_face
13 | from tools.sqlite_func import Sqlite_Func
14 |
15 |
16 | # 交并比
17 | def iou(a, b):
18 | area_a = (a[2] - a[0]) * (a[3] - a[1])
19 | area_b = (b[2] - b[0]) * (b[3] - b[1])
20 |
21 | iou_x1 = np.maximum(a[0], b[0])
22 | iou_y1 = np.maximum(a[1], b[1])
23 | iou_x2 = np.minimum(a[2], b[2])
24 | iou_y2 = np.minimum(a[3], b[3])
25 |
26 | iou_w = iou_x2 - iou_x1
27 | iou_h = iou_y2 - iou_y1
28 | area_iou = iou_w * iou_h
29 | iou = area_iou / (area_a + area_b - area_iou)
30 |
31 | return iou
32 |
33 |
34 | # 获取最大人脸索引
35 | def max_face(area, position):
36 | max_face_position = []
37 | max_area_index = np.argmax(area)
38 | # print('最大面积索引:', np.argmax(area), '最大面积:', max(area))
39 | max_face_position = position[max_area_index]
40 | return max_face_position
41 |
42 |
43 | class face():
44 | def __init__(self):
45 | self.init_mtcnn()
46 | self.train = False
47 | self.sqlite = Sqlite_Func()
48 |
49 | # 初始化MTCNN
50 | def init_mtcnn(self):
51 | print('初始化MTCNN')
52 | with tf.Graph().as_default():
53 | gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=1.0)
54 | sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options,
55 | log_device_placement=False))
56 | with sess.as_default():
57 | global pnet, rnet, onet
58 | pnet, rnet, onet = align.detect_face.create_mtcnn(sess, None)
59 |
60 | # 提前计算pre_embadding
61 | def init_pre_embdading(slef):
62 | print('初始化 Facenet')
63 | with tf.Graph().as_default():
64 | with tf.Session() as sess:
65 | model = '../20170512-110547/'
66 | facenet.load_model(model)
67 | images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
68 | embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
69 | phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
70 | image = []
71 | nrof_images = 0
72 | global compare_emb, compare_num, all_obj_name
73 | emb_dir = '../emb_img'
74 | all_obj_name = []
75 | for i in os.listdir(emb_dir):
76 | all_obj_name.append(i)
77 | img = imageio.imread(os.path.join(emb_dir, i))
78 | print('img.shape:', img.shape)
79 | prewhitened = facenet.prewhiten(img) # 预白化去除冗余信息
80 | image.append(prewhitened)
81 | nrof_images = nrof_images + 1
82 | # global compare_emb, compare_num
83 | images = np.stack(image) # 沿着新轴连接数组的序列。
84 | feed_dict = {
85 | images_placeholder: images,
86 | phase_train_placeholder: False}
87 | # 计算对比图片embadding,embdadding是一个128维的张量
88 | compare_emb = sess.run(embeddings, feed_dict=feed_dict)
89 | print('compare_emb:', compare_emb)
90 | print('compare_emb_shape:', compare_emb.shape)
91 | compare_num = len(compare_emb)
92 | print("pre_embadding计算完成")
93 | return compare_emb, compare_num, all_obj_name # 数据库embadding,人数,目录标签
94 |
95 | def main(self, face, checkwork):
96 | with tf.Graph().as_default():
97 | with tf.Session() as sess:
98 | model = '../20170512-110547/'
99 | facenet.load_model(model)
100 | images_placeholder = tf.get_default_graph().get_tensor_by_name("input:0")
101 | embeddings = tf.get_default_graph().get_tensor_by_name("embeddings:0")
102 | phase_train_placeholder = tf.get_default_graph().get_tensor_by_name("phase_train:0")
103 |
104 | '''
105 | id:学号
106 | compare_emb:特征值
107 | compare_num:数据库中的数据条数
108 | '''
109 |
110 | # 找到当表主键
111 | face_key_idx, face_key = self.sqlite.find_primary_key(self.sqlite.DB_STUDENTFACE_PATH, face)
112 | # cw_key_idx,cw_key=self.sqlite.find_primary_key(self.sqlite.DB_STUDENTCHECKWORK_PATH,checkwork)
113 |
114 | # 从数据库获取人脸数据
115 | cmd = self.sqlite.auto_select(face)
116 | rows = self.sqlite.executeCMD(self.sqlite.DB_STUDENTFACE_PATH, cmd)
117 |
118 | id = []
119 |
120 | num = len(rows)
121 | emb_idx = len(rows[0]) - 1
122 |
123 | compare_num = num
124 | compare_emb = np.zeros([num, 128])
125 |
126 | for lineIndex in range(num):
127 | row = rows[lineIndex] # 获取某一行的数据,类型是tuple
128 | id.append(row[face_key_idx]) # 获取id
129 | emb_str = row[emb_idx] # 获取一个组数据中的emb数据
130 | if emb_str is None:
131 | compare_emb[lineIndex] = np.full((1, 128), 10)
132 | else:
133 | str_list = emb_str.split(' ') # 以空格分割字符串
134 | if len(str_list) < 10:
135 | continue
136 | for i in range(128):
137 | compare_emb[lineIndex][i] = float(str_list[i]) # 'list转ndarray:',str->float
138 |
139 | capture = cv2.VideoCapture(0)
140 | cv2.namedWindow("face recognition", 1)
141 |
142 | while True:
143 | ret, frame = capture.read()
144 | frame = cv2.flip(frame, 1)
145 | rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
146 |
147 | # 识别框
148 | cv2.putText(frame, 'Identification Box', (200, 90), cv2.FONT_HERSHEY_COMPLEX_SMALL,
149 | 1, (0, 0, 255),
150 | thickness=2,
151 | lineType=1)
152 | cv2.rectangle(frame, (150, 100), (490, 380), (165, 245, 25), 2)
153 | BOX = [150, 100, 490, 380]
154 |
155 | # 获取视频流中的最大人脸 判断标识 bounding_box crop_image
156 | mark, bounding_box, crop_image = self.load_and_align_data(rgb_frame, 160)
157 |
158 | '''
159 | 范围限制
160 | '''
161 | if mark:
162 | if bounding_box[0] < 75:
163 | mark = False
164 | # print('left')
165 | if bounding_box[2] > 565:
166 | mark = False
167 | # print('right')
168 |
169 | if mark:
170 | # print('计算视频帧的embadding')
171 | emb = sess.run(embeddings, feed_dict={images_placeholder: crop_image,
172 | phase_train_placeholder: False})
173 | pre_person_num = len(emb)
174 | find_obj = []
175 | # print('识别到的人数:', pre_person_num)
176 | cv2.putText(frame,
177 | 'Press esc to exit',
178 | (10, 30),
179 | cv2.FONT_HERSHEY_COMPLEX_SMALL,
180 | 1, (0, 0, 255),
181 | thickness=1,
182 | lineType=1)
183 | # 逐一对比
184 | for i in range(pre_person_num): # 为bounding_box 匹配标签
185 | dist_list = [] # 距离列表
186 |
187 | for j in range(compare_num):
188 | # 求误差(欧氏距离)
189 | dist = np.sqrt(np.sum(np.square(np.subtract(emb[i, :], compare_emb[j, :]))))
190 | dist_list.append(dist)
191 | # 求视频帧和对比图直接最小的差值,即表示为最相似的图片
192 | min_value = min(dist_list)
193 | # print("最小差值:", min_value)
194 | if min_value > 0.65:
195 | find_obj.append('Unknow')
196 | else:
197 | dist_index = dist_list.index(min_value)
198 | find_obj.append(id[dist_index])
199 |
200 | # 在frame上绘制边框和文字
201 | cv2.rectangle(frame,
202 | (bounding_box[0], bounding_box[1]),
203 | (bounding_box[2], bounding_box[3]),
204 | (0, 255, 0), 1, 8, 0)
205 | cv2.putText(frame, str(find_obj[0]),
206 | (bounding_box[0], bounding_box[1]),
207 | cv2.FONT_HERSHEY_COMPLEX_SMALL,
208 | 1,
209 | (0, 0, 255),
210 | thickness=2,
211 | lineType=2)
212 |
213 | # 将学号插入到选择的考勤表中
214 | if find_obj[0] != "Unknow":
215 | self.sqlite.update_checkwork(self.sqlite.DB_STUDENTCHECKWORK_PATH, checkwork, find_obj[0])
216 | cv2.imshow('face recognition', frame)
217 | key = cv2.waitKey(3)
218 | if key == 27:
219 | break
220 | capture.release()
221 | cv2.destroyWindow("face recognition")
222 |
223 | def load_and_align_data(self, img, image_size):
224 |
225 | minsize = 20
226 | threshold = [0.6, 0.7, 0.7]
227 | factor = 0.709
228 | bounding_boxes, _ = align.detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
229 | Index = [] # 序列
230 | Area = [] # 面积
231 | Position = [] # 坐标
232 |
233 | # print('len(bounding_boxes):', len(bounding_boxes))
234 |
235 | # 如果未发现目标 直接返回
236 | if len(bounding_boxes) < 1:
237 | # print('没有发现人脸')
238 | return False, 0, 0
239 |
240 | for i, face_position in enumerate(bounding_boxes):
241 | face_position = face_position.astype(int)
242 | w = face_position[2] - face_position[0]
243 | h = face_position[3] - face_position[1]
244 | S = w * h
245 | # print('第:', i)
246 | # print('w:', w)
247 | # print('h:', h)
248 |
249 | Index.append(i)
250 | Area.append(S)
251 | Position.append(face_position)
252 |
253 | max_face_position = max_face(Area, Position)
254 |
255 | # print('bbox:', (max_face_position[0], max_face_position[1]),
256 | # (max_face_position[2], max_face_position[3]))
257 |
258 | # 裁剪
259 | temp_crop = img[max_face_position[1]:max_face_position[3], max_face_position[0]:max_face_position[2], :]
260 |
261 | if max_face_position[0] < 75: # 左边
262 | return False, 0, 0
263 |
264 | if max_face_position[2] > 565: # 右边
265 | return False, 0, 0
266 |
267 | if max_face_position[1] < 75: # 上面
268 | return False, 0, 0
269 |
270 | aligned = cv2.resize(temp_crop, (image_size, image_size),
271 | interpolation=cv2.INTER_CUBIC)
272 | face_out = facenet.prewhiten(aligned)
273 | crop_image = []
274 | crop_image.append(np.stack(face_out))
275 | return True, max_face_position, crop_image # mark标记位置,回归边框,切割图片
276 |
277 |
278 | if __name__ == '__main__':
279 | face_test = face()
280 | face_test.main('cs172', 'cs172')
281 |
--------------------------------------------------------------------------------
/ui_src/addStudent.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'addStudent.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.9.2
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore, QtGui, QtWidgets
10 |
11 | class Ui_Form_Student(object):
12 | def setupUi(self, Form):
13 | Form.setObjectName("Form")
14 | Form.resize(730, 379)
15 | self.layoutWidget = QtWidgets.QWidget(Form)
16 | self.layoutWidget.setGeometry(QtCore.QRect(50, 50, 639, 282))
17 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
18 | sizePolicy.setHorizontalStretch(0)
19 | sizePolicy.setVerticalStretch(0)
20 | sizePolicy.setHeightForWidth(self.layoutWidget.sizePolicy().hasHeightForWidth())
21 | self.layoutWidget.setSizePolicy(sizePolicy)
22 | self.layoutWidget.setObjectName("layoutWidget")
23 | self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget)
24 | self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
25 | self.verticalLayout_3.setObjectName("verticalLayout_3")
26 | self.horizontalLayout = QtWidgets.QHBoxLayout()
27 | self.horizontalLayout.setObjectName("horizontalLayout")
28 | self.verticalLayout = QtWidgets.QVBoxLayout()
29 | self.verticalLayout.setObjectName("verticalLayout")
30 | self.lab_addTest_6 = QtWidgets.QLabel(self.layoutWidget)
31 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
32 | sizePolicy.setHorizontalStretch(0)
33 | sizePolicy.setVerticalStretch(0)
34 | sizePolicy.setHeightForWidth(self.lab_addTest_6.sizePolicy().hasHeightForWidth())
35 | self.lab_addTest_6.setSizePolicy(sizePolicy)
36 | font = QtGui.QFont()
37 | font.setPointSize(16)
38 | self.lab_addTest_6.setFont(font)
39 | self.lab_addTest_6.setLayoutDirection(QtCore.Qt.LeftToRight)
40 | self.lab_addTest_6.setAlignment(QtCore.Qt.AlignCenter)
41 | self.lab_addTest_6.setObjectName("lab_addTest_6")
42 | self.verticalLayout.addWidget(self.lab_addTest_6)
43 | self.lab_addTest = QtWidgets.QLabel(self.layoutWidget)
44 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
45 | sizePolicy.setHorizontalStretch(0)
46 | sizePolicy.setVerticalStretch(0)
47 | sizePolicy.setHeightForWidth(self.lab_addTest.sizePolicy().hasHeightForWidth())
48 | self.lab_addTest.setSizePolicy(sizePolicy)
49 | font = QtGui.QFont()
50 | font.setPointSize(16)
51 | self.lab_addTest.setFont(font)
52 | self.lab_addTest.setLayoutDirection(QtCore.Qt.LeftToRight)
53 | self.lab_addTest.setAlignment(QtCore.Qt.AlignCenter)
54 | self.lab_addTest.setObjectName("lab_addTest")
55 | self.verticalLayout.addWidget(self.lab_addTest)
56 | self.lab_addTest_2 = QtWidgets.QLabel(self.layoutWidget)
57 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
58 | sizePolicy.setHorizontalStretch(0)
59 | sizePolicy.setVerticalStretch(0)
60 | sizePolicy.setHeightForWidth(self.lab_addTest_2.sizePolicy().hasHeightForWidth())
61 | self.lab_addTest_2.setSizePolicy(sizePolicy)
62 | font = QtGui.QFont()
63 | font.setPointSize(16)
64 | self.lab_addTest_2.setFont(font)
65 | self.lab_addTest_2.setLayoutDirection(QtCore.Qt.LeftToRight)
66 | self.lab_addTest_2.setAlignment(QtCore.Qt.AlignCenter)
67 | self.lab_addTest_2.setObjectName("lab_addTest_2")
68 | self.verticalLayout.addWidget(self.lab_addTest_2)
69 | self.lab_addTest_3 = QtWidgets.QLabel(self.layoutWidget)
70 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
71 | sizePolicy.setHorizontalStretch(0)
72 | sizePolicy.setVerticalStretch(0)
73 | sizePolicy.setHeightForWidth(self.lab_addTest_3.sizePolicy().hasHeightForWidth())
74 | self.lab_addTest_3.setSizePolicy(sizePolicy)
75 | font = QtGui.QFont()
76 | font.setPointSize(16)
77 | self.lab_addTest_3.setFont(font)
78 | self.lab_addTest_3.setLayoutDirection(QtCore.Qt.LeftToRight)
79 | self.lab_addTest_3.setAlignment(QtCore.Qt.AlignCenter)
80 | self.lab_addTest_3.setObjectName("lab_addTest_3")
81 | self.verticalLayout.addWidget(self.lab_addTest_3)
82 | self.lab_addTest_4 = QtWidgets.QLabel(self.layoutWidget)
83 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
84 | sizePolicy.setHorizontalStretch(0)
85 | sizePolicy.setVerticalStretch(0)
86 | sizePolicy.setHeightForWidth(self.lab_addTest_4.sizePolicy().hasHeightForWidth())
87 | self.lab_addTest_4.setSizePolicy(sizePolicy)
88 | font = QtGui.QFont()
89 | font.setPointSize(16)
90 | self.lab_addTest_4.setFont(font)
91 | self.lab_addTest_4.setLayoutDirection(QtCore.Qt.LeftToRight)
92 | self.lab_addTest_4.setAlignment(QtCore.Qt.AlignCenter)
93 | self.lab_addTest_4.setObjectName("lab_addTest_4")
94 | self.verticalLayout.addWidget(self.lab_addTest_4)
95 | self.horizontalLayout.addLayout(self.verticalLayout)
96 | self.verticalLayout_2 = QtWidgets.QVBoxLayout()
97 | self.verticalLayout_2.setObjectName("verticalLayout_2")
98 | self.SelectClass = QtWidgets.QComboBox(self.layoutWidget)
99 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
100 | sizePolicy.setHorizontalStretch(0)
101 | sizePolicy.setVerticalStretch(0)
102 | sizePolicy.setHeightForWidth(self.SelectClass.sizePolicy().hasHeightForWidth())
103 | self.SelectClass.setSizePolicy(sizePolicy)
104 | self.SelectClass.setObjectName("SelectClass")
105 | self.verticalLayout_2.addWidget(self.SelectClass)
106 | self.line_addLabel = QtWidgets.QLineEdit(self.layoutWidget)
107 | self.line_addLabel.setEnabled(True)
108 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
109 | sizePolicy.setHorizontalStretch(0)
110 | sizePolicy.setVerticalStretch(0)
111 | sizePolicy.setHeightForWidth(self.line_addLabel.sizePolicy().hasHeightForWidth())
112 | self.line_addLabel.setSizePolicy(sizePolicy)
113 | font = QtGui.QFont()
114 | font.setPointSize(16)
115 | self.line_addLabel.setFont(font)
116 | self.line_addLabel.setLayoutDirection(QtCore.Qt.LeftToRight)
117 | self.line_addLabel.setObjectName("line_addLabel")
118 | self.verticalLayout_2.addWidget(self.line_addLabel)
119 | self.line_addName = QtWidgets.QLineEdit(self.layoutWidget)
120 | self.line_addName.setEnabled(True)
121 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
122 | sizePolicy.setHorizontalStretch(0)
123 | sizePolicy.setVerticalStretch(0)
124 | sizePolicy.setHeightForWidth(self.line_addName.sizePolicy().hasHeightForWidth())
125 | self.line_addName.setSizePolicy(sizePolicy)
126 | font = QtGui.QFont()
127 | font.setPointSize(16)
128 | self.line_addName.setFont(font)
129 | self.line_addName.setLayoutDirection(QtCore.Qt.LeftToRight)
130 | self.line_addName.setObjectName("line_addName")
131 | self.verticalLayout_2.addWidget(self.line_addName)
132 | self.line_addSex = QtWidgets.QLineEdit(self.layoutWidget)
133 | self.line_addSex.setEnabled(True)
134 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
135 | sizePolicy.setHorizontalStretch(0)
136 | sizePolicy.setVerticalStretch(0)
137 | sizePolicy.setHeightForWidth(self.line_addSex.sizePolicy().hasHeightForWidth())
138 | self.line_addSex.setSizePolicy(sizePolicy)
139 | font = QtGui.QFont()
140 | font.setPointSize(16)
141 | self.line_addSex.setFont(font)
142 | self.line_addSex.setLayoutDirection(QtCore.Qt.LeftToRight)
143 | self.line_addSex.setObjectName("line_addSex")
144 | self.verticalLayout_2.addWidget(self.line_addSex)
145 | self.line_addId = QtWidgets.QLineEdit(self.layoutWidget)
146 | self.line_addId.setEnabled(True)
147 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
148 | sizePolicy.setHorizontalStretch(0)
149 | sizePolicy.setVerticalStretch(0)
150 | sizePolicy.setHeightForWidth(self.line_addId.sizePolicy().hasHeightForWidth())
151 | self.line_addId.setSizePolicy(sizePolicy)
152 | font = QtGui.QFont()
153 | font.setPointSize(16)
154 | self.line_addId.setFont(font)
155 | self.line_addId.setLayoutDirection(QtCore.Qt.LeftToRight)
156 | self.line_addId.setObjectName("line_addId")
157 | self.verticalLayout_2.addWidget(self.line_addId)
158 | self.horizontalLayout.addLayout(self.verticalLayout_2)
159 | self.verticalLayout_3.addLayout(self.horizontalLayout)
160 | self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
161 | self.horizontalLayout_2.setObjectName("horizontalLayout_2")
162 | self.btn_confirm = QtWidgets.QPushButton(self.layoutWidget)
163 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
164 | sizePolicy.setHorizontalStretch(0)
165 | sizePolicy.setVerticalStretch(0)
166 | sizePolicy.setHeightForWidth(self.btn_confirm.sizePolicy().hasHeightForWidth())
167 | self.btn_confirm.setSizePolicy(sizePolicy)
168 | self.btn_confirm.setMaximumSize(QtCore.QSize(200, 60))
169 | font = QtGui.QFont()
170 | font.setPointSize(16)
171 | font.setBold(False)
172 | font.setWeight(50)
173 | self.btn_confirm.setFont(font)
174 | self.btn_confirm.setLayoutDirection(QtCore.Qt.LeftToRight)
175 | self.btn_confirm.setObjectName("btn_confirm")
176 | self.horizontalLayout_2.addWidget(self.btn_confirm)
177 | self.btn_refresh = QtWidgets.QPushButton(self.layoutWidget)
178 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
179 | sizePolicy.setHorizontalStretch(0)
180 | sizePolicy.setVerticalStretch(0)
181 | sizePolicy.setHeightForWidth(self.btn_refresh.sizePolicy().hasHeightForWidth())
182 | self.btn_refresh.setSizePolicy(sizePolicy)
183 | self.btn_refresh.setMaximumSize(QtCore.QSize(200, 60))
184 | font = QtGui.QFont()
185 | font.setPointSize(16)
186 | font.setBold(False)
187 | font.setWeight(50)
188 | self.btn_refresh.setFont(font)
189 | self.btn_refresh.setLayoutDirection(QtCore.Qt.LeftToRight)
190 | self.btn_refresh.setObjectName("btn_refresh")
191 | self.horizontalLayout_2.addWidget(self.btn_refresh)
192 | self.btn_cancel = QtWidgets.QPushButton(self.layoutWidget)
193 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
194 | sizePolicy.setHorizontalStretch(0)
195 | sizePolicy.setVerticalStretch(0)
196 | sizePolicy.setHeightForWidth(self.btn_cancel.sizePolicy().hasHeightForWidth())
197 | self.btn_cancel.setSizePolicy(sizePolicy)
198 | self.btn_cancel.setMaximumSize(QtCore.QSize(200, 60))
199 | font = QtGui.QFont()
200 | font.setPointSize(16)
201 | font.setBold(False)
202 | font.setWeight(50)
203 | self.btn_cancel.setFont(font)
204 | self.btn_cancel.setLayoutDirection(QtCore.Qt.LeftToRight)
205 | self.btn_cancel.setObjectName("btn_cancel")
206 | self.horizontalLayout_2.addWidget(self.btn_cancel)
207 | self.verticalLayout_3.addLayout(self.horizontalLayout_2)
208 |
209 | self.retranslateUi(Form)
210 | QtCore.QMetaObject.connectSlotsByName(Form)
211 |
212 | def retranslateUi(self, Form):
213 | _translate = QtCore.QCoreApplication.translate
214 | Form.setWindowTitle(_translate("Form", "添加新用户"))
215 | self.lab_addTest_6.setText(_translate("Form", "选择人脸数据表"))
216 | self.lab_addTest.setText(_translate("Form", "添加用户标签(姓名拼音)"))
217 | self.lab_addTest_2.setText(_translate("Form", "添加用户姓名"))
218 | self.lab_addTest_3.setText(_translate("Form", "添加用户性别"))
219 | self.lab_addTest_4.setText(_translate("Form", "添加用户学号"))
220 | self.btn_confirm.setText(_translate("Form", "确定"))
221 | self.btn_refresh.setText(_translate("Form", "刷新"))
222 | self.btn_cancel.setText(_translate("Form", "取消"))
223 |
224 |
--------------------------------------------------------------------------------
/src/Sqlite_UI.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from PyQt5.QtWidgets import QDialog, QLabel, QTableView, QLineEdit, QPushButton, QMessageBox
4 | from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout
5 | from PyQt5 import QtWidgets
6 | from PyQt5.QtWidgets import QWidget
7 | from PyQt5.QtWidgets import QFileDialog
8 | from PyQt5.QtWidgets import QApplication, QAbstractItemView
9 | from PyQt5.Qt import Qt
10 | from PyQt5.QtGui import QStandardItemModel, QStandardItem
11 | from PyQt5.QtCore import pyqtSignal
12 |
13 | from ui_src.sqlite_main_window import Ui_SqliteMainWindow
14 | from ui_src.Add_Data import Ui_Dialog_Add_Data
15 | from ui_src.Add_Table import Ui_Dialog_Add_Table
16 | from functools import partial
17 | from tools.sqlite_func import Sqlite_Func
18 |
19 |
20 | class Add_Table_UI(QDialog, Ui_Dialog_Add_Table):
21 | signal_status = pyqtSignal()
22 |
23 | def __init__(self, db_path, parent=None):
24 | super(Add_Table_UI, self).__init__(parent)
25 |
26 | self.db_path = db_path
27 |
28 | self.sf = Sqlite_Func()
29 |
30 | h_layout = QHBoxLayout()
31 | label_table_name = QLabel("表名字:")
32 | self.lineEdit_table_name = QLineEdit()
33 | # 水平放置
34 | h_layout.addWidget(label_table_name)
35 | h_layout.addWidget(self.lineEdit_table_name)
36 |
37 | btn_ok = QPushButton()
38 | btn_ok.setText("OK")
39 |
40 | v_layout = QVBoxLayout()
41 |
42 | # 垂直放置
43 | v_layout.addLayout(h_layout)
44 | v_layout.addWidget(btn_ok)
45 |
46 | self.setLayout(v_layout)
47 |
48 | btn_ok.clicked.connect(self.create_table)
49 |
50 | def create_table(self):
51 | sstr = self.db_path.split('/')
52 | self.db_type = sstr[len(sstr) - 1]
53 | print("db_type:", self.db_type)
54 | print("创建新表")
55 | if self.lineEdit_table_name == "":
56 | print("表名字为空")
57 | else:
58 | self.sf.create_table(self.db_path, self.lineEdit_table_name.text(), str(self.db_type).upper())
59 | status = 1
60 |
61 | self.signal_status.emit()
62 | self.close()
63 |
64 | def test(self, s):
65 | print("s:", s)
66 |
67 |
68 | class Add_Data_UI(QDialog, Ui_Dialog_Add_Data):
69 | signal_status = pyqtSignal()
70 |
71 | def __init__(self, db_path, table, field, parent=None):
72 | super(Add_Data_UI, self).__init__(parent)
73 |
74 | self.db_path = db_path
75 | self.table = table
76 | self.field = field
77 |
78 | self.sf = Sqlite_Func()
79 |
80 | v_label_layout = QVBoxLayout()
81 | v_layout = QVBoxLayout()
82 | v_lineEdit_layout = QVBoxLayout()
83 |
84 | h_layout = QHBoxLayout()
85 |
86 | self.lineEdit_list = []
87 | self.field_len = len(field)
88 |
89 | db_type = str(db_path).split('/')
90 | print("db type:", db_type[len(db_type) - 1].upper())
91 | if db_type[len(db_type) - 1].upper() == self.sf.DB_TYPE_CHECKWORK:
92 | self.field_len = len(field) - 1
93 |
94 | for i in range(self.field_len):
95 | label = QLabel()
96 | label.setText("{}:".format(str(field[i]).upper()))
97 | v_label_layout.addWidget(label)
98 |
99 | lineEdit = QLineEdit()
100 | self.lineEdit_list.append(lineEdit)
101 |
102 | v_lineEdit_layout.addWidget(lineEdit)
103 |
104 | if db_type[len(db_type) - 1].upper() == self.sf.DB_TYPE_CHECKWORK:
105 | # 对于考勤表 flag不允许手动写入
106 |
107 | label = QLabel()
108 | label.setText("{}:".format(str(field[self.field_len]).upper()))
109 | v_label_layout.addWidget(label)
110 |
111 | lineEdit_flag = QLineEdit()
112 | lineEdit_flag.setReadOnly(True)
113 | lineEdit_flag.setText("0")
114 |
115 | self.lineEdit_list.append(lineEdit_flag)
116 | v_lineEdit_layout.addWidget(lineEdit_flag)
117 |
118 | h_layout.addLayout(v_label_layout)
119 | h_layout.addLayout(v_lineEdit_layout)
120 |
121 | btn_ok = QPushButton()
122 | btn_ok.setText("确定")
123 |
124 | v_layout.addLayout(h_layout)
125 | v_layout.addWidget(btn_ok)
126 |
127 | self.setLayout(v_layout)
128 |
129 | self.setupUi(self)
130 | btn_ok.clicked.connect(self.insert_data)
131 |
132 | def insert_data(self):
133 | lineEdit_data = []
134 | for i in range(len(self.lineEdit_list)):
135 | lineEdit_data.append(self.lineEdit_list[i].text())
136 |
137 | # 插入数据库
138 | ret = self.sf.insert(self.db_path, self.table, lineEdit_data)
139 | if ret == -1:
140 | QMessageBox.about(self, "Error", "有数据为空")
141 | if ret == -2:
142 | QMessageBox.about(self, "Error", "主键重复")
143 | self.signal_status.emit()
144 | self.close()
145 |
146 |
147 | class Sqlite_UI(QtWidgets.QMainWindow, Ui_SqliteMainWindow):
148 | def __init__(self, parent=None):
149 | super(Sqlite_UI, self).__init__(parent)
150 | self.setupUi(self)
151 |
152 | # 隐藏两个组件:因为我不想写了
153 | self.label_cmd.hide()
154 | self.lineEdit_cmd.hide()
155 |
156 | # slot init
157 | self.slot_init()
158 |
159 | self.sf = Sqlite_Func()
160 |
161 | # 数据库路径
162 | self.db_path = ""
163 | # 选择的表名
164 | self.table = ""
165 | # 所有数据表
166 | self.table_list = []
167 | # 当前表所有字段
168 | self.field_list = []
169 | # 创建的按钮字段列表
170 | self.btn_field_list = []
171 | # 被勾选的字段
172 | self.select_field_list = []
173 | # 当前行列
174 | self.len_row = 0
175 | self.len_col = 0
176 |
177 | self.model = QStandardItemModel()
178 |
179 | # 数据库类型
180 | self.db_type = ""
181 |
182 | def slot_init(self):
183 | print("slot init...")
184 | self.actionOpen_File.triggered.connect(self.open_db)
185 |
186 | self.radioButton_all.clicked.connect(self.selectAll_radiobtn)
187 | self.radioButton_notall.clicked.connect(self.selectNotAll_radiobtn)
188 |
189 | self.pushButton_query.clicked.connect(self.query)
190 | self.pushButton_update.clicked.connect(self.update_data)
191 | self.pushButton_del.clicked.connect(self.delete_data)
192 | self.pushButton_add.clicked.connect(self.add_data)
193 | self.pushButton_delTable.clicked.connect(self.del_table)
194 | self.pushButton_newTable.clicked.connect(self.add_table)
195 |
196 | def open_db(self):
197 | print("打开文件")
198 | self.db_path, file_type = QFileDialog.getOpenFileName(self, "select db files", "",
199 | "*.db;;*.png;;All Files(*)")
200 | print("文件路径:{}\n文件类型:{}\n".format(self.db_path, file_type))
201 |
202 | self.table_list = self.sf.check_table(self.db_path)
203 | print("当前数据库含有表:", self.table_list)
204 |
205 | # 设置窗口名字
206 | QDialog.setWindowTitle(self, self.db_path)
207 | sstr = self.db_path.split('/')
208 |
209 | print(sstr)
210 | self.groupBox_table_field.setTitle("数据库:{}".format(sstr[len(sstr) - 1]))
211 |
212 | self.db_type = sstr[len(sstr) - 1]
213 |
214 | self.create_radiobox_table()
215 |
216 | # 创建数据库表选项
217 | def create_radiobox_table(self):
218 | self.count = 0
219 | self.btn_layer = QWidget()
220 | for i, data in enumerate(self.table_list):
221 | self.count += 1
222 | self.btn = QtWidgets.QRadioButton(self.btn_layer)
223 | self.btn.setText(str(data))
224 | self.btn.clicked.connect(partial(self.create_checkbox_field, self.btn.text(), False))
225 | self.btn.move(10, i * 60)
226 |
227 | self.btn_layer.setMinimumSize(250, self.count * 60)
228 | self.scrollArea_table.setWidget(self.btn_layer)
229 | self.scrollArea_table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
230 |
231 | # 创建字段表
232 | def create_checkbox_field(self, table, ischeck):
233 | self.btn_field_list.clear()
234 | self.count = 0
235 |
236 | self.table = table
237 | print("选择了{}表".format(str(table)))
238 | ret = self.sf.check_field(self.db_path, table)
239 | self.field_list = ret
240 | print("当前表含有{}字段:".format(ret))
241 | self.btn_layer = QWidget()
242 | for i, data in enumerate(ret):
243 | self.count += 1
244 | self.btn = QtWidgets.QCheckBox(self.btn_layer)
245 | self.btn.setText("{}".format(str(data)))
246 | self.btn.setChecked(ischeck)
247 | self.btn.move(10, i * 60)
248 | self.btn_field_list.append(self.btn)
249 |
250 | self.btn_layer.setMinimumSize(250, self.count * 60)
251 | self.scrollArea_field.setWidget(self.btn_layer)
252 | self.scrollArea_field.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
253 |
254 | def selectAll_radiobtn(self):
255 | if self.btn_field_list == []:
256 | print("没有选择表")
257 | else:
258 | print("全选字段")
259 | self.create_checkbox_field(self.table, True)
260 | self.select_field_list.clear()
261 | for btn in self.btn_field_list:
262 | self.select_field_list.append(btn.text())
263 |
264 | def selectNotAll_radiobtn(self):
265 | if self.btn_field_list == []:
266 | print("没有选择表")
267 | else:
268 | print("全选字段")
269 | self.create_checkbox_field(self.table, False)
270 | self.select_field_list.clear()
271 |
272 | # param:字段,内容
273 | def show_table(self, fields, data):
274 | print("显示表内容")
275 | print("字段:{}\n数据:{}".format(fields, data))
276 |
277 | # 行数
278 | # 列数
279 | self.len_row = len(data)
280 | self.len_col = len(fields)
281 | print("row:{},col:{}".format(self.len_row, self.len_col))
282 | # self.model = QStandardItemModel(self.len_row, self.len_col, self)
283 | self.model.setRowCount(self.len_row)
284 | self.model.setColumnCount(self.len_col)
285 | for row in range(self.len_row):
286 | for col in range(len(data[0])):
287 | item = QStandardItem("{}".format(data[row][col]))
288 |
289 | self.model.setItem(row, col, item)
290 |
291 | self.tableView_content.setModel(self.model)
292 | self.tableView_content.horizontalHeader().setStretchLastSection(True)
293 | self.tableView_content.setEditTriggers(QAbstractItemView.DoubleClicked)
294 | self.tableView_content.clicked.connect(lambda x: print(self.tableView_content.currentIndex().data()))
295 |
296 | # 通过按键更新数据到数据库
297 | def update_data(self):
298 | print(self.btn_field_list)
299 | if self.btn_field_list == []:
300 | print("没有选择表")
301 | else:
302 | update_data = []
303 | if self.len_row == 0:
304 | print("没有数据")
305 | return
306 |
307 | # 读取新数据
308 | for i in range(self.len_row):
309 | update_data_item = []
310 | for j in range(self.len_col):
311 | if self.model.item(i, j).text() != None:
312 | update_data_item.append(self.model.item(i, j).text())
313 | update_data.append(update_data_item)
314 | print("update data", update_data)
315 |
316 | if len(update_data[0]) != len(self.field_list):
317 | print("数据不足")
318 | return
319 | # 查找主键
320 | i, key = self.sf.find_primary_key(self.db_path, self.table)
321 |
322 | # 更新数据
323 | ret = self.sf.update(self.db_path, self.table, self.field_list, update_data, i)
324 | if ret == -1:
325 | QMessageBox.about(self, "Error", "有数据为空")
326 | if ret==-2:
327 | print("更新异常")
328 | if ret == -3:
329 | print("主键被修改,停止更新")
330 | QMessageBox.about(self,"Error","主键被修改")
331 | else:
332 | print("更新完成\n")
333 |
334 | # 查询
335 | def query(self):
336 | self.select_field_list.clear()
337 | for btn in self.btn_field_list:
338 | print(btn.isChecked())
339 | if btn.isChecked() == True:
340 | self.select_field_list.append(btn.text())
341 |
342 | print("self.select_field_list:", self.select_field_list)
343 |
344 | if self.select_field_list != []:
345 |
346 | # 根据所选字段和表构建查询语句:select field1,field2,...,fieldN from table
347 | str_sql = self.sf.auto_select(self.table, self.select_field_list)
348 | ret = self.sf.executeCMD(self.db_path, str_sql)
349 | print(ret)
350 | for i, data in enumerate(ret):
351 | print("{}->{}\n".format(i, data))
352 |
353 | # 打印数据
354 | self.show_table(self.select_field_list, ret)
355 |
356 | if self.select_field_list == []:
357 | self.tableView_content.setModel(self.model.clear())
358 |
359 | # 进行删除操作需要选中所有字段
360 | def delete_data(self):
361 | if self.table == "":
362 | print("未选择表")
363 | return
364 | if self.select_field_list == []:
365 | print("未选择字段")
366 | return
367 | if self.tableView_content.currentIndex().row() == -1:
368 | print("未选择数据")
369 | return
370 | else:
371 | del_row = self.tableView_content.currentIndex().row()
372 | print("选择{}行".format(del_row))
373 |
374 | # 主键index和获取主键
375 | key_idx, key = self.sf.find_primary_key(self.db_path, self.table)
376 | del_data = []
377 | # 读取当前行所有数据
378 | for i in range(self.len_col):
379 | if self.model.item(del_row, i).text() != None:
380 | del_data.append(self.model.item(del_row, i).text())
381 |
382 | if len(del_data) != len(self.field_list):
383 | print("数据不全")
384 | return
385 | print("del data:", del_data)
386 | self.sf.delete(self.db_path, self.table, key, key_idx, del_data)
387 | self.query()
388 |
389 | def add_data(self):
390 | if self.db_path == "":
391 | print("未选择数据库")
392 | return
393 | if self.table == "":
394 | print("未选择表")
395 | return
396 | if self.select_field_list == []:
397 | print("未选择字段")
398 | return
399 |
400 | print("添加数据")
401 | self.add_data_ui = Add_Data_UI(self.db_path, self.table, self.field_list)
402 | self.add_data_ui.show()
403 | self.add_data_ui.signal_status.connect(self.query)
404 | # self.query()
405 |
406 | def flash_table(self):
407 | # 刷新数据库表
408 | self.table_list = self.sf.check_table(self.db_path)
409 | print("当前数据库含有表:", self.table_list)
410 | self.create_radiobox_table()
411 |
412 | def add_table(self):
413 |
414 | if self.db_path == "":
415 | print("没有选择数据库")
416 | else:
417 | self.add_table_ui = Add_Table_UI(self.db_path)
418 | self.add_table_ui.show()
419 |
420 | # 子窗口链接主窗口函数
421 | self.add_table_ui.signal_status.connect(self.flash_table)
422 |
423 | def del_table(self):
424 | if self.table == "":
425 | print("没有选择表")
426 | return
427 | print("当前选择表:{}".format(self.table))
428 | ret = QMessageBox.question(self, "delete table", "sure to delete this table?", QMessageBox.Yes | QMessageBox.No,
429 | QMessageBox.No)
430 | if ret == QMessageBox.Yes:
431 | self.sf.delete_table(self.db_path, self.table)
432 | self.tableView_content.setModel(self.model.clear())
433 |
434 | # 刷新数据库表
435 | self.table_list = self.sf.check_table(self.db_path)
436 | print("当前数据库含有表:", self.table_list)
437 | self.create_radiobox_table()
438 |
439 |
440 | if __name__ == "__main__":
441 | app = QApplication(sys.argv)
442 | ui = Sqlite_UI()
443 | # ui = Add_Data_UI()
444 | ui.show()
445 | sys.exit((app.exec_()))
446 |
--------------------------------------------------------------------------------
/src/facenet.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import
2 | from __future__ import division
3 | from __future__ import print_function
4 |
5 | import os
6 | from subprocess import Popen, PIPE
7 | import tensorflow as tf
8 | import numpy as np
9 | from scipy import misc
10 | from sklearn.model_selection import KFold
11 | from scipy import interpolate
12 | from tensorflow.python.training import training
13 | import random
14 | import re
15 | from tensorflow.python.platform import gfile
16 | import math
17 | from six import iteritems
18 |
19 |
20 | def triplet_loss(anchor, positive, negative, alpha):
21 | """Calculate the triplet loss according to the FaceNet paper
22 |
23 | Args:
24 | anchor: the embeddings for the anchor images.
25 | positive: the embeddings for the positive images.
26 | negative: the embeddings for the negative images.
27 |
28 | Returns:
29 | the triplet loss according to the FaceNet paper as a float tensor.
30 | """
31 | with tf.variable_scope('triplet_loss'):
32 | pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), 1)
33 | neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), 1)
34 |
35 | basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
36 | loss = tf.reduce_mean(tf.maximum(basic_loss, 0.0), 0)
37 |
38 | return loss
39 |
40 |
41 | def center_loss(features, label, alfa, nrof_classes):
42 | """Center loss based on the paper "A Discriminative Feature Learning Approach for Deep Face Recognition"
43 | (http://ydwen.github.io/papers/WenECCV16.pdf)
44 | """
45 | nrof_features = features.get_shape()[1]
46 | centers = tf.get_variable('centers', [nrof_classes, nrof_features], dtype=tf.float32,
47 | initializer=tf.constant_initializer(0), trainable=False)
48 | label = tf.reshape(label, [-1])
49 | centers_batch = tf.gather(centers, label)
50 | diff = (1 - alfa) * (centers_batch - features)
51 | centers = tf.scatter_sub(centers, label, diff)
52 | with tf.control_dependencies([centers]):
53 | loss = tf.reduce_mean(tf.square(features - centers_batch))
54 | return loss, centers
55 |
56 |
57 | # 获取图片路径和标签
58 | def get_image_paths_and_labels(dataset):
59 | image_paths_flat = []
60 | labels_flat = []
61 | for i in range(len(dataset)):
62 | image_paths_flat += dataset[i].image_paths
63 | labels_flat += [i] * len(dataset[i].image_paths)
64 | return image_paths_flat, labels_flat
65 |
66 |
67 | def shuffle_examples(image_paths, labels):
68 | shuffle_list = list(zip(image_paths, labels))
69 | random.shuffle(shuffle_list)
70 | image_paths_shuff, labels_shuff = zip(*shuffle_list)
71 | return image_paths_shuff, labels_shuff
72 |
73 |
74 | # 随机旋转图像
75 | def random_rotate_image(image):
76 | angle = np.random.uniform(low=-10.0, high=10.0)
77 | return misc.imrotate(image, angle, 'bicubic')
78 |
79 |
80 | # 1: Random rotate 2: Random crop 4: Random flip 8: Fixed markdown_imgs standardization 16: Flip
81 | RANDOM_ROTATE = 1
82 | RANDOM_CROP = 2
83 | RANDOM_FLIP = 4
84 | FIXED_STANDARDIZATION = 8
85 | FLIP = 16
86 |
87 |
88 | def create_input_pipeline(input_queue, image_size, nrof_preprocess_threads, batch_size_placeholder):
89 | images_and_labels_list = []
90 | for _ in range(nrof_preprocess_threads):
91 | filenames, label, control = input_queue.dequeue()
92 | images = []
93 | for filename in tf.unstack(filenames):
94 | file_contents = tf.read_file(filename)
95 | image = tf.image.decode_image(file_contents, 3)
96 | image = tf.cond(get_control_flag(control[0], RANDOM_ROTATE),
97 | lambda: tf.py_func(random_rotate_image, [image], tf.uint8),
98 | lambda: tf.identity(image))
99 | image = tf.cond(get_control_flag(control[0], RANDOM_CROP),
100 | lambda: tf.random_crop(image, image_size + (3,)),
101 | lambda: tf.image.resize_image_with_crop_or_pad(image, image_size[0], image_size[1]))
102 | image = tf.cond(get_control_flag(control[0], RANDOM_FLIP),
103 | lambda: tf.image.random_flip_left_right(image),
104 | lambda: tf.identity(image))
105 | image = tf.cond(get_control_flag(control[0], FIXED_STANDARDIZATION),
106 | lambda: (tf.cast(image, tf.float32) - 127.5) / 128.0,
107 | lambda: tf.image.per_image_standardization(image))
108 | image = tf.cond(get_control_flag(control[0], FLIP),
109 | lambda: tf.image.flip_left_right(image),
110 | lambda: tf.identity(image))
111 | # pylint: disable=no-member
112 | image.set_shape(image_size + (3,))
113 | images.append(image)
114 | images_and_labels_list.append([images, label])
115 |
116 | image_batch, label_batch = tf.train.batch_join(
117 | images_and_labels_list, batch_size=batch_size_placeholder,
118 | shapes=[image_size + (3,), ()], enqueue_many=True,
119 | capacity=4 * nrof_preprocess_threads * 100,
120 | allow_smaller_final_batch=True)
121 |
122 | return image_batch, label_batch
123 |
124 |
125 | def get_control_flag(control, field):
126 | return tf.equal(tf.mod(tf.floor_div(control, field), 2), 1)
127 |
128 |
129 | def _add_loss_summaries(total_loss):
130 | """Add summaries for losses.
131 |
132 | Generates moving average for all losses and associated summaries for
133 | visualizing the performance of the network.
134 |
135 | Args:
136 | total_loss: Total loss from loss().
137 | Returns:
138 | loss_averages_op: op for generating moving averages of losses.
139 | """
140 | # Compute the moving average of all individual losses and the total loss.
141 | loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg')
142 | losses = tf.get_collection('losses')
143 | loss_averages_op = loss_averages.apply(losses + [total_loss])
144 |
145 | # Attach a scalar summmary to all individual losses and the total loss; do the
146 | # same for the averaged version of the losses.
147 | for l in losses + [total_loss]:
148 | # Name each loss as '(raw)' and name the moving average version of the loss
149 | # as the original loss name.
150 | tf.summary.scalar(l.op.name + ' (raw)', l)
151 | tf.summary.scalar(l.op.name, loss_averages.average(l))
152 |
153 | return loss_averages_op
154 |
155 |
156 | def train(total_loss, global_step, optimizer, learning_rate, moving_average_decay, update_gradient_vars,
157 | log_histograms=True):
158 | # Generate moving averages of all losses and associated summaries.
159 | loss_averages_op = _add_loss_summaries(total_loss)
160 | # 计算梯度
161 | with tf.control_dependencies([loss_averages_op]):
162 | if optimizer == 'ADAGRAD':
163 | opt = tf.train.AdagradOptimizer(learning_rate)
164 | elif optimizer == 'ADADELTA':
165 | opt = tf.train.AdadeltaOptimizer(learning_rate, rho=0.9, epsilon=1e-6)
166 | elif optimizer == 'ADAM':
167 | opt = tf.train.AdamOptimizer(learning_rate, beta1=0.9, beta2=0.999, epsilon=0.1)
168 | elif optimizer == 'RMSPROP':
169 | opt = tf.train.RMSPropOptimizer(learning_rate, decay=0.9, momentum=0.9, epsilon=1.0)
170 | elif optimizer == 'MOM':
171 | opt = tf.train.MomentumOptimizer(learning_rate, 0.9, use_nesterov=True)
172 | else:
173 | raise ValueError('Invalid optimization algorithm')
174 |
175 | grads = opt.compute_gradients(total_loss, update_gradient_vars)
176 |
177 | # Apply gradients.
178 | apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
179 |
180 | # Add histograms for trainable variables.
181 | if log_histograms:
182 | for var in tf.trainable_variables():
183 | tf.summary.histogram(var.op.name, var)
184 |
185 | # Add histograms for gradients.
186 | if log_histograms:
187 | for grad, var in grads:
188 | if grad is not None:
189 | tf.summary.histogram(var.op.name + '/gradients', grad)
190 |
191 | # Track the moving averages of all trainable variables.
192 | variable_averages = tf.train.ExponentialMovingAverage(
193 | moving_average_decay, global_step)
194 | variables_averages_op = variable_averages.apply(tf.trainable_variables())
195 |
196 | with tf.control_dependencies([apply_gradient_op, variables_averages_op]):
197 | train_op = tf.no_op(name='train')
198 |
199 | return train_op
200 |
201 |
202 | def prewhiten(x):
203 | mean = np.mean(x)
204 | std = np.std(x)
205 | std_adj = np.maximum(std, 1.0 / np.sqrt(x.size))
206 | y = np.multiply(np.subtract(x, mean), 1 / std_adj)
207 | return y
208 |
209 |
210 | def crop(image, random_crop, image_size):
211 | if image.shape[1] > image_size:
212 | sz1 = int(image.shape[1] // 2)
213 | sz2 = int(image_size // 2)
214 | if random_crop:
215 | diff = sz1 - sz2
216 | (h, v) = (np.random.randint(-diff, diff + 1), np.random.randint(-diff, diff + 1))
217 | else:
218 | (h, v) = (0, 0)
219 | image = image[(sz1 - sz2 + v):(sz1 + sz2 + v), (sz1 - sz2 + h):(sz1 + sz2 + h), :]
220 | return image
221 |
222 |
223 | def flip(image, random_flip):
224 | if random_flip and np.random.choice([True, False]):
225 | image = np.fliplr(image)
226 | return image
227 |
228 |
229 | def to_rgb(img):
230 | w, h = img.shape
231 | ret = np.empty((w, h, 3), dtype=np.uint8)
232 | ret[:, :, 0] = ret[:, :, 1] = ret[:, :, 2] = img
233 | return ret
234 |
235 |
236 | def load_data(image_paths, do_random_crop, do_random_flip, image_size, do_prewhiten=True):
237 | nrof_samples = len(image_paths)
238 | images = np.zeros((nrof_samples, image_size, image_size, 3))
239 | for i in range(nrof_samples):
240 | img = misc.imread(image_paths[i])
241 | if img.ndim == 2:
242 | img = to_rgb(img)
243 | if do_prewhiten:
244 | img = prewhiten(img)
245 | img = crop(img, do_random_crop, image_size)
246 | img = flip(img, do_random_flip)
247 | images[i, :, :, :] = img
248 | return images
249 |
250 |
251 | def get_label_batch(label_data, batch_size, batch_index):
252 | nrof_examples = np.size(label_data, 0)
253 | j = batch_index * batch_size % nrof_examples
254 | if j + batch_size <= nrof_examples:
255 | batch = label_data[j:j + batch_size]
256 | else:
257 | x1 = label_data[j:nrof_examples]
258 | x2 = label_data[0:nrof_examples - j]
259 | batch = np.vstack([x1, x2])
260 | batch_int = batch.astype(np.int64)
261 | return batch_int
262 |
263 |
264 | def get_batch(image_data, batch_size, batch_index):
265 | nrof_examples = np.size(image_data, 0)
266 | j = batch_index * batch_size % nrof_examples
267 | if j + batch_size <= nrof_examples:
268 | batch = image_data[j:j + batch_size, :, :, :]
269 | else:
270 | x1 = image_data[j:nrof_examples, :, :, :]
271 | x2 = image_data[0:nrof_examples - j, :, :, :]
272 | batch = np.vstack([x1, x2])
273 | batch_float = batch.astype(np.float32)
274 | return batch_float
275 |
276 |
277 | def get_triplet_batch(triplets, batch_index, batch_size):
278 | ax, px, nx = triplets
279 | a = get_batch(ax, int(batch_size / 3), batch_index)
280 | p = get_batch(px, int(batch_size / 3), batch_index)
281 | n = get_batch(nx, int(batch_size / 3), batch_index)
282 | batch = np.vstack([a, p, n])
283 | return batch
284 |
285 |
286 | def get_learning_rate_from_file(filename, epoch):
287 | with open(filename, 'r') as f:
288 | for line in f.readlines():
289 | line = line.split('#', 1)[0]
290 | if line:
291 | par = line.strip().split(':')
292 | e = int(par[0])
293 | if par[1] == '-':
294 | lr = -1
295 | else:
296 | lr = float(par[1])
297 | if e <= epoch:
298 | learning_rate = lr
299 | else:
300 | return learning_rate
301 |
302 |
303 | class ImageClass():
304 | "Stores the paths to images for a given class"
305 |
306 | def __init__(self, name, image_paths):
307 | self.name = name
308 | self.image_paths = image_paths
309 |
310 | def __str__(self):
311 | return self.name + ', ' + str(len(self.image_paths)) + ' images'
312 |
313 | def __len__(self):
314 | return len(self.image_paths)
315 |
316 |
317 | def get_dataset(path, has_class_directories=True):
318 | dataset = []
319 | path_exp = os.path.expanduser(path)
320 | classes = [path for path in os.listdir(path_exp) \
321 | if os.path.isdir(os.path.join(path_exp, path))]
322 | classes.sort()
323 | nrof_classes = len(classes)
324 | for i in range(nrof_classes):
325 | class_name = classes[i]
326 | facedir = os.path.join(path_exp, class_name)
327 | image_paths = get_image_paths(facedir)
328 | dataset.append(ImageClass(class_name, image_paths))
329 |
330 | return dataset
331 |
332 |
333 | def get_image_paths(facedir):
334 | image_paths = []
335 | if os.path.isdir(facedir):
336 | images = os.listdir(facedir)
337 | image_paths = [os.path.join(facedir, img) for img in images]
338 | return image_paths
339 |
340 |
341 | def split_dataset(dataset, split_ratio, min_nrof_images_per_class, mode):
342 | if mode == 'SPLIT_CLASSES':
343 | nrof_classes = len(dataset)
344 | class_indices = np.arange(nrof_classes)
345 | np.random.shuffle(class_indices)
346 | split = int(round(nrof_classes * (1 - split_ratio)))
347 | train_set = [dataset[i] for i in class_indices[0:split]]
348 | test_set = [dataset[i] for i in class_indices[split:-1]]
349 | elif mode == 'SPLIT_IMAGES':
350 | train_set = []
351 | test_set = []
352 | for cls in dataset:
353 | paths = cls.image_paths
354 | np.random.shuffle(paths)
355 | nrof_images_in_class = len(paths)
356 | split = int(math.floor(nrof_images_in_class * (1 - split_ratio)))
357 | if split == nrof_images_in_class:
358 | split = nrof_images_in_class - 1
359 | if split >= min_nrof_images_per_class and nrof_images_in_class - split >= 1:
360 | train_set.append(ImageClass(cls.name, paths[:split]))
361 | test_set.append(ImageClass(cls.name, paths[split:]))
362 | else:
363 | raise ValueError('Invalid train/test split mode "%s"' % mode)
364 | return train_set, test_set
365 |
366 |
367 | def load_model(model, input_map=None):
368 | # Check if the model is a model directory (containing a metagraph and a checkpoint file)
369 | # or if it is a protobuf file with a frozen graph
370 | model_exp = os.path.expanduser(model)
371 | if (os.path.isfile(model_exp)):
372 | print('Model filename: %s' % model_exp)
373 | with gfile.FastGFile(model_exp, 'rb') as f:
374 | graph_def = tf.GraphDef()
375 | graph_def.ParseFromString(f.read())
376 | tf.import_graph_def(graph_def, input_map=input_map, name='')
377 | else:
378 | print('Model directory: %s' % model_exp)
379 | meta_file, ckpt_file = get_model_filenames(model_exp)
380 |
381 | print('Metagraph file: %s' % meta_file)
382 | print('Checkpoint file: %s' % ckpt_file)
383 |
384 | saver = tf.train.import_meta_graph(os.path.join(model_exp, meta_file), input_map=input_map)
385 | saver.restore(tf.get_default_session(), os.path.join(model_exp, ckpt_file))
386 |
387 |
388 | def get_model_filenames(model_dir):
389 | files = os.listdir(model_dir)
390 | meta_files = [s for s in files if s.endswith('.meta')]
391 | if len(meta_files) == 0:
392 | raise ValueError('No meta file found in the model directory (%s)' % model_dir)
393 | elif len(meta_files) > 1:
394 | raise ValueError('There should not be more than one meta file in the model directory (%s)' % model_dir)
395 | meta_file = meta_files[0]
396 | ckpt = tf.train.get_checkpoint_state(model_dir)
397 | if ckpt and ckpt.model_checkpoint_path:
398 | ckpt_file = os.path.basename(ckpt.model_checkpoint_path)
399 | return meta_file, ckpt_file
400 |
401 | meta_files = [s for s in files if '.ckpt' in s]
402 | max_step = -1
403 | for f in files:
404 | step_str = re.match(r'(^model-[\w\- ]+.ckpt-(\d+))', f)
405 | if step_str is not None and len(step_str.groups()) >= 2:
406 | step = int(step_str.groups()[1])
407 | if step > max_step:
408 | max_step = step
409 | ckpt_file = step_str.groups()[0]
410 | return meta_file, ckpt_file
411 |
412 |
413 | def distance(embeddings1, embeddings2, distance_metric=0):
414 | if distance_metric == 0:
415 | # Euclidian distance
416 | diff = np.subtract(embeddings1, embeddings2)
417 | dist = np.sum(np.square(diff), 1)
418 | elif distance_metric == 1:
419 | # Distance based on cosine similarity
420 | dot = np.sum(np.multiply(embeddings1, embeddings2), axis=1)
421 | norm = np.linalg.norm(embeddings1, axis=1) * np.linalg.norm(embeddings2, axis=1)
422 | similarity = dot / norm
423 | dist = np.arccos(similarity) / math.pi
424 | else:
425 | raise 'Undefined distance metric %d' % distance_metric
426 |
427 | return dist
428 |
429 |
430 | def calculate_roc(thresholds, embeddings1, embeddings2, actual_issame, nrof_folds=10, distance_metric=0,
431 | subtract_mean=False):
432 | assert (embeddings1.shape[0] == embeddings2.shape[0])
433 | assert (embeddings1.shape[1] == embeddings2.shape[1])
434 | nrof_pairs = min(len(actual_issame), embeddings1.shape[0])
435 | nrof_thresholds = len(thresholds)
436 | k_fold = KFold(n_splits=nrof_folds, shuffle=False)
437 |
438 | tprs = np.zeros((nrof_folds, nrof_thresholds))
439 | fprs = np.zeros((nrof_folds, nrof_thresholds))
440 | accuracy = np.zeros((nrof_folds))
441 |
442 | indices = np.arange(nrof_pairs)
443 |
444 | for fold_idx, (train_set, test_set) in enumerate(k_fold.split(indices)):
445 | if subtract_mean:
446 | mean = np.mean(np.concatenate([embeddings1[train_set], embeddings2[train_set]]), axis=0)
447 | else:
448 | mean = 0.0
449 | dist = distance(embeddings1 - mean, embeddings2 - mean, distance_metric)
450 |
451 | # Find the best threshold for the fold
452 | acc_train = np.zeros((nrof_thresholds))
453 | for threshold_idx, threshold in enumerate(thresholds):
454 | _, _, acc_train[threshold_idx] = calculate_accuracy(threshold, dist[train_set], actual_issame[train_set])
455 | best_threshold_index = np.argmax(acc_train)
456 | for threshold_idx, threshold in enumerate(thresholds):
457 | tprs[fold_idx, threshold_idx], fprs[fold_idx, threshold_idx], _ = calculate_accuracy(threshold,
458 | dist[test_set],
459 | actual_issame[
460 | test_set])
461 | _, _, accuracy[fold_idx] = calculate_accuracy(thresholds[best_threshold_index], dist[test_set],
462 | actual_issame[test_set])
463 |
464 | tpr = np.mean(tprs, 0)
465 | fpr = np.mean(fprs, 0)
466 | return tpr, fpr, accuracy
467 |
468 |
469 | def calculate_accuracy(threshold, dist, actual_issame):
470 | predict_issame = np.less(dist, threshold)
471 | tp = np.sum(np.logical_and(predict_issame, actual_issame))
472 | fp = np.sum(np.logical_and(predict_issame, np.logical_not(actual_issame)))
473 | tn = np.sum(np.logical_and(np.logical_not(predict_issame), np.logical_not(actual_issame)))
474 | fn = np.sum(np.logical_and(np.logical_not(predict_issame), actual_issame))
475 |
476 | tpr = 0 if (tp + fn == 0) else float(tp) / float(tp + fn)
477 | fpr = 0 if (fp + tn == 0) else float(fp) / float(fp + tn)
478 | acc = float(tp + tn) / dist.size
479 | return tpr, fpr, acc
480 |
481 |
482 | def calculate_val(thresholds, embeddings1, embeddings2, actual_issame, far_target, nrof_folds=10, distance_metric=0,
483 | subtract_mean=False):
484 | assert (embeddings1.shape[0] == embeddings2.shape[0])
485 | assert (embeddings1.shape[1] == embeddings2.shape[1])
486 | nrof_pairs = min(len(actual_issame), embeddings1.shape[0])
487 | nrof_thresholds = len(thresholds)
488 | k_fold = KFold(n_splits=nrof_folds, shuffle=False)
489 |
490 | val = np.zeros(nrof_folds)
491 | far = np.zeros(nrof_folds)
492 |
493 | indices = np.arange(nrof_pairs)
494 |
495 | for fold_idx, (train_set, test_set) in enumerate(k_fold.split(indices)):
496 | if subtract_mean:
497 | mean = np.mean(np.concatenate([embeddings1[train_set], embeddings2[train_set]]), axis=0)
498 | else:
499 | mean = 0.0
500 | dist = distance(embeddings1 - mean, embeddings2 - mean, distance_metric)
501 |
502 | # Find the threshold that gives FAR = far_target
503 | far_train = np.zeros(nrof_thresholds)
504 | for threshold_idx, threshold in enumerate(thresholds):
505 | _, far_train[threshold_idx] = calculate_val_far(threshold, dist[train_set], actual_issame[train_set])
506 | if np.max(far_train) >= far_target:
507 | f = interpolate.interp1d(far_train, thresholds, kind='slinear')
508 | threshold = f(far_target)
509 | else:
510 | threshold = 0.0
511 |
512 | val[fold_idx], far[fold_idx] = calculate_val_far(threshold, dist[test_set], actual_issame[test_set])
513 |
514 | val_mean = np.mean(val)
515 | far_mean = np.mean(far)
516 | val_std = np.std(val)
517 | return val_mean, val_std, far_mean
518 |
519 |
520 | def calculate_val_far(threshold, dist, actual_issame):
521 | predict_issame = np.less(dist, threshold)
522 | true_accept = np.sum(np.logical_and(predict_issame, actual_issame))
523 | false_accept = np.sum(np.logical_and(predict_issame, np.logical_not(actual_issame)))
524 | n_same = np.sum(actual_issame)
525 | n_diff = np.sum(np.logical_not(actual_issame))
526 | val = float(true_accept) / float(n_same)
527 | far = float(false_accept) / float(n_diff)
528 | return val, far
529 |
530 |
531 | def store_revision_info(src_path, output_dir, arg_string):
532 | try:
533 | # Get git hash
534 | cmd = ['git', 'rev-parse', 'HEAD']
535 | gitproc = Popen(cmd, stdout=PIPE, cwd=src_path)
536 | (stdout, _) = gitproc.communicate()
537 | git_hash = stdout.strip()
538 | except OSError as e:
539 | git_hash = ' '.join(cmd) + ': ' + e.strerror
540 |
541 | try:
542 | # Get local changes
543 | cmd = ['git', 'diff', 'HEAD']
544 | gitproc = Popen(cmd, stdout=PIPE, cwd=src_path)
545 | (stdout, _) = gitproc.communicate()
546 | git_diff = stdout.strip()
547 | except OSError as e:
548 | git_diff = ' '.join(cmd) + ': ' + e.strerror
549 |
550 | # Store a text file in the log directory
551 | rev_info_filename = os.path.join(output_dir, 'revision_info.txt')
552 | with open(rev_info_filename, "w") as text_file:
553 | text_file.write('arguments: %s\n--------------------\n' % arg_string)
554 | text_file.write('tensorflow version: %s\n--------------------\n' % tf.__version__) # @UndefinedVariable
555 | text_file.write('git hash: %s\n--------------------\n' % git_hash)
556 | text_file.write('%s' % git_diff)
557 |
558 |
559 | def list_variables(filename):
560 | reader = training.NewCheckpointReader(filename)
561 | variable_map = reader.get_variable_to_shape_map()
562 | names = sorted(variable_map.keys())
563 | return names
564 |
565 |
566 | def put_images_on_grid(images, shape=(16, 8)):
567 | nrof_images = images.shape[0]
568 | img_size = images.shape[1]
569 | bw = 3
570 | img = np.zeros((shape[1] * (img_size + bw) + bw, shape[0] * (img_size + bw) + bw, 3), np.float32)
571 | for i in range(shape[1]):
572 | x_start = i * (img_size + bw) + bw
573 | for j in range(shape[0]):
574 | img_index = i * shape[0] + j
575 | if img_index >= nrof_images:
576 | break
577 | y_start = j * (img_size + bw) + bw
578 | img[x_start:x_start + img_size, y_start:y_start + img_size, :] = images[img_index, :, :, :]
579 | if img_index >= nrof_images:
580 | break
581 | return img
582 |
583 |
584 | def write_arguments_to_file(args, filename):
585 | with open(filename, 'w') as f:
586 | for key, value in iteritems(vars(args)):
587 | f.write('%s: %s\n' % (key, str(value)))
588 |
--------------------------------------------------------------------------------