毕业设计——基于OpenCV的视频人脸识别检测系统的设计与实现

这篇具有很好参考价值的文章主要介绍了毕业设计——基于OpenCV的视频人脸识别检测系统的设计与实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

如需完整源码,可以联系博主获取

本系统基于OpenCV使用Haar级联与dlib库进行人脸检测及实时跟踪,应用LBPH算法开发了一个功能相对完整的人脸识别系统。系统采用sqlite3进行序列化数据存储,能够对陌生人脸闯入进行报警,并拥有基于PyQt5设计的GUI实现。

一、引言

随着计算机视觉和人工智能技术的快速发展,人脸识别技术已经成为现代社会安全监控、身份验证等领域的重要工具。OpenCV作为开源的计算机视觉库,为开发高效、稳定的人脸识别检测系统提供了强大的支持。本论文旨在基于OpenCV设计并实现一个功能相对完整的视频人脸识别检测系统,该系统采用Haar级联与dlib库进行人脸检测及实时跟踪,应用LBPH算法进行人脸识别,并使用sqlite3进行序列化数据存储。此外,系统还集成了基于PyQt5设计的图形用户界面(GUI),能够实现对陌生人脸的识别与报警功能。

二、相关技术介绍

OpenCV

OpenCV是一个开源的计算机视觉库,包含了大量的图像和视频处理函数,适用于实时计算机视觉。在本系统中,OpenCV主要用于视频流的读取、图像预处理、特征提取与匹配等关键环节。

Haar级联与dlib库

Haar级联是一种基于特征的检测器,通过训练大量的正负样本来学习目标的特征。dlib库则提供了人脸检测与关键点定位的算法实现。在本系统中,我们结合使用Haar级联与dlib库进行人脸检测,确保在各种场景下都能准确、快速地定位人脸。

LBPH算法

LBPH(Local Binary Patterns Histograms)是一种基于局部二值模式直方图的人脸识别算法。它通过计算图像局部区域的二值模式并统计直方图来提取特征,对于光照变化和表情变化具有一定的鲁棒性。在本系统中,我们采用LBPH算法进行人脸识别,实现对已知人脸的准确识别。

sqlite3序列化数据存储

sqlite3是一个轻量级的关系型数据库,支持数据的序列化存储和高效检索。在本系统中,我们使用sqlite3存储人脸特征数据,以便在识别过程中快速匹配。同时,通过序列化存储,我们可以方便地实现数据的备份、迁移和共享。

PyQt5 GUI设计

PyQt5是一个用于创建图形用户界面的Python库,基于Qt框架。在本系统中,我们使用PyQt5设计并实现了友好的用户界面,使得用户可以方便地进行视频流的选择、人脸识别参数的配置以及识别结果的查看等操作。

三、系统设计与实现

本系统主要分为视频流处理、人脸检测与跟踪、人脸识别、数据存储和GUI设计等几个模块。首先,通过OpenCV读取视频流并进行预处理。然后,利用Haar级联与dlib库进行人脸检测,并通过实时跟踪算法确保人脸位置的准确性。接着,提取人脸特征并使用LBPH算法进行识别。识别结果将存储在sqlite3数据库中,并通过PyQt5设计的GUI展示给用户。当系统检测到陌生人脸时,将触发报警功能,提醒用户进行进一步处理。

四、结论与展望

本论文基于OpenCV设计并实现了一个功能相对完整的视频人脸识别检测系统。该系统采用先进的人脸检测与识别算法,结合sqlite3数据库和PyQt5 GUI设计,实现了高效、准确的人脸识别与实时跟踪功能。未来,我们将进一步优化算法性能,提升系统的识别速度和准确率,并探索更多应用场景下的人脸识别技术。

通过本系统的设计与实现,我们为相关领域的研究者和实践者提供了一个有效的技术解决方案,并为人脸识别技术的发展和应用推广做出了积极贡献。

五、系统部署与演示
需求库:
numpy1.14.2
PyQt5
5.9.2
PySocks1.6.8
python-telegram-bot
10.0.1

