当前位置: 首页 > news >正文

人工智能|深度学习——基于Xception实现戴口罩人脸表情识别

一、项目背景

近年来,随着人工智能技术的不断发展,人脸表情识别已经成为了计算机视觉领域中的重要研究方向之一。然而,在当前的疫情形势下,佩戴口罩已经成为了一项必要的防疫措施,但是佩戴口罩会遮挡住人脸的部分区域,给表情识别带来了一定的挑战。

目前,已经有很多关于没有遮挡人脸的表情识别的技术研究,例如基于深度学习的卷积神经网络(CNN)和循环神经网络(RNN)等。这些技术已经取得了不错的成果,并且已经应用于实际的场景中,例如情感识别、人机交互等。
然而,在佩戴口罩的情况下,传统的表情识别技术无法识别出人脸的表情信息,因为口罩遮挡了人脸的大部分区域,导致识别的准确率降低。因此,一些研究人员开始关注口罩人脸识别技术,并提出了一些新的方法来解决这个问题。例如,他们使用图像处理技术来减少口罩的遮挡效果,或者使用额外的传感器来收集面部表情的其他数据。
然而,戴口罩人脸表情识别存在一些技术难点。首先,佩戴口罩会导致人脸的特征信息被遮挡,难以准确识别。其次,戴口罩人脸的表情信息可能会因为口罩遮挡而变得不够丰富,这也给表情识别带来了一定的挑战。最后,因为戴口罩人脸表情识别的研究资料较少,数据集需要个人收集标注。因此,如何在遮挡的情况下准确地识别出人脸表情信息是戴口罩人脸表情识别技术研究的重要问题之一

二、数据集来源与详情

2.1 来源

本项目基于fer2013人脸表情数据集,它于2013年国际机器学习会议(ICML)上推出,并成为比较表情识别模型性能的基准之一,同时也作为了2013年Kaggle人脸识别比赛的数据。Fer2013包含28709张训练集图像、3589张公开测试集图像和3589张私有测试集图像,每张图像为4848大小的灰度图片,如下图所示。Fer2013数据集中由有生气(angry)、厌恶(disgust)、恐惧(fear)、开心(happy)、难过(sad)、惊讶(surprise)和中性(neutral)七个类别组成。由于这个数据集大多是通过爬虫在互联网上进行爬取所得,因此存在一定的误差性。

本项目使用face-mask对人脸添加口罩,简单介绍一下face-mask是基于dlib和face_recognition两大人脸检测的库实现的人脸关键点检测的方法。处理完成后共得到11870张训练集,3016张测试集(原数据集存在一些不能被face-mask所识别到的人脸)。经过实验发现sad、disgust、anger眼部特征十分相识,因此本试验只进行对anger、fear、happy、surprise的分类。

2.2 详细处理

  • 安装face-mask 在安装之前要先配置dlib,具体过程请大家自行探索。
pip install face-mask
  • 关键代码
