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

基于Yolov8面部七种表情检测与识别C++模型部署

表情识别

七种表情识别是一个多学科交叉的研究领域,它结合了心理学、认知科学、计算机视觉和机器学习等学科的知识和技术。

基本概念

  • 表情的定义:表情是人们在情绪体验时面部肌肉活动的结果,是人类情感交流的基本方式之一。
  • 基本表情理论:心理学家Paul Ekman提出,人类有七种基本情绪,每种情绪都有其特定的面部表情模式。

七种基本表情

  1. 快乐:通常与积极情绪相关,特征是嘴角上扬,眼睛周围肌肉收缩。
  2. 悲伤:与失落或痛苦相关,特征是眉毛下垂,嘴角下拉。
  3. 愤怒:与愤怒或挫败相关,特征是眉毛下压,嘴唇紧闭。
  4. 惊讶:与意外或震惊相关,特征是眼睛和嘴巴张开。
  5. 恐惧:与害怕或焦虑相关,特征是眼睛瞪大,眉毛提升。
  6. 厌恶:与反感或不喜欢相关,特征是上唇提升,嘴角下拉。
  7. 轻蔑:与鄙视或不屑一顾相关,特征是嘴角一侧上扬。

应用领域

  • 心理健康监测:通过表情识别来评估个体的情绪状态。
  • 人机交互:使机器人或计算机系统能够理解和响应用户的情绪。
  • 安全监控:在安全检查中识别可疑行为或情绪异常。
  • 娱乐和媒体:在电影、游戏和虚拟现实中生成逼真的虚拟角色表情。

挑战和限制

  • 个体差异:不同人表达相同情绪的方式可能不同。
  • 文化差异:不同文化背景下,表情的表达和解读可能存在差异。
  • 环境因素:光照、遮挡和面部表情的微妙变化可能影响识别的准确性。
  • 实时性要求:在某些应用场景下,如视频监控或实时交互,对系统的处理速度有较高要求。

发展趋势

  • 多模态识别:结合面部表情以外的信息,如语音、心率等,以提高识别的准确性。
  • 迁移学习:利用预训练的深度学习模型来提高小样本学习的性能。
  • 无监督和半监督学习:减少对大量标注数据的依赖,提高模型的泛化能力。

数据集

数据集内容:RAF-DB数据集是一个大规模面部表情数据库,由315名工作人员(大学的学生和教职员工)对表情进行标注。

在对表情的选择上,从一系列表情(例如:微笑,咯咯笑声,哭泣,愤怒,害怕,害怕,恐惧,震惊,惊讶,厌恶,无表情)中,挑选出六种基本情感以及中立情感,一共7种表情进行表情标注。

数据集数量:RAF-DB数据集,包含大约3万张面部图像。除了表情标注外,对每个人脸还有5个特征点标注,人脸边界框,种族,年龄范围和性别等属性的标注。

数据集功能:表情识别、人脸检测、年龄估计

下载链接:http://www.whdeng.cn/RAF/model1.html

在这里插入图片描述

Yolov8目标检测

YOLOv8是YOLO系列的最新迭代产品,它在目标检测领域带来了一系列创新和改进。以下是YOLOv8的一些关键特点和功能:

  1. 模型结构:YOLOv8采用了新的SOTA模型,包括不同分辨率的目标检测网络和基于YOLACT的实例分割模型。它在骨干网络和Neck部分可能参考了YOLOv7 ELAN的设计思想,将YOLOv5的C3结构换成了C2f结构,并对不同尺度模型调整了不同的通道数。

  2. Head部分:与YOLOv5相比,YOLOv8的Head部分改动较大,换成了目前主流的解耦头结构,将分类和检测头分离,并且从Anchor-Based换成了Anchor-Free。

  3. Loss计算:YOLOv8采用了TaskAlignedAssigner正样本分配策略,并引入了Distribution Focal Loss,这有助于提高检测过程的准确性和效率。

  4. 数据增强:在训练过程中,YOLOv8引入了YOLOX中的最后10个epoch关闭Mosaic增强的操作,这可以有效地提升精度。

  5. 训练策略:YOLOv8的模型训练总epoch数从300提升到了500,这导致训练时间增加,但可能有助于进一步提升模型性能。

  6. 性能和速度:YOLOv8专注于保持精度与速度之间的最佳平衡,适用于各种应用领域的实时目标检测任务。

  7. 预训练模型:YOLOv8提供一系列预训练模型,以满足各种任务和性能要求,从而更容易为您的特定用例找到合适的模型。

  8. 支持的任务和模式:YOLOv8系列提供多种模型,每种模型都专门用于计算机视觉中的特定任务,如物体检测、实例分割、姿态/关键点检测等。

  9. 性能基准测试:YOLOv8可以进行性能基准测试,以评估在不同导出格式下的速度和准确性。

  10. 实战应用:有教程提供了YOLOv8在LabVIEW中的部署,包括模型的导出、图片和视频推理的实现。

