书接上文,得到了训练好的模型后,就可以使用这个模型做人脸识别了。当然,范围只限于被我拍照的几个人。

另外,我做了一个简单的界面,这个系统是用在windows下,和之前的训练模型在Ubuntu下不一样,所以我重新建立了一个工程。并使用了 Keras2.2.4
,OpenCV4.1, Python3.6.7,Pyqt5.0。

好了。开始干活

1. 画界面。

这个没啥好说的,我用QtDesigner画的界面,大致是下面这个样子,左边放了一个QLabel放摄像头捕获的图形,右边三个按钮

QtDesigner自动生成的代码如下:
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file
'D:\exceise\main_window.ui' # # Created by: PyQt5 UI code generator 5.6 # #
WARNING! All changes made in this file will be lost! from PyQt5 import QtCore,
QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow") MainWindow.resize(1024, 768)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget") self.FaceCollect =
QtWidgets.QPushButton(self.centralwidget)
self.FaceCollect.setGeometry(QtCore.QRect(790, 130, 151, 51))
self.FaceCollect.setObjectName("FaceCollect") self.OpenCamera =
QtWidgets.QPushButton(self.centralwidget)
self.OpenCamera.setGeometry(QtCore.QRect(790, 40, 151, 51))
self.OpenCamera.setObjectName("OpenCamera") self.FaceIdentify =
QtWidgets.QPushButton(self.centralwidget)
self.FaceIdentify.setGeometry(QtCore.QRect(790, 220, 151, 51))
self.FaceIdentify.setObjectName("FaceIdentify") self.ImageView =
QtWidgets.QLabel(self.centralwidget)
self.ImageView.setGeometry(QtCore.QRect(30, 20, 711, 681))
self.ImageView.setObjectName("ImageView")
MainWindow.setCentralWidget(self.centralwidget) self.menubar =
QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0,
1024, 26)) self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar) self.statusbar =
QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self,
MainWindow): _translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "人脸识别"))
self.FaceCollect.setText(_translate("MainWindow", "采集人脸"))
self.OpenCamera.setText(_translate("MainWindow", "打开摄像头"))
self.FaceIdentify.setText(_translate("MainWindow", "人脸识别"))
self.ImageView.setText(_translate("MainWindow", "")) if __name__ == "__main__":
import sys app = QtWidgets.QApplication(sys.argv) MainWindow =
QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow)
MainWindow.show() sys.exit(app.exec_())
我不想直接改动QtDesigner直接生成的代码,所以自己写一个窗口类,继承在自动生成的这个窗口。