# -*- coding: utf-8 -*-
import os
import numpy as np
from PIL import Image, ImageFile__version__ = '0.3.0'IMAGE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'images')
DEFAULT_IMAGE_PATH = os.path.join(IMAGE_DIR, 'default-mask.png')
BLACK_IMAGE_PATH = os.path.join(IMAGE_DIR, 'black-mask.png')
BLUE_IMAGE_PATH = os.path.join(IMAGE_DIR, 'blue-mask.png')
RED_IMAGE_PATH = os.path.join(IMAGE_DIR, 'red-mask.png')class FaceMasker:KEY_FACIAL_FEATURES = ('nose_bridge', 'chin')def __init__(self, face_path, mask_path, show=False, model='hog'):self.face_path = face_pathself.mask_path = mask_pathself.show = showself.model = modelself._face_img: ImageFile = Noneself._mask_img: ImageFile = Nonedef mask(self):import face_recognitionface_image_np = face_recognition.load_image_file(self.face_path)face_locations = face_recognition.face_locations(face_image_np, model=self.model)face_landmarks = face_recognition.face_landmarks(face_image_np, face_locations)self._face_img = Image.fromarray(face_image_np)self._mask_img = Image.open(self.mask_path)found_face = Falsefor face_landmark in face_landmarks:# check whether facial features meet requirementskip = Falsefor facial_feature in self.KEY_FACIAL_FEATURES:if facial_feature not in face_landmark:skip = Truebreakif skip:continue# mask facefound_face = Trueself._mask_face(face_landmark)if found_face:if self.show:self._face_img.show()# saveself._save()else:print('Found no face.')def _mask_face(self, face_landmark: dict):nose_bridge = face_landmark['nose_bridge']nose_point = nose_bridge[len(nose_bridge) * 1 // 4]nose_v = np.array(nose_point)chin = face_landmark['chin']chin_len = len(chin)chin_bottom_point = chin[chin_len // 2]chin_bottom_v = np.array(chin_bottom_point)chin_left_point = chin[chin_len // 8]chin_right_point = chin[chin_len * 7 // 8]# split mask and resizewidth = self._mask_img.widthheight = self._mask_img.heightwidth_ratio = 1.2new_height = int(np.linalg.norm(nose_v - chin_bottom_v))# leftmask_left_img = self._mask_img.crop((0, 0, width // 2, height))mask_left_width = self.get_distance_from_point_to_line(chin_left_point, nose_point, chin_bottom_point)mask_left_width = int(mask_left_width * width_ratio)mask_left_img = mask_left_img.resize((mask_left_width, new_height))# rightmask_right_img = self._mask_img.crop((width // 2, 0, width, height))mask_right_width = self.get_distance_from_point_to_line(chin_right_point, nose_point, chin_bottom_point)mask_right_width = int(mask_right_width * width_ratio)mask_right_img = mask_right_img.resize((mask_right_width, new_height))# merge masksize = (mask_left_img.width + mask_right_img.width, new_height)mask_img = Image.new('RGBA', size)mask_img.paste(mask_left_img, (0, 0), mask_left_img)mask_img.paste(mask_right_img, (mask_left_img.width, 0), mask_right_img)# rotate maskangle = np.arctan2(chin_bottom_point[1] - nose_point[1], chin_bottom_point[0] - nose_point[0])rotated_mask_img = mask_img.rotate(angle, expand=True)# calculate mask locationcenter_x = (nose_point[0] + chin_bottom_point[0]) // 2center_y = (nose_point[1] + chin_bottom_point[1]) // 2offset = mask_img.width // 2 - mask_left_img.widthradian = angle * np.pi / 180box_x = center_x + int(offset * np.cos(radian)) - rotated_mask_img.width // 2box_y = center_y + int(offset * np.sin(radian)) - rotated_mask_img.height // 2# add maskself._face_img.paste(mask_img, (box_x, box_y), mask_img)def _save(self):path_splits = os.path.splitext(self.face_path)new_face_path = path_splits[0] + '-with-mask' + path_splits[1]self._face_img.save(new_face_path)print(f'Save to {new_face_path}')@staticmethoddef get_distance_from_point_to_line(point, line_point1, line_point2):distance = np.abs((line_point2[1] - line_point1[1]) * point[0] +(line_point1[0] - line_point2[0]) * point[1] +(line_point2[0] - line_point1[0]) * line_point1[1] +(line_point1[1] - line_point2[1]) * line_point1[0]) / \np.sqrt((line_point2[1] - line_point1[1]) * (line_point2[1] - line_point1[1]) +(line_point1[0] - line_point2[0]) * (line_point1[0] - line_point2[0]))return int(distance)if __name__ == '__main__':FaceMasker("./face/1.jpg", DEFAULT_IMAGE_PATH, True, 'hog').mask()
  • 本项目已为大家提供处理好的数据集地址 ,后边直接使用。如果想了解更多处理细节请关注我的主页

三、模型介绍

3.1 Xception简介

Xception是Google公司继Inception后提出的对 Inception-v3 的另一种改进。作者认为,通道之间的相关性与空间相关性最好要分开处理。于是采用 Separable Convolution来替换原来 Inception-v3中的卷积操作。
传统卷积的实现过程:

Depthwise Separable Convolution 的实现过程:

