抬手、放手识别算法
在一款智能手表中, 平时手表处于息屏的状态, 用于节省功耗,延长使用时间。 在用户进行抬手的时候,其实是希望能够及时看一下时间、消息通知等信息的。这时手表应该能够检测到用户的抬手动作,自动进行屏幕的点亮。当用户垂手返回的时候,也应该识别到,及时进行屏幕的关闭。
对于这种动作的侦测,采用加速度传感器,是常见的选择。加速度传感采用固定的频率,进行X轴、Y轴、Z轴三轴数据的采集,放置在FIFO队列中, MCU可以定期去获取这些数据, 对于这些数据进行处理和特征识别。 当识别出抬手、放手时,进行相应的逻辑处理。
1. 数据
这个特征是怎么样的呢?我们可以先看一下,在反复进行抬手、放手动作时,所抓取到的数据。
wrist_algo_timeout_handler(82): 1730099274701: wrist: i = 0, x = -8.842969, y = 2.871094, z = 0.976172
wrist_algo_timeout_handler(82): 1730099274703: wrist: i = 1, x = -8.842969, y = 2.890234, z = 0.899609
wrist_algo_timeout_handler(82): 1730099274705: wrist: i = 2, x = -8.823829, y = 2.909375, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274707: wrist: i = 3, x = -8.862109, y = 2.928516, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274710: wrist: i = 4, x = -8.900391, y = 2.947656, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274712: wrist: i = 5, x = -8.900391, y = 2.966797, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274714: wrist: i = 6, x = -8.900391, y = 2.966797, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274716: wrist: i = 7, x = -8.881250, y = 2.909375, z = 0.842188
wrist_algo_timeout_handler(82): 1730099274719: wrist: i = 8, x = -8.919532, y = 2.947656, z = 0.842188
wrist_algo_timeout_handler(82): 1730099274721: wrist: i = 9, x = -8.919532, y = 2.966797, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274723: wrist: i = 10, x = -8.957812, y = 2.966797, z = 0.899609
wrist_algo_timeout_handler(82): 1730099274726: wrist: i = 11, x = -8.900391, y = 2.928516, z = 0.899609
wrist_algo_timeout_handler(82): 1730099274728: wrist: i = 12, x = -8.938672, y = 2.947656, z = 0.880469
wrist_algo_timeout_handler(82): 1730099274730: wrist: i = 13, x = -8.957812, y = 2.909375, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274733: wrist: i = 14, x = -8.957812, y = 2.928516, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274735: wrist: i = 15, x = -8.976954, y = 2.966797, z = 0.880469
wrist_algo_timeout_handler(82): 1730099274737: wrist: i = 16, x = -8.996094, y = 3.005078, z = 0.823047
wrist_algo_timeout_handler(82): 1730099274739: wrist: i = 17, x = -9.034375, y = 3.024219, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274742: wrist: i = 18, x = -8.957812, y = 3.062500, z = 0.861328
wrist_algo_timeout_handler(82): 1730099274744: wrist: i = 19, x = -8.996094, y = 3.062500, z = 0.880469
wrist_algo_timeout_handler(82): 1730099274746: wrist: i = 20, x = -8.919532, y = 3.024219, z = 0.880469
wrist_algo_timeout_handler(82): 1730099274749: wrist: i = 21, x = -8.900391, y = 3.043360, z = 0.880469
wrist_algo_timeout_handler(82): 1730099274751: wrist: i = 22, x = -8.919532, y = 3.024219, z = 0.880469
wrist_algo_timeout_handler(82): 1730099274753: wrist: i = 23, x = -8.996094, y = 3.043360, z = 0.899609
wrist_algo_timeout_handler(82): 1730099274756: wrist: i = 24, x = -8.938672, y = 3.043360, z = 0.995313
wrist_algo_timeout_handler(82): 1730099275212: wrist: i = 0, x = -8.919532, y = 3.005078, z = 1.014453
wrist_algo_timeout_handler(82): 1730099275214: wrist: i = 1, x = -8.976954, y = 3.024219, z = 1.033594
wrist_algo_timeout_handler(82): 1730099275216: wrist: i = 2, x = -8.919532, y = 3.005078, z = 1.033594
wrist_algo_timeout_handler(82): 1730099275218: wrist: i = 3, x = -8.900391, y = 3.024219, z = 1.052734
wrist_algo_timeout_handler(82): 1730099275221: wrist: i = 4, x = -8.881250, y = 2.947656, z = 1.014453
wrist_algo_timeout_handler(82): 1730099275223: wrist: i = 5, x = -8.862109, y = 2.947656, z = 1.014453
wrist_algo_timeout_handler(82): 1730099275225: wrist: i = 6, x = -8.938672, y = 2.966797, z = 0.995313
wrist_algo_timeout_handler(82): 1730099275228: wrist: i = 7, x = -8.976954, y = 3.005078, z = 0.976172
wrist_algo_timeout_handler(82): 1730099275230: wrist: i = 8, x = -8.957812, y = 3.005078, z = 0.995313
wrist_algo_timeout_handler(82): 1730099275232: wrist: i = 9, x = -8.957812, y = 2.966797, z = 0.957031......................................................
2. 波形
对于三轴的数据, 我们可以进行波形绘制, 观察出具体的特征。
import os
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MultipleLocator#从Log中解析出来X、Y、Z三轴的原始数据
raw_data_file = "data/data.txt"
count = 0
lineNo = 0
listX = []
listY = []
listZ = []
listV = []with open(raw_data_file, 'r', encoding='utf-8') as fread:for text in fread.readlines():lineNo += 1xyz = text.split(',')xyz.pop(0)x = xyz.pop(0)y = xyz.pop(0)z = xyz.pop(0)dataX = float(x[4:])dataY = float(y[4:])dataZ = float(z[4:])dataV = np.sqrt(dataX*dataX + dataY*dataY +dataZ*dataZ)listX.append(dataX)listY.append(dataY)listZ.append(dataZ)listV.append(dataV)count += 1print("count no : " + str(count))plt.figure()
ax=plt.subplot(1,1,1)
ax.plot(listX[0:count], label='X', color='red')
ax.plot(listY[0:count], label='Y', color='blue')
ax.plot(listZ[0:count], label='Z', color='green')ax.grid(True)
ax.xaxis.set_major_locator(MultipleLocator(10))
ax.yaxis.set_major_locator(MultipleLocator(1))
plt.show()
具体的波形,可以如下图:
.
可以截取一段,看得更加清楚:
3. 算法
主要的算法依据是,当手臂下垂时,假设X轴垂直于表盘,Z轴垂直于地面,如果处于静止状态,则X轴的值为0g, Z轴为1g,当抬手转动到用户面前的时候,这时,X轴的值为1g,Z轴的值为0g, 当垂手灭屏的时候,与之相反,所以,需要重点关注两个轴向的数据变化,则可以实现抬手、垂手这两个动作的识别。
下面我们介绍采用代码进行动作识别的过程。
# 1. 进行滤波
# 2. 进行动态阈值
# 3. 进行动态精度
# 4. 判断峰值,侦测动作类型
一些全局的变量定义如下:
class peak_value:def __init__(self):self.newMax = 0.0self.newMin = 0.0self.oldMax = 0.0self.oldMin = 0.0SAMPLE_SIZE = 100
DYNAMIC_PRECISION = 0.01
FILTER_CNT = 4
NULL = 0
UP = 1
DOWN = 2
MAXTIMEOUT = 10 #翻腕时间阈值设定为400ms
THRESHOLD = 2.0 #翻腕的值应该超过1.0g
DELAYCOUNT = 10 #应该延迟几个点进行判断
filtered_sample_x = 0.0
filter_fifo_x = []
filtered_sample_z = 0.0
filter_fifo_z = []
peak_x = peak_value()
peak_z = peak_value()
threshold_x = 0.0
threshold_z = 0.0
th_x = []
th_z = []
sample_size_x = 0
sample_size_z = 0
newSample_x = 0.0
oldSample_x = 0.0
newSample_z = 0.0
oldSample_z = 0.0
hand_on = 0
hand_off = 0
timeCount = 0
lastTimeCount_x = 0
lastTimeCount_z = 0
timeInterval_x = 0
timeInterval_z = 0
x_status = NULL
z_status = NULLdef MAX(a, b):if (a>b):return aelse:return bdef MIN(a, b):if (a<b):return aelse:return b
3.1 滤波
滤波的方式有很多种, 在这里我们采用均值滤波, 可以消除一下毛刺。不能过滤的过于平滑, 会失去特征。
#进行均值滤波
def filter_calculate_x(sample_x):global filtered_sample_x, filter_fifo_xfilter_fifo_x.pop(0)filter_fifo_x.append(sample_x)x_sum = 0.0for i in range(0, FILTER_CNT):x_sum += filter_fifo_x[i]filtered_sample_x = x_sum/FILTER_CNTdef filter_calculate_z(sample_z):global filtered_sample_z, filter_fifo_zfilter_fifo_z.pop(0)filter_fifo_z.append(sample_z)z_sum = 0.0for i in range(0, FILTER_CNT):z_sum += filter_fifo_z[i]filtered_sample_z = z_sum/FILTER_CNT
3.2 动态阈值
一个轴向上从0G到1G,另一个轴向上从1G到0G,这是比较理想的情况, 其实用户在佩戴过程中, 是不会有这么准确的值的。应该是采用动态阈值的情况,不能采用绝对的值。
#采用设置动态阈值的方式
sample_fifo_x = []
def peak_update_x(cur_sample_x):global sample_size_x, peak_x, threshold_x, sample_fifo_xsample_fifo_x.append(cur_sample_x)sample_size_x += 1if (sample_size_x >= SAMPLE_SIZE):peak_x.newMax = sample_fifo_x[0]peak_x.newMin = sample_fifo_x[0]for i in range(0, SAMPLE_SIZE):peak_x.newMax = MAX(peak_x.newMax, sample_fifo_x[i])peak_x.newMin = MIN(peak_x.newMin, sample_fifo_x[i])peak_x.oldMax = peak_x.newMaxpeak_x.oldMin = peak_x.newMinthreshold_x = (peak_x.oldMax + peak_x.oldMin)/2sample_fifo_x.pop(0)sample_fifo_z = []
def peak_update_z(cur_sample_z):global sample_size_z, peak_z, threshold_z, sample_fifo_zsample_fifo_z.append(cur_sample_z)sample_size_z += 1if (sample_size_z >= SAMPLE_SIZE):peak_z.newMax = sample_fifo_z[0]peak_z.newMin = sample_fifo_z[0]for i in range(0, SAMPLE_SIZE):peak_z.newMax = MAX(peak_z.newMax, sample_fifo_z[i])peak_z.newMin = MIN(peak_z.newMin, sample_fifo_z[i])peak_z.oldMax = peak_z.newMaxpeak_z.oldMin = peak_z.newMinthreshold_z = (peak_z.oldMax + peak_z.oldMin)/2sample_fifo_z.pop(0)
3.3 动态精度
对于相邻的点,如果变化很小, 可以丢弃掉。
#动态精度
def slide_update_x(cur_sample_x):res = Falseglobal newSample_x, oldSample_xif (abs(cur_sample_x - newSample_x) > DYNAMIC_PRECISION):oldSample_x = newSample_xnewSample_x = cur_sample_xres = Trueelse:oldSample_x = newSample_xreturn resdef slide_update_z(cur_sample_z):res = Falseglobal newSample_z, oldSample_zif (abs(cur_sample_z - newSample_z) > DYNAMIC_PRECISION):oldSample_z = newSample_znewSample_z = cur_sample_zres = Trueelse:oldSample_z = newSample_zreturn res
3.4 动作识别
对于一段数据,设置完阈值后,进行两轴向数据的判断,从而识别出抬手、放手的动作。
#姿态判断
def detect_tilt():global hand_on, hand_off, oldSample_x, oldSample_z, newSample_x, newSample_z, threshold_x, threshold_z, lastTimeCount_x, lastTimeCount_z, timeInterval_x, timeInterval_z, x_status, z_status, timeCounttimeInterval_x = timeCount - lastTimeCount_xtimeInterval_z = timeCount - lastTimeCount_zif (timeInterval_x > MAXTIMEOUT):x_status = NULLif (timeInterval_z > MAXTIMEOUT):z_status = NULLif (np.abs(newSample_x - peak_x.oldMax) >= THRESHOLD or np.abs(newSample_x - peak_x.oldMin) >= THRESHOLD):if (oldSample_x > threshold_x and newSample_x < threshold_x):x_status = DOWNlastTimeCount_x = timeCount#print("x down : " + str(timeCount))if (oldSample_x < threshold_x and newSample_x > threshold_x):x_status = UPlastTimeCount_x = timeCount#print("x up : " + str(timeCount))if (np.abs(newSample_z - peak_z.oldMax)>= THRESHOLD or np.abs(newSample_z - peak_z.oldMin) >= THRESHOLD):if (oldSample_z > threshold_z and newSample_z < threshold_z):z_status = DOWNlastTimeCount_z = timeCount#print("z down : " + str(timeCount))if (oldSample_z < threshold_z and newSample_z > threshold_z):z_status = UPlastTimeCount_z = timeCount#print("z up : " + str(timeCount))if (x_status == UP and z_status == DOWN):hand_on += 1print("timeCount : " + str(timeCount))print("hand on : " + str(hand_on))x_status = NULLz_status = NULLif (x_status == DOWN and z_status == UP):hand_off += 1print("timeCount : " + str(timeCount) )print("hand off : " + str(hand_off))x_status = NULLz_status = NULL
这几个函数的具体调用过程,如下:
#进行第一次X轴、Z轴阈值设定
peak_x.newMax = listX[0]
peak_x.newMin = listX[0]
peak_x.oldMax = listX[0]
peak_x.oldMin = listX[0]peak_z.newMax = listZ[0]
peak_z.newMin = listZ[0]
peak_z.oldMax = listZ[0]
peak_z.oldMin = listZ[0]for i in range(0, SAMPLE_SIZE):cur_sample_x = listX[i]cur_sample_z = listZ[i]peak_update_x(cur_sample_x)peak_update_z(cur_sample_z)#设定第一个滤波器的数据
for i in range(0, FILTER_CNT):cur_sample_x = listX[i]cur_sample_z = listZ[i]filter_fifo_x.append(cur_sample_x)filter_fifo_z.append(cur_sample_z)#循环获取Sample的点, 进行动态阈值的更新, 抬手+垂手动作姿势的侦测
mean_listX = []
mean_listY = []
mean_listZ = []listX_buffer = []
listZ_buffer = []for i in range(0, count):timeCount += 1cur_sample_x = listX[i]cur_sample_z = listZ[i]filter_calculate_x(cur_sample_x)filter_calculate_z(cur_sample_z)peak_update_x(filtered_sample_x)peak_update_z(filtered_sample_z)th_x.append(threshold_x)th_z.append(threshold_z)listX_buffer.append(filtered_sample_x)listZ_buffer.append(filtered_sample_z)if (timeCount > DELAYCOUNT):x = listX_buffer.pop(0)z = listZ_buffer.pop(0)mean_listX.append(x)mean_listZ.append(z)slide_update_x(x)slide_update_z(z)detect_tilt()print("hand on : " + str(hand_on))
print("hand off : " + str(hand_off))
3.5 波形示意
可以把增加了动态阈值,和滤波后的波形,与原始波形进行对比, 如下所示:
#绘制波形
#前面几个值要补齐
for i in range(0, DELAYCOUNT):mean_listX.insert(0, 0.0)mean_listZ.insert(0, 0.0)count = len(mean_listX)
plt.figure()
ax=plt.subplot(1,1,1)
ax.plot(mean_listX[0:count], label='X', color='red')
ax.plot(th_x[0:count], ls = "--", label='th_x', color = 'red')
ax.plot(mean_listZ[0:count], label='Z', color='green')
ax.plot(th_z[0:count], ls = "--", label='th_z', color = 'green')
ax.grid(True)
ax.xaxis.set_major_locator(MultipleLocator(10))
ax.yaxis.set_major_locator(MultipleLocator(1))
plt.show()
相关文章:

