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

使用MediaPipe Face Mesh 面部动作检测

一、技术选型

  1. OpenCV(Open Source Computer Vision Library)

    • 用于视频流捕捉、图像预处理和基本图像处理操作。
  2. MediaPipe

    • 提供高效的人脸检测与关键点提取功能(Face Mesh)。
  3. Python

    • 作为后端开发语言,整合上述库进行图像处理和动作识别。
  4. Flask/Django(可选)

    • 用于构建后端API服务,处理前端请求。

二、整体流程概述

  1. 视频流或图片获取

    • 前端通过摄像头捕捉视频流或图片,并将数据发送至后端。
  2. 图像预处理

    • 对接收到的图像数据进行解码、缩放和颜色空间转换。
  3. 人脸检测与关键点提取

    • 使用 MediaPipe 提取面部关键点(Face Mesh)。
  4. 动作识别

    • 根据关键点数据,分析用户的具体动作(如转头、眨眼、张嘴)。
  5. 结果返回

    • 将识别结果以 JSON 格式返回前端。

三、详细实现步骤

1. 视频流或图片获取

前端(微信小程序)捕捉到视频帧或图片后,通过 API 将图像数据(通常为 Base64 编码或二进制数据)发送至后端。

前端发送图像数据示例(微信小程序)

wx.chooseImage({count: 1,success: function(res) {const tempFilePaths = res.tempFilePaths;wx.getFileSystemManager().readFile({filePath: tempFilePaths[0],encoding: 'base64',success: function(data) {wx.request({url: 'https://localhost/api/task/detect',method: 'POST',data: {user_id: 'unique_user_id',image_data: data.data},success: function(response) {// 处理后端返回的检测结果}});}});}
});
2. 图像预处理

后端接收到图像数据后,进行解码和预处理。

示例代码(Python)

import base64
import cv2
import numpy as npdef decode_image(image_base64):# 解码 Base64 图像数据img_data = base64.b64decode(image_base64)# 转换为 numpy 数组np_arr = np.frombuffer(img_data, np.uint8)# 使用 OpenCV 解码图像img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)return img
3. 人脸检测与关键点提取

使用 MediaPipe 的 Face Mesh 模型提取面部关键点。

安装 MediaPipe

pip install mediapipe

示例代码(Python)

import mediapipe as mp# 初始化 MediaPipe Face Mesh
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=False,max_num_faces=1,refine_landmarks=True,min_detection_confidence=0.5,min_tracking_confidence=0.5
)def get_face_landmarks(image):# 将图像从 BGR 转换为 RGBrgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 获取关键点results = face_mesh.process(rgb_image)if results.multi_face_landmarks:# 返回第一个人脸的关键点return results.multi_face_landmarks[0]else:return None
4. 动作识别

基于提取的关键点数据,分析用户的具体动作。以下分别介绍左右转头、眨眼和张嘴的检测方法。

4.1 左右转头检测

通过分析左右眼和鼻子的关键点位置,计算头部的旋转角度。

关键点选择

  • 鼻尖(例如 MediaPipe Face Mesh 的 1 号关键点)
  • 左眼外角(例如 33 号关键点)
  • 右眼外角(例如 263 号关键点)

实现步骤

  1. 计算左眼外角与鼻尖的连线向量。
  2. 计算右眼外角与鼻尖的连线向量。
  3. 通过向量之间的角度差,判断头部是否向左或向右转动。

示例代码

import mathdef calculate_angle(p1, p2):# 计算两点连线的角度(相对于水平线)delta_y = p2.y - p1.ydelta_x = p2.x - p1.xangle = math.degrees(math.atan2(delta_y, delta_x))return angledef detect_head_turn(landmarks):# 关键点索引(根据 MediaPipe Face Mesh)nose_tip = landmarks.landmark[1]left_eye_outer = landmarks.landmark[33]right_eye_outer = landmarks.landmark[263]# 计算角度left_angle = calculate_angle(nose_tip, left_eye_outer)right_angle = calculate_angle(nose_tip, right_eye_outer)# 计算平均角度avg_angle = (left_angle + right_angle) / 2# 定义阈值(根据实际测试调整)TURN_LEFT_THRESHOLD = -15  # 向左转头TURN_RIGHT_THRESHOLD = 15  # 向右转头if avg_angle < TURN_LEFT_THRESHOLD:return 'left'elif avg_angle > TURN_RIGHT_THRESHOLD:return 'right'else:return 'straight'
4.2 眨眼检测

通过监测眼睛的纵横比(EAR, Eye Aspect Ratio)来检测眨眼次数。

关键点选择

  • 左眼:关键点 362, 385, 387, 263, 373, 380
  • 右眼:关键点 33, 160, 158, 133, 153, 144

实现步骤

  1. 计算每只眼睛的 EAR。
  2. 当 EAR 低于某个阈值时,判断为闭眼。
  3. 记录眨眼次数。

示例代码

def eye_aspect_ratio(landmarks, eye_indices):# 计算 EAR# eye_indices 包含 6 个关键点的索引p1 = landmarks.landmark[eye_indices[1]]p2 = landmarks.landmark[eye_indices[5]]p3 = landmarks.landmark[eye_indices[2]]p4 = landmarks.landmark[eye_indices[4]]p5 = landmarks.landmark[eye_indices[0]]p6 = landmarks.landmark[eye_indices[3]]# 纵向距离vertical_1 = math.sqrt((p2.x - p4.x)**2 + (p2.y - p4.y)**2)vertical_2 = math.sqrt((p3.x - p5.x)**2 + (p3.y - p5.y)**2)# 横向距离horizontal = math.sqrt((p1.x - p6.x)**2 + (p1.y - p6.y)**2)ear = (vertical_1 + vertical_2) / (2.0 * horizontal)return eardef detect_blink(landmarks, blink_counter, total_blinks):LEFT_EYE = [362, 385, 387, 263, 373, 380]RIGHT_EYE = [33, 160, 158, 133, 153, 144]EAR_THRESHOLD = 0.21  # 根据实际测试调整CONSEC_FRAMES = 3  # 眨眼最少持续的帧数left_ear = eye_aspect_ratio(landmarks, LEFT_EYE)right_ear = eye_aspect_ratio(landmarks, RIGHT_EYE)ear = (left_ear + right_ear) / 2.0if ear < EAR_THRESHOLD:blink_counter += 1else:if blink_counter >= CONSEC_FRAMES:total_blinks += 1blink_counter = 0return blink_counter, total_blinks
4.3 张嘴检测

通过计算嘴部纵横比(MAR, Mouth Aspect Ratio)来检测张嘴动作。

关键点选择

  • 上唇上方(例如 13 号关键点)
  • 下唇下方(例如 14 号关键点)
  • 左嘴角(78 号关键点)
  • 右嘴角(308 号关键点)

实现步骤

  1. 计算嘴部的 MAR。
  2. 当 MAR 超过某个阈值时,判断为张嘴。

示例代码

def mouth_aspect_ratio(landmarks):# 关键点索引(根据 MediaPipe Face Mesh)upper_lip = landmarks.landmark[13]lower_lip = landmarks.landmark[14]left_mouth = landmarks.landmark[78]right_mouth = landmarks.landmark[308]# 纵向距离vertical = math.sqrt((upper_lip.x - lower_lip.x)**2 + (upper_lip.y - lower_lip.y)**2)# 横向距离horizontal = math.sqrt((left_mouth.x - right_mouth.x)**2 + (left_mouth.y - right_mouth.y)**2)mar = vertical / horizontalreturn mardef detect_mouth_open(landmarks, mouth_opened):MAR_THRESHOLD = 0.6  # 根据实际测试调整mar = mouth_aspect_ratio(landmarks)if mar > MAR_THRESHOLD:mouth_opened = Trueelse:mouth_opened = Falsereturn mouth_opened
5. 综合动作识别

将上述各个动作的检测方法整合,形成综合的动作识别流程。

示例代码

def recognize_actions(landmarks, state):# state 包含用于记录眨眼状态的变量,如 blink_counter, total_blinks, mouth_openedaction_results = {}# 检测左右转头head_direction = detect_head_turn(landmarks)action_results['head_turn'] = head_direction# 检测眨眼state['blink_counter'], state['total_blinks'] = detect_blink(landmarks, state['blink_counter'], state['total_blinks'])action_results['blink_count'] = state['total_blinks']# 检测张嘴state['mouth_opened'] = detect_mouth_open(landmarks, state['mouth_opened'])action_results['mouth_opened'] = state['mouth_opened']return action_results
6. 后端 API 实现

使用 Flask 构建后端 API,处理前端请求,执行上述图像处理和动作识别逻辑,并返回结果。

安装 Flask

pip install Flask

示例代码(Flask 应用)

from flask import Flask, request, jsonify
import cv2
import base64
import numpy as npapp = Flask(__name__)# 初始化 MediaPipe Face Mesh
import mediapipe as mp
mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(static_image_mode=False,max_num_faces=1,refine_landmarks=True,min_detection_confidence=0.5,min_tracking_confidence=0.5
)# 状态管理(简单示例,实际应用建议使用数据库或缓存)
user_states = {}@app.route('/api/task/detect', methods=['POST'])
def detect_task():data = request.jsonuser_id = data.get('user_id')image_base64 = data.get('image_data')if not user_id or not image_base64:return jsonify({'success': False, 'message': '缺少参数'}), 400# 解码图像try:img = decode_image(image_base64)except Exception as e:return jsonify({'success': False, 'message': '图像解码失败'}), 400# 获取关键点landmarks = get_face_landmarks(img)if not landmarks:return jsonify({'success': False, 'message': '未检测到人脸'}), 200# 初始化用户状态if user_id not in user_states:user_states[user_id] = {'current_step': 1,'blink_counter': 0,'total_blinks': 0,'mouth_opened': False}state = user_states[user_id]current_step = state['current_step']# 识别动作action_results = recognize_actions(landmarks, state)# 判断当前步骤success = Falsenext_task = ''if current_step == 1:if action_results['head_turn'] in ['left', 'right']:success = Truenext_task = '请眨眼'state['current_step'] += 1elif current_step == 2:if action_results['blink_count'] >= 1:success = Truenext_task = '请张嘴'state['current_step'] += 1elif current_step == 3:if action_results['mouth_opened']:success = Truenext_task = '所有任务完成'state['current_step'] += 1else:# 所有任务完成success = Truenext_task = '所有任务已完成'if success:if state['current_step'] > 3:return jsonify({'success': True,'message': '成功完成所有任务','next_task': '完成','current_step': state['current_step']}), 200else:return jsonify({'success': True,'message': '检测成功,进入下一步','next_task': next_task,'current_step': state['current_step']}), 200else:return jsonify({'success': False,'message': '检测失败,请重新开始','current_step': 1}), 200@app.route('/api/task/reset', methods=['POST'])
def reset_task():data = request.jsonuser_id = data.get('user_id')if not user_id:return jsonify({'success': False, 'message': '缺少 user_id'}), 400user_states[user_id] = {'current_step': 1,'blink_counter': 0,'total_blinks': 0,'mouth_opened': False}return jsonify({'success': True,'message': '任务已重置','current_step': 1}), 200def decode_image(image_base64):img_data = base64.b64decode(image_base64)np_arr = np.frombuffer(img_data, np.uint8)img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)return imgdef get_face_landmarks(image):rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)results = face_mesh.process(rgb_image)if results.multi_face_landmarks:return results.multi_face_landmarks[0]else:return None# 包含上述动作检测函数的 recognize_actions 等if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

四、示例说明

假设用户正在进行 “检测用户是否向左转头” 的第一步任务:

  1. 前端捕捉图像

    • 用户在小程序中启动任务,摄像头捕捉当前帧,并将图像数据发送至后端的 /api/task/detect 接口。
  2. 后端处理

    • 解码图像数据,并使用 MediaPipe 提取面部关键点。
    • 计算鼻尖与左右眼外角的角度差,判断用户是否向左或向右转头。
    • 假设检测到用户向左转头,更新用户任务状态为第二步。
  3. 后端返回结果

    • 返回 success: true,提示用户进入下一步任务“请眨眼”。
  4. 前端反馈

    • 小程序根据后端返回的结果,更新界面提示用户“请眨眼”,并更新进度条。

具体代码执行过程

  • 用户完成向左转头动作,前端发送图像数据。
  • 后端解码图像,提取关键点,计算角度。
  • 检测到头部向左转动,detect_head_turn 返回 'left'
  • 后端判断当前步骤为 1,检测成功,更新步骤为 2,提示下一步任务。
  • 前端接收到 success: true,显示“请眨眼”。

五、优化与注意事项

  1. 实时性与性能优化

    • 后端:使用异步框架(如 FastAPI)提升并发处理能力;使用 GPU 加速(如 NVIDIA CUDA)提升 MediaPipe 的处理速度。
    • 前端:优化图像上传频率,减少网络传输延迟;使用合适的图像分辨率,平衡识别精度与传输速度。
  2. 准确性提升

    • 调整动作识别的阈值(如 EAR_THRESHOLD、MAR_THRESHOLD),根据实际测试数据进行优化。
    • 使用更多关键点或更复杂的算法(如深度学习模型)提升动作识别的准确性。
  3. 错误处理与用户体验

    • 后端:处理异常情况,如未检测到人脸,返回友好的错误信息。
    • 前端:根据后端返回的错误信息,提供明确的用户指引,如“未检测到人脸,请调整位置并重试”。
  4. 安全性

    • 使用 HTTPS 协议保护数据传输安全。
    • 对上传的图像数据进行限制,防止恶意攻击(如限制图像大小、格式等)。
  5. 扩展性

    • 设计模块化的代码结构,便于后续增加更多动作识别任务。
    • 使用数据库或缓存系统(如 Redis)管理用户状态,支持大规模用户同时使用。

六、扩展示例:添加“微笑”检测

假设需要增加一个新任务,检测用户是否微笑。以下为实现步骤:

  1. 关键点选择

    • 上嘴唇中点(例如 13 号关键点)
    • 下嘴唇中点(例如 14 号关键点)
    • 左嘴角(78 号关键点)
    • 右嘴角(308 号关键点)
  2. 微笑检测逻辑

    def smile_aspect_ratio(landmarks):# 关键点索引upper_lip = landmarks.landmark[13]lower_lip = landmarks.landmark[14]left_mouth = landmarks.landmark[78]right_mouth = landmarks.landmark[308]# 纵向距离vertical = math.sqrt((upper_lip.x - lower_lip.x)**2 + (upper_lip.y - lower_lip.y)**2)# 横向距离horizontal = math.sqrt((left_mouth.x - right_mouth.x)**2 + (left_mouth.y - right_mouth.y)**2)sar = vertical / horizontalreturn sardef detect_smile(landmarks):SAR_THRESHOLD = 0.5  # 根据实际测试调整sar = smile_aspect_ratio(landmarks)return sar > SAR_THRESHOLD
    
  3. 集成到后端 API

    recognize_actions 函数中添加微笑检测逻辑,并在任务流程中增加相应步骤。


后端实现对视频流或图片的人脸检测与动作识别功能,关键在于有效利用 MediaPipe 提供的高效人脸关键点提取功能,并基于这些关键点设计合理的动作识别算法。结合前端的摄像头捕捉和后端的高效处理,可以实现实时、准确的任务检测与反馈,提升用户体验。

附录: 关键点索引参考

MediaPipe Face Mesh 提供 468 个面部关键点,常用的一些关键点索引如下:

  • 鼻尖:1
  • 左眼外角:33
  • 右眼外角:263
  • 左眼上方:159
  • 左眼下方:145
  • 右眼上方:386
  • 右眼下方:374
  • 上唇上方:13
  • 下唇下方:14
  • 左嘴角:78
  • 右嘴角:308

详细的关键点索引可以参考 MediaPipe Face Mesh 。

相关文章:

使用MediaPipe Face Mesh 面部动作检测

一、技术选型 OpenCV&#xff08;Open Source Computer Vision Library&#xff09; 用于视频流捕捉、图像预处理和基本图像处理操作。 MediaPipe 提供高效的人脸检测与关键点提取功能&#xff08;Face Mesh&#xff09;。 Python 作为后端开发语言&#xff0c;整合上述库进行…...

【Vue】<script setup>和 <script>区别是什么?在使用时的写法区别?

<script setup> 是 Vue 3 引入的一种新的脚本语法&#xff0c;它提供了一种更简洁和声明式的方式来编写组件逻辑。它是为了解决传统 <script> 标签在 Vue 单文件组件&#xff08;SFC&#xff09;中的一些局限性而设计的。 <script setup> 与 <script>…...

微服务框架,Http异步编程中,如何保证数据的最终一致性

一、背景 在微服务框架下&#xff0c;跨服务之间的调用&#xff0c;当遇到操作耗时或者量大的情况&#xff0c;我们一般会采用异步编程实现。 本文出现的问题是&#xff1a;异步回调过来时&#xff0c;却未查询到数据库中的任务&#xff0c;导致未能正常处理回调。 下面是当…...

vue3-dom-diff算法

vue3diff算法 什么是vue3diff算法 Vue3中的diff算法是一种用于比较虚拟DOM树之间差异的算法&#xff0c;其目的是为了高效地更新真实DOM&#xff0c;减少不必要的重渲染 主要过程 整个过程主要分为以下五步 前置预处理后置预处理仅处理新增仅处理后置处理包含新增、卸载、…...

年会抽奖Html

在这里插入图片描述 <!-- <video id"backgroundMusic" src"file:///D:/background.mp3" loop autoplay></video> --> <divstyle"width: 290px; height: 580px; margin-left: 20px; margin-top: 20px; background: url(D:/nianhu…...

ubuntu16 重启之后lvm信息丢失故障恢复

一、背景 1、问题背景 业务有一台物理开发服务器&#xff0c;文件系统有损坏&#xff1b;由于重启时没有检查&#xff0c;导致重启卡住。后面通过断电重新启动之后&#xff0c;无法进入系统&#xff1b;进入救援模式&#xff0c;注释数据盘挂载。重启之后进入系统&#xff0c…...

【华为OD-E卷 - 热点网站统计 100分(python、java、c++、js、c)】

【华为OD-E卷 - 热点网站统计 100分&#xff08;python、java、c、js、c&#xff09;】 题目 企业路由器的统计页面&#xff0c;有一个功能需要动态统计公司访问最多的网页URL top N。请设计一个算法&#xff0c;可以高效动态统计Top N的页面 输入描述 每一行都是一个URL或…...

Ubuntu下安装Android Sdk

下载android sdk命令行工具 https://developer.android.com/studio?hlzh-cn#command-tools mkdir android-sdk cd android-sdk unzip commandlinetools-linux-11076708_latest.zip 添加环境变量到~/.bashrc export ANDROID_HOME$HOME/android-sdk export PATH$PATH:$ANDRO…...

【JVM】总结篇-类的加载篇之 类的加载器 和ClassLoader分析

文章目录 类的加载器ClassLoader自定义类加载器双亲委派机制概念源码分析优势劣势如何打破Tomcat 沙箱安全机制JDK9 双亲委派机制变化 类的加载器 获得当前类的ClassLoader clazz.getClassLoader() 获得当前线程上下文的ClassLoader Thread.currentThread().getContextClassLoa…...

怎样修改el-table主题样式

起因&#xff1a;el-table有主题样式&#xff0c;部分需要单独设置 环境&#xff1a;ideanodejs插件谷歌浏览器 第一步&#xff1a;找到scss文件&#xff1a; 谷歌浏览器打开表格页面&#xff0c;ctrlshifti打开开发者工具&#xff0c;点击后鼠标移动到表格单元格上单击一下…...

MySQL(二)MySQL DDL数据库定义语言

1. MySQL DDL数据库定义语言 1.1. MySQL定义语言 进入MySQL mysql -u root -p(回车后输入密码&#xff0c;即可进入mysq1)1.1.1. 数据库操作 &#xff08;1&#xff09;查看数据库 mysql>show databases;注:MySQL语句分隔符为“&#xff1b;”   mysql库很重要它里面有…...

Spring Boot 项目启动报 NoClassDefFoundError 异常的原因分析与解决方案 - jackson 版本不一致

目录 报错: 问题分析&#xff1a; 解决方案&#xff1a; 方案 1&#xff1a;对 Jackson 版本进行统一 方案 2&#xff1a;升级 Springfox 版本 方案 3&#xff1a;替换 Springfox 为 springdoc-openapi&#xff08;推荐&#xff09; 方案 4&#xff1a;排除冲突的 Jack…...

原型与原型链

什么是原型&#xff08;对象&#xff09; 在JavaScript中&#xff0c;每个对象都具有一个原型对象prototype&#xff0c;目的是&#xff1a;利用原型对象实现在同一原型链中的原型方法共享 在理解原型对象前&#xff0c;需要先了解什么是构造函数 构造函数 用来初始化对象的…...

【Linux】信号处理

一、Linux系统信号 1、常见的系统信号 常见的Linux系统信号 信号值描述1SIGHUP挂起&#xff08;hang up&#xff09;进程2SIGINT中断进&#xff08;interrupt&#xff09;程3SIGQUIT停止&#xff08;stop&#xff09;进程9SIGKILL无条件终止&#xff08;terminate&#xff09;…...

5个不同类型的mysql数据库安装

各种社区版本下载官方地址&#xff1a;MySQL :: MySQL Community Downloads 一、在线YUM仓库&#xff08;Linux&#xff09; 选择 MySQL Yum Repository 选择对应版本下载仓库安装包&#xff08;No thanks, just start my download.&#xff09; 下载方法1&#xff1a;下载到本…...

python学习笔记—12—布尔类型、if语句

1. 布尔类型 (1) 定义 (2) 比较运算符 (3) 代码演示 1. 手动定义 bool_1 True bool_2 False print(f"bool_1的内容是&#xff1a;{bool_1}, 类型是&#xff1a;{type(bool_1)}") print(f"bool_2的内容是&#xff1a;{bool_2}, 类型是&#xff1a;{type(bool…...

分数阶傅里叶变换代码 MATLAB实现

function Faf myfrft(f, a) %分数阶傅里叶变换函数 %输入参数&#xff1a; %f&#xff1a;原始信号 %a&#xff1a;阶数 %输出结果&#xff1a; %原始信号的a阶傅里叶变换N length(f);%总采样点数 shft rem((0:N-1)fix(N/2),N)1;%此项等同于fftshift(1:N)&#xff0c;起到翻…...

《数据结构》期末考试测试题【中】

《数据结构》期末考试测试题【中】 21.循环队列队空的判断条件为&#xff1f;22. 单链表的存储密度比1&#xff1f;23.单链表的那些操作的效率受链表长度的影响&#xff1f;24.顺序表中某元素的地址为&#xff1f;25.m叉树第K层的结点数为&#xff1f;26. 在双向循环链表某节点…...

openwrt 清缓存命令行

一、查看缓存 &#xff1a; free -m 二、清缓存&#xff1a;echo 3 > /proc/sys/vm/drop_caches  三、详解。 释放物理页缓存 echo 1 > /proc/sys/vm/drop_caches 释放可回收的slab对象&#xff0c;包含inode and dentry echo 2 > /proc/sys/vm/drop_caches 同时…...

RP2K:一个面向细粒度图像的大规模零售商品数据集

这是一种用于细粒度图像分类的新的大规模零售产品数据集。与以往专注于相对较少产品的数据集不同&#xff0c;我们收集了2000多种不同零售产品的35万张图像&#xff0c;这些图像直接在真实的零售商店的货架上拍摄。我们的数据集旨在推进零售对象识别的研究&#xff0c;该研究具…...

PG 分区表的缺陷

简介 好久没发文&#xff0c;是最近我实在不知道写点啥。随着国产化进程&#xff0c;很多 oracle 都在进行迁移&#xff0c;最近遇到了一个分区表迁移之后唯一性的问题。oracle 数据库中创建主键或者唯一索引&#xff0c;不需要引用分区键&#xff0c;但是 PG 就不行&#xff…...

低功耗MQTT物联网架构Java实现揭秘

文章目录 一、引言二、相关技术概述2.1 物联网概述2.2 MQTT协议java三、基于MQTT的Iot物联网架构设计3.1 架构总体设计3.2 MQTT代理服务器选择3.3 物联网设备设计3.4 应用服务器设计四、基于MQTT的Iot物联网架构的Java实现4.1 开发环境搭建4.2 MQTT客户端实现4.3 应用服务器实现…...

3. 简述node.js特性与底层原理

&#x1f63a;&#x1f63a;&#x1f63a; 一、Node.js 底层原理&#xff08;简化版&#xff09; Node.js 是一个 基于 Chrome V8 引擎构建的 JavaScript 运行时&#xff0c;底层核心由几部分组成&#xff1a; 组成部分简要说明 1.V8 引擎 将 JS 编译成机器码执行&#xff0…...

rec_pphgnetv2完整代码学习(二)

六、TheseusLayer PaddleOCRv5 中的 TheseusLayer 深度解析 TheseusLayer 是 PaddleOCRv5 中 rec_pphgnetv2 模型的核心网络抽象层&#xff0c;提供了强大的网络结构调整和特征提取能力。以下是对其代码的详细解读&#xff1a; 1. 整体设计思想 核心概念&#xff1a; 网络…...

获取 OpenAI API Key

你可以按照以下步骤来获取 openai.api_key&#xff0c;用于调用 OpenAI 的 GPT-4、DALLE、Whisper 等 API 服务&#xff1a; &#x1f9ed; 获取 OpenAI API Key 的步骤&#xff1a; ✅ 1. 注册或登录 OpenAI 账号 打开 https://platform.openai.com/ 使用你的邮箱或 Google/…...

Flutter知识点汇总

Flutter架构解析 1. Flutter 是什么?它与其他移动开发框架有什么不同? Flutter 是 Google 开发的开源移动应用开发框架,可用于快速构建高性能、高保真的移动应用(iOS 和 Android),也支持 Web、桌面和嵌入式设备。。它与其他移动开发框架(如 React Native、Xamarin、原…...

前后端交互过程中—各类文件/图片的上传、下载、显示转换

前后端交互过程中—各类文件/图片的上传、下载、显示转换 图片补充&#xff1a;new Blob()URL.createObjectURL()替代方案&#xff1a;FileReader.readAsDataURL()​​对比&#xff1a; tiff文件TIFF库TIFF转换通过url转换tiff文件为png通过文件选择的方式转换tiff文件为png 下…...

六、【ESP32开发全栈指南:深入解析ESP32 IDF中的WiFi AP模式开发】

1. 引言&#xff1a;AP模式的核心价值 ESP32的AP&#xff08;Access Point&#xff09;模式使设备成为独立无线热点&#xff0c;适用于&#xff1a; 设备配网&#xff08;SmartConfig&#xff09;无路由器场景的本地组网数据直采终端&#xff08;传感器集中器&#xff09;临时…...

护网行动面试试题(2)

文章目录 51、常见的安全工具有哪些&#xff1f;52、说说Nmap工具的使用&#xff1f;53、近几年HW常见漏洞有哪些&#xff1f;54、HW 三&#xff08;四&#xff09;大洞56、获得文件读取漏洞&#xff0c;通常会读哪些文件57、了解过反序列化漏洞吗&#xff1f;58、常见的框架漏…...

开始在本地部署自己的 Gitea 服务器

0.简介 在软件开发和团队协作中&#xff0c;代码管理是至关重要的环节。笔者一直使用gitblit管理自己的仓库。然鹅&#xff0c;这个软件已经很久没有更新了。经过多方考察&#xff0c;发现Gitea 是一款轻量级的开源代码托管平台&#xff0c;具有易于部署、资源占用少、功能丰富…...