深度可分离卷积 Depthwise Separable Convolution
Depthwise Separable Convolution 与 极致的 Inception 区别:
极致的 Inception:

  • 第一步:普通 1×1 卷积。
  • 第二步:对 1×1 卷积结果的每个 channel,分别进行 3×3卷积操作,并将结果 concat。

Depthwise Separable Convolution:

  • 第一步:Depthwise 卷积,对输入的每个channel,分别进行 3×3卷积操作,并将结果 concat。
  • 第二步:Pointwise 卷积,对 Depthwise 卷积中的 concat 结果,进行1×1卷积操作。

两种操作的顺序不一致:Inception 先进行1×1卷积,再进行3×3 卷积;Depthwise Separable Convolution 先进行 3×3卷积,再进行 1×1卷积。

3.2 Xception网络框架

先进行普通卷积操作,再对 1×1 卷积后的每个channel分别进行 3×3 卷积操作,最后将结果 concat。

注:Xception包含三个部分:输入部分,中间部分和结尾部分;其中所有卷积层和可分离卷积层后面都使用Batch Normalization处理,所有的可分离卷积层使用一个深度乘数1(深度方向并不进行扩充)。

三、技术路线

3.1 PaddleClas简介

飞桨图像分类套件PaddleClas是飞桨为工业界和学术界所准备的一个图像分类任务的工具集,助力使用者训练出更好的视觉模型和应用落地。

PaddleClas特性:

  1. 丰富的模型库:基于ImageNet1k分类数据集,PaddleClas提供了29个系列的分类网络结构和训练配置,133个预训练模型和性能评估。
  2. SSLD知识蒸馏:基于该方案蒸馏模型的识别准确率普遍提升3%以上。
  3. 数据增广:支持AutoAugment、Cutout、Cutmix等8种数据增广算法详细介绍、代码复现和在统一实验环境下的效果评估。
  4. 10万类图像分类预训练模型:百度自研并开源了基于10万类数据集训练的 ResNet50_vd 模型,在一些实际场景中,使用该预训练模型的识别准确率最多可以提升30%。
  5. 多种训练方案,包括多机训练、混合精度训练等。
  6. 多种预测推理、部署方案,包括TensorRT预测、Paddle-Lite预测、模型服务化部署、模型量化、Paddle Hub等。可运行于Linux、Windows、MacOS等多种系统。

3.2 模型库链接

Paddleclas代码GitHub链接: https://github.com/PaddlePaddle/PaddleClas

Paddleclas代码Gitee链接: https://gitee.com/PaddlePaddle/PaddleClas

Paddleclas文档链接: https://paddleclas.readthedocs.io

四、环境配置

  • 更新pip(很重要,要不然很多包装不上)
pip install --upgrade pip
  • 克隆Paddleclas仓库
%cd /home/aistudio/work/
# 克隆Paddleclas仓库
# gitee 国内下载比较快
!git clone https://gitee.com/PaddlePaddle/PaddleClas.git
# github 
# !git clone https://github.com/PaddlePaddle/PaddleClas.git
  • 导入package
%cd /home/aistudio/work/PaddleClas
# 导入package
!pip install -r requirements.txt
  • 解压数据集
# 解压数据集
# 注意数据集压缩包的名字和位置
!echo "解压数据集"
!unzip -oq /home/aistudio/data/data201630/fer2013(添加口罩_四分类) _.zip -d /home/aistudio/work/PaddleClas/dataset
  • 数据集结构
dataset:train:imags            # 训练集图片train_list.txt   # 训练集标签eval:imags            # 评估图片eval_list.txt    # 评估标签test:imags            #测试图片test_list.txt    #测试标签list.txt           # 标签对应含义

五、模型训练

5.1 配置训练参数文件(已为大家提供参考参数文件)

  • 本项目使用的配置文件是