抬手、放手识别算法
在一款智能手表中, 平时手表处于息屏的状态, 用于节省功耗,延长使用时间。 在用户进行抬手的时候,其实是希望能够及时看一下时间、消息通知等信息的。这时手表应该能够检测到用户的抬手动作,自动进行屏幕的点亮。当用户…...

深度学习篇---AnacondaLabelImg
文章目录 前言第一部分:Anaconda是什么?1.简介2.特点(1)包管理器Conda(2)环境管理(3)预装包(4)跨平台(5)社区支持 3.安装WindowsLinux…...
探索云原生可观测性:技术与团队协作的深度结合
TheNewStack 出品的电子书《Cloud Native Observability for DevOps Teams》读后感,老书新读,还是另有一番领悟。 阅读原文请转到:https://jimmysong.io/blog/cloud-native-observability-devops/ 最近读了 TheNewStack 发布的电子书《Cloud …...
解决 Django 5.1 中的 TemplateSyntaxError 错误
解决 Django 5.1 中的 TemplateSyntaxError 错误 在 Django 开发过程中,我们经常会遇到 TemplateSyntaxError 错误,尤其是在模板文件中使用不被支持或错误的模板标签时。最近,我们遇到的一个常见错误是: Invalid block tag on l…...

基于SSM的自助购药小程序设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...