创建Python虚拟环境

$ conda create -n opencv python=3.6
$ activate opencv

安装OpenCV

$ cd modules
$ pip install opencv_python-3.4.1+contrib-cp36-cp36m-win_amd64.whl

安装dlib

$ pip install dlib-19.8.1-cp36-cp36m-win_amd64.whl

安装其它依赖包

$ cd ..
$ pip install -r requirements.txt

运行核心框架

$ python core.py

运行人脸采集系统

$ python dataRecord.py

运行数据管理系统

$ python dataManage.py

opencv实现人脸识别系统与sql联系,计算机课程毕设源码,毕业设计,opencv,音视频,人工智能,计算机视觉,毕业设计,课程设计opencv实现人脸识别系统与sql联系,计算机课程毕设源码,毕业设计,opencv,音视频,人工智能,计算机视觉,毕业设计,课程设计
opencv实现人脸识别系统与sql联系,计算机课程毕设源码,毕业设计,opencv,音视频,人工智能,计算机视觉,毕业设计,课程设计

六、核心源码文章来源地址https://www.toymoban.com/news/detail-848278.html

#!/usr/bin/env python3

import telegram
import cv2
import dlib

from 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

import os
import webbrowser
import logging
import logging.config
import sqlite3
import sys
import threading
import queue
import multiprocessing
import winsound

from configparser import ConfigParser
from datetime import datetime


# 找不到已训练的人脸数据文件
class TrainingDataNotFoundError(FileNotFoundError):
    pass


# 找不到数据库文件
class DatabaseNotFoundError(FileNotFoundError):
    pass


class CoreUI(QMainWindow):
    database = './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/Core.ui', self)
        self.setWindowIcon(QIcon('./icons/icon.png'))
        self.setFixedSize(1161, 623)

        # 图像捕获
        self.isExternalCameraUsed = False
        self.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 = 10
        self.panalarmThread = threading.Thread(target=self.recieveAlarm, daemon=True)
        self.isBellEnabled = True
        self.bellCheckBox.stateChanged.connect(lambda: self.enableBell(self.bellCheckBox))
        self.isTelegramBotPushEnabled = False
        self.telegramBotPushCheckBox.stateChanged.connect(
            lambda: self.enableTelegramBotPush(self.telegramBotPushCheckBox))
        self.telegramBotSettingsButton.clicked.connect(self.telegramBotSettings)

        # 帮助与支持
        self.viewGithubRepoButton.clicked.connect(
            lambda: webbrowser.open('https://github.com/winterssy/face_recognition_py'))
        self.contactDeveloperButton.clicked.connect(lambda: webbrowser.open('https://t.me/winterssy'))

        # 日志系统
        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 DatabaseNotFoundError
            if not os.path.isfile(self.trainingData):
                raise TrainingDataNotFoundError

            conn = 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 = True
        else:
            self.isExternalCameraUsed = False

    # 打开/关闭摄像头
    def startWebcam(self):
        if not self.cap.isOpened():
            if self.isExternalCameraUsed:
                camID = 1
            else:
                camID = 0
            self.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 -> RGB
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # default:The image is stored using 8-bit indexes into a colormap, for example:a gray image
        qformat = QImage.Format_Indexed8

        if 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_RGBA8888
            else:
                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 = True
            self.statusBar().showMessage('设备发声:开启')
        else:
            if self.isTelegramBotPushEnabled:
                self.isBellEnabled = False
                self.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 = True
            self.statusBar().showMessage('TelegramBot推送:开启')
        else:
            if self.isBellEnabled:
                self.isTelegramBotPushEnabled = False
                self.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 = False
        if 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()

    # 设备响铃进程
    @staticmethod
    def bellProcess(queue):
        logQueue = queue
        logQueue.put('Info:设备正在响铃...')
        winsound.PlaySound('./alarm.wav', winsound.SND_FILENAME)

    # TelegramBot推送进程
    @staticmethod
    def telegramBotPushProcess(queue, img=None):
        logQueue = queue
        cfg = 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)

            # 发送疑似陌生人脸截屏到Telegram
            if 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 = None
                    p2 = 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()  # 自动滚屏

    # 系统对话框
    @staticmethod
    def 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/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 False
        else:
            return True