/home/aistudio/work/PaddleClas/ppcls/configs/ImageNet/Xception/Xception65.yaml
# global configs
Global:...output_dir: ./output/ # 模型保存路径epochs: 200       # 训练步数...use_visualdl: Ture  # 训练可视化,在训练时可以绘制出可视化图像...save_inference_dir: ./inference #导出模型保存路径....Optimizer:....lr:name: Cosinelearning_rate: 0.045 # 学习率,根据训练时的可视化图像进行调整regularizer:name: 'L2'coeff: 0.0001
.....
# data loader for train and eval
DataLoader:Train:dataset:name: ImageNetDatasetimage_root: ./dataset/ # 图片路径cls_label_path: ./dataset/train/train_list.txt # 标签路径......sampler:name: DistributedBatchSamplerbatch_size: 64 # 根据配置进行调整,在环境最左边工具栏的监控中根据显存和cup占用率进行调整....Eval:dataset: name: ImageNetDatasetimage_root: ./dataset/cls_label_path: ./dataset/eval/eval_list.txt # 同上.....Infer:infer_imgs: ./dataset/test/imags/10276.jpg  # 预测的图片batch_size: 10 # 根据实际调整....class_id_map_file: ./dataset/test/list.txt# 此文件是标签对应的含义,根据开始数据集说明时的图片可知:0对应生气 1害怕.....

5.2 训练

%cd /home/aistudio/work/PaddleClas
!echo "开始炼丹"
!python3 -m paddle.distributed.launch tools/train.py \
-c /home/aistudio/work/PaddleClas/ppcls/configs/ImageNet/Xception/Xception65.yaml
  • 精确度

5.3 加载训练可视化

  • 设置VisualDL服务

  • 加载logdir

  • 启动打开

5.4 效果

六、模型预测

备注:

  • 这里-o Global.pretrained_model="/home/aistudio/work/PaddleClas/output/Xception65/best_model" 指定了当前最佳权重所在的路径,如果指定其他权重,只需替换对应的路径即可。
  • 默认是对 /home/aistudio/work/data/test 进行预测,此处也可以通过增加字段 -o Infer.infer_imgs=xxx 对其他图片预测。
  • 默认输出的是 Top-5 的值,如果希望输出 Top-k 的值,可以指定-o Infer.PostProcess.topk=k,其中,k 为您指定的值。

修改 /home/aistudio/work/PaddleClas-2.4.0/ppcls/engine/engine.py 中的推理代码 infer(self),将推理结果存入csv文件。

@paddle.no_grad()def infer(self):assert self.mode == "infer" and self.eval_mode == "classification"total_trainer = dist.get_world_size()local_rank = dist.get_rank()image_list = get_image_list(self.config["Infer"]["infer_imgs"])# data splitimage_list = image_list[local_rank::total_trainer]with open("/home/aistudio/work/PaddleClas/dataset/eval/eval_list.txt", "r") as f:dat = f.readlines()Dta= {}for delr in dat:wed=delr.replace('./eval/imags/','').replace('\n','').split(' ')Dta[wed[0]] =wed[1]print(Dta)csvfile = open("/home/aistudio/work/PaddleClas/output/result.csv", "w", newline="")writer = csv.writer(csvfile)batch_size = self.config["Infer"]["batch_size"]self.model.eval()batch_data = []image_file_list = []for idx, image_file in enumerate(image_list):with open(image_file, 'rb') as f:x = f.read()for process in self.preprocess_func:x = process(x)batch_data.append(x)image_file_list.append(image_file)if len(batch_data) >= batch_size or idx == len(image_list) - 1:batch_tensor = paddle.to_tensor(batch_data)if self.amp and self.amp_eval:with paddle.amp.auto_cast(custom_black_list={"flatten_contiguous_range", "greater_than"},level=self.amp_level):out = self.model(batch_tensor)else:out = self.model(batch_tensor)if isinstance(out, list):out = out[0]if isinstance(out, dict) and "Student" in out:out = out["Student"]if isinstance(out, dict) and "logits" in out:out = out["logits"]if isinstance(out, dict) and "output" in out:out = out["output"]result = self.postprocess_func(out, image_file_list)print(result)for res in result:file_name = res['file_name'].split('/')[-1]class_id  = res['class_ids'][0]try:ture_id = Dta[file_name]writer.writerow([file_name, class_id,ture_id])except:passbatch_data.clear()image_file_list.clear()
%cd /home/aistudio/work/PaddleClas/
!echo "模型预测"
!python tools/infer.py \-c /home/aistudio/work/PaddleClas/ppcls/configs/ImageNet/Xception/Xception65.yaml\-o Global.pretrained_model=/home/aistudio/work/PaddleClas/output/Xception65/best_model
  • 提取预测结果