04JavaWeb——Maven-SpringBootWeb入门
Maven 课程内容 初识Maven Maven概述 Maven模型介绍 Maven仓库介绍 Maven安装与配置 IDEA集成Maven 依赖管理 01. Maven课程介绍 1.1 课程安排 学习完前端Web开发技术后,我们即将开始学习后端Web开发技术。做为一名Java开发工程师,后端Web开发…...

场馆预定平台高并发时间段预定实现V2
🎯 本文档介绍了场馆预订系统接口V2的设计与实现,旨在解决V1版本中库存数据不一致及性能瓶颈的问题。通过引入令牌机制确保缓存和数据库库存的最终一致性,避免因服务器故障导致的库存错误占用问题。同时,采用消息队列异步处理库存…...
如何利用边缘节点服务打造极致用户体验?
随着互联网和数字化技术的飞速发展,用户对网络访问速度和服务体验的要求也在不断提高。在一个信息快速传播的时代,延迟过高或访问卡顿的问题会直接影响用户体验,甚至导致用户流失。因此,企业如何优化网络性能、提升用户访问速度&a…...

C语言之小型成绩管理系统
🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 C语言之小型成绩管理系统 目录 设计题目设计目的设计任务描述设计要求输入和输出要求验收要…...
ASP.NET Core 中基于 Cookie 的身份鉴权实现
在 ASP.NET Core 应用中,基于 Cookie 的身份鉴权是一种常见的身份验证方式,特别适用于传统的 Web 应用程序。Cookie 能够在用户的浏览器中存储身份验证数据,从而在用户访问应用的不同页面时保持登录状态。 一、配置 Cookie 身份验证 首先&a…...
为什么要学习C++?
在编程语言的广阔天地中,C 以其独特的魅力和强大的功能占据着重要的一席之地。尽管它并非新兴的热门语言,学习曲线也相对陡峭,但这丝毫没有阻挡开发者们对它的热情。那么,究竟为什么要学习 C 呢?接下来,我们…...
freecad1.0的编译
最近freecad发布了1.0版本,通常意义上,1.0也代表了稳定版本的发布。但是在编译的过程中遇到很多问题,再次做下记录,以便后续再编译时有参考。 1 freecad1.0编译环境 参考:https://blog.csdn.net/qq_26221775/article/details/144406212 环境:vs2022,win10,camke3.26.4;…...

