最后主要讲述神经网络模型的训练过程,使用OpenCV模块中的LBPH(LOCAL BINARY PATTERNS HISTOGRAMS)人脸识别器算法

人脸识别的过程也非常简单,通过使用OpenCV模块读取“.yml”后缀的识别模型文件,实现人脸识别。(ps:图来自原作者)

主要代码如下:

#!/usr/bin/env python3
#CSDN:https://blog.csdn.net/BC_COM/
#邮箱:botron.campus@aliyun.com
import telegram
import cv2
import dlibfrom PyQt5.QtCore import QTimer, QThread, pyqtSignal, QRegExp, Qt
from PyQt5.QtGui import QImage, QPixmap, QIcon, QTextCursor, QRegExpValidator
from PyQt5.QtWidgets import QDialog, QApplication, QMainWindow, QMessageBox
from PyQt5.uic import loadUi###############
from configparser import ConfigParser
from datetime import datetime# 找不到已训练的人脸数据文件
class TrainingDataNotFoundError(FileNotFoundError):pass
# 找不到数据库文件
class DatabaseNotFoundError(FileNotFoundError):pass
class CoreUI(QMainWindow):database = './Facedata/FaceBase.db'trainingData = './recognizer/trainingData.yml'cap = cv2.VideoCapture()captureQueue = queue.Queue()  # 图像队列alarmQueue = queue.LifoQueue()  # 报警队列,后进先出logQueue = multiprocessing.Queue()  # 日志队列receiveLogSignal = pyqtSignal(str)  # LOG信号def __init__(self):super(CoreUI, self).__init__()loadUi('./ui/GUI/Core.ui', self)self.setWindowIcon(QIcon('./icons/icon.png'))self.setFixedSize(1161, 621)# 图像捕获self.isExternalCameraUsed = Falseself.useExternalCameraCheckBox.stateChanged.connect(lambda: self.useExternalCamera(self.useExternalCameraCheckBox))self.faceProcessingThread = FaceProcessingThread()self.startWebcamButton.clicked.connect(self.startWebcam)# 数据库self.initDbButton.setIcon(QIcon('./icons/warning.png'))self.initDbButton.clicked.connect(self.initDb)self.timer = QTimer(self)  # 初始化一个定时器self.timer.timeout.connect(self.updateFrame)# 功能开关self.faceTrackerCheckBox.stateChanged.connect(lambda: self.faceProcessingThread.enableFaceTracker(self))self.faceRecognizerCheckBox.stateChanged.connect(lambda: self.faceProcessingThread.enableFaceRecognizer(self))self.panalarmCheckBox.stateChanged.connect(lambda: self.faceProcessingThread.enablePanalarm(self))# 直方图均衡化self.equalizeHistCheckBox.stateChanged.connect(lambda: self.faceProcessingThread.enableEqualizeHist(self))# 调试模式self.debugCheckBox.stateChanged.connect(lambda: self.faceProcessingThread.enableDebug(self))self.confidenceThresholdSlider.valueChanged.connect(lambda: self.faceProcessingThread.setConfidenceThreshold(self))self.autoAlarmThresholdSlider.valueChanged.connect(lambda: self.faceProcessingThread.setAutoAlarmThreshold(self))# 报警系统self.alarmSignalThreshold = 10self.panalarmThread = threading.Thread(target=self.recieveAlarm, daemon=True)self.isBellEnabled = Trueself.bellCheckBox.stateChanged.connect(lambda: self.enableBell(self.bellCheckBox))self.isTelegramBotPushEnabled = Falseself.telegramBotPushCheckBox.stateChanged.connect(lambda: self.enableTelegramBotPush(self.telegramBotPushCheckBox))self.telegramBotSettingsButton.clicked.connect(self.telegramBotSettings)# 帮助与支持self.viewGithubRepoButton.clicked.connect(lambda: webbrowser.open('https://blog.csdn.net'))self.contactDeveloperButton.clicked.connect(lambda: webbrowser.open('https://blog.csdn.net'))# 日志系统self.receiveLogSignal.connect(lambda log: self.logOutput(log))self.logOutputThread = threading.Thread(target=self.receiveLog, daemon=True)self.logOutputThread.start()# 检查数据库状态def initDb(self):try:if not os.path.isfile(self.database):raise DatabaseNotFoundErrorif not os.path.isfile(self.trainingData):raise TrainingDataNotFoundErrorconn = sqlite3.connect(self.database)cursor = conn.cursor()cursor.execute('SELECT Count(*) FROM users')result = cursor.fetchone()dbUserCount = result[0]except DatabaseNotFoundError:logging.error('系统找不到数据库文件{}'.format(self.database))self.initDbButton.setIcon(QIcon('./icons/error.png'))self.logQueue.put('Error:未发现数据库文件,你可能未进行人脸采集')except TrainingDataNotFoundError:logging.error('系统找不到已训练的人脸数据{}'.format(self.trainingData))self.initDbButton.setIcon(QIcon('./icons/error.png'))self.logQueue.put('Error:未发现已训练的人脸数据文件,请完成训练后继续')except Exception as e:logging.error('读取数据库异常,无法完成数据库初始化')self.initDbButton.setIcon(QIcon('./icons/error.png'))self.logQueue.put('Error:读取数据库异常,初始化数据库失败')else:cursor.close()conn.close()if not dbUserCount > 0:logging.warning('数据库为空')self.logQueue.put('warning:数据库为空,人脸识别功能不可用')self.initDbButton.setIcon(QIcon('./icons/warning.png'))else:self.logQueue.put('Success:数据库状态正常,发现用户数:{}'.format(dbUserCount))self.initDbButton.setIcon(QIcon('./icons/success.png'))self.initDbButton.setEnabled(False)self.faceRecognizerCheckBox.setToolTip('须先开启人脸跟踪')self.faceRecognizerCheckBox.setEnabled(True)# 是否使用外接摄像头def useExternalCamera(self, useExternalCameraCheckBox):if useExternalCameraCheckBox.isChecked():self.isExternalCameraUsed = Trueelse:self.isExternalCameraUsed = False# 打开/关闭摄像头def startWebcam(self):if not self.cap.isOpened():if self.isExternalCameraUsed:camID = 1else:camID = 0self.cap.open(camID)self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)ret, frame = self.cap.read()if not ret:logging.error('无法调用电脑摄像头{}'.format(camID))self.logQueue.put('Error:初始化摄像头失败')self.cap.release()self.startWebcamButton.setIcon(QIcon('./icons/error.png'))else:self.faceProcessingThread.start()  # 启动OpenCV图像处理线程self.timer.start(5)  # 启动定时器self.panalarmThread.start()  # 启动报警系统线程self.startWebcamButton.setIcon(QIcon('./icons/success.png'))self.startWebcamButton.setText('关闭摄像头')else:text = '如果关闭摄像头,须重启程序才能再次打开。'informativeText = '<b>是否继续?</b>'ret = CoreUI.callDialog(QMessageBox.Warning, text, informativeText, QMessageBox.Yes | QMessageBox.No,QMessageBox.No)if ret == QMessageBox.Yes:self.faceProcessingThread.stop()if self.cap.isOpened():if self.timer.isActive():self.timer.stop()self.cap.release()self.realTimeCaptureLabel.clear()self.realTimeCaptureLabel.setText('<font color=red>摄像头未开启</font>')self.startWebcamButton.setText('摄像头已关闭')self.startWebcamButton.setEnabled(False)self.startWebcamButton.setIcon(QIcon())# 定时器,实时更新画面def updateFrame(self):if self.cap.isOpened():# ret, frame = self.cap.read()# if ret:#     self.showImg(frame, self.realTimeCaptureLabel)if not self.captureQueue.empty():captureData = self.captureQueue.get()realTimeFrame = captureData.get('realTimeFrame')self.displayImage(realTimeFrame, self.realTimeCaptureLabel)# 显示图片def displayImage(self, img, qlabel):# BGR -> RGBimg = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# default:The image is stored using 8-bit indexes into a colormap, for example:a gray imageqformat = QImage.Format_Indexed8if len(img.shape) == 3:  # rows[0], cols[1], channels[2]if img.shape[2] == 4:# The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8)# A: alpha channel,不透明度参数。如果一个像素的alpha通道数值为0%,那它就是完全透明的qformat = QImage.Format_RGBA8888else:qformat = QImage.Format_RGB888# img.shape[1]:图像宽度width,img.shape[0]:图像高度height,img.shape[2]:图像通道数# QImage.__init__ (self, bytes data, int width, int height, int bytesPerLine, Format format)# 从内存缓冲流获取img数据构造QImage类# img.strides[0]:每行的字节数(width*3),rgb为3,rgba为4# strides[0]为最外层(即一个二维数组所占的字节长度),strides[1]为次外层(即一维数组所占字节长度),strides[2]为最内层(即一个元素所占字节长度)# 从里往外看,strides[2]为1个字节长度(uint8),strides[1]为3*1个字节长度(3即rgb 3个通道)# strides[0]为width*3个字节长度,width代表一行有几个像素outImage = QImage(img, img.shape[1], img.shape[0], img.strides[0], qformat)qlabel.setPixmap(QPixmap.fromImage(outImage))qlabel.setScaledContents(True)  # 图片自适应大小# 报警系统:是否允许设备响铃def enableBell(self, bellCheckBox):if bellCheckBox.isChecked():self.isBellEnabled = Trueself.statusBar().showMessage('设备发声:开启')else:if self.isTelegramBotPushEnabled:self.isBellEnabled = Falseself.statusBar().showMessage('设备发声:关闭')else:self.logQueue.put('Error:操作失败,至少选择一种报警方式')self.bellCheckBox.setCheckState(Qt.Unchecked)self.bellCheckBox.setChecked(True)# print('isBellEnabled:', self.isBellEnabled)# 报警系统:是否允许TelegramBot推送def enableTelegramBotPush(self, telegramBotPushCheckBox):if telegramBotPushCheckBox.isChecked():self.isTelegramBotPushEnabled = Trueself.statusBar().showMessage('TelegramBot推送:开启')else:if self.isBellEnabled:self.isTelegramBotPushEnabled = Falseself.statusBar().showMessage('TelegramBot推送:关闭')else:self.logQueue.put('Error:操作失败,至少选择一种报警方式')self.telegramBotPushCheckBox.setCheckState(Qt.Unchecked)self.telegramBotPushCheckBox.setChecked(True)# print('isTelegramBotPushEnabled:', self.isTelegramBotPushEnabled)# TelegramBot设置def telegramBotSettings(self):cfg = ConfigParser()cfg.read('./config/telegramBot.cfg', encoding='utf-8-sig')read_only = cfg.getboolean('telegramBot', 'read_only')# read_only = Falseif read_only:text = '基于安全考虑,系统拒绝了本次请求。'informativeText = '<b>请联系设备管理员。</b>'CoreUI.callDialog(QMessageBox.Critical, text, informativeText, QMessageBox.Ok)else:token = cfg.get('telegramBot', 'token')chat_id = cfg.get('telegramBot', 'chat_id')proxy_url = cfg.get('telegramBot', 'proxy_url')message = cfg.get('telegramBot', 'message')self.telegramBotDialog = TelegramBotDialog()self.telegramBotDialog.tokenLineEdit.setText(token)self.telegramBotDialog.telegramIDLineEdit.setText(chat_id)self.telegramBotDialog.socksLineEdit.setText(proxy_url)self.telegramBotDialog.messagePlainTextEdit.setPlainText(message)self.telegramBotDialog.exec()# 设备响铃进程@staticmethoddef bellProcess(queue):logQueue = queuelogQueue.put('Info:设备正在响铃...')winsound.PlaySound('./icon/alarm.wav', winsound.SND_FILENAME)# TelegramBot推送进程@staticmethoddef telegramBotPushProcess(queue, img=None):logQueue = queuecfg = ConfigParser()try:cfg.read('./config/telegramBot.cfg', encoding='utf-8-sig')# 读取TelegramBot配置token = cfg.get('telegramBot', 'token')chat_id = cfg.getint('telegramBot', 'chat_id')proxy_url = cfg.get('telegramBot', 'proxy_url')message = cfg.get('telegramBot', 'message')# 是否使用代理if proxy_url:proxy = telegram.utils.request.Request(proxy_url=proxy_url)bot = telegram.Bot(token=token, request=proxy)else:bot = telegram.Bot(token=token)bot.send_message(chat_id=chat_id, text=message)# 发送疑似陌生人脸截屏到Telegramif img:bot.send_photo(chat_id=chat_id, photo=open(img, 'rb'), timeout=10)except Exception as e:logQueue.put('Error:TelegramBot推送失败')else:logQueue.put('Success:TelegramBot推送成功')# 报警系统服务常驻,接收并处理报警信号def recieveAlarm(self):while True:jobs = []# print(self.alarmQueue.qsize())if self.alarmQueue.qsize() > self.alarmSignalThreshold:  # 若报警信号触发超出既定计数,进行报警if not os.path.isdir('./unknown'):os.makedirs('./unknown')lastAlarmSignal = self.alarmQueue.get()timestamp = lastAlarmSignal.get('timestamp')img = lastAlarmSignal.get('img')# 疑似陌生人脸,截屏存档cv2.imwrite('./unknown/{}.jpg'.format(timestamp), img)logging.info('报警信号触发超出预设计数,自动报警系统已被激活')self.logQueue.put('Info:报警信号触发超出预设计数,自动报警系统已被激活')# 是否进行响铃if self.isBellEnabled:p1 = multiprocessing.Process(target=CoreUI.bellProcess, args=(self.logQueue,))p1.start()jobs.append(p1)# 是否进行TelegramBot推送if self.isTelegramBotPushEnabled:if os.path.isfile('./unknown/{}.jpg'.format(timestamp)):img = './unknown/{}.jpg'.format(timestamp)else:img = Nonep2 = multiprocessing.Process(target=CoreUI.telegramBotPushProcess, args=(self.logQueue, img))p2.start()jobs.append(p2)# 等待本轮报警结束for p in jobs:p.join()# 重置报警信号with self.alarmQueue.mutex:self.alarmQueue.queue.clear()else:continue# 系统日志服务常驻,接收并处理系统日志def receiveLog(self):while True:data = self.logQueue.get()if data:self.receiveLogSignal.emit(data)else:continue# LOG输出def logOutput(self, log):# 获取当前系统时间time = datetime.now().strftime('[%Y/%m/%d %H:%M:%S]')log = time + ' ' + log + '\n'self.logTextEdit.moveCursor(QTextCursor.End)self.logTextEdit.insertPlainText(log)self.logTextEdit.ensureCursorVisible()  # 自动滚屏# 系统对话框@staticmethoddef callDialog(icon, text, informativeText, standardButtons, defaultButton=None):msg = QMessageBox()msg.setWindowIcon(QIcon('./icons/icon.png'))msg.setWindowTitle('OpenCV Face Recognition System - Core')msg.setIcon(icon)msg.setText(text)msg.setInformativeText(informativeText)msg.setStandardButtons(standardButtons)if defaultButton:msg.setDefaultButton(defaultButton)return msg.exec()# 窗口关闭事件,关闭OpenCV线程、定时器、摄像头def closeEvent(self, event):if self.faceProcessingThread.isRunning:self.faceProcessingThread.stop()if self.timer.isActive():self.timer.stop()if self.cap.isOpened():self.cap.release()event.accept()# TelegramBot设置对话框
class TelegramBotDialog(QDialog):def __init__(self):super(TelegramBotDialog, self).__init__()loadUi('./ui/GUI/TelegramBotDialog.ui', self)self.setWindowIcon(QIcon('./icons/icon.png'))self.setFixedSize(550, 358)chat_id_regx = QRegExp('^\d+$')chat_id_validator = QRegExpValidator(chat_id_regx, self.telegramIDLineEdit)self.telegramIDLineEdit.setValidator(chat_id_validator)self.okButton.clicked.connect(self.telegramBotSettings)def telegramBotSettings(self):# 获取用户输入token = self.tokenLineEdit.text().strip()chat_id = self.telegramIDLineEdit.text().strip()proxy_url = self.socksLineEdit.text().strip()message = self.messagePlainTextEdit.toPlainText().strip()# 校验并处理用户输入if not (token and chat_id and message):self.okButton.setIcon(QIcon('./icons/error.png'))CoreUI.logQueue.put('Error:API Token、Telegram ID和消息内容为必填项')else:ret = self.telegramBotTest(token, proxy_url)if ret:cfg_file = './config/telegramBot.cfg'cfg = ConfigParser()cfg.read(cfg_file, encoding='utf-8-sig')cfg.set('telegramBot', 'token', token)cfg.set('telegramBot', 'chat_id', chat_id)cfg.set('telegramBot', 'proxy_url', proxy_url)cfg.set('telegramBot', 'message', message)try:with open(cfg_file, 'w', encoding='utf-8') as file:cfg.write(file)except:logging.error('写入telegramBot配置文件发生异常')CoreUI.logQueue.put('Error:写入配置文件时发生异常,更新失败')else:CoreUI.logQueue.put('Success:测试通过,系统已更新TelegramBot配置')self.close()else:CoreUI.logQueue.put('Error:测试失败,无法更新TelegramBot配置')# TelegramBot 测试def telegramBotTest(self, token, proxy_url):try:# 是否使用代理if proxy_url:proxy = telegram.utils.request.Request(proxy_url=proxy_url)bot = telegram.Bot(token=token, request=proxy)else:bot = telegram.Bot(token=token)bot.get_me()except Exception as e:return Falseelse:return True
# OpenCV线程
class FaceProcessingThread(QThread):def __init__(self):super(FaceProcessingThread, self).__init__()self.isRunning = Trueself.isFaceTrackerEnabled = Trueself.isFaceRecognizerEnabled = Falseself.isPanalarmEnabled = Trueself.isDebugMode = Falseself.confidenceThreshold = 50self.autoAlarmThreshold = 65self.isEqualizeHistEnabled = False# 是否开启人脸跟踪def enableFaceTracker(self, coreUI):if coreUI.faceTrackerCheckBox.isChecked():self.isFaceTrackerEnabled = TruecoreUI.statusBar().showMessage('人脸跟踪:开启')else:self.isFaceTrackerEnabled = FalsecoreUI.statusBar().showMessage('人脸跟踪:关闭')# 是否开启人脸识别def enableFaceRecognizer(self, coreUI):if coreUI.faceRecognizerCheckBox.isChecked():if self.isFaceTrackerEnabled:self.isFaceRecognizerEnabled = TruecoreUI.statusBar().showMessage('人脸识别:开启')else:CoreUI.logQueue.put('Error:操作失败,请先开启人脸跟踪')coreUI.faceRecognizerCheckBox.setCheckState(Qt.Unchecked)coreUI.faceRecognizerCheckBox.setChecked(False)else:self.isFaceRecognizerEnabled = FalsecoreUI.statusBar().showMessage('人脸识别:关闭')# 是否开启报警系统def enablePanalarm(self, coreUI):if coreUI.panalarmCheckBox.isChecked():self.isPanalarmEnabled = TruecoreUI.statusBar().showMessage('报警系统:开启')else:self.isPanalarmEnabled = FalsecoreUI.statusBar().showMessage('报警系统:关闭')# 是否开启调试模式def enableDebug(self, coreUI):if coreUI.debugCheckBox.isChecked():self.isDebugMode = TruecoreUI.statusBar().showMessage('调试模式:开启')else:self.isDebugMode = FalsecoreUI.statusBar().showMessage('调试模式:关闭')# 设置置信度阈值def setConfidenceThreshold(self, coreUI):if self.isDebugMode:self.confidenceThreshold = coreUI.confidenceThresholdSlider.value()coreUI.statusBar().showMessage('置信度阈值:{}'.format(self.confidenceThreshold))# 设置自动报警阈值def setAutoAlarmThreshold(self, coreUI):if self.isDebugMode:self.autoAlarmThreshold = coreUI.autoAlarmThresholdSlider.value()coreUI.statusBar().showMessage('自动报警阈值:{}'.format(self.autoAlarmThreshold))# 直方图均衡化def enableEqualizeHist(self, coreUI):if coreUI.equalizeHistCheckBox.isChecked():self.isEqualizeHistEnabled = TruecoreUI.statusBar().showMessage('直方图均衡化:开启')else:self.isEqualizeHistEnabled = FalsecoreUI.statusBar().showMessage('直方图均衡化:关闭')def run(self):faceCascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')# 帧数、人脸ID初始化frameCounter = 0currentFaceID = 0# 人脸跟踪器字典初始化faceTrackers = {}isTrainingDataLoaded = FalseisDbConnected = Falsewhile self.isRunning:if CoreUI.cap.isOpened():ret, frame = CoreUI.cap.read()gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 是否执行直方图均衡化if self.isEqualizeHistEnabled:gray = cv2.equalizeHist(gray)faces = faceCascade.detectMultiScale(gray, 1.3, 5, minSize=(90, 90))# 预加载数据文件if not isTrainingDataLoaded and os.path.isfile(CoreUI.trainingData):recognizer = cv2.face.LBPHFaceRecognizer_create()recognizer.read(CoreUI.trainingData)isTrainingDataLoaded = Trueif not isDbConnected and os.path.isfile(CoreUI.database):conn = sqlite3.connect(CoreUI.database)cursor = conn.cursor()isDbConnected = TruecaptureData = {}realTimeFrame = frame.copy()alarmSignal = {}# 人脸跟踪if self.isFaceTrackerEnabled:# 要删除的人脸跟踪器列表初始化fidsToDelete = []for fid in faceTrackers.keys():# 实时跟踪trackingQuality = faceTrackers[fid].update(realTimeFrame)# 如果跟踪质量过低,删除该人脸跟踪器if trackingQuality < 7:fidsToDelete.append(fid)# 删除跟踪质量过低的人脸跟踪器for fid in fidsToDelete:faceTrackers.pop(fid, None)for (_x, _y, _w, _h) in faces:isKnown = Falseif self.isFaceRecognizerEnabled:cv2.rectangle(realTimeFrame, (_x, _y), (_x + _w, _y + _h), (232, 138, 30), 2)face_id, confidence = recognizer.predict(gray[_y:_y + _h, _x:_x + _w])logging.debug('face_id:{},confidence:{}'.format(face_id, confidence))if self.isDebugMode:CoreUI.logQueue.put('Debug -> face_id:{},confidence:{}'.format(face_id, confidence))# 从数据库中获取识别人脸的身份信息try:cursor.execute("SELECT * FROM users WHERE face_id=?", (face_id,))result = cursor.fetchall()if result:en_name = result[0][3]else:raise Exceptionexcept Exception as e:logging.error('读取数据库异常,系统无法获取Face ID为{}的身份信息'.format(face_id))CoreUI.logQueue.put('Error:读取数据库异常,系统无法获取Face ID为{}的身份信息'.format(face_id))en_name = ''# 若置信度评分小于置信度阈值,认为是可靠识别if confidence < self.confidenceThreshold:isKnown = Truecv2.putText(realTimeFrame, en_name, (_x - 5, _y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1,(0, 97, 255), 2)else:# 若置信度评分大于置信度阈值,该人脸可能是陌生人cv2.putText(realTimeFrame, 'unknown', (_x - 5, _y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1,(0, 0, 255), 2)# 若置信度评分超出自动报警阈值,触发报警信号if confidence > self.autoAlarmThreshold:# 检测报警系统是否开启if self.isPanalarmEnabled:alarmSignal['timestamp'] = datetime.now().strftime('%Y%m%d%H%M%S')alarmSignal['img'] = realTimeFrameCoreUI.alarmQueue.put(alarmSignal)logging.info('系统发出了报警信号')# 帧数自增frameCounter += 1# 每读取10帧,检测跟踪器的人脸是否还在当前画面内if frameCounter % 10 == 0:# 这里必须转换成int类型,因为OpenCV人脸检测返回的是numpy.int32类型,# 而dlib人脸跟踪器要求的是int类型x = int(_x)y = int(_y)w = int(_w)h = int(_h)# 计算中心点x_bar = x + 0.5 * wy_bar = y + 0.5 * h# matchedFid表征当前检测到的人脸是否已被跟踪matchedFid = Nonefor fid in faceTrackers.keys():# 获取人脸跟踪器的位置# tracked_position 是 dlib.drectangle 类型,用来表征图像的矩形区域,坐标是浮点数tracked_position = faceTrackers[fid].get_position()# 浮点数取整t_x = int(tracked_position.left())t_y = int(tracked_position.top())t_w = int(tracked_position.width())t_h = int(tracked_position.height())# 计算人脸跟踪器的中心点t_x_bar = t_x + 0.5 * t_wt_y_bar = t_y + 0.5 * t_h# 如果当前检测到的人脸中心点落在人脸跟踪器内,且人脸跟踪器的中心点也落在当前检测到的人脸内# 说明当前人脸已被跟踪if ((t_x <= x_bar <= (t_x + t_w)) and (t_y <= y_bar <= (t_y + t_h)) and(x <= t_x_bar <= (x + w)) and (y <= t_y_bar <= (y + h))):matchedFid = fid# 如果当前检测到的人脸是陌生人脸且未被跟踪if not isKnown and matchedFid is None:# 创建一个人脸跟踪器tracker = dlib.correlation_tracker()# 锁定跟踪范围tracker.start_track(realTimeFrame, dlib.rectangle(x - 5, y - 10, x + w + 5, y + h + 10))# 将该人脸跟踪器分配给当前检测到的人脸faceTrackers[currentFaceID] = tracker# 人脸ID自增currentFaceID += 1# 使用当前的人脸跟踪器,更新画面,输出跟踪结果for fid in faceTrackers.keys():tracked_position = faceTrackers[fid].get_position()t_x = int(tracked_position.left())t_y = int(tracked_position.top())t_w = int(tracked_position.width())t_h = int(tracked_position.height())# 在跟踪帧中圈出人脸cv2.rectangle(realTimeFrame, (t_x, t_y), (t_x + t_w, t_y + t_h), (0, 0, 255), 2)cv2.putText(realTimeFrame, 'tracking...', (15, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255),2)captureData['originFrame'] = framecaptureData['realTimeFrame'] = realTimeFrameCoreUI.captureQueue.put(captureData)else:continue# 停止OpenCV线程def stop(self):self.isRunning = Falseself.quit()self.wait()
if __name__ == '__main__':logging.config.fileConfig('./config/logging.cfg')app = QApplication(sys.argv)window = CoreUI()window.show()sys.exit(app.exec())