下面代码中center_window函数是让窗口自动居中,closeEvent是窗口关闭事件。slot_init是初始化槽函数

 
import sys import cv2 from PyQt5 import QtGui, QtWidgets from PyQt5.QtCore
import * from keras.models import load_model from windows.main_window import
Ui_MainWindow # 导入创建的GUI类 class Window1(QtWidgets.QMainWindow, Ui_MainWindow):
color = (0, 255, 0) # 人脸矩形框的颜色 model = load_model("model\CNN.model") def
__init__(self): super(Window1, self).__init__() self.setupUi(self)
self.center_window() self.timer_camera = QTimer() self.cap = cv2.VideoCapture()
self.CAM_NUM = 0 self.slot_init() def closeEvent(self, event): ok =
QtWidgets.QPushButton() cacel = QtWidgets.QPushButton() msg =
QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, u"关闭", u"是否关闭!")
msg.addButton(ok,QtWidgets.QMessageBox.ActionRole) msg.addButton(cacel,
QtWidgets.QMessageBox.RejectRole) ok.setText(u'确定') cacel.setText(u'取消') #
msg.setDetailedText('sdfsdff') if msg.exec_() ==
QtWidgets.QMessageBox.RejectRole: event.ignore() else: #
self.socket_client.send_command(self.socket_client.current_user_command) if
self.cap.isOpened(): self.cap.release() if self.timer_camera.isActive():
self.timer_camera.stop() event.accept() if __name__ == '__main__': app =
QtWidgets.QApplication(sys.argv) window = Window1() window.show()
sys.exit(app.exec_())
然后解释把摄像头在QT窗口上显示的原理,理解了这个原理基本上就明白代码怎么写了。这个原理就是
通过OpenCV打开摄像头,读取每一帧图像,然后输出到QLabel上。所以要有一个Timer定时器,每隔一段时间读一帧摄像头信息,然后输出给QLabel。代码如下:
def show_camera(self): # 加载分类器 classfier =
cv2.CascadeClassifier("..\haarcascade_frontalface_alt2.xml") #
读取一帧数据,flag表示摄像头读取状态,self.image表示摄像头读取的图像矩阵mat类型 flag, self.image =
self.cap.read() # 图像灰度化,灰度化在后面检测时可以降低计算量 show = cv2.cvtColor(self.image,
cv2.COLOR_BGR2RGB) # detectMultiScale完成人脸探测工作,returns the positions of detected
faces as Rect(x,y,w,h),x、y是左上角起始坐标,h、w是高和宽 #
grey是要识别的图像数据,scaleFactor图像缩放比例,可以理解为同一个物体与相机距离不同,其大小亦不同,必须将其缩放到一定大小才方便识别,该参数指定每次缩放的比例
Rects = classfier.detectMultiScale(show, scaleFactor=1.2, minNeighbors=3,
minSize=(32, 32)) if len(Rects) > 0: for Rect in Rects: x, y, w, h = Rect #
如果监测到人脸,在人脸范围画绿色的框,其中self.color = (0, 255, 0) cv2.rectangle(show, (x, y), (x +
w, y + h), self.color, 2) # 画出矩形框 # 将监测到的人脸送给之前的模型进行人脸识别 img = cv2.resize(show,
(128, 128)) img = img.reshape(1, 128, 128, 3).astype('float32') predicted =
self.model.predict(img) # 由于QLabel不能直接显示img类型,需要转化成QImage类型 showImage =
QtGui.QImage(show.data, show.shape[1], show.shape[0],
QtGui.QImage.Format_RGB888)
self.ImageView.setPixmap(QtGui.QPixmap.fromImage(showImage))

