Python + MediaPipe 手势绘画高级应用:从基础到创意交互 - 实践

news/2025/9/27 17:04:38/文章来源:https://www.cnblogs.com/ljbguanli/p/19115318

Python + MediaPipe 手势绘画高级应用:从基础到创意交互 - 实践

在计算机视觉与手势交互领域,MediaPipe 凭借其轻量、高效的姿态/手势识别能力,成为开发创意应用的热门工具。本文将带大家突破“基础手势跟踪”的局限,掌握 **手势绘画的高级技巧**——包括动态笔触控制、多手势协同交互、画布分层管理,最终实现一个可通过手势“隔空作画”的交互式应用。文中附完整代码与效果演示,零基础也能快速上手。

一、核心技术栈与原理

在开始前,先明确我们用到的工具和核心逻辑,避免后续开发“知其然不知其所以然”。

1. 技术栈选型

  • Python 3.8+:主开发语言,生态丰富且易上手;

  • MediaPipe Hands:谷歌开源的手势识别库,可实时检测21个手部关键点(如指尖、指节);

  • OpenCV-Python:负责摄像头捕获、图像渲染与画布绘制;

  • NumPy:处理手部关键点坐标计算(如距离、角度)。

2. 手势绘画核心原理

MediaPipe Hands 会将每个手部关键点映射为屏幕坐标系中的 (x, y) 坐标。我们通过**解析关键点的位置关系**,判断用户的“绘画意图”:

  • 例1:当拇指与食指指尖距离小于阈值 → 判定为“选中画笔”,移动时绘制轨迹;

  • 例2:当五指张开 → 判定为“清空画布”;

  • 例3:当无名指弯曲、其他手指伸直 → 判定为“切换画笔颜色”。

通过这种“关键点关系→手势指令→画布操作”的映射,实现“无接触绘画”。

二、基础准备:环境搭建与核心函数

首先完成环境配置,并封装2个核心工具函数(手部检测、坐标转换),为后续高级功能打基础。

1. 环境安装

打开终端,执行以下命令安装依赖:

pip install mediapipe opencv-python numpy

2. 核心工具函数封装

创建 hand_utils.py 文件,封装手部检测和坐标转换逻辑(避免主代码冗余):

