机器学习实战 | emojify 使用Python创建自己的表情符号(深度学习初级)

news2024/11/18 20:33:13

目录

  • 简介
  • 技术流程
    • 1. 加载依赖包
    • 2. 初始化训练和验证生成器
    • 3. 建立网络结构
    • 4. 编译和训练模型
    • 5. 保存模型权重
    • 6. 输出预测结果
  • 完整程序
    • 1. train.py程序
    • 2. gui.py程序

简介

准备写个系列博客介绍机器学习实战中的部分公开项目。首先从初级项目开始。


本文主要介绍机器学习项目实战之训练和创建自己的表情符号。项目原网址为:Emojify – Create your own emoji with Deep Learning。

这个外文网址中的一些链接打不开,因此这里给出程序中用到的相关文件并且给出部分程序分析,希望能够帮大家从0构建深度学习项目。

技术流程

Emojify – Create your own emoji with Deep Learning,
该机器学习项目的目的是对人的面部表情进行分类并将其映射为表情符号。
程序中将建立一个卷积神经网络来识别面部表情,然后将使用相应的表情符号或头像来映射这些情感。

以下图为例,左侧摄像头实时拍摄到人脸照片,右侧显示检测结果“surprised”,并将其映射为表情符号。
在这里插入图片描述

1. 加载依赖包

import numpy as np
import cv2
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D
from keras.optimizers import Adam
from keras.layers import MaxPooling2D
from keras.preprocessing.image import ImageDataGenerator

解析:

这个项目的深度学习网络调用了keras包,因此需要提前在电脑里安装kerasTensorFlow, 我配置成功的包版本为:

keras 2.10.0
tensorflow 2.10.0

命令行安装命令为:

pip install keras==2.10.0
pip install TensorFlow==2.10.0

除此之外其他安装包如有需要,也就是说运行程序提示缺少**包,就相应安装什么包。

2. 初始化训练和验证生成器

train_dir = 'data/train'
val_dir = 'data/test'
train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(48, 48),
        batch_size=64,
        color_mode="grayscale",
        class_mode='categorical')

validation_generator = val_datagen.flow_from_directory(
        val_dir,
        target_size=(48,48),
        batch_size=64,
        color_mode="grayscale",
        class_mode='categorical')

解析:

  • ImageDataGenerator:from keras.preprocessing.image import ImageDataGenerator, 对图片进行批量预处理
  • flow_from_directory:以文件夹路径为参数,生成经过数据提升/归一化后的数据,参数包括目录名val_dir、批尺寸batch_size等。

batch_size 表示一次迭代所需要的样本量,batch_size=total即梯度下降法,bach_size=1即随机梯度下降法SGD;
iteration 表示迭代次数,跑完一个batch更新参数;
epoch 表示所有样本训练一遍。

3. 建立网络结构

emotion_model = Sequential()

emotion_model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
emotion_model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))

emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))

emotion_model.add(Flatten())
emotion_model.add(Dense(1024, activation='relu'))
emotion_model.add(Dropout(0.5))
emotion_model.add(Dense(7, activation='softmax'))
  • Sequential(): 序贯模型,与函数式模型对立。from keras.models import Sequential, 序贯模型通过一层层神经网络连接构建深度神经网络。
  • add(): 叠加网络层,参数可为conv2D卷积神经网络层,MaxPooling2D二维最大赤化层, Dropout随机失活层(防止过拟合), Dense密集层(全连接FC层,在Keras层中FC层被写作Dense层)

函数式模型:Model(), 调用已经训练好的模型,比如VGG、Inception等神经网络结构,多输入、多输出模型。

4. 编译和训练模型

emotion_model.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.0001, decay=1e-6),metrics=['accuracy'])
emotion_model_info = emotion_model.fit_generator(
        train_generator,
        steps_per_epoch=28709 // 64,
        epochs=50,
        validation_data=validation_generator,
        validation_steps=7178 // 64)
  • compile(): 编译神经网络结构,参数包括:loss,字符串结构,指定损失函数;optimizer,表示优化方式;metrics,列表,用来衡量模型指标。
  • fit_generator: 在搭建完成后,将数据送入模型进行训练,返回一个history对象,记录训练过程中的损失和评估值。参数包括:generator,生成器函数,steps_per_epoch: 每个epoch中生成器执行生成数据的次数;epochs,迭代次数;valdation_data: 数据集验证。

5. 保存模型权重

emotion_model.save_weights('emotion_model.h5')
  • save_weights: 保存模型权重

6. 输出预测结果

cv2.ocl.setUseOpenCL(False)
emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}