环境安装

安装环境:

conda create -n yolov8 python=3.8
activate ylolv8
pip install ultralytics

转onnx

安装完成之后,分割数据进行模型训练。训练完之后把模型转成onnx,使用以下命令将YOLO模型从PyTorch导出为ONNX格式,并设置opset为12:

yolo export model=yolov8s.pt format=onnx dynamic=False opset=12

命令的含义解释如下:

yolo export: 使用YOLO导出功能、
model=yolov8s.pt: 指定PyTorch模型的路径
format=onnx: 导出为ONNX格式
dynamic=False: 关闭动态输入
opset=12: 设置ONNX模型的opset版本为12

转ncnn模型

得到onnx模型之后要转成ncnn的模型,可以使用onnx2ncnn.exe进行模型转换,也可以使用在线的模型转换工具。

模型C++推理部署

ncnn库

从官方下载以编译好的ncnn库,我这里使用的IDE是vs2022,下载对应自己的库。导入lib和include,如果想要指用GPU进行推理,则要编译vulkan库。

C++ 推理代码

#include "FacialEmotion.h"static float fast_exp(float x)
{union {uint32_t i;float f;} v{};v.i = (1 << 23) * (1.4426950409 * x + 126.93490512f);return v.f;
}static inline float sigmoid(float x)
{return 1.0f / (1.0f + fast_exp(-x));
}
static float intersection_area(const Object& a, const Object& b)
{cv::Rect_<float> inter = a.rect & b.rect;return inter.area();
}static void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)
{int i = left;int j = right;float p = faceobjects[(left + right) / 2].prob;while (i <= j){while (faceobjects[i].prob > p)i++;while (faceobjects[j].prob < p)j--;if (i <= j){// swapstd::swap(faceobjects[i], faceobjects[j]);i++;j--;}}//     #pragma omp parallel sections{//         #pragma omp section{if (left < j) qsort_descent_inplace(faceobjects, left, j);}//         #pragma omp section{if (i < right) qsort_descent_inplace(faceobjects, i, right);}}
}static void qsort_descent_inplace(std::vector<Object>& faceobjects)
{if (faceobjects.empty())return;qsort_descent_inplace(faceobjects, 0, faceobjects.size() - 1);
}static void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked, float nms_threshold)
{picked.clear();const int n = faceobjects.size();std::vector<float> areas(n);for (int i = 0; i < n; i++){areas[i] = faceobjects[i].rect.width * faceobjects[i].rect.height;}for (int i = 0; i < n; i++){const Object& a = faceobjects[i];int keep = 1;for (int j = 0; j < (int)picked.size(); j++){const Object& b = faceobjects[picked[j]];// intersection over unionfloat inter_area = intersection_area(a, b);float union_area = areas[i] + areas[picked[j]] - inter_area;// float IoU = inter_area / union_areaif (inter_area / union_area > nms_threshold)keep = 0;}if (keep)picked.push_back(i);}
}
static void generate_grids_and_stride(const int target_w, const int target_h, std::vector<int>& strides, std::vector<GridAndStride>& grid_strides)
{for (int i = 0; i < (int)strides.size(); i++){int stride = strides[i];int num_grid_w = target_w / stride;int num_grid_h = target_h / stride;for (int g1 = 0; g1 < num_grid_h; g1++){for (int g0 = 0; g0 < num_grid_w; g0++){GridAndStride gs;gs.grid0 = g0;gs.grid1 = g1;gs.stride = stride;grid_strides.push_back(gs);}}}
}static void generate_proposals(std::vector<GridAndStride> grid_strides, const ncnn::Mat& pred, float prob_threshold, std::vector<Object>& objects)
{const int num_points = grid_strides.size();const int num_class = 7;const int reg_max_1 = 16;for (int i = 0; i < num_points; i++) //out.h{const float* scores = pred.row(i) + 4 * reg_max_1;// find label with max scoreint label = -1;float score = -FLT_MAX;for (int k = 0; k < num_class; k++){float confidence = scores[k];if (confidence > score){label = k;score = confidence;}}float box_prob = sigmoid(score);if (box_prob >= prob_threshold){ncnn::Mat bbox_pred(reg_max_1, 4, (void*)pred.row(i));{ncnn::Layer* softmax = ncnn::create_layer(ncnn::layer_to_index("Softmax"));
//                ncnn::layer_to_index("Softmax")ncnn::ParamDict pd;pd.set(0, 1); // axis
//                pd.set(1, 1);softmax->load_param(pd);ncnn::Option opt;opt.num_threads = 1;opt.use_packing_layout = false;softmax->create_pipeline(opt);softmax->forward_inplace(bbox_pred, opt);softmax->destroy_pipeline(opt);delete softmax;}float pred_ltrb[4];for (int k = 0; k < 4; k++){float dis = 0.f;const float* dis_after_sm = bbox_pred.row(k);for (int l = 0; l < reg_max_1; l++){dis += l * dis_after_sm[l];}pred_ltrb[k] = dis * grid_strides[i].stride;}float pb_cx = (grid_strides[i].grid0 + 0.5f) * grid_strides[i].stride; float pb_cy = (grid_strides[i].grid1 + 0.5f) * grid_strides[i].stride;float x0 = pb_cx - pred_ltrb[0];float y0 = pb_cy - pred_ltrb[1];float x1 = pb_cx + pred_ltrb[2];float y1 = pb_cy + pred_ltrb[3];Object obj;obj.rect.x = x0;obj.rect.y = y0;obj.rect.width = x1 - x0;obj.rect.height = y1 - y0;obj.label = label;obj.prob = box_prob;objects.push_back(obj);}}
}//调用ncnn转置操作
static void transpose(const ncnn::Mat& in, ncnn::Mat& out)
{ncnn::Option opt;opt.num_threads = 1;opt.use_fp16_storage = false;opt.use_packing_layout = true;ncnn::Layer* op = ncnn::create_layer("Permute");// set paramncnn::ParamDict pd;pd.set(0, 1);// order_type=1op->load_param(pd);op->create_pipeline(opt);op->forward(in,out, opt);op->destroy_pipeline(opt);delete op;
}FacialEmotion::FacialEmotion()
{blob_pool_allocator.set_size_compare_ratio(0.f);workspace_pool_allocator.set_size_compare_ratio(0.f);
}int FacialEmotion::load(std::string parma_path,std::string bin_path,int _target_size,bool use_gpu)
{yolo.clear();blob_pool_allocator.clear();workspace_pool_allocator.clear();ncnn::set_cpu_powersave(2);ncnn::set_omp_num_threads(ncnn::get_big_cpu_count());yolo.opt = ncnn::Option();#if NCNN_VULKANyolo.opt.use_vulkan_compute = use_gpu;
#endifyolo.opt.num_threads = 2;yolo.opt.blob_allocator = &blob_pool_allocator;yolo.opt.workspace_allocator = &workspace_pool_allocator;yolo.load_param(parma_path.c_str());yolo.load_model(bin_path.c_str());target_size = _target_size;return 0;
}int FacialEmotion::detect(const cv::Mat& rgb, std::vector<Object>& objects, float prob_threshold, float nms_threshold)
{int width = rgb.cols;int height = rgb.rows;// pad to multiple of 32int w = width;int h = height;float scale = 1.f;if (w > h){scale = (float)target_size / w;w = target_size;h = h * scale;}else{scale = (float)target_size / h;h = target_size;w = w * scale;}ncnn::Mat in = ncnn::Mat::from_pixels_resize(rgb.data, ncnn::Mat::PIXEL_BGR, width, height, w, h);// pad to target_size rectangleint wpad = (w + 31) / 32 * 32 - w;int hpad = (h + 31) / 32 * 32 - h;ncnn::Mat in_pad;ncnn::copy_make_border(in, in_pad, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, ncnn::BORDER_CONSTANT, 0.f);in_pad.substract_mean_normalize(0, norm_vals);ncnn::Extractor ex = yolo.create_extractor();ex.input("images", in_pad);std::vector<Object> proposals;ncnn::Mat out;ex.extract("/model.22/Concat_3_output_0", out);ncnn::Mat out1;transpose(out, out1);std::vector<int> strides = {8, 16, 32}; // might have stride=64std::vector<GridAndStride> grid_strides;generate_grids_and_stride(in_pad.w, in_pad.h, strides, grid_strides);generate_proposals(grid_strides, out1, prob_threshold, proposals);qsort_descent_inplace(proposals);// apply nms with nms_thresholdstd::vector<int> picked;nms_sorted_bboxes(proposals, picked, nms_threshold);int count = picked.size();objects.resize(count);for (int i = 0; i < count; i++){objects[i] = proposals[picked[i]];// adjust offset to original unpaddedfloat x0 = (objects[i].rect.x - (wpad / 2)) / scale;float y0 = (objects[i].rect.y - (hpad / 2)) / scale;float x1 = (objects[i].rect.x + objects[i].rect.width - (wpad / 2)) / scale;float y1 = (objects[i].rect.y + objects[i].rect.height - (hpad / 2)) / scale;// clipx0 = std::max(std::min(x0, (float)(width - 1)), 0.f);y0 = std::max(std::min(y0, (float)(height - 1)), 0.f);x1 = std::max(std::min(x1, (float)(width - 1)), 0.f);y1 = std::max(std::min(y1, (float)(height - 1)), 0.f);objects[i].rect.x = x0;objects[i].rect.y = y0;objects[i].rect.width = x1 - x0;objects[i].rect.height = y1 - y0;}// sort objects by areastruct{bool operator()(const Object& a, const Object& b) const{return a.rect.area() > b.rect.area();}} objects_area_greater;std::sort(objects.begin(), objects.end(), objects_area_greater);return 0;
}int FacialEmotion::draw(cv::Mat& rgb, const std::vector<Object>& objects)
{static const char *class_names[] = {"surprise", "fear","disgust","happiness","sadness","anger","neutral"};static const unsigned char colors[19][3] = {{ 54,  67, 244},{ 99,  30, 233},{176,  39, 156},{183,  58, 103},{181,  81,  63},{243, 150,  33},{244, 169,   3},{212, 188,   0},{136, 150,   0},{ 80, 175,  76},{ 74, 195, 139},{ 57, 220, 205},{ 59, 235, 255},{  7, 193, 255},{  0, 152, 255},{ 34,  87, 255},{ 72,  85, 121},{158, 158, 158},{139, 125,  96}};int color_index = 0;for (size_t i = 0; i < objects.size(); i++){const Object& obj = objects[i];const unsigned char* color = colors[color_index % 19];color_index++;cv::Scalar cc(color[0], color[1], color[2]);cv::rectangle(rgb, obj.rect, cc, 2);char text[256];sprintf(text, "%s %.1f%%", class_names[obj.label], obj.prob * 100);int baseLine = 0;cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);int x = obj.rect.x;int y = obj.rect.y - label_size.height - baseLine;if (y < 0)y = 0;if (x + label_size.width > rgb.cols)x = rgb.cols - label_size.width;cv::rectangle(rgb, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)), cc, -1);cv::Scalar textcc = (color[0] + color[1] + color[2] >= 381) ? cv::Scalar(0, 0, 0) : cv::Scalar(255, 255, 255);cv::putText(rgb, text, cv::Point(x, y + label_size.height), cv::FONT_HERSHEY_SIMPLEX, 0.5, textcc, 1);}return 0;
}