汇编与逆向(一)-汇编工具简介
RadASM是一款著名的WIN32汇编编辑器,支持MASM、TASM等多种汇编编译器,Windows界面,支持语法高亮,自带一个资源编辑器和一个调试器。 一、汇编IDE工具:RadASM RadASM有内置的语言包 下载地址:RadASM asse…...
.NET Framework
.NET Framework 是微软推出的一个软件开发平台,主要用于构建和运行 Windows 应用程序。它是 .NET 生态系统的早期版本,专注于 Windows 平台,并提供了丰富的类库和运行时环境。 注意事项 跨平台限制:.NET Framework 主要适用于 W…...

LabVIEW太赫兹二维扫描成像系统
使用LabVIEW设计太赫兹二维扫描成像系统。通过LabVIEW平台开发,结合硬件如太赫兹源、平移台、锁相放大器等,实现了高效、精准的成像功能。系统采用蛇形扫描方式,通过动态调整扫描参数,达到优化成像质量的目的。 项目背景 在非…...
图片专栏——概念
欢迎来到图片世界,大家一起学习交流! 1. 像素(Pixel) 定义:像素是图像的最小单位,是“图像元素”的缩写。你可以把像素想象成拼图中的一个最小块,无数个像素组合在一起就形成了完整的图像。作用ÿ…...