# start the webcam feed
cap = cv2.VideoCapture(0)
while True:
    # Find haar cascade to draw bounding box around face
    ret, frame = cap.read()
    frame = cv2.resize(frame, (300, 300))

    if not ret:
        break

    bounding_box = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    num_faces = bounding_box.detectMultiScale(gray_frame, scaleFactor=1.3, minNeighbors=5)

    for (x, y, w, h) in num_faces:
        cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
        roi_gray_frame = gray_frame[y:y + h, x:x + w]
        cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray_frame, (48, 48)), -1), 0)
        emotion_prediction = emotion_model.predict(cropped_img)
        maxindex = int(np.argmax(emotion_prediction))
        cv2.putText(frame, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)

    cv2.imshow('Video', cv2.resize(frame,(300, 300), interpolation=cv2.INTER_CUBIC))
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

使用openCV中haarcascade. xml检测网络摄像头中人脸的边界框,并预测情绪.

  • cv2.ocl.setUseOpenCL(False):关闭OpenGL加速。
  • cv2.VideoCapture( ):输入参数为0时表示调用/打开笔记本的内置摄像头;参数为文件路径名时表示打开指定视频文件。
  • cv2.CascadeClassifier():加载人脸harr级联分类器。该步骤容易包括,安装的OpenCV包中可能不包含该文件,为了方便大家调试,将该文件压缩上传到:人脸harr级联分类器保存的.xml文件,下载完后解压保存在cv2.data.haarcascades默认路径下,cv2.data.haarcascades表示输出cv2.data的路径,默认地址为:**\anaconda3\lib\site-packages\cv2\data
  • detectMultiScale:输入参数包括:minNeighbors,每一个目标至少被检测到的次数;minSize,目标最小尺寸;maxSize:目标最大尺寸等。通过灵活调节这三个参数可以用来排除干扰项。

完整程序

train.py : 人脸情绪训练代码。此外,将第4节训练过程备注,增加调用程序,可以用来实时测试结果。

gui.py: GUI窗口,输出可互动的界面。

1. train.py程序

"""
Emojify--create your own emoji with deep learning
"""

"""
1. Imports
"""
import numpy as np
import cv2
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D
from keras.optimizers import Adam
from keras.layers import MaxPooling2D
from keras.preprocessing.image import ImageDataGenerator

"""
2. Initialize the training and validation generators
"""
train_dir = 'data/train'
val_dir = 'data/test'
train_datagen = ImageDataGenerator(rescale=1./255)
val_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(48, 48),
        batch_size=64,
        color_mode="grayscale",
        class_mode='categorical')

validation_generator = val_datagen.flow_from_directory(
        val_dir,
        target_size=(48,48),
        batch_size=64,
        color_mode="grayscale",
        class_mode='categorical')

"""
3. Build convolution network architecture 
"""
emotion_model = Sequential()

emotion_model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
emotion_model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))

emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))

emotion_model.add(Flatten())
emotion_model.add(Dense(1024, activation='relu'))
emotion_model.add(Dropout(0.5))
emotion_model.add(Dense(7, activation='softmax'))


"""
4. Compile and train the model
"""
# emotion_model.compile(loss='categorical_crossentropy',optimizer=Adam(lr=0.0001, decay=1e-6),metrics=['accuracy'])
# emotion_model_info = emotion_model.fit_generator(
#         train_generator,
#         steps_per_epoch=28709 // 64,
#         epochs=50,
#         validation_data=validation_generator,
#         validation_steps=7178 // 64)
#
# """
# 5. Save the model weights
# """
# emotion_model.save_weights('emotion_model.h5')

"""
6. Using openCV haarcascade xml detect the bounding boxes of face in the webcam and predict the emotions
"""

# 加载已经训练好的表情识别权重
emotion_model.load_weights('emotion_model.h5')

cv2.ocl.setUseOpenCL(False)
emotion_dict = {0: "Angry", 1: "Disgusted", 2: "Fearful", 3: "Happy", 4: "Neutral", 5: "Sad", 6: "Surprised"}