实现的效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
源码地址:https://download.csdn.net/download/matt45m/89612957

相关文章:

基于Yolov8面部七种表情检测与识别C++模型部署

表情识别 七种表情识别是一个多学科交叉的研究领域&#xff0c;它结合了心理学、认知科学、计算机视觉和机器学习等学科的知识和技术。 基本概念 表情的定义&#xff1a;表情是人们在情绪体验时面部肌肉活动的结果&#xff0c;是人类情感交流的基本方式之一。基本表情理论&a…...

未确认融资费用含义及会计处理流程

文章目录 一、含义二、会计处理流程2.1、初始计量2.2、后续计量2.3、报表列式 三、实务中的注意事项 一、含义 未确认融资费用: 由于企业现有资金不足&#xff0c;购买资产时选择分期支付款项&#xff0c;导致实际支付的款项大于资产的购入价值&#xff0c;两者的差额就是由于…...

Linux配置go程序为service后台开机自启动

1.编写需要启动的项目路径以及简单配置 sudo nano /etc/systemd/system/go.service#定义服务的元数据和依赖关系。 [Unit] #这是对服务的简短描述。 DescriptionMy Go Service #network.target 是一个虚拟目标&#xff0c;它表示网络服务已经初始化完成。该指令告诉 systemd 在…...