import glob
import matplotlib.pyplot as plt
import pandas as pd
import cv2data_1=pd.read_csv("/home/aistudio/work/PaddleClas/output/result.csv",",",encoding="utf-8",header=None)
# 随机抽取数据
data_2=data_1.sample(10)
print(data_2)ji = 1
for index, row in data_2.iterrows():i=row.tolist()img = cv2.imread("/home/aistudio/work/PaddleClas/dataset/eval/imags/"+str(i[0]))title='pri:'+str(i[1])+'    true:'+str(i[2])plt.subplot(3,5,ji)plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.title(title,fontsize=10)ji=ji+1plt.tight_layout()
plt.show()
sum_num = 0
cr_num = 0
for index, row in data_1.iterrows():i = row.tolist()if int(i[1])==int(i[2]):cr_num = cr_num + 1sum_num = sum_num + 1print("正确:",cr_num,"\n总数:",sum_num)
print('ACC:',cr_num*100/sum_num,"%")

七、模型导出

# 导出模型
!echo "模型导出"
!python tools/export_model.py -c /home/aistudio/work/PaddleClas/ppcls/configs/ImageNet/Xception/Xception65.yaml\-o Global.pretrained_model=/home/aistudio/work/PaddleClas/output/Xception65/best_model\-o Global.save_inference_dir=./inference
  • 模型结构

八、模型部署

参考
  • EfficientNet实现农业病害识别(FastDeploy部署和安卓端部署)
  • 基于PP-PicoDet行车检测(完成安卓端部署))

九、项目总结

本次项目的完成可谓是经历重重困难,在看到题目时是懵懵的。在我以往学习的知识里,单纯人脸表情识别并没有太大的难度,但是要求对遮挡人脸的表情进行识别(口罩遮挡),查阅资料发现连数据集都没有找到,后来只能自己构建数据集,就利用以往做人脸表情识别的经验,使用未遮挡人脸通过检测人脸面部特征,定位眼、口、鼻、嘴给面部添加口罩。又学习了face-mask的一些操作,算是把数据集构建完成。当选取神经网络时问题有来了,该选取什么网络才好呢?从主流的ResNet、SwinTransformer、VGG效果都不是很理想。仔细分析问题,发现数据集中sad、disgust、anger眼部特征十分相识,所以就减少分类,重新处理数据集。在探索过程中隐约发现Xception网络特性(上文已介绍)可能对此数据集能产生较好的效果,果断进行测试,分别使用Xception41_deeplab和Xception65进行对比,发现ception65精度上升较快(这里可能不严谨,lr等当时并未考虑太多),紧接着使用可视化训练,观察lr,loss,acc曲线变化关系,调整参数,最终只实现了0.72左右精度。因为时间的原因,我没有办法继续优化项目,再以后的时间里我会不断的学习相关知识和优化项目,如果大家有好的想法和观点,欢迎给我留言!!!

相关文章:

人工智能|深度学习——基于Xception实现戴口罩人脸表情识别

一、项目背景 近年来,随着人工智能技术的不断发展,人脸表情识别已经成为了计算机视觉领域中的重要研究方向之一。然而,在当前的疫情形势下,佩戴口罩已经成为了一项必要的防疫措施,但是佩戴口罩会遮挡住人脸的部分区域&…...

【HTML】简单制作一个动态3D正方体

目录 前言 开始 HTML部分 JS部分 CSS部分 效果图 总结 前言 无需多言,本文将详细介绍一段代码,具体内容如下: 开始 首先新建文件夹,创建两个文本文档,其中HTML的文件名改为[index.html],JS的文件名改…...

Linux 常用指令及其理论知识

个人主页:仍有未知等待探索-CSDN博客 专题分栏:http://t.csdnimg.cn/Tvyou 欢迎各位指教!!! 目录 一、理论知识 二、基础指令 1、ls指令(列出该目录下的所有子目录和文件) 语法: …...

论文阅读——Sat2Vid