import mediapipe as mp
import numpy as np
# 初始化 MediaPipe Hands
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
class HandDetector:def __init__(self, max_num_hands=1, min_detection_confidence=0.7, min_tracking_confidence=0.7):"""初始化手势检测器:param max_num_hands: 最大检测手数(默认1,避免多手干扰):param min_detection_confidence: 检测置信度阈值:param min_tracking_confidence: 跟踪置信度阈值"""self.hands = mp_hands.Hands(max_num_hands=max_num_hands,min_detection_confidence=min_detection_confidence,min_tracking_confidence=min_tracking_confidence)def detect_hands(self, frame):"""检测图像中的手部关键点:param frame: OpenCV 读取的 BGR 图像(需转 RGB):return: 处理后的图像、手部关键点列表(含坐标)"""# BGR → RGB(MediaPipe 要求输入为 RGB)rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 禁用写操作(提升性能)rgb_frame.flags.writeable = False# 检测手部results = self.hands.process(rgb_frame)# 恢复写操作(后续绘制用)rgb_frame.flags.writeable = True# 存储关键点坐标(屏幕坐标系)hand_landmarks = []if results.multi_hand_landmarks:for hand_lm in results.multi_hand_landmarks:# 绘制关键点(可选,调试用)mp_drawing.draw_landmarks(frame, hand_lm, mp_hands.HAND_CONNECTIONS,mp_drawing.DrawingSpec(color=(0,255,0), thickness=2, circle_radius=2),mp_drawing.DrawingSpec(color=(0,0,255), thickness=2))# 提取关键点坐标(转换为屏幕像素值)h, w, _ = frame.shapelm_list = [(int(lm.x * w), int(lm.y * h)) for lm in hand_lm.landmark]hand_landmarks.append(lm_list)return frame, hand_landmarks
def calculate_distance(point1, point2):"""计算两点间欧氏距离(用于判断手指开合)"""return np.sqrt((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2)

三、高级技巧实战:5个核心功能实现

基础工具就绪后,我们逐一实现手势绘画的高级功能。最终效果是:**通过拇指+食指控制画笔,中指切换颜色,五指张开清空画布,握拳保存图片**。

1. 技巧1:动态笔触(根据手指距离调整画笔粗细)

传统手势绘画的笔触粗细固定,体验生硬。我们可以通过**拇指与食指的距离**动态调整画笔粗细——距离越远,笔触越粗;距离越近,笔触越细。

核心逻辑
  • 计算拇指尖(关键点4)与食指尖(关键点8)的距离 dist

  • 将距离映射到 [2, 20] 的画笔粗细范围(避免过细或过粗);

  • 移动时,根据实时距离更新画笔粗细。

代码实现(片段)
# 假设 hand_lm 是当前手部关键点列表(来自 HandDetector)
thumb_tip = hand_lm[4]   # 拇指尖
index_tip = hand_lm[8]   # 食指尖
dist = calculate_distance(thumb_tip, index_tip)
# 距离映射为画笔粗细(dist范围:20~200 → 粗细2~20)
brush_thickness = int(np.interp(dist, [20, 200], [2, 20]))

2. 技巧2:多手势协同(绘画/切换/清空/保存)

通过解析不同手指的状态,实现多指令协同——避免依赖键盘/鼠标,纯手势操作更自然。

手势指令定义

先明确4个核心手势的判定规则(基于 MediaPipe 21个关键点):

功能

手势判定规则

绘画

拇指与食指距离 < 30(“捏合”状态),且其他手指弯曲(避免误触)

切换颜色

中指伸直(关键点12的y坐标 < 关键点10的y坐标),其他手指保持绘画姿势

清空画布

五指均伸直(拇指尖y < 指节y,其他指尖y < 对应指节y)

保存图片

握拳(所有指尖y > 对应指节y,且拇指与食指距离 > 50)

代码实现(片段)
def is_drawing(hand_lm):"""判定是否为“绘画手势”:拇指+食指捏合,其他手指弯曲"""thumb_tip = hand_lm[4]index_tip = hand_lm[8]# 拇指与食指距离 < 30(捏合)if calculate_distance(thumb_tip, index_tip) > 30:return False# 中指、无名指、小指弯曲(指尖y > 指节y)middle_tip = hand_lm[12]middle_mcp = hand_lm[10]  # 中指掌指关节ring_tip = hand_lm[16]ring_mcp = hand_lm[14]pinky_tip = hand_lm[20]pinky_mcp = hand_lm[18]if (middle_tip[1] < middle_mcp[1]) or (ring_tip[1] < ring_mcp[1]) or (pinky_tip[1] < pinky_mcp[1]):return Falsereturn True
def is_switch_color(hand_lm):"""判定是否为“切换颜色手势”:中指伸直"""if not is_drawing(hand_lm):return Falsemiddle_tip = hand_lm[12]middle_mcp = hand_lm[10]return middle_tip[1] < middle_mcp[1]  # 中指指尖高于掌指关节(伸直)
def is_clear_canvas(hand_lm):"""判定是否为“清空画布手势”:五指伸直"""# 拇指伸直(指尖x < 指节x,因拇指方向与其他手指不同)thumb_tip = hand_lm[4]thumb_ip = hand_lm[3]    # 拇指指间关节if thumb_tip[0] > thumb_ip[0]:return False# 其他四指伸直(指尖y < 掌指关节y)fingers = [(8,10), (12,14), (16,18), (20,22)]  # (指尖, 掌指关节)for tip_idx, mcp_idx in fingers:if hand_lm[tip_idx][1] > hand_lm[mcp_idx][1]:return Falsereturn True
def is_save_image(hand_lm):"""判定是否为“保存图片手势”:握拳"""# 所有指尖y > 对应掌指关节y(弯曲)fingers = [(4,2), (8,6), (12,10), (16,14), (20,18)]for tip_idx, mcp_idx in fingers:if hand_lm[tip_idx][1] < hand_lm[mcp_idx][1]:return False# 拇指与食指距离 > 50(避免与“绘画捏合”混淆)if calculate_distance(hand_lm[4], hand_lm[8]) < 50:return Falsereturn True

3. 技巧3:画布分层管理(避免画面混乱)

如果直接在摄像头帧上绘画,画面会随摄像头移动而“抖动”。我们可以创建一个**独立的画布层**,将绘画轨迹保存在画布上,再与摄像头帧叠加显示——实现“固定画布+动态手势”的效果。

代码实现(片段)
import cv2
import time
from hand_utils import HandDetector, calculate_distance
# 初始化画布(与摄像头分辨率一致,黑色背景)
cap = cv2.VideoCapture(0)  # 0表示默认摄像头
ret, frame = cap.read()
if not ret:raise Exception("无法打开摄像头")
h, w, _ = frame.shape
canvas = np.zeros((h, w, 3), dtype=np.uint8)  # 黑色画布
# 初始化画笔参数
current_color = (255, 0, 0)  # 初始颜色:蓝色
color_list = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255)]  # 颜色列表
color_idx = 0
prev_pos = None  # 上一帧画笔位置(用于绘制连续轨迹)
detector = HandDetector()
# 主循环
while cap.isOpened():ret, frame = cap.read()if not ret:break# 水平翻转帧(镜像效果,操作更直观)frame = cv2.flip(frame, 1)# 检测手部关键点frame, hand_landmarks = detector.detect_hands(frame)if hand_landmarks:hand_lm = hand_landmarks[0]  # 只处理第一只手current_pos = hand_lm[8]     # 画笔位置:食指尖# 1. 清空画布if is_clear_canvas(hand_lm):canvas = np.zeros((h, w, 3), dtype=np.uint8)time.sleep(0.5)  # 防抖(避免误触多次清空)prev_pos = None# 2. 保存图片elif is_save_image(hand_lm):save_path = f"hand_drawing_{time.time()}.png"cv2.imwrite(save_path, canvas)print(f"图片已保存至:{save_path}")# 在帧上显示提示cv2.putText(frame, "Saved!", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)time.sleep(1)  # 防抖# 3. 切换颜色elif is_switch_color(hand_lm):color_idx = (color_idx + 1) % len(color_list)current_color = color_list[color_idx]# 在帧上显示当前颜色cv2.circle(frame, (50, 100), 20, current_color, -1)time.sleep(0.5)  # 防抖# 4. 绘画(连续轨迹)elif is_drawing(hand_lm):# 计算动态画笔粗细dist = calculate_distance(hand_lm[4], hand_lm[8])brush_thickness = int(np.interp(dist, [20, 200], [2, 20]))# 绘制线段(上一位置→当前位置)if prev_pos is not None:cv2.line(canvas, prev_pos, current_pos, current_color, brush_thickness)prev_pos = current_pos  # 更新上一位置# 非绘画状态:重置上一位置else:prev_pos = None# 叠加画布与摄像头帧(半透明效果,更美观)combined_frame = cv2.addWeighted(frame, 0.7, canvas, 0.3, 0)# 显示操作提示cv2.putText(combined_frame, "Pinch: Draw | Open Hand: Clear | Fist: Save",(10, h-20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1)# 显示窗口cv2.imshow("Hand Drawing (Press 'q' to quit)", combined_frame)cv2.imshow("Canvas", canvas)  # 单独显示画布(可选)# 按 'q' 退出if cv2.waitKey(1) & 0xFF == ord('q'):break
# 释放资源
cap.release()
cv2.destroyAllWindows()