汇舟问卷:完成16份调查,挣了40美金,换算后美滋滋

这个世界有太多的人30​岁&#xff0c;35岁以后&#xff0c;当初没有去做自己想做的工作&#xff0c;没有花时间去坚持想做的工作&#xff0c;他们在选择这份想做的事业的前提被自己的父母朋友爱人阻断了。 他们告诉你&#xff0c;要努力的做好现在的工作&#xff0c;争取升职…...

Nacos 202407月RCE漏洞(0day)与复现

免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 一、背景与…...

Dynamo修改共享参数绑定的分组——群问题整理005

Hello大家好!我是九哥~ 今天继续给大家分享一些短平快的小教程,是来自群里面的问题。 问题005:Dynamo修改共享参数绑定的分组 今天看到群里询问如何修改参数所在的分组,查了下API,项目参数是不行的,不过共享参数是允许ReInsert()的,那么就好办了。 然后在Document下…...

聚焦汽车软件开发与测试:静态代码扫描、单元测试与集成测试等方面的实践应用

2024年7月18-19日&#xff0c;龙智携汽车软件开发及管理解决方案创新亮相2024 ATC汽车软件与安全技术周。龙智技术支持部负责人&Atlassian认证专家叶燕秀、龙智功能安全高级工程师景玉鑫在活动主会场联合发表了精彩演讲&#xff0c;分享推动汽车软件开发与功能安全的创新实…...