Sat2Vid: Street-view Panoramic Video Synthesis from a Single Satellite Image 提出了一种新颖的方法,用于从单个卫星图像和摄像机轨迹合成时间和几何一致的街景全景视频。 即根据单个卫星图像和给定的观看位置尽可能真实地、尽可能一致地合成街景全景视频序列。…...

js怎样判断status

相信大家都知道Switch开关吧,他有两种状态,通常用1/2表示,开启时为true,关闭时为false,那么我们该怎样判断他是否为开启还是关闭你? 我们可以声明一个变量,让它等于status,判断它是否等于1/2&…...

多态.Java

(1)什么是多态? 同类型的对象,表现出不同的形态。前者指父类,后者指不同的子类 说简单点,就是父类的同一种方法,可以在不同子类中表现出不同的状态,或者说在不同子类中可以实现不同…...

SSL根证书是什么

根证书是什么? 根证书是CA认证中心给自己颁发的证书,是信任链的起始点。安装根证书意味着对这个CA认证中心的信任。 从技术上讲,证书其实包含三部分,用户的信息,用户的公钥,还有CA中心对该证书里面的信息的签名&#…...

大模型量化技术-GPTQ

大模型量化技术-GPTQ 2022年,Frantar等人发表了论文 GPTQ:Accurate Post-Training Quantization for Generative Pre-trained Transformers。 这篇论文详细介绍了一种训练后量化算法,适用于所有通用的预训练 Transformer模型,同时只有微小的性能下降。 GPTQ算法需要通过…...

NzN的数据结构--实现双向链表

上一章中,我们学习了链表中的单链表,那今天我们来学习另一种比较常见的链表--双向链表!! 目录 一、双向链表的结构 二、 双向链表的实现 1. 双向链表的初始化和销毁 2. 双向链表的打印 3. 双向链表的头插/尾插 4. 双向链表的…...

easyexcel-获取文件资源和导入导出excel