# start the webcam feed
cap = cv2.VideoCapture(0)
while True:
    # Find haar cascade to draw bounding box around face
    ret, frame = cap.read()
    frame = cv2.resize(frame, (300, 300))

    if not ret:
        break

    bounding_box = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    num_faces = bounding_box.detectMultiScale(gray_frame, scaleFactor=1.3, minNeighbors=5)

    for (x, y, w, h) in num_faces:
        cv2.rectangle(frame, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
        roi_gray_frame = gray_frame[y:y + h, x:x + w]
        cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray_frame, (48, 48)), -1), 0)
        emotion_prediction = emotion_model.predict(cropped_img)
        maxindex = int(np.argmax(emotion_prediction))
        cv2.putText(frame, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)

    cv2.imshow('Video', cv2.resize(frame,(300, 300), interpolation=cv2.INTER_CUBIC))
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

2. gui.py程序


"""
Code for GUI and mapping with emojis
"""

import tkinter as tk
from tkinter import *
import cv2
from PIL import Image, ImageTk
import os
import numpy as np

import numpy as np
import cv2
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D
from keras.optimizers import Adam
from keras.layers import MaxPooling2D
from keras.preprocessing.image import ImageDataGenerator

emotion_model = Sequential()

emotion_model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(48,48,1)))
emotion_model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))

emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
emotion_model.add(MaxPooling2D(pool_size=(2, 2)))
emotion_model.add(Dropout(0.25))

emotion_model.add(Flatten())
emotion_model.add(Dense(1024, activation='relu'))
emotion_model.add(Dropout(0.5))
emotion_model.add(Dense(7, activation='softmax'))
emotion_model.load_weights('emotion_model.h5')

cv2.ocl.setUseOpenCL(False)

emotion_dict = {0: "   Angry   ", 1: "Disgusted", 2: "  Fearful  ", 3: "   Happy   ", 4: "  Neutral  ", 5: "    Sad    ", 6: "Surprised"}


emoji_dist={0:"./emojis/angry.png",2:"./emojis/disgusted.png",2:"./emojis/fearful.png",3:"./emojis/happy.png",4:"./emojis/neutral.png",5:"./emojis/sad.png",6:"./emojis/surpriced.png"}

global last_frame1                                    
last_frame1 = np.zeros((480, 640, 3), dtype=np.uint8)
global cap1
show_text=[0]
def show_vid():      
    cap1 = cv2.VideoCapture(0)                                 
    if not cap1.isOpened():                             
        print("cant open the camera1")
    flag1, frame1 = cap1.read()
    frame1 = cv2.resize(frame1,(600,500))

    bounding_box = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    gray_frame = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
    num_faces = bounding_box.detectMultiScale(gray_frame,scaleFactor=1.3, minNeighbors=5)

    for (x, y, w, h) in num_faces:
        cv2.rectangle(frame1, (x, y-50), (x+w, y+h+10), (255, 0, 0), 2)
        roi_gray_frame = gray_frame[y:y + h, x:x + w]
        cropped_img = np.expand_dims(np.expand_dims(cv2.resize(roi_gray_frame, (48, 48)), -1), 0)
        prediction = emotion_model.predict(cropped_img)
        
        maxindex = int(np.argmax(prediction))
        # cv2.putText(frame1, emotion_dict[maxindex], (x+20, y-60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
        show_text[0]=maxindex
    if flag1 is None:
        print ("Major error!")
    elif flag1:
        global last_frame1
        last_frame1 = frame1.copy()
        pic = cv2.cvtColor(last_frame1, cv2.COLOR_BGR2RGB)     
        img = Image.fromarray(pic)
        imgtk = ImageTk.PhotoImage(image=img)
        lmain.imgtk = imgtk
        lmain.configure(image=imgtk)
        # lmain.after(10, show_vid)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        exit()


def show_vid2():
    frame2=cv2.imread(emoji_dist[show_text[0]])
    pic2=cv2.cvtColor(frame2,cv2.COLOR_BGR2RGB)
    img2=Image.fromarray(frame2)
    imgtk2=ImageTk.PhotoImage(image=img2)
    lmain2.imgtk2=imgtk2
    lmain3.configure(text=emotion_dict[show_text[0]],font=('arial',45,'bold'))
    
    lmain2.configure(image=imgtk2)
    # lmain2.after(10, show_vid2)