「队列」实现FIFO队列(先进先出队列|queue)的功能 / 手撕数据结构(C++)

概述 队列&#xff0c;是一种基本的数据结构&#xff0c;也是一种数据适配器。它在底层上以链表方法实现。 队列的显著特点是他的添加元素与删除元素操作&#xff1a;先加入的元素总是被先弹出。 一个队列应该应该是这样的&#xff1a; --------------QUEUE-------------——…...

C++ STL中 `set` 和 `multiset` 简单对比

在 C STL 中&#xff0c;set 和 multiset 都是用于存储唯一或重复元素的关联容器&#xff0c;但它们在处理元素的唯一性和特性方面有显著的区别。以下是这两个容器的详细比较&#xff1a; 1. 数据结构 set&#xff1a;基于红黑树&#xff08;自平衡的二叉搜索树&#xff09;实…...

代码随想录算法训练营Day20 | Leetcode 235 二叉搜索树的最近公共祖先 Leetcode 701 二叉搜索树中的插入操作

Leetcode 235 二叉搜索树的最近公共祖先 题目链接&#xff1a;235. 二叉搜索树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 代码随想录题解&#xff1a;代码随想录 (programmercarl.com) 思路&#xff1a;相比普通二叉树更简单&#xff0c;因为二叉搜索树的节点…...