4. 技巧4:防抖动处理(避免误操作)

手势识别中,手指轻微抖动可能导致“误触发”(如误判“清空画布”)。我们通过2种方式防抖:

  1. 时间防抖:触发指令后延迟0.5~1秒,期间不响应同指令(如 time.sleep(0.5));

  2. 多帧验证:连续2~3帧检测到同一手势,才执行指令(进阶优化,代码可扩展)。

5. 技巧5:镜像显示与视觉反馈

为提升用户体验,增加2个细节优化:

  • 镜像显示:用 cv2.flip(frame, 1) 水平翻转摄像头帧,让手势操作与屏幕显示“同步”(就像照镜子);

  • 视觉反馈

    • 切换颜色时,在屏幕左上角画一个彩色圆点,提示当前颜色;

    • 保存图片时,显示“Saved!”文字;

    • 绘制时,实时显示画笔轨迹(画布与帧叠加)。

四、效果演示与优化方向

1. 效果展示(图文说明)

功能场景

实际效果描述

示意图(文字描述)

动态笔触绘画

拇指与食指捏合,移动时绘制蓝色轨迹;手指张开一点,笔触变粗;靠近一点,笔触变细

屏幕显示:蓝色线条,粗细随手指距离变化

切换颜色

保持绘画姿势,伸直中指 → 颜色从蓝色切换为绿色,左上角出现绿色圆点提示