# OpenCV线程
class FaceProcessingThread(QThread):
    def __init__(self):
        super(FaceProcessingThread, self).__init__()
        self.isRunning = True

        self.isFaceTrackerEnabled = True
        self.isFaceRecognizerEnabled = False
        self.isPanalarmEnabled = True

        self.isDebugMode = False
        self.confidenceThreshold = 50
        self.autoAlarmThreshold = 65

        self.isEqualizeHistEnabled = False

    # 是否开启人脸跟踪
    def enableFaceTracker(self, coreUI):
        if coreUI.faceTrackerCheckBox.isChecked():
            self.isFaceTrackerEnabled = True
            coreUI.statusBar().showMessage('人脸跟踪:开启')
        else:
            self.isFaceTrackerEnabled = False
            coreUI.statusBar().showMessage('人脸跟踪:关闭')

    # 是否开启人脸识别
    def enableFaceRecognizer(self, coreUI):
        if coreUI.faceRecognizerCheckBox.isChecked():
            if self.isFaceTrackerEnabled:
                self.isFaceRecognizerEnabled = True
                coreUI.statusBar().showMessage('人脸识别:开启')
            else:
                CoreUI.logQueue.put('Error:操作失败,请先开启人脸跟踪')
                coreUI.faceRecognizerCheckBox.setCheckState(Qt.Unchecked)
                coreUI.faceRecognizerCheckBox.setChecked(False)
        else:
            self.isFaceRecognizerEnabled = False
            coreUI.statusBar().showMessage('人脸识别:关闭')

    # 是否开启报警系统
    def enablePanalarm(self, coreUI):
        if coreUI.panalarmCheckBox.isChecked():
            self.isPanalarmEnabled = True
            coreUI.statusBar().showMessage('报警系统:开启')
        else:
            self.isPanalarmEnabled = False
            coreUI.statusBar().showMessage('报警系统:关闭')

    # 是否开启调试模式
    def enableDebug(self, coreUI):
        if coreUI.debugCheckBox.isChecked():
            self.isDebugMode = True
            coreUI.statusBar().showMessage('调试模式:开启')
        else:
            self.isDebugMode = False
            coreUI.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 = True
            coreUI.statusBar().showMessage('直方图均衡化:开启')
        else:
            self.isEqualizeHistEnabled = False
            coreUI.statusBar().showMessage('直方图均衡化:关闭')

    def run(self):
        faceCascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')

        # 帧数、人脸ID初始化
        frameCounter = 0
        currentFaceID = 0

        # 人脸跟踪器字典初始化
        faceTrackers = {}

        isTrainingDataLoaded = False
        isDbConnected = False

        while 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 = True
                if not isDbConnected and os.path.isfile(CoreUI.database):
                    conn = sqlite3.connect(CoreUI.database)
                    cursor = conn.cursor()
                    isDbConnected = True

                captureData = {}
                realTimeFrame = frame.copy()
                alarmSignal = {}

                # 人脸跟踪
                # Reference:https://github.com/gdiepen/face-recognition
                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 = False

                        if 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 Exception
                            except 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 = True
                                cv2.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'] = realTimeFrame
                                        CoreUI.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 * w
                            y_bar = y + 0.5 * h

                            # matchedFid表征当前检测到的人脸是否已被跟踪
                            matchedFid = None

                            for 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_w
                                t_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'] = frame
                captureData['realTimeFrame'] = realTimeFrame
                CoreUI.captureQueue.put(captureData)

            else:
                continue

    # 停止OpenCV线程
    def stop(self):
        self.isRunning = False
        self.quit()
        self.wait()


if __name__ == '__main__':
    logging.config.fileConfig('./config/logging.cfg')
    app = QApplication(sys.argv)
    window = CoreUI()
    window.show()
    sys.exit(app.exec())

