项目介绍
我们先来看看成果:
首先写了一个能够操作的GUI界面。
其中两个按钮对应相应的功能:
采集人脸:
识别功能:
我可是牺牲了色相五五五五。。。(电脑像素不是很好大家将就一下嘿嘿嘿)
项目思路
本项目是借助于python的一个cv2图像识别库,通过调取电脑的摄像头进行识别人脸并保存人脸图片的功能,然后在通过cv2中的这两个训练工具对保存的人脸图片进行训练(这些都是已经写好的人脸识别算法)我们直接调用就可以。
项目模块
本项目大致细分能分四个模块。
1.人脸采集
通过
cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
对摄像头的图片进行人脸信息的对比,找到人脸的核心区域然后用长方形方框给圈出来,等待指令,并且进行下一步的保存人脸图片:
这些都是我保存好的(我可是牺牲了色相呜呜呜)这些用来进行数据训练。
2.数据训练
将某一目录下的图片转化为数组,获取每张图片中人脸部分的数据保存到事先创建好的列表中,同时获取每张图片的ID,同样保存在事先创建好的列表中,最后将训练后的数据保存。
3.人脸识别
cv2会把训练好的数据放在一个文件中,我们在识别的时候直接调用这个数据和摄像头上面的人脸进行对比。
上图为训练好的一个文件。
识别效果在上面大家也看到了!!!
4.GUI界面
这个我是通过pyqt来设计了一个简单的GUI界面,配置pyqt环境我在我之前的一篇博客介绍过了——pyqt的介绍
使用了两个简单的button来进行一个可视化。
项目代码
人脸采集
import numpy as np import cv2 def b(): print('正在调用摄像头!') faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') cap = cv2.VideoCapture(0) cap.set(3,640) # set Width cap.set(4,480) # set Height while True: ret, img = cap.read() #将彩色图转为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=5 , minSize=(20, 20) ) for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] cv2.imshow('video',img) k = cv2.waitKey(30) & 0xff if k == ord('s'): n = input('请输入编号:') cv2.imwrite('./data/jm/'+n+'.jpg',roi_gray) if k == 27: # press 'ESC' to quit break cap.release() cv2.destroyAllWindows() b()
数据训练
i
mport os import cv2 import sys from PIL import Image import numpy as np def getImageAndLabels(path): facesSamples=[] ids=[] imagePaths=[os.path.join(path,f) for f in os.listdir(path)] #检测人脸 face_detector = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml') #打印数组imagePaths print('数据排列:',imagePaths) #遍历列表中的图片 for imagePath in imagePaths: #打开图片,黑白化 PIL_img=Image.open(imagePath).convert('L') #将图像转换为数组,以黑白深浅 # PIL_img = cv2.resize(PIL_img, dsize=(400, 400)) img_numpy=np.array(PIL_img,'uint8') #获取图片人脸特征 faces = face_detector.detectMultiScale(img_numpy) #获取每张图片的id和姓名 id = int(os.path.split(imagePath)[1].split('.')[0]) #预防无面容照片 for x,y,w,h in faces: ids.append(id) facesSamples.append(img_numpy[y:y+h,x:x+w]) #打印脸部特征和id #print('fs:', facesSamples) print('id:', id) #print('fs:', facesSamples[id]) print('fs:', facesSamples) #print('脸部例子:',facesSamples[0]) #print('身份信息:',ids[0]) return facesSamples,ids if __name__ == '__main__': #图片路径 path='./data/jm/' #获取图像数组和id标签数组和姓名 faces,ids=getImageAndLabels(path) #获取训练对象 recognizer=cv2.face.LBPHFaceRecognizer_create() #recognizer.train(faces,names)#np.array(ids) recognizer.train(faces,np.array(ids)) #保存文件 recognizer.write('trainer/trainer3.yml')
人脸识别
import cv2 import os def a(): #加载识别器 recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.read('trainer/trainer3.yml') #加载分类器 cascade_path = "haarcascade_frontalface_alt2.xml" face_cascade = cv2.CascadeClassifier(cascade_path) cam = cv2.VideoCapture(0) minW = 0.1*cam.get(3) minH = 0.1*cam.get(4) font = cv2.FONT_HERSHEY_SIMPLEX names = [] agelist=[21,21,21,21,21,21,22] path='./data/jm/' imagePaths=[os.path.join(path,f) for f in os.listdir(path)] for imagePath in imagePaths: id = int(os.path.split(imagePath)[1].split('.')[0]) names.append(id) while True: ret, img = cam.read() gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale( gray, scaleFactor=1.3, minNeighbors=5, minSize=(int(minW), int(minH)) ) for (x, y, w, h) in faces: cv2.rectangle(img, (x , y ), (x + w , y + h ), (225, 0, 0), 2) img_id, confidence = recognizer.predict(gray[y:y + h, x:x + w]) print(img_id,confidence) if confidence < 50: confidence = "{0}%".format(round(100 - confidence)) else: img_id = "Unknown" confidence = "{0}%".format(round(100 - confidence)) if img_id != "Unknown": print('识别成功!!') else: print('识别失败!!') cv2.putText(img, str(img_id), (x, y + h), font, 0.55, (0, 255, 0), 1) cv2.putText(img, "18", (x , y + 500), font, 1, (0, 255, 0), 1) cv2.putText(img, "18", (x , y +h + 150), font, 1, (0, 255, 0), 1) cv2.putText(img, str(confidence), (x + 5, y - 5), font, 1, (0, 255, 0), 1) cv2.imshow('face', img) if cv2.waitKey(5) & 0xFF == 27: break cam.release() cv2.destroyAllWindows() 合并GUI from PyQt5 import QtCore, QtGui, QtWidgets import cv2 class Ui_MainWindow(QtWidgets.QMainWindow): def __init__(self): super(Ui_MainWindow,self).__init__() def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(565, 331) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(70, 190, 111, 61)) self.pushButton.setObjectName("pushButton") self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget) self.pushButton_2.setGeometry(QtCore.QRect(310, 190, 121, 61)) self.pushButton_2.setObjectName("pushButton_2") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(180, 60, 161, 81)) self.label.setObjectName("label") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 565, 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", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "采集人脸信息")) self.pushButton_2.setText(_translate("MainWindow", "开始识别")) # self.label.setText(_translate("MainWindow", "结果:")) self.pushButton.clicked.connect(self.b) self.pushButton_2.clicked.connect(self.final) def b(self): print('正在调用摄像头!') print("输入'esc'为退出!!!") faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') cap = cv2.VideoCapture(0) cap.set(3, 640) # set Width cap.set(4, 480) # set Height print("请输入字母's'保存信息!!") while True: ret, img = cap.read() # 将彩色图转为灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale( gray, scaleFactor=1.2, minNeighbors=5 , minSize=(20, 20) ) for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = gray[y:y + h, x:x + w] roi_color = img[y:y + h, x:x + w] cv2.imshow('video', img) k = cv2.waitKey(30) & 0xff if k == ord('s'): n = input('请输入编号:') cv2.imwrite('./data/jm/' + n + '.jpg', roi_gray) if k == 27: break cap.release() cv2.destroyAllWindows() print("正在训练!!!") self.train() def final(self): import face_zhineng.final_face face_zhineng.final_face.a() def train(self): import cv2 import numpy as np import face_zhineng.training # 图片路径 path = './data/jm/' faces, ids = face_zhineng.training.getImageAndLabels(path) # 获取训练对象 recognizer = cv2.face.LBPHFaceRecognizer_create() recognizer.train(faces, np.array(ids)) # 保存文件 recognizer.write('trainer/trainer3.yml') print("训练完毕!!!") 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_())
项目总结
这个项目终于完工了,长长的叹了一口气哈哈哈哈哈哈哈哈哈哈,以后python的项目都不知道啥时候在去写了,目前正在学Java,可能Java的项目会变多,但是我也会一定时间去重写一个python项目。
对于这个项目其实还可以拓展到一些人脸打开的软件上面去,本来是打算这样写的,但是由于时间和精力不是很充裕,我就简单的弄了一下,如果有兴趣的小伙伴可以自己去试试哦!