最后得说的是 非常感谢原作者 :  不脱发的程序猿

参考文章:

1.https://blog.csdn.net/m0_38106923/article/details/96108803

简单用Python+OpenCv实现AI人脸识别--(4)-训练人脸识别模型相关推荐

  1. 简单用Python+OpenCv实现AI人脸识别--(3)—训练人脸识别模型

    案例引入 首先简要讲解数据集训练生成模型的原理,这里使用的是LBPH算法,在OpenCV模块中已经有内嵌的方法cv2.face.LBPHFaceRecognizer_create(),为了方便小伙伴们 ...

  2. Python+OpenCv实现AI人脸识别身份认证系统(2)——人脸数据采集、存储

    原 Python+OpenCv实现AI人脸识别身份认证系统(2)--人脸数据采集.存储 2019年07月02日 08:47:52 不脱发的程序猿 阅读数 602更多 所属专栏: 人脸识别身份认证系统设 ...

  3. Python+OpenCv实现AI人脸识别身份认证系统(1)——人脸识别原理

    原 Python+OpenCv实现AI人脸识别身份认证系统(1)--人脸识别原理 置顶 2019年07月02日 08:47:40 不脱发的程序猿 阅读数 1255更多 所属专栏: 人脸识别身份认证系统 ...

  4. Python+OpenCV实现AI人脸识别身份认证系统(4)—人脸识别

    本篇博文是Python+OpenCV实现AI人脸识别身份认证系统的收官之作,在人脸识别原理到数据采集.存储和训练识别模型基础上,实现人脸识别,废话少说,上效果图: 案例引入 在Python+OpenC ...

  5. Python+OpenCv实现AI人脸识别身份认证系统(3)——训练人脸识别模型

    目录 案例引入 本节项目 最近有小伙伴们一直在催本项目的进度,好吧,今晚熬夜加班编写,在上一节中,实现了人脸数据的采集,在本节中将对采集的人脸数据进行训练,生成识别模型. 案例引入 首先简要讲解数据集 ...

  6. python dlib学习(八):训练人脸特征点检测器

    前言 前面的博客(python dlib学习(二):人脸特征点标定)介绍了使用dlib识别68个人脸特征点,但是当时使用的是dlib官方给出的训练好的模型,这次要自己训练一个特征点检测器出来.当然,想 ...

  7. Python+OpenCV实现AI人脸识别身份认证系统(3)—训练人脸识别模型

    目录 案例引入 本节项目 最近有小伙伴们一直在催本项目的进度,好吧,今晚熬夜加班编写,在上一节中,实现了人脸数据的采集,在本节中将对采集的人脸数据进行训练,生成识别模型. 案例引入 首先简要讲解数据集 ...

  8. 【python ++ opencv + pytorch 】车牌提取、分割、识别

    话不多说,先看最后成果图(如果想要全部工程,文章最后我会把github链接放上): 可以看到最终的识别车牌号码是:苏G99999. 其实前年冬天偶然想着用c++来做一个小项目,然后就用 c++ ope ...

  9. 【python + opencv + pytorch】车牌提取、分割、识别 pro版

    老规矩,先看最后成果图(如果想要全部工程,文章最后我会把github链接放上) 1.分割车牌 2.分割字符 3.识别字符 最终识别的车牌号码是:浙F99999 整个车牌识别分五步: 1.一个分割车牌的 ...

  10. matlab中识别过程训练,人脸识别PCA算法matlab实现及详细步骤讲解

    %FaceRec.m %PCA人脸识别修订版,识别率88% %calc xmean,sigma and its eigen decomposition allsamples=[];%所有训练图像 fo ...