#
if __name__ == '__main__':
    root=tk.Tk()   
    img = ImageTk.PhotoImage(Image.open("logo.png"))
    heading = Label(root,image=img,bg='black')
    
    heading.pack() 
    heading2=Label(root,text="Photo to Emoji",pady=20, font=('arial',45,'bold'),bg='black',fg='#CDCDCD')                                 
    
    heading2.pack()
    lmain = tk.Label(master=root,padx=50,bd=10)
    lmain2 = tk.Label(master=root,bd=10)

    lmain3=tk.Label(master=root,bd=10,fg="#CDCDCD",bg='black')
    lmain.pack(side=LEFT)
    lmain.place(x=50,y=250)
    lmain3.pack()
    lmain3.place(x=960,y=250)
    lmain2.pack(side=RIGHT)
    lmain2.place(x=900,y=350)
    


    root.title("Photo To Emoji")            
    root.geometry("1400x900+100+10") 
    root['bg']='black'
    exitbutton = Button(root, text='Quit',fg="red",command=root.destroy,font=('arial',25,'bold')).pack(side = BOTTOM)
    show_vid()
    show_vid2()
    root.mainloop()

gui.py输出结果:
在这里插入图片描述


如有问题,欢迎指出和讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/705245.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

.Net 4726.0 Razor编译时的小差异

前言 几个月前在进行着.Net 472到6.0的升级,复用原有代码,在对Razor进行迁移中,发现原运行正常的代码,却存在报错,深入研究发现是Core下对Razor编译有一些变动。 问题复现 472 创建视图 新建.Net Framework下Mvc&#…

常州工学院单片机及应用系统设计2021-2022 学年第 二 学期 考试类型 开卷 课程编码 0302005

第一题 #include "SC95F861x_C.H" #include <INTRINS.H> unsigned char keydata0; void delay(unsigned int timer) //延时函数 { while(timer>0) timer--; } void IOinit() { P5CON0x00; P5PH0x03; P3CON0xFF; P3PH0xFF; } void readke…

字节跳动算法 提前批offer复盘

作者 | zjwang 面试锦囊之面经分享系列&#xff0c;持续更新中 欢迎后台回复"面试"加入讨论组交流噢 写在前面 北航本硕&#xff0c;非科班对搜索推荐比较感兴趣&#xff0c;平时看的文章比较多&#xff0c;所以聊的比较偏这一块大四时一段五个月的nlp方向实习&…

Dlib —— Windows下Vs2017编译dlib源码

Dlib Dlib 是一个现代C工具包&#xff0c;包含机器学习算法和 用于创建复杂软件的工具&#xff0c;C解决现实世界的问题。 它用于工业界和学术界的广泛领域 包括机器人、嵌入式设备、手机和大型高 性能计算环境。Dlib的开源许可允许您在任何应用程序中免费使用它。   Dlib相关…

项目计划、进度与控制

思维导图 项目计划、进度与控制-思维导图 第一部分 项目管理概述 什么是项目 约瑟夫朱兰博士也说过&#xff0c;项目就是在已经确定好的时间内必须解决的问题 什么是项目管理 图1-1 项目管理就是工具、人和系统 image.png 组织是人的集合&#xff0c;过程是人在处理。如果人…

Docker cuda libnvidia-compute Invalid cross-device link

docker apt 安装 cuda rootyeqiang-PC:/opt/speccpu2006# docker exec -it 881 /bin/bash root8815d0425401:/# apt --fix-broken install Reading package lists... Done Building dependency tree Reading state information... Done Correcting dependencies... Don…

Redis 事务与数据持久化

目录 一、Redis 事务 1.1 事务本质 1.2 数据库事务与redis事务 1.2.1 数据库事务 1.2.2 Redis事务 1.2.2.1 两种错误不同处理方式 1&#xff09;代码语法错误&#xff08;编译时异常&#xff09; 2&#xff09;代码逻辑错误&#xff08;运行时错误&#xff09; 1.2.2.2 这种做…

线性代数行列式的几何含义

行列式可以看做是一系列列向量的排列&#xff0c;并且每个列向量的分量可以理解为其对应标准正交基下的坐标。 行列式有非常直观的几何意义&#xff0c;例如&#xff1a; 二维行列式按列向量排列依次是 a \mathbf{a} a和 b \mathbf{b} b&#xff0c;可以表示 a \mathbf{a} a和…