到了这里,关于毕业设计——基于OpenCV的视频人脸识别检测系统的设计与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux毕业设计:基于OpenCV和QT库实现的人脸识别考勤/门禁系统(arm嵌入式ubuntu)

            本文介绍:Linux上以opencv和qt库实现的人脸识别系统,可应用于考勤、门禁等场景,具有人脸录入、删除、人脸检测、识别、用户管理等完整功能。可运行于ARM嵌入式linux、ubuntu即纯软件、ARM+PC组合等多种方式,应用场景多样且易于移植各个平台。 毕业设计题目汇

    2024年02月04日
    浏览(63)
  • 毕业设计 深度学习 机器视觉 人脸识别系统 - opencv python

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年01月16日
    浏览(97)
  • 毕业设计-基于深度学习的人脸表情识别

    目录 前言 课题背景和意义 实现技术思路 一、深度学习理论基础  二、AdaBoost 结合 SVM 算法表情识别  三、基于 MTCNN 算法的人脸表情识别 实现效果图样例 最后     📅大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计

    2024年02月01日
    浏览(79)
  • python人脸识别考勤系统 考勤签到系统 OpenCV 大数据 毕业设计(源码)✅

    毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏) 毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总 🍅 感兴趣的可以先收藏起来,点赞、关注不迷路,大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助同学们顺利毕业 。

    2024年02月19日
    浏览(73)
  • python人脸识别考勤系统 dlib+OpenCV和Pyqt5、数据库sqlite 人脸识别系统 计算机 毕业设计 源码

    Python语言、dlib、OpenCV、Pyqt5界面设计、sqlite3数据库 本系统使用dlib作为人脸识别工具,dlib提供一个方法可将人脸图片数据映射到128维度的空间向量,如果两张图片来源于同一个人,那么两个图片所映射的空间向量距离就很近,否则就会很远。因此,可以通过提取图片并映射到

    2024年02月08日
    浏览(57)
  • 基于Python的人脸识别系统 深度学习 毕业设计 (附源码)

             人脸识别系统是一种基于人脸图像或视频进行人物身份认证和识别的技术。 技术进步:随着计算机视觉和深度学习技术的发展,人脸识别系统取得了长足进步。特别是卷积神经网络(CNN)的出现,使得人脸识别系统在准确性、鲁棒性和性能上都有了显著提升。

    2024年02月05日
    浏览(71)
  • 人脸识别系统OpenCV+dlib+python(含数据库)Pyqt5界面设计 项目源码 毕业设计

    Python语言、dlib、OpenCV、Pyqt5界面设计、sqlite3数据库      本系统使用dlib作为人脸识别工具,dlib提供一个方法可将人脸图片数据映射到128维度的空间向量,如果两张图片来源于同一个人,那么两个图片所映射的空间向量距离就很近,否则就会很远。因此,可以通过提取图片并

    2024年02月05日
    浏览(68)
  • 基于Java(SpringBoot框架)毕业设计作品成品(28)AI毕业设计人脸识别考勤签到系统设计与实现

    博主介绍: 《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月08日
    浏览(70)
  • 毕业设计:基于深度学习的摄像头人脸识别系统 人工智能

    目录 前言 课题背景和意义 实现技术思路 一、算法理论基础 1.1 人脸检测技术 1.2 活体检测技术 二、 数据集 2.1 数据集 2.2 数据扩充 三、实验及结果分析 3.1 实验环境搭建 3.2 模型训练 最后     📅大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就

    2024年04月27日
    浏览(58)
  • 毕业设计——基于Pytorch的人脸识别及人像卡通化算法设计与实现(源码+数据+模型)

    如需完整项目,请私信博主 基于Pytorch的人脸识别及人像卡通化算法设计与实现综述 一、引言 随着深度学习技术的飞速发展,人脸识别与人像卡通化作为计算机视觉领域的两大重要应用,近年来受到了广泛关注。基于Pytorch的人脸识别技术通过构建深度学习模型,实现对人脸

    2024年04月17日
    浏览(80)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包