第九届世界3D渲染大赛:赛程安排、赛事规则

第九届世界3D渲染大赛即将拉开帷幕&#xff0c;汇聚全球顶尖CG艺术家&#xff0c;展现最具有视觉盛宴的CG创作。那么该赛事的行程如何安排呢&#xff0c;赛事规则又是什么呢&#xff1f;本篇整理了赛事安排、赛事规则等内容&#xff0c;希望帮助大家。 赛事主题&#xff1a;Kin…...

RocketMQ5.0 Consumer Group

消费者分组的概念 消费者分组&#xff08;Consumer Group&#xff09;是指一组消费同一类消息的消费者实例。每个消费者分组有一个唯一的名称&#xff0c;用于标识该分组。消费者分组的设计使得消息能够被多个消费者实例并行消费&#xff0c;同时确保每条消息只被一个消费者实例…...

vulnhub之serial

这次我们来做这个靶场 项目地址https://download.vulnhub.com/serial/serial.zip 使用vm新建虚拟机 以下为注意事项 第一步&#xff0c;收集资产 扫描靶场ip netdiscover -i eth0 -r 192.168.177.0/24 抓个包 扫描目录 看到了cookie中有一个user Tzo0OiJVc2VyIjoyOntzOj…...

卷积神经网络(CNN)简单原理与简单代码实现

卷积神经网络&#xff08;CNN&#xff09;简单原理与简单代码实现 卷积神经网络&#xff08;CNN&#xff09;简单原理基本原理卷积层&#xff08;Convolutional Layer&#xff09;&#xff1a;激活层&#xff08;Activation Layer&#xff09;&#xff1a;池化层&#xff08;Po…...

实时数仓分层架构详解

首先&#xff0c;我们从数据仓库说起。 数据仓库的概念可以追溯到20世纪80年代&#xff0c;当时IBM的研究人员提出了商业数据仓库的概念。数据仓库概念的提出&#xff0c;是为了解决和数据流相关的各种问题&#xff0c;特别是多重数据复制带来的高成本问题。 数据仓库之父Bill …...

计算机“八股文”在实际工作中是助力、阻力还是空谈?

“八股文”在实际工作中是助力、阻力还是空谈&#xff1f; 作为现在各类大中小企业面试程序员时的必问内容&#xff0c;“八股文”似乎是很重要的存在。但“八股文”是否能在实际工作中发挥它“敲门砖”应有的作用呢&#xff1f;有IT人士不禁发出疑问&#xff1a;程序员面试考…...

新160个crackme - 022-CM_2

运行分析 需破解Name和Serial&#xff0c;输入的小写字母都会变为大写字母 PE分析 C程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 发现关键字符串 ida动态调试&#xff0c;发现Name和Serial长度需要大于5&#xff0c;且Serial前6位明文爆出&#xff0c;6287-A …...

在.c和.h 文件里定义数组的区别

在C语言开发中&#xff0c;掌握如何在.c文件和.h文件中合理定义数组&#xff0c;对于维护代码的模块化和避免不必要的编译错误至关重要。本文将探讨在这两种类型的文件中定义数组时需要注意的几个关键方面&#xff0c;包括定义性质、作用域、重复定义问题以及外部可见性等&…...

使用Step Functions运行AWS Backup时必备的权限要点

引言 在尝试从Step Functions执行AWS Backup的按需备份时&#xff0c;我在权限方面遇到了一些困难。为了备忘&#xff0c;我将这些经验写成这篇文章。 概述 从Step Functions执行AWS Backup时&#xff0c;需要分配以下权限&#xff1a; AWS Backup相关权限 执行备份的权限…...

强化JS基础水平的10个单行代码来喽!(必看)

目录 生成数组 数组简单数据去重 多数组取交集 重新加载当前页面 滚动到页面顶部 查找最大值索引 进制转换 文本粘贴 删除无效属性 随机颜色生成 生成数组 当你需要要生成一个0-99的数组 // 生成一个0-99的数组 // 方案一 const createArr n > Array.from(new A…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...