目标检测mAP

概述 AP (Average precision) is a popular metric in measuring the accuracy of object detectors like Faster R-CNN, SSD, etc. Average precision computes the average precision value for recall value over 0 to 1. It sounds complicated but actually pretty simple…

安卓热修系列-插件资源冲突解决方案

作者&#xff1a;37手游移动客户端团队 背景 在做插件化过程中&#xff0c;宿主需要用到插件的资源&#xff0c;涉及到加载插件的资源&#xff1b; 因为插件是以apk的方式存在的&#xff0c;所以插件的ID和宿主的ID可能导致重复&#xff1b; 为了解决这个问题&#xff0c;需…

[游戏开发][Unity]点击Play按钮卡顿特别久

一般小工程不会遇到这个问题&#xff0c;我在公司接手了几个老项目&#xff0c;都遇到了这个问题。每次Play卡顿几分钟甚至十几分钟&#xff0c;很是头疼。

DL学习11-nin-mnist

对于使用卷积神经网络加全连接层的结构而言&#xff0c;对于全连接的参数的巨大了&#xff0c;对于简单的任务容易造成过拟合&#xff0c;且会增加模型的额外开销&#xff0c;例如alexnet&#xff0c;vgg等&#xff0c;全连接层的开销会随着参数的增加而爆炸式增长。 nin旨在使…

ELK增量同步数据【MySql->ES】

一、前置条件 1. linux&#xff0c;已经搭建好的logstasheskibana【系列版本7.0X】&#xff0c;es 的plugs中安装ik分词器 ES版本&#xff1a; Logstash版本&#xff1a; &#xff08;以上部署&#xff0c;都是运维同事搞的&#xff0c;我不会部署&#xff0c;同事给力&#…

动态SLAM论文(3) — Detect-SLAM: Making Object Detection and SLAM Mutually Beneficial

目录 1 Introduction 2 Related Work 3 Detect-SLAM 3.1 移动物体去除 3.2 Mapping Objects 3.3 增强SLAM检测器 4 实验 4.1 动态环境下的鲁棒SLAM 4.2. 提升检测性能 5 结论 Abstract&#xff1a;近年来&#xff0c;在SLAM和目标检测方面取得了显著进展&#xff0c;…

使用python sdk添加删除阿里云pvc路由

1. 前言 由于线路供应商sdwan存在单点问题&#xff0c;需要实现线路高可用解决方案&#xff0c;需要设计自动切换阿里云vpc路由解决方案。通过阿里云文档了解&#xff0c;可通过阿里云专有网络Python SDK&#xff0c;通过sdk实现创建、删除、查询等vpc网络相关操作&#xff08…

如何与德科斯米尔Draexlmaier 建立 EDI 连接?

德科斯米尔Draexlmaier&#xff08;以下简称为DRX&#xff09;是一家总部位于德国的汽车零部件供应商和系统集成商&#xff0c;如今已成为全球领先的汽车内部装饰系统、电气和电子系统、电缆技术以及储能系统的制造商之一。EDI 帮助DRX与其交易伙伴之间实现信息流的一致性、无误…

CHATGPT使用笔记

CHATGPT是帮你做事&#xff0c;而不是替你做事 1、联网插件&#xff1a; 使用Webpilot插件联网时还可以同时使用其它两种插件&#xff08;一次可以同时使用三个插件&#xff09;&#xff0c;而使用Web Browsing插件功能联网时无法使用插件功能&#xff08;联网功能和插件只能…

SpringBoot2+Vue2实战(八)文件上传实现

一、文件上传 创建数据库表 Files import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data;Data TableName("sys_file") public cl…

18.RocketMQ中消息重复的场景和幂等处理

highlight: arduino-light 消息重复的场景 发送消息异常,重试发送导致消息重复★ 当一条消息已被成功发送到服务端并完成持久化。此时出现网络闪断或者客户端宕机&#xff0c;导致服务端对生产者的确认应答失败。生产者发送消息到mq时发送成功未获取到响应,然后生产者进行消息发…

信号链噪声分析18

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 到目前为止&#xff0c;我们考虑的是基带采样情况&#xff0c;即所有目标信号均位于第一奈奎斯特区内。 图 显示了另外一种情况&#xff0c;其中采样信号频带局限于第一奈奎斯…