Linux内存管理(Linux内存架构,malloc,slab的实现)
文章目录 前言一、Linux进程空间内存分配二、malloc的实现机理三、物理内存与虚拟内存1.物理内存2.虚拟内存 四、磁盘和物理内存区别五、页页的基本概念:分页管理的核心概念:Linux 中分页的实现:总结: 六、伙伴算法伙伴算法的核心…...

【C++】模板(进阶)
本篇我们来介绍更多关于C模板的知识。模板初阶移步至:【C】模板(初阶) 1.非类型模板参数 1.1 非类型模板参数介绍 模板参数可以是类型形参,也可以是非类型形参。类型形参就是我们目前接触到的一些模板参数。 //类型模板参数 …...

Esxi下虚拟机磁盘类型厚置备改精简置备
Esxi虚拟机磁盘类型厚置备改精简置备 一、esxi报错磁盘不足 1.1、虚拟机报错磁盘不足 1.2、虚拟机磁盘类型 VMware vSphere 中有两种主要类型的虚拟硬盘:精简配置磁盘和厚置备磁盘。 厚置备磁盘有两种分配模型:厚置备延迟置零和厚置备置零。 三者比…...
Element使用表单重置如果不使用prop,重置无法生效
文章目录 为什么需要 prop?示例:使用 prop 的正确方式关键点总结 在 element-ui 的 el-form 组件中, prop 属性是与表单验证和表单字段绑定密切相关的,尤其在使用 resetFields() 重置表单数据时。 如果不使用 prop࿰…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...