基于OpenCV的人脸识别和模型训练系统(万字详解)
前言
我们身边的人脸识别有车站检票,监控人脸,无人超市,支付宝人脸支付,上班打卡,人脸解锁手机。
人脸检测是人脸识别系统组成的关键部分之一,其目的是检测出任意给定图片中的包含的一个或多个人脸,是人脸识别、表情识别等下游任务的基础。人脸识别是通过采集包含人脸的图像或视频数据,通过对比和分析人脸特征信息从而实现身份识别的生物识别技术,是人脸识别系统的核心组件。
随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍基于OpenCV的人脸识别和模型训练系统。适合新手学习,下面展示效果图:
效果图
大家也可以看看我之前写的文章:
基于OpenCV的人脸识别https://broken.blog.csdn.net/article/details/129634466?spm=1001.2014.3001.5502
基于OpenCV的图片和视频人脸识别https://broken.blog.csdn.net/article/details/129760012?spm=1001.2014.3001.5502
OpenCV 简介
OpenCV 的全称是 Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV 是由英特尔公司发起并参与开发,以 BSD 许可证授权发行,可以在商业和研究领域中免费使用。OpenCV 可用于开发实时的图像处理、计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的 IPP 进行加速处理。
OpenCV 用 C++语言编写,它的主要接口也是 C++语言,但是依然保留了大量的 C 语言接口。该库也有大量的Python、Java and MATLAB/OCTAVE(版本 2.5)的接口。这些语言的 API 接口函数可以通过在线文档获得。如今也提供对于 C#、Ch、Ruby、GO 的支持。
安装 OpenCV 模块
OpenCV 已经支持 python 的模块了,直接使用 pip 就可以进行安装,命令如下:
pip install opencv-python
XML文件名称
我们安装完open-cv库之后,会在文件夹data中看到这样的一个文件夹haarcascades。该文件夹包含了所有 OpenCV 的人脸检测的XML 文件,这些可用于检测静止图像、视频和摄像头所得到图像中的人脸。
我们今天要用到的就是第一个,后面也会说到。
人脸检测器(默认):haarcascade_frontalface_default.xml
人脸检测器(快速 Harr):haarcascade_frontalface_alt2.xml
人脸检测器(侧视):haarcascade_profileface.xml
眼部检测器(左眼):haarcascade_lefteye_2splits.xml
眼部检测器(右眼):haarcascade_righteye_2splits.xml
嘴部检测器:haarcascade_mcs_mouth.xml
鼻子检测器:haarcascade_mcs_nose.xml
身体检测器:haarcascade_fullbody.xml
人脸检测器(快速 LBP):lbpcascade_frontalface.xml
部分核心代码
人脸检测与识别是机器视觉领域最热门的研究方向之一,本文详细介绍了人脸识别与模型训练系统。本系统实现了集人脸识别、训练人脸模型在内的多项功能:包括通过摄像头进行人脸的实时识别,博文提供了完整的Python代码和使用教程,适合新入门的朋友参考,完整代码资源文件请转至本文绑定的资源地址。
PS:也可以基于这个继续开发其他功能,什么本地照片识别训练,什么人脸管理功能等等,大家如果感兴趣可以研究。
导入库
本博文最难安装的库大概就是Open-cv库了,大家如果安装遇到了什么问题,可以看看我之前的文章,或者评论区留言,百度搜索都可以。
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QTableWidgetItem, QProgressBar
from PyQt5.QtGui import QImage, QPixmap, QTextCursor
from PyQt5.QtCore import QBasicTimer
import sys
import cv2
import numpy as np
from datetime import datetime
import numpy
import os
import random
from PIL import Image
from face_ui import Ui_FaceDetection
控件函数
在这里,有两个路径,一个是日志所在的路径,一个是打开人脸模型文件所在文件夹的路径,大家也可以自行修改这个路径,这个是相对路径,不会因为在不同盘而不能运行。
def initUI(self): # 控件回调函数(按钮绑定对应功能函数)self.pushButton_cameraon.clicked.connect(lambda: self.callcamera('on')) # 初始化摄像头self.pushButton_cameraoff.clicked.connect(lambda: self.callcamera('off')) # 关闭摄像头self.pushButton_openlogfolder.clicked.connect(lambda: self.openfolder('.\OpenCV_face')) # 打开日志文件所在文件夹(绝对路径)self.pushButton_opendbfolder.clicked.connect(lambda: self.openfolder('.\OpenCV_face\model_training\existed_model')) # 打开人脸模型文件所在文件夹(绝对路径)self.pushButton_exit.clicked.connect(self.closeevent) # 退出程序self.checkBox_trackingbox.setChecked(True) # 人脸追踪框默认勾选self.checkBox_grayscale.setChecked(False) # 灰度图框默认不选self.pushButton_catchfaces.setEnabled(False) # 人脸图像采集按钮默认不可选self.pushButton_catchfaces.clicked.connect(self.catch_faces) # 采集人脸图像self.pushButton_trainmodel.setEnabled(False) # 模型训练按钮默认不可选self.pushButton_trainmodel.clicked.connect(self.train_model) # 人脸模型训练self.lineEdit_faceimagessetname.setReadOnly(True) # 人脸图集命名默认不可用self.lineEdit_inputfacemodelname.setReadOnly(True) # 人脸图集输入默认不可用self.lineEdit_facemodelname.setReadOnly(True) # 人脸模型命名默认不可用# 进度条用self.timer1 = QBasicTimer()self.step1 = 0self.timer2 = QBasicTimer()self.step2 = 0
下面展示了进度条的功能:
调用摄像头并显示画面
我们这里主要实现的功能就是调用本地的摄像头,大家也可以修改代码,调用手机的摄像头。这里的功能也就是我们效果图中显示画面的地方。
def callcamera(self, status): # 调用摄像头并显示画面、分辨率和帧率cap = cv2.VideoCapture(700) # 掉调用本地摄像头if cap.isOpened(): # 检测摄像头是否调用成功# 初始化摄像头后启用已下控件self.pushButton_catchfaces.setEnabled(True)self.pushButton_trainmodel.setEnabled(True)self.lineEdit_faceimagessetname.setReadOnly(False)self.lineEdit_inputfacemodelname.setReadOnly(False)self.lineEdit_facemodelname.setReadOnly(False)while True:# 手动关闭摄像头#!需要点击两次关闭摄像头键才能清空屏幕if status == 'off':cap.release()cv2.destroyAllWindows()# 摄像头关闭时重置以下控件self.pushButton_catchfaces.setEnabled(False)self.pushButton_trainmodel.setEnabled(False)self.lineEdit_faceimagessetname.setReadOnly(True)self.lineEdit_inputfacemodelname.setReadOnly(True)self.lineEdit_facemodelname.setReadOnly(True)self.label_showfps.setText(' --')self.label_showres.setText(' --')self.label_showfacesnum.setText('0')self.realTimeCaptureLabel.clear()breakret, frame = cap.read() # 读取图像(frame就是读取的视频帧,对frame处理就是对整个视频的处理)if not ret: # 没有帧了直接退出循环breakglobal height, width, depthheight, width, depth = frame.shape
下面是关于摄像头操作的截图:
核心代码——人脸识别
这里就是最为核心的代码,人脸识别功能,我们在这个调用官方的模型,大家这里的路径要改,我的路径这里是:
C:\Users\18483\AppData\Local\Programs\Python\Python39\Lib\site-packages\cv2\data\haarcascade_frontalface_alt.xml
大家只要找到怎么python安装的位置就可以了,后面的路径都是一样的,大家可以用这个更方便自己找到对应的文件。
Python39\Lib\site-packages\cv2\data\haarcascade_frontalface_alt.xml
下面,我们看看这一块的功能怎么实现,并简单介绍一下:
def face_detection(self, frame, trackornot): # 人脸检测face_detector = cv2.CascadeClassifier(r'C:\Users\18483\AppData\Local\Programs\Python\Python39\Lib\site-packages\cv2\data\haarcascade_frontalface_alt.xml') # 调用官方的人脸数据模型faces = face_detector.detectMultiScale(frame) # 使用detectMultiScale函数检测frame中的人脸,并将人脸的坐标返回给facesif isinstance(faces, tuple): # 未检测到人脸返回tuple类型数据,用于人脸数量的判断self.label_showfacesnum.setText('0')return self.cv22image(frame)elif isinstance(faces, numpy.ndarray): # 检测到人脸返回numpy.ndarray类型数据,用于人脸数量的判断self.label_showfacesnum.setText('%s' % len(faces))cv2.waitKey(30)if trackornot == 'track': # 打开人脸追踪框for a, b, c, d in faces:cv2.rectangle(frame, pt1=(a, b), pt2=(a + c, b + d), color=[0, 0, 255],thickness=2) # 在已检测到的人脸上绘制一个红色方框return self.cv22image(frame)elif trackornot == 'not': # 取消人脸追踪框return self.cv22image(frame)
这个函数的工作流程如下:
- 首先,它创建了一个CascadeClassifier对象,这个对象加载了一个已经训练好的人脸检测模型。这个模型文件是
haarcascade_frontalface_alt.xml
,这是一个专门用于检测人脸的模型。 - 接着,它使用
detectMultiScale
函数在输入的帧(frame)中检测人脸。这个函数会返回一个numpy数组,数组中的每个元素是一个二元组,表示一个人脸的位置和大小。 - 如果
detectMultiScale
函数没有检测到任何人脸,那么它会返回一个tuple类型的值。在这种情况下,函数会更新显示人脸数量的标签,并返回未改变的帧。 - 如果检测到了人脸,那么它会返回一个numpy数组。在这种情况下,函数会更新显示人脸数量的标签,然后根据
trackornot
参数来决定是否在检测到的人脸周围绘制一个红色的矩形框。如果trackornot
为'track',那么会在每个人脸周围绘制矩形框,并返回处理后的帧;如果trackornot
为'not',那么直接返回未改变的帧。
这个函数的功能就是进行人脸检测,并根据需要决定是否在检测到的人脸周围绘制矩形框。
格式转化
在这里,我们还要调用一个函数,把cv2生成的画面转化为pyqt支持的格式并返回。
def cv22image(self, frame): # 将cv2生成的画面转化为pyqt支持的格式并返回frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB, frame)image = QImage(frame.data, width, height, width * depth, QImage.Format_RGB888)cv2.waitKey(30)return image
核心代码——人脸采集功能
def catch_faces(self): # 人脸采集 #!捕获到的画面中无论有没有人脸都会采集,建议改为有人脸捕获,无人脸跳过atlas_name = self.lineEdit_faceimagessetname.text() # 返回给atlas_name的值是人脸图像集名,不能为中文# 判断保存路径是否存在images_path = './OpenCV_face/model_training/collected_images/%s/' % atlas_nameif os.path.exists(images_path):passelse:os.mkdir(images_path)if len(atlas_name) == 0:QMessageBox.information(self, 'Info', '请为人脸图像集命名', )passelse:cap = cv2.VideoCapture(700) # 调用本地摄像头num = 1self.logOutput('Info:人脸图像[%s]采集开始' % atlas_name)
这段代码的功能是进行人脸采集。它首先从界面获取人脸图像集的名称(atlas_name),然后检查保存路径是否存在,如果不存在则创建该路径。接下来,如果atlas_name为空,它会弹出一个信息框提示用户为人脸图像集命名。如果atlas_name不为空,它会打开本地摄像头并开始采集人脸图像。
模型训练
接下来,就是核心代码模型训练,把我们之前采集的照片训练成我们自己的模型。
def train_model(self): # 人脸模型训练import time# 设置控件input_atlas_name = self.lineEdit_inputfacemodelname.text() # 获取需要训练的人脸图集的名称facemodel_name = self.lineEdit_facemodelname.text() # 获取人脸模型的名称if len(input_atlas_name) == 0:QMessageBox.information(self, 'Info', '请输入人脸图集名称')passelif len(facemodel_name) == 0:QMessageBox.information(self, 'Info', '请为人脸模型命名')passelse:# 输入路径ids = []faces_samples = []try:self.logOutput('Info:人脸模型[%s]训练开始' % facemodel_name)# 进度条for i in range(1, 101):self.step2 = iself.progressBar_trainmodel.setValue(i)if i == 101:self.timer2.stop()breaktime.sleep(0.2)atlas_path = './OpenCV_face/model_training/collected_images/%s/' % input_atlas_name # 需要训练的人脸图集的路径images_paths = [os.path.join(atlas_path, i) for i in os.listdir(atlas_path)]face_detector = cv2.CascadeClassifier(r"C:\Users\18483\AppData\Local\Programs\Python\Python39\Lib\site-packages\cv2\data\haarcascade_frontalface_alt.xml")
日志
我们在此版本中还加入了日志的功能,我们把它保存在了一个log.txt文件中。
def logOutput(self, log): # 日志time = datetime.now().strftime('[%Y/%m/%d %H:%M:%S]') # 获取当前系统时间log = time + ' ' + log + '\n'with open('./OpenCV_face/log.txt', 'a+') as f: # 将日志写入本地日志文件f.write(log)self.textBrowser_showlog.moveCursor(QTextCursor.End)self.textBrowser_showlog.insertPlainText(log) # 输出日志self.textBrowser_showlog.ensureCursorVisible() # 自动滚屏
下面是该功能区域的截图:
打开文件夹
def openfolder(self, path): # 打开文件夹folder_path = path# 异常捕获,当要打开的文件夹路径不存在时输出报错日志try:os.startfile(folder_path)except Exception as error:self.logOutput('Error:打开文件夹失败,请检查路径(%s)是否存在' % path)
退出程序
def closeevent(self, cap): # 关闭并退出程序answer = QMessageBox.question(self, '退出', '确定要退出吗?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)if answer == QMessageBox.Yes:cv2.destroyAllWindows()app.quit()else:pass
face_ui
这个是我们最后页面的UI代码,博主不才,可能不是很好看,大家也可以尝试优化这些代码。下面给大家展示UI的部分代码,由于篇幅有限。
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_FaceDetection(object):def setupUi(self, FaceDetection):FaceDetection.resize(1050, 820)FaceDetection.setObjectName("FaceDetection")self.groupBox_facedetect = QtWidgets.QGroupBox(FaceDetection)self.groupBox_facedetect.setGeometry(QtCore.QRect(20, 10, 641, 491))self.groupBox_facedetect.setTitle("")self.groupBox_facedetect.setAlignment(QtCore.Qt.AlignCenter)self.groupBox_facedetect.setObjectName("groupBox_facedetect")self.realTimeCaptureLabel = QtWidgets.QLabel(self.groupBox_facedetect)self.realTimeCaptureLabel.setGeometry(QtCore.QRect(20, 40, 601, 401))self.realTimeCaptureLabel.setStyleSheet("border: 2px solid grey; border-radius: 4px; color: rgb(20,20,20); background-color: #FFFFFF; text-align: center;}QProgressBar::chunk {background-color: rgb(100,200,200); border-radius: 10px; margin: 0.1px; width: 1px;")self.realTimeCaptureLabel.setFrameShape(QtWidgets.QFrame.Box)self.realTimeCaptureLabel.setAlignment(QtCore.Qt.AlignCenter)self.realTimeCaptureLabel.setObjectName("realTimeCaptureLabel")self.label_realtimescreen = QtWidgets.QLabel(self.groupBox_facedetect)self.label_realtimescreen.setGeometry(QtCore.QRect(280, 440, 91, 31))self.label_realtimescreen.setObjectName("label_realtimescreen")self.line_2 = QtWidgets.QFrame(self.groupBox_facedetect)self.line_2.setGeometry(QtCore.QRect(380, 450, 241, 16))self.line_2.setFrameShape(QtWidgets.QFrame.HLine)self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)self.line_2.setObjectName("line_2")self.line_3 = QtWidgets.QFrame(self.groupBox_facedetect)self.line_3.setGeometry(QtCore.QRect(20, 450, 251, 16))self.line_3.setFrameShape(QtWidgets.QFrame.HLine)self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)self.line_3.setObjectName("line_3")
界面展示
这个我们软件的主界面:
下载链接
若您想获得博文中涉及的实现完整全部程序文件(包括图片,py, UI文件等,如下图),这里已打包上传至博主的CSDN下载资源。
注意:本资源已经过调试通过,下载后可通过Pycharm运行;运行界面的主程序为face_decognition.py。为确保程序顺利运行,请配置Python版本:3.9,或以上版本。我们这里的文件夹默认在代码的路径下。
结束语
由于博主能力有限,博文中提及的方法即使经过试验,也难免会有疏漏之处。希望您能热心指出其中的错误,以便下次修改时能以一个更完美更严谨的样子,呈现在大家面前。同时如果有更好的实现方法也请您不吝赐教。
相关文章:

基于OpenCV的人脸识别和模型训练系统(万字详解)
前言 我们身边的人脸识别有车站检票,监控人脸,无人超市,支付宝人脸支付,上班打卡,人脸解锁手机。 人脸检测是人脸识别系统组成的关键部分之一,其目的是检测出任意给定图片中的包含的一个或多个人脸&#…...

Docker容器与虚拟化技术:Docker镜像创建、Dockerfile实例
目录 一、理论 1.Docker镜像的创建方法 2.Docker镜像结构的分层 3.Dockerfile 案例 4.构建Systemctl镜像(基于SSH镜像) 5.构建Tomcat 镜像 6.构建Mysql镜像 二、实验 1.Docker镜像的创建 2. Dockerfile 案例 3.构建Systemctl镜像(…...

每天一道leetcode:646. 最长数对链(动态规划中等)
今日份题目: 给你一个由 n 个数对组成的数对数组 pairs ,其中 pairs[i] [lefti, righti] 且 lefti < righti 。 现在,我们定义一种 跟随 关系,当且仅当 b < c 时,数对 p2 [c, d] 才可以跟在 p1 [a, b] 后面…...

651页23万字智慧教育大数据信息化顶层设计及建设方案WORD
导读:原文《651页23万字智慧教育大数据信息化顶层设计及建设方案WORD》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 目录 一、 方案背景 1.1 以教育…...

Vue3 使用json编辑器
安装 npm install json-editor-vue3 main中引入 main.js 中加入下面代码 import "jsoneditor";不然会有报错,如jsoneditor does not provide an export named ‘default’。 图片信息来源-github 代码示例 <template><json-editor-vue class…...
centos7 docker离线安装教程
centos7 docker离线安装教程 离线安装包下载# docker离线安装时需要两个安装包:selinux包、docker包, 下载地址: https://download.docker.com/linux/centos/7/x86_64/stable/Packages/selinux包下载 https://download.docker.com/linux/…...

解决爬虫上下行传输效率问题的实用指南
嗨,大家好!作为一名专业的爬虫程序员,我们经常会面临上下行传输效率低下的问题。在处理大量数据时,如果传输效率不高,可能会导致爬虫任务速度慢,甚至中断。今天,我将和大家分享一些解决爬虫上下…...

Vue2入门学习汇总
1.介绍及安装 1.1 介绍 Vue是一套构建用户界面的渐进式框架。Vue只关注视图层,采用自底向上增量开发的设计。Vue的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 学习vue之前主要掌握的知识:HTML、CSS、JavaScript、TypeScript …...

收支明细高效管理,轻松查看和统计时间段内的开销收支明细!
亲爱的用户们,您是否经常需要查看某一时间段内的所有开销和收支明细,并进行自动统计和分析?现在,我们为您带来一款智能财务管家,让您轻松管理财务! 首先,我们要进入晨曦记账本主页面࿰…...
c++ 成绩统计
Q: 有一个二维表格数据,它的值全部是整数,其中存储了若干个选手参与5分钟汉字输入比赛的成绩。数据中每一行是一条记录,每条记录包含两个整数,第1个整数为选手编号,它应该是一个4位整数;第2个整…...

PostgreSQL-UDF用户自定义函数-扩展插件
目录 PostgreSQL-UDF用户自定义函数-扩展插件零、前置条件一、创建 .c 和 .sql 文件创建.c文件创建.sql文件 二、创建 .control 和 Makefile 文件创建 .control 文件创建 Makefile 文件 三、编译 & 链接四、psql(或者其他PG backend)中创建扩展 Post…...

接口测试及接口抓包常用测试工具和方法?
作为测试领域中不可或缺的一环,接口测试和抓包技术在软件开发过程中扮演着至关重要的角色。不论你是新手还是有一些经验的小伙伴,本篇文章都会为你详细介绍接口测试的基本概念、常用测试工具和实际操作技巧,让你轻松掌握这一技能。 接口测试…...

C语言入门_Day 6布尔数与比较运算
目录 前言 1.布尔数 2.比较运算 3.易错点 4.思维导图 前言 除了算术计算以外,编程语言中还会大量使用比较运算,并会根据比较运算的结果是“真”还是“假”,来执行不同的代码。 当你想买一杯奶茶,准备支付的时候,支…...

Java中的JDBC
什么是JDBC 1.Java数据库连接技术(Java DataBase Connectivity),能实现Java程序对各种数据库的访问 2.由一组使用Java语言编写的类和接口(JDBC API)组成,它们位于java.sql以及javax.sql中 JDBC访问数据库的步骤: 步骤 1.Class.forName()加载…...

Vue 安装开发者工具
1.下载开发者工具,下载地址:http://book.wiyp.top/App/Vue3开发者工具-谷歌/Vue3.crx 2.打开谷歌浏览器,点击扩展,点击管理扩展程序。 3.开启开发者模式,将 Vue3 开发者工具文件拖拽到浏览器中进行安装。 注ÿ…...
oracle修改临时表出现已使用的事务正在处理临时表问题
错误提示: ORA-14450:试图访问已经在使用的事务处理临时表 解决方法: 通过第一句sql来查找临时表的object_id ,然后代入第二局sql来生成第三句sql语句。 最后再执行第三句sql语句即可kill session,执行修改表的操作。 SELECT * F…...

RestTemplate
RestTemplate介绍 RestTemplate是Spring提供的用于访问RESTful服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),…...

rabbitMQ服务自动停止(已解决
1、 在rabbitmq的sbin目录下操作 rabbitmq-plugins enable rabbitmq_management 2、 自己去rabbitmq_server-3.7.5文件夹下创建一个data,再执行这个命令(用自己的目录哈 set RABBITMQ_BASED:\RabbitTools\RabbitMQ\rabbitmq_server-3.7.5\data 然后去配…...

Qt平滑弹出页面
目标功能: (1)按下btn,弹出绿色页面。 (2)按下btn2,绿色页面隐藏。 (3)按下左边余下的区域,绿色页面也隐藏。 (4)平滑地显示和隐藏 效果: form.h #ifndef FORM_H #define FORM_H#include <QWidget>namespace Ui { class…...

第07天 Static关键字作用及用法
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏:每天一个知识点 ✨特色专栏:…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...