最新文章

  1. [JAVAEE] 初识ThymeLeaf
  2. 用Python从零开始创建区块链
  3. 自定义FireFox浏览器滚动条
  4. linux centos7 xen虚拟机 安装方法
  5. Java语言编程基础:数组
  6. 二维数组常用的赋值方式
  7. python如何输出两行_python pandas dataframe拆分行(某些行一行拆成多行)
  8. Linux系统下MySQL导出数据库和导入数据库的命令
  9. linux 真实内存,Linux计算真实可用内存
  10. Java初学01:学习路线,韩顺平java教程百度云
  11. 极路由2(极贰)ROOT并刷了OpenWrt
  12. 一、基础知识(3)-共轭函数、次梯度
  13. android应用备份,Android备份App及数据
  14. jmeter(二十):Logic Controller:逻辑控制器(上)
  15. android img 制作工具,Android 镜像文件制作 【ramdisk.img system.img userdata.img】
  16. 视频教程-Layabox3D游戏开发入门-微信3D小游戏案例 -微信开发
  17. 背景动态线条js特效html5代码
  18. python求圆柱表面积_ZZULIOJ.1011: 圆柱体表面积 —— 1021:三个整数的最大值(C语言 Vs Python)...
  19. Python中Pygal库的简单使用
  20. sap甲方_SAP顾问现状

热门文章

  1. 质量数据分析工具软件的应用
  2. 多益网络校招 —— web前端笔试题
  3. 自动化技术、计算机技术核心期刊整理及介绍
  4. 计算机科学的两本圣经_计算机科学中的两个难题
  5. 微信小程序地图实现多个位置标记marker
  6. Python 标准库 xml 详解
  7. 我的海淀驾校考驾照之路
  8. excel如何随机抽样
  9. 通俗易懂的虚短、虚断的使用条件?
  10. 整合SSM框架 -- 简单基础SSM项目