上面的代码里就实现了人脸检测,没错就是这段代码。通过调试predicted你会发现predicted[4]=1,没错,记得上篇文章吗,我就是4号。可能有朋友要问,为什么不做个QMessageBox之类的东西,发现4号弹一个有名字的消息框,答案是我懒病犯了,不想弄。这个理由充足不!
# 将监测到的人脸送给之前的模型进行人脸识别 img = cv2.resize(show, (128, 128)) img = img.reshape(1,
128, 128, 3).astype('float32') predicted = self.model.predict(img)
同样你也要实现按钮的按下事件
def OpenCameraButtonClick(self): if self.timer_camera.isActive() == False:
flag = self.cap.open(self.CAM_NUM) if flag == False: msg =
QtWidgets.QMessageBox.warning(self, u"Warning", u"请检测相机与电脑是否连接正确",
buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok) else:
self.timer_camera.start(30) self.OpenCamera.setText(u'关闭相机') else:
self.timer_camera.stop() self.cap.release() self.ImageView.clear()
self.OpenCamera.setText(u'打开相机')
整体的代码:
import sys import cv2 from PyQt5 import QtGui, QtWidgets from PyQt5.QtCore
import * from keras.models import load_model from windows.main_window import
Ui_MainWindow # 导入创建的GUI类 class Window1(QtWidgets.QMainWindow, Ui_MainWindow):
color = (0, 255, 0) # 人脸矩形框的颜色 model = load_model("..\model\CNN.model") def
__init__(self): super(Window1, self).__init__() self.setupUi(self)
self.center_window() self.timer_camera = QTimer() self.cap = cv2.VideoCapture()
self.CAM_NUM = 0 self.slot_init() def center_window(self): desktop_geometry =
QtWidgets.QApplication.desktop() # 获取屏幕大小 main_window_width =
desktop_geometry.width() # 屏幕的宽 main_window_height = desktop_geometry.height()
# 屏幕的高 rect = self.geometry() # 获取窗口界面大小 window_width = rect.width() # 窗口界面的宽
window_height = rect.height() # 窗口界面的高 x = (main_window_width - window_width)
// 2 # 计算窗口左上角点横坐标 y = (main_window_height - window_height) // 2 # 计算窗口左上角点纵坐标
self.setGeometry(x, y, window_width, window_height) # 设置窗口界面在屏幕上的位置 def
slot_init(self): self.OpenCamera.clicked.connect(self.OpenCameraButtonClick)
self.timer_camera.timeout.connect(self.show_camera) def
OpenCameraButtonClick(self): if self.timer_camera.isActive() == False: flag =
self.cap.open(self.CAM_NUM) if flag == False: msg =
QtWidgets.QMessageBox.warning(self, u"Warning", u"请检测相机与电脑是否连接正确",
buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok) else:
self.timer_camera.start(30) self.OpenCamera.setText(u'关闭相机') else:
self.timer_camera.stop() self.cap.release() self.ImageView.clear()
self.OpenCamera.setText(u'打开相机') def show_camera(self): # 加载分类器 classfier =
cv2.CascadeClassifier("..\haarcascade_frontalface_alt2.xml") #
读取一帧数据,flag表示摄像头读取状态,self.image表示摄像头读取的图像矩阵mat类型 flag, self.image =
self.cap.read() # 图像灰度化,灰度化在后面检测时可以降低计算量 show = cv2.cvtColor(self.image,
cv2.COLOR_BGR2RGB) # detectMultiScale完成人脸探测工作,returns the positions of detected
faces as Rect(x,y,w,h),x、y是左上角起始坐标,h、w是高和宽 #
grey是要识别的图像数据,scaleFactor图像缩放比例,可以理解为同一个物体与相机距离不同,其大小亦不同,必须将其缩放到一定大小才方便识别,该参数指定每次缩放的比例
Rects = classfier.detectMultiScale(show, scaleFactor=1.2, minNeighbors=3,
minSize=(32, 32)) if len(Rects) > 0: for Rect in Rects: x, y, w, h = Rect #
如果监测到人脸,在人脸范围画绿色的框,其中self.color = (0, 255, 0) cv2.rectangle(show, (x, y), (x +
w, y + h), self.color, 2) # 画出矩形框 # 将监测到的人脸送给之前的模型进行人脸识别 img = cv2.resize(show,
(128, 128)) img = img.reshape(1, 128, 128, 3).astype('float32') predicted =
self.model.predict(img) # 由于QLabel不能直接显示img类型,需要转化成QImage类型 showImage =
QtGui.QImage(show.data, show.shape[1], show.shape[0],
QtGui.QImage.Format_RGB888)
self.ImageView.setPixmap(QtGui.QPixmap.fromImage(showImage)) def
closeEvent(self, event): ok = QtWidgets.QPushButton() cacel =
QtWidgets.QPushButton() msg =
QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, u"关闭", u"是否关闭!")
msg.addButton(ok,QtWidgets.QMessageBox.ActionRole) msg.addButton(cacel,
QtWidgets.QMessageBox.RejectRole) ok.setText(u'确定') cacel.setText(u'取消') #
msg.setDetailedText('sdfsdff') if msg.exec_() ==
QtWidgets.QMessageBox.RejectRole: event.ignore() else: #
self.socket_client.send_command(self.socket_client.current_user_command) if
self.cap.isOpened(): self.cap.release() if self.timer_camera.isActive():
self.timer_camera.stop() event.accept() if __name__ == '__main__': app =
QtWidgets.QApplication(sys.argv) window = Window1() window.show()
sys.exit(app.exec_())
 

技术
©2020 ioDraw All rights reserved
46岁微软:从盖茨缔造帝国到纳德拉复兴第二章 初识C语言常量2021前端高频面试题(一定要看哦!!!)滤波器,窗函数以及切比雪夫逼近法新手快速了解冒泡排序、插入排序的详解pytorch训练过程中GPU利用率低Golang经典面试题初识Mongdb之数据查询篇(三)人类第一架火星直升机正在部署 择机在这颗异域星球首飞python判断两个列表(list)中的值是否相同([1,2,3]和[3,2,1])