左上角:绿色圆点;画布轨迹:从蓝变绿

清空画布

五指完全张开 → 画布瞬间变黑(所有轨迹清除)

画布:从有图案变为纯黑色

保存图片

握拳 → 控制台打印保存路径,屏幕显示“Saved!”,画布图片保存到本地

屏幕:“Saved!”文字;本地:新增 PNG 文件

2. 进阶优化方向

如果想进一步提升应用体验,可以尝试以下方向:

  • 多手协同:支持左手控制颜色/粗细,右手绘画(修改 HandDetectormax_num_hands=2);

  • 形状识别:通过关键点识别“圆形”“方形”手势,自动绘制对应图形;

  • 撤销功能:记录画布历史状态,通过“双击手势”实现撤销上一步;

  • 背景虚化:用 MediaPipe Selfie Segmentation 虚化摄像头背景,突出手势与画布;

  • 导出视频:用 OpenCV 录制绘画过程,生成 MP4 视频。

五、完整代码汇总

将上述代码整合为一个完整文件 hand_drawing.py,直接运行即可:

import cv2
import time
import numpy as np
import mediapipe as mp
# ---------------------- 初始化 MediaPipe Hands ----------------------
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
class HandDetector:def __init__(self, max_num_hands=1, min_detection_confidence=0.7, min_tracking_confidence=0.7):self.hands = mp_hands.Hands(max_num_hands=max_num_hands,min_detection_confidence=min_detection_confidence,min_tracking_confidence=min_tracking_confidence)def detect_hands(self, frame):rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)rgb_frame.flags.writeable = Falseresults = self.hands.process(rgb_frame)rgb_frame.flags.writeable = Truehand_landmarks = []if results.multi_hand_landmarks:for hand_lm in results.multi_hand_landmarks:mp_drawing.draw_landmarks(frame, hand_lm, mp_hands.HAND_CONNECTIONS,mp_drawing.DrawingSpec(color=(0,255,0), thickness=2, circle_radius=2),mp_drawing.DrawingSpec(color=(0,0,255), thickness=2))h, w, _ = frame.shapelm_list = [(int(lm.x * w), int(lm.y * h)) for lm in hand_lm.landmark]hand_landmarks.append(lm_list)return frame, hand_landmarks
# ---------------------- 辅助函数 ----------------------
def calculate_distance(point1, point2):return np.sqrt((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2)
def is_drawing(hand_lm):thumb_tip = hand_lm[4]index_tip = hand_lm[8]if calculate_distance(thumb_tip, index_tip) > 30:return Falsemiddle_tip = hand_lm[12]middle_mcp = hand_lm[10]ring_tip = hand_lm[16]ring_mcp = hand_lm[14]pinky_tip = hand_lm[20]pinky_mcp = hand_lm[18]if (middle_tip[1] < middle_mcp[1]) or (ring_tip[1] < ring_mcp[1]) or (pinky_tip[1] < pinky_mcp[1]):return Falsereturn True
def is_switch_color(hand_lm):if not is_drawing(hand_lm):return Falsemiddle_tip = hand_lm[12]middle_mcp = hand_lm[10]return middle_tip[1] < middle_mcp[1]
def is_clear_canvas(hand_lm):thumb_tip = hand_lm[4]thumb_ip = hand_lm[3]if thumb_tip[0] > thumb_ip[0]:return Falsefingers = [(8,10), (12,14), (16,18), (20,22)]for tip_idx, mcp_idx in fingers:if hand_lm[tip_idx][1] > hand_lm[mcp_idx][1]:return Falsereturn True
def is_save_image(hand_lm):fingers = [(4,2), (8,6), (12,10), (16,14), (20,18)]for tip_idx, mcp_idx in fingers:if hand_lm[tip_idx][1] < hand_lm[mcp_idx][1]:return Falseif calculate_distance(hand_lm[4], hand_lm[8]) < 50:return Falsereturn True
# ---------------------- 主程序 ----------------------
if __name__ == "__main__":# 初始化摄像头与画布cap = cv2.VideoCapture(0)ret, frame = cap.read()if not ret:raise Exception("无法打开摄像头,请检查设备连接")h, w, _ = frame.shapecanvas = np.zeros((h, w, 3), dtype=np.uint8)# 画笔参数color_list = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255)]color_idx = 0current_color = color_list[color_idx]prev_pos = Nonedetector = HandDetector()# 主循环while cap.isOpened():ret, frame = cap.read()if not ret:breakframe = cv2.flip(frame, 1)frame, hand_landmarks = detector.detect_hands(frame)if hand_landmarks:hand_lm = hand_landmarks[0]current_pos = hand_lm[8]# 清空画布if is_clear_canvas(hand_lm):canvas = np.zeros((h, w, 3), dtype=np.uint8)time.sleep(0.5)prev_pos = None# 保存图片elif is_save_image(hand_lm):save_path = f"hand_drawing_{int(time.time())}.png"cv2.imwrite(save_path, canvas)cv2.putText(frame, "Saved!", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)time.sleep(1)# 切换颜色elif is_switch_color(hand_lm):color_idx = (color_idx + 1) % len(color_list)current_color = color_list[color_idx]cv2.circle(frame, (50, 100), 20, current_color, -1)time.sleep(0.5)# 绘画elif is_drawing(hand_lm):dist = calculate_distance(hand_lm[4], hand_lm[8])brush_thickness = int(np.interp(dist, [20, 200], [2, 20]))if prev_pos is not None:cv2.line(canvas, prev_pos, current_pos, current_color, brush_thickness)prev_pos = current_poselse:prev_pos = None# 叠加画布与帧combined_frame = cv2.addWeighted(frame, 0.7, canvas, 0.3, 0)# 显示提示cv2.putText(combined_frame, "Pinch:Draw | Open:Clear | Fist:Save | Middle:Color",(10, h-20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,255), 1)# 显示窗口cv2.imshow("Hand Drawing (Press 'q' to quit)", combined_frame)cv2.imshow("Canvas", canvas)if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源cap.release()cv2.destroyAllWindows()

六、运行说明

  1. 确保电脑已连接摄像头;

  2. 运行代码:python hand_drawing.py

  3. 操作指南:

    1. 拇指+食指捏合 → 移动绘制;

    2. 保持捏合,伸直中指 → 切换颜色;

    3. 五指张开 → 清空画布;

    4. 握拳 → 保存图片;

    5. q 键退出程序。

通过本文的高级技巧,你不仅能实现“隔空绘画”,更能理解 MediaPipe 手势识别的核心逻辑——在此基础上,还可以扩展出更多创意应用(如手势控制PPT、游戏交互等)。动手试试吧!

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

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

相关文章

有建设网站的软件吗吉林市最新消息今天

这是连续剧般的文章&#xff0c;请关注&#xff0c;持续更新中... 系列文章: http://t.csdnimg.cn/Os83Qhttp://t.csdnimg.cn/Os83Q这篇文章将我们的reactro转变成http服务器... HTTP HTTP介绍 HTTP是一个基于TCP通信协议的基础上的应用层协议。接下来我们需要解析HTTP请求消息…

网站怎么做百度认证做照片有那些网站好

这篇文章主要介绍了opencv python图像梯度实例详解,文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下一阶导数与Soble算子二阶导数与拉普拉斯算子图像边缘&#xff1a;Soble算子&#xff1a;二阶导数&#xff1a;拉…

天津智能网站建设制作桓台网站建设

转自&#xff1a;进阶 JavaScript 必知的 33 个点【进阶必备】 进阶 JavaScript 必知的 33 个点【进阶必备】 Original 前端小菜鸡之菜鸡互啄 前端开发爱好者 2022-04-11 08:32 收录于话题#javaScript进阶1个 点击下方“前端开发爱好者”&#xff0c;选择“设为星标” 第一…

Crypto 2021 s Accepted papers

转载自:https://crypto.iacr.org/2021/acceptedpapers.phpAccepted Papers 接收论文These papers are listed in order of submission.这些论文按提交顺序排列。White Box Traitor Tracing白盒背叛追踪 Mark Zhand…

详细介绍:【数据结构】哈希表(Hash Table)详解

详细介绍:【数据结构】哈希表(Hash Table)详解2025-09-27 16:57 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; displa…

Github 12.3kstar, 3分钟起步做中后台?Go+Vue 脚手架,把权限、代码生成、RBAC 都封装好了

嗨,我是小华同学,专注解锁高效工作与前沿AI工具!每日精选开源技术、实战技巧,助你省时50%、领先他人一步。👉免费订阅,与10万+技术人共享升级秘籍!go-admin 是一个基于 Gin + Vue 的前后端分离权限管理脚手架,…

电子商务网站建设行情建设网站的网站叫什么男

0 前言 无人驾驶技术是机器学习为主的一门前沿领域&#xff0c;在无人驾驶领域中机器学习的各种算法随处可见&#xff0c;今天学长给大家介绍无人驾驶技术中的车道线检测。 1 车道线检测 在无人驾驶领域每一个任务都是相当复杂&#xff0c;看上去无从下手。那么面对这样极其…

河南城乡建设部网站首页中国十大购物网站排行榜

题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的&#xff0c;区间右边的人往区间最右的那些空位跑&#xff0c;区间左边的人往区间最左的那些空位跑 找到这些空位就用二分 主席树 理应可以在主席树上的区间二分而做到\(O(nlogn)\)&…

苏州app制作大型网站的优化方法

网络连通性测试与网络命令验证实验报告西工大计算机网络原理实验报告网络原理实验报告实验名称&#xff1a; 网络连通性测试与网络命令验证 日期&#xff1a; 2015.11&#xff0e;09 班级&#xff1a;学号&#xff1a; 姓名&#xff1a;【一】 预习内容5个常用网络命令&#xf…

北京网站seo哪家公司好wordpress 在线教育主题

存储引擎&#xff1a; 存储引擎是Inndb。它支持行级锁&#xff0c;以及表级锁&#xff0c; 支持事务操作&#xff0c; 需要主键&#xff0c;若未声明主键&#xff0c;则会寻找表中的 not null 以及 unique 修饰的字段。若表中无此类字段&#xff0c;会隐式生成字段。 索引&…

网站需求清单如何用c 做网站

文章目录 一、softmax函数1.1 引入指数形式的优点1.2 引入指数形式的缺点 二、交叉熵损失函数2.1 交叉熵损失函数2.2 softmax与交叉熵损失 参考资料 一、softmax函数 softmax用于多分类过程中&#xff0c;它将多个神经元的输出&#xff0c;映射到&#xff08;0,1&#xff09;区…

250927

目录JT-JY5T1S1-1JT-JY5T1S1-2FT-(JY&VOAs) JT-JY5T1S1-1Good afternoon, Dream Time Travel, How can i help you? Oh, hello, i am interested in the hoilday you offer along the coast near here. Yes, we o…

Ti 毫米波雷达FFT的缩放问题

struct DPU_RangeProcHWA_FFTtuning_t{ /*! @brief Specify amount of right (divide) shift to apply to convert HWA internal 24-bit Range FFT output to 16-bit RadarCube. User should adjust this based on th…

完整教程:多线程——单例模式

完整教程:多线程——单例模式pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…

A Twisty Movement

CF933A A Twisty Movement 简化题目 给定一个有 \(1\),\(2\) 两个数字组成的数组中,选择一个子串,将 \(1\) 变成 \(2\),将 \(2\) 变成 \(1\),求出变化后的序列的最长上升子序列。 思路 简单的情况 如果没有变换操…

佛山新网站建设渠道天津工程网站建设

MySQL 中的集群部署方案 前言 这里来聊聊&#xff0c;MySQL 中常用的部署方案。 MySQL Replication MySQL Replication 是官方提供的主从同步方案&#xff0c;用于将一个 MySQL 的实例同步到另一个实例中。Replication 为保证数据安全做了重要的保证&#xff0c;是目前运用…

山东网站建设设计小清新个人网站

七、高并发内存池–Page Cache 7.1 PageCache的工作原理 PageCache是以span的大小(以页为单位)和下标一一对应为映射关系的哈希桶&#xff0c;下标是几就说明这个哈希桶下挂的span的大小就是几页的&#xff0c;是绝对映射的关系。因为PageCache也是全局只有唯一一个的&#x…

完整教程:iOS 混淆与反调试反 Hook 实战,运行时防护、注入检测与安全加固流程

完整教程:iOS 混淆与反调试反 Hook 实战,运行时防护、注入检测与安全加固流程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-f…

3.WPF - 依赖属性 - 实践

3.WPF - 依赖属性 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &q…

Attention进阶史(MHA, MQA, GQA, MLA)

在深度学习领域,注意力机制(Attention Mechanism)自诞生以来便成为推动自然语言处理和计算机视觉等任务发展的核心动力。从最初的多头注意力(MHA)到如今的高效变体,如多查询注意力(MQA)、分组查询注意力(GQA)…