1、获取本地资源文件,根据模板填充数据导出 public void exportExcel(HttpServletResponse httpResponse, RequestBody AssayReportDayRecordQuery query) {AssayReportDayRecordDTO dto this.queryByDate(query);ExcelWriter excelWriter null;ExcelUtil.config…...

Android Monkey自动化测试

monkey一般用于压力测试,用户模拟用户事件 monkey 基本用法 adb shell monkey [参数] [随机事件数]monkey常用命令 -v:用于指定反馈信息级别,总共分三个等级-v -v -vadb shell mokey -v -v -v 100-s:用于指定伪随机数生成器的种…...

C++ //练习 11.20 重写11.1节练习(第376页)的单词计数程序,使用insert代替下标操作。你认为哪个程序更容易编写和阅读?解释原因。

C Primer(第5版) 练习 11.20 练习 11.20 重写11.1节练习(第376页)的单词计数程序,使用insert代替下标操作。你认为哪个程序更容易编写和阅读?解释原因。 环境:Linux Ubuntu(云服务…...

Nginx 安装与实践

目录 一、安装 Nginx1、先安装 Brew2、再安装 Nginx 二、常用的 Nginx 命令三、简单的 Nginx 配置四、查看日志的 Linux 命令1、查看日志的 Linux 命令2、实时查看项目运行时打印的日志 一、安装 Nginx 推荐使用 HomeBrew 来安装 Nginx。 1、先安装 Brew 详见:Home…...

QT 创建线程的几种方法

//qt创建线程的几种方法 //在Qt中,创建线程的主要方法有以下几种: //1.继承QThread类重写run方法 class MyThread : public QThread { Q_OBJECT public: void run() override { // 在这里执行你的代码 } }; // 使用 MyThread *myThread n…...

RocketMQ的简单使用

这里需要创建2.x版本的springboot项目 导入依赖 <dependencies><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.2.3</version></dependency>&…...

速盾:服务器有cdn 带宽上限建议多少

CDN&#xff08;内容传输网络&#xff09;是一种通过分布在全球不同地点的服务器来提供高效内容分发的技术。当用户请求访问某个网站时&#xff0c;CDN会根据用户的地理位置&#xff0c;将内容从离用户最近的服务器上提供给用户&#xff0c;这样可以减少延迟和带宽消耗&#xf…...

智慧工地安全+绿色施工方案

塔机监测 塔吊监测可以实现对塔机监测、群塔防碰撞、塔机区域防护和吊钩可视化 1司机身份识别认证:只有司机在监控设备进行刷卡、指纹、人脸、虹膜验证身份后才能进行设备的作业操作。 2运行工况采集与显示:清晰实时显示起重机械设备运行工况,主要显示的内容:起重量、起…...

SQL Server 存储过程:BBS论坛(表结构文档下载及30个存储过程)

基于 Asp.Net 和 SQL Server 实现了一个BBS论坛&#xff0c;论坛功能比较强大&#xff0c;论坛大部分业务逻辑基于存储过程实现&#xff0c;记录一下。 BBS论坛存储过程清单 序号存储过程功能说明1sp_bbs_admin_add添加管理员2sp_bbs_admin_del删除系统管理员3sp_bbs_admin_m…...

03 Python进阶:MySQL - mysql-connector

mysql-connector安装 要在 Python 中使用 MySQL 数据库&#xff0c;你需要安装 MySQL 官方提供的 MySQL Connector/Python。下面是安装 MySQL Connector/Python 的步骤&#xff1a; 首先&#xff0c;确保你已经安装了 Python&#xff0c;如果没有安装&#xff0c;可以在 Python…...

InnoDB 行记录格式(“存储一行行数据的结构“)

1.行格式 1.1 Compact行格式 1.1.1 示意图 1.1.2 准备一下 1&#xff09;建表 mysql> CREATE TABLE record_format_demo (-> c1 VARCHAR(10),-> c2 VARCHAR(10) NOT NULL,-> c3 CHAR(10),-> c4 VARCHAR(10)-> ) CHARSETascii ROW_FORMATCOM…...

【洛谷】P9236 [蓝桥杯 2023 省 A] 异或和之和

题目链接 P9236 [蓝桥杯 2023 省 A] 异或和之和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路 1. 暴力求解 直接枚举出所有子数组&#xff0c;求每个子数组的异或和&#xff0c;再对所有的异或和求和 枚举所有子数组的时间复杂度为O&#xff08;N^2&#xff09;&…...

ThreadLocal加切面实现线程级别的方法缓存

1、实现效果 当一个请求线程多次请求A方法时,只会触发一次A方法的实际调用,会将方法结果缓存起来,避免多次调用。 2、实现过程 1. 需要一个注解ThreadLocalCache,在需要缓存的方法上加上该注解 2. 需要一个切面,借助ThreadLocal,将结果缓存起来,利用环绕通知来实现方法拦截从…...

使用 Flume 将 CSV 数据导入 Kafka:实现实时数据流

使用 Flume 将 CSV 数据导入 Kafka&#xff1a;实现实时数据流 文介绍了如何使用 Apache Flume 将 CSV 格式的数据从本地文件系统导入到 Apache Kafka 中&#xff0c;以实现实时数据流处理。通过 Flume 的配置和操作步骤&#xff0c;我们可以轻松地将数据从 CSV 文件中读取并发…...

对代理模式的理解

目录 一、前言二、案例1 代码2 自定义代理类【静态代理】2.1 一个接口多个实现&#xff0c;到底注入哪个依赖呢&#xff1f;2.1.1 Primary注解2.1.2 Resource注解&#xff08;指定name属性&#xff09;2.1.3 Qualifier注解 2.2 面向接口编程2.3 如果没接口咋办呢&#xff1f;2.…...

#QT项目实战(天气预报)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a; 3.记录&#xff1a; &#xff08;1&#xff09;调用API的Url a.调用API获取IP whois.pconline.com.cn/ipJson.jsp?iphttp://whois.pconline.com.cn/ipJson.jsp?ip if(window.IPCallBack) {IPCallBack({"ip":&quo…...

数据挖掘|关联分析与Apriori算法详解

数据挖掘|关联分析与Apriori算法 1. 关联分析2. 关联规则相关概念2.1 项目2.2 事务2.3 项目集2.4 频繁项目集2.5 支持度2.6 置信度2.7 提升度2.8 强关联规则2.9 关联规则的分类 3. Apriori算法3.1 Apriori算法的Python实现3.2 基于mlxtend库的Apriori算法的Python实现 1. 关联分…...

ChatGPT Excel 大师

原文&#xff1a;ChatGPT Excel Mastery 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 序言 欢迎来到 Excel 掌握的变革之旅&#xff0c;在这里&#xff0c;尖端技术和永恒专业知识在“ChatGPT Excel 掌握&#xff1a;释放专家技巧和窍门的力量”中融合。在当今快节…...

C 语言中的 end, _end 符号

使用 man 3 end 可以看到相关符号的解释 这些符号不是在 C 语言文件和头文件中定义的&#xff0c;它们是 ld 在链接所有 .o 文件的时候自己添加的。 end 和 _end 的地址&#xff0c;就是最终程序的堆的起始地址 要打印它们的话&#xff0c;一个样例程序在下面&#xff1a; …...

绿联 安装PDF工具

这是一个强大的本地托管的基于 Web 的 PDF 操作工具&#xff0c;使用 docker&#xff0c;允许您对 PDF 文件执行各种操作&#xff0c;例如拆分、合并、转换、重组、添加图像、旋转、压缩等。这个本地托管的 Web 应用程序最初是 100% ChatGPT 制作的应用程序&#xff0c;现已发展…...

备战蓝桥杯---数论相关问题

目录 一、最大公约数和最小公倍数 二、素数判断 三、同余 四、唯一分解定理 五、约数个数定理 六、约数和定理 五、快速幂 六、费马小定理 七、逆元 一、最大公约数和最小公倍数 文章链接&#xff1a;最大公约数和最小公倍数 二、素数判断 文章链接&#xff1a;在J…...

网域高科学校网站管理系统漏洞/seo专员很难吗

【异周话题 第 20 期】三年后&#xff0c;人工智能将彻底改变前端开发&#xff1f;话题背景去年&#xff0c;阿里阿里正式公开了人工智能设计系统“鲁班”&#xff0c;到去年双 11&#xff0c;鲁班的水平已经达到了阿里内部 P6 水准&#xff0c;一天能够制作 4,000 万张海报&am…...

哪些网站是动态的/专业搜索引擎优化电话

在上半年因为疫情的缘故&#xff0c;荣耀在线上举行了“生活与你一起升级”的发布会&#xff0c;正式确立了“honor life”&#xff0c;带来了荣耀Magicbook Pro 2020英特尔等新品。这不到了2020的下半年&#xff0c;“生活与你一起升级”第二季来袭了&#xff0c;荣耀智慧生活…...

本机做网站服务上传到/视频号广告推广

然后删除生成的src目录。 此时的父类pom文件是 然后在项目上右键new- module 创建dubbo-api&#xff0c;选择quickstart 注意此时&#xff0c;父类pom已经自动生成依赖 相同方法生成dubbo-service 最后一个dubbo-web 选择webapp 此时已经全部完成 转载于:https://www.cnblogs.c…...

wordpress+微官网主题/山西seo优化公司

代理模式中一个类代表另外一个类的功能&#xff0c;以便对外界提供功能接口。 1. 介绍 意图&#xff1a;为其他对象提供一种代理以控制针对这个对象的访问。 主要解决&#xff1a;再直接访问对象时带来的问题。比如说&#xff0c;要访问的对象再远程的机器上&#xff0c;可以…...

ci设计/seo服务外包

WCF开发实战系列五&#xff1a;创建WCF客户端程序 WCF开发实战系列五&#xff1a;创建WCF客户端程序 (原创&#xff1a;灰灰虫的家http://hi.baidu.com/grayworm) 在前面的三篇文章中我们分别介绍了WCF服务的三种载体&#xff1a;IIS、Self-Host、Windows Service Host。当W…...

wordpress循环所有文脏/搜索引擎技术基础

我写的程序员面试系列文章 Java面试系列-webapp文件夹和WebContent文件夹的区别&#xff1f; 程序员面试系列&#xff1a;Spring MVC能响应HTTP请求的原因&#xff1f; Java程序员面试系列-什么是Java Marker Interface&#xff08;标记接口&#xff09; 使用JDK自带的工具jsta…...