AI健身体能测试之基于paddlehub实现引体向上计数个数统计

news2024/11/13 9:08:07

【引体向上计数】

本项目使用PaddleHub中的骨骼检测模型human_pose_estimation_resnet50_mpii,进行人体运动分析,实现对引体向上的自动计数。

1. 项目介绍

人体运动分析是近几年许多领域研究的热点问题。在学科的交叉研究上,人体运动分析涉及到计算机科学、运动人体科学、环境行为学和材料科学等。随着研究的深入以及计算机视觉、5G通信的飞速发展,人体运动分析技术已应用于自动驾驶、影视创作、安防异常事件监测和体育竞技分析、康复等实际场景人体运动分析已成为人工智能领域研究的前沿课题。

在体育课上,引体向上是一个常规的运动,体育老师有时需要对每位同学做引体向上项目时需要计数,那如何利用AI技术进行人体运动分析可以实现引体向上的自动计数,从而减轻老师的工作量呢?本项目我们就实现AI引体向上计数功能的实现,项目效果如下:

2.项目分析与解决方案设计

对于引体向上计数任务,首先使用录像设备将每个人的动作录制成视频,然后对视频进行拆帧拆解成多张图像,对每张图像进行人体关键骨骼点检测,然后获取每张图像的头部关键点的纵坐标,以七张图像为一个单位,判断第四张图像的头部关键骨骼关键点的纵坐标是否为七张图像中的最小值f(4)<=f(x),如果是记录为1,如果不是则记录为0,最后将记录的值进行累加,得到的值便是引体向上的数目,最后实现可视化计数,便于我们查看结果。这样我们就实现了引体向上计数!

本项目实现基本可以分为7步,分别是新建项目与数据导入、人体骨骼关键点模型的安装、模块导入、定义数据、人体骨骼点检测、将计数过程可视化、最后一步实现引体向上计数,引体向上计数就可以实现了,实现流程如下图所示:

了解了项目实现的基本流程,接下来我们就按顺序完成每一个模块功能的实现。

3.项目准备

我们要完成此项目,该做哪些准备呢? 首先是实验实施环境,本项目我们使用windows系统+nvidia RTX2070 super显卡安装环境:

aiofiles==23.2.1
aiohttp==3.9.1
aiosignal==1.3.1
altair==5.2.0
annotated-types==0.6.0
anyio==4.2.0
astor==0.8.1
async-timeout==4.0.3
attrdict==2.0.1
attrs==23.2.0
Babel==2.14.0
bce-python-sdk==0.9.2
beautifulsoup4==4.12.2
blinker==1.7.0
cachetools==5.3.2
certifi==2023.11.17
charset-normalizer==3.3.2
click==8.1.7
colorama==0.4.6
colorlog==6.8.0
contourpy==1.1.1
cssselect==1.2.0
cssutils==2.9.0
cycler==0.12.1
Cython==3.0.8
datasets==2.16.1
decorator==5.1.1
dill==0.3.4
easydict==1.11
et-xmlfile==1.1.0
exceptiongroup==1.2.0
fastapi==0.109.0
ffmpy==0.3.1
filelock==3.13.1
fire==0.5.0
Flask==3.0.0
Flask-Babel==2.0.0
fonttools==4.47.2
frozenlist==1.4.1
fsspec==2023.10.0
future==0.18.3
gradio==4.14.0
gradio_client==0.8.0
h11==0.14.0
httpcore==1.0.2
httpx==0.26.0
huggingface-hub==0.20.2
idna==3.6
imageio==2.33.1
imgaug==0.4.0
importlib-metadata==7.0.1
importlib-resources==6.1.1
itsdangerous==2.1.2
jieba==0.42.1
Jinja2==3.1.3
joblib==1.3.2
jsonschema==4.20.0
jsonschema-specifications==2023.12.1
kiwisolver==1.4.5
lanms-neo==1.0.2
lap==0.4.0
lazy_loader==0.3
lmdb==1.4.1
lxml==5.1.0
markdown-it-py==3.0.0
MarkupSafe==2.1.3
matplotlib==3.7.4
mdurl==0.1.2
motmetrics==1.4.0
multidict==6.0.4
multiprocess==0.70.12.2
networkx==3.1
numpy==1.23.5
onnx==1.15.0
opencv-contrib-python==4.6.0.66
opencv-python==4.6.0.66
openpyxl==3.1.2
opt-einsum==3.3.0
orjson==3.9.10
packaging==23.2
paddle-bfloat==0.1.7
paddle2onnx==1.0.6
paddledet==2.6.0
paddlefsl==1.1.0
paddlehub==2.4.0
paddlenlp==2.5.2
paddlepaddle-gpu==2.4.2.post117
paddleseg==2.8.0
pafy==0.5.5
pandas==2.0.3
pdf2docx==0.5.7
pillow==10.3.0
pkgutil_resolve_name==1.3.10
Polygon3==3.0.9.1
PPOCRLabel==2.1.3
premailer==3.10.0
prettytable==3.9.0
protobuf==3.20.2
psutil==5.9.7
py-cpuinfo==9.0.0
pyarrow==14.0.2
pyarrow-hotfix==0.6
pyclipper==1.3.0.post5
pycocotools==2.0.7
pycryptodome==3.20.0
pydantic==2.5.3
pydantic_core==2.14.6
pydub==0.25.1
Pygments==2.17.2
PyMuPDF==1.20.2
pyparsing==3.1.1
PyQt5==5.15.10
PyQt5-Qt5==5.15.2
PyQt5-sip==12.13.0
python-dateutil==2.8.2
python-docx==1.1.0
python-multipart==0.0.6
pytz==2023.3.post1
PyWavelets==1.4.1
PyYAML==6.0.1
pyzmq==25.1.2
rapidfuzz==3.6.1
rarfile==4.1
referencing==0.32.1
requests==2.31.0
rich==13.7.0
rpds-py==0.17.1
safetensors==0.4.1
scikit-image==0.21.0
scikit-learn==1.3.2
scipy==1.10.1
seaborn==0.13.2
semantic-version==2.10.0
sentencepiece==0.1.99
seqeval==1.2.2
shapely==2.0.2
shellingham==1.5.4
six==1.16.0
sklearn==0.0
sniffio==1.3.0
soupsieve==2.5
starlette==0.35.1
termcolor==2.4.0
terminaltables==3.1.10
threadpoolctl==3.2.0
tifffile==2023.7.10
tomlkit==0.12.0
toolz==0.12.0
tqdm==4.66.1
typeguard==4.1.5
typer==0.9.0
typing_extensions==4.9.0
tzdata==2023.4
ultralytics==8.2.30
ultralytics-thop==0.2.8
urllib3==2.1.0
uvicorn==0.25.0
visualdl==2.4.2
wcwidth==0.2.13
websockets==11.0.3
Werkzeug==3.0.1
xlrd==1.2.0
xmltodict==0.13.0
xxhash==3.4.1
yarl==1.9.4
youtube-dl==2021.12.17
zipp==3.17.0

以上是对项目实现环境的要求,在此基础上还需要准备一个视频,我们将视频命名为引体向上.mp4

4.代码实现

In [2]

# 导入实验项目需要使用的库
import paddlehub as hub#调用paddlehub中预训练模型的库
import cv2# 能够快速的实现一些图像处理和识别的库
import os#含了很多操作文件和目录的函数的库
import numpy as np#一个由多维数组对象和用于处理数组的例程集合组成的库
from tqdm import tqdm#进度条库,可以帮助我们监测代码进度
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/scipy/sparse/sputils.py:16: DeprecationWarning: `np.typeDict` is a deprecated alias for `np.sctypeDict`.
  supported_dtypes = [np.typeDict[x] for x in supported_dtypes]
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/scipy/special/orthogonal.py:81: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  from numpy import (exp, inf, pi, sqrt, floor, sin, cos, around, int,
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/scipy/linalg/__init__.py:217: DeprecationWarning: The module numpy.dual is deprecated.  Instead of using dual, use the functions directly from numpy or scipy.
  from numpy.dual import register_func

第1步:定义数据

在这一部分需要定义实现引体向上项目需要的数据:

  1. 定义引体向上视频路径pull_up_path引体向上.mp4,用做引体向上计数视频;
  2. 定义一个bool值visualiztiontomp4,是否将计数结果保存到视频中;
  3. 定义一个窗口compare_window3,作为每次引体向上计数窗口大小;
  4. 定义一个视频名称video_namecount_引体向上.mp4,用于保存视频的名称。

实现方法如下:

In [3]

#定义数据
pull_up_path='引体向上.mp4'#定义引体向上视频路径
visualizationtomp4 = True#是否将结果保存为视频
compare_window=3#定义每次引体向上计数的帧数范围
video_name = "output_count_引体向上.mp4"#定义保存视频名称

第2步:人体骨骼点检测

人体关键骨骼点检测功能一共分为两步:

  • 第一步,加载模型human_pose_estimation_resnet50_mpii,此时model就变成具备人体关键骨骼点检测功能的“检测器”,第二步便是利用其keyponit_detection()函数检测输入图片列表中的所有骨骼点的位置。

  • 第二步,将骨骼点检测得到的位置坐标信息储存在result中,便于下一个环节使用,这里我们将这两步骤封装为point_detection(images)函数,参数images为存放图像的列表,并将检测结果返回,也就是在图片上标出骨骼关键点的位置,如下图所示:

实现代码如下所示:

In [4]

# 定义模型预测函数,实现人体关键骨骼点检测
# 图片数据,ndarray.shape 为 [H, W, C];
def point_detection(images): 
    # 初始化module,调用人体关键点检测模型  
    model = hub.Module(name="human_pose_estimation_resnet50_mpii")    
    # 预测API,识别出人体骨骼关键点
    result = model.keypoint_detection(images,visualization=True)
    return result

第3步:计数过程可视化

经过以上操作我们完成了项目环境的准备,定义了本项目所用到的数据,和获取人体关键骨骼点的函数方法point_detection(images),接下来我们定义一个imagestovideo(images,is_up_list,video_name,fps)函数,该函数的作用是将预测的结果可视化,并且实现计数功能。

Imagestovideo( )函数中一共包含四个函数:

  • images(list):包含了视频中每一帧的图像;
  • is_up_list(list):用于记录每一帧的位置是否完成依次引体向上;
  • video_name(str):视频保存路径;
  • fps(int):视频的帧率。

具体的实现方法如下:

In [5]

# 将计数过程保存成视频
def imagestovideo(images, #(list): 每一帧视频图片
                  is_up_list, #(list): 视频每一帧的位置是否为引体向上完成一次
                  video_name, #(str): 保存视频路径
                  fps):#(int)保存视频帧率
    size = images[0].shape[:2]  #获取图片格式大小
    #定义视频video,用于存放处理完的视频
    video = cv2.VideoWriter(video_name, cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps, size[::-1])
    count = 0#定义count,用于存放引体向上次数
    for i in tqdm(range(len(images))):
        count += is_up_list[i] #累加引体向上次数
        frame = images[i]#读取每一张图像
        #在图像上添加文字,用于记录引体向上次数
        cv2.putText(frame, f'pull up count: {count}', (5, 25), cv2.FONT_HERSHEY_SIMPLEX, 
                    0.5, (55,255,155), 2)
        video.write(frame)#将图像写入视频中
    video.release()#释放视频对象

第4步:实现引体向上计数过程

经过上一步骤我们得到了人体关键骨骼点检测的方法point_detection()和将计数过程可视化的方法imagestovideo(),接下里我们具体的实现引体向上计数的过程,实现步骤如下:

In [6]

def countbyhead_with_mp4(
                        mp4_path,#待处理视频路径;
                        video_name,#视频保存名称
                        compare_window=5,#计数窗口;
                        visualizationtomp4=False):#是否可视化计数。
    '''
    第一步:
    我们定义一个列表images,用于存放视频中的每一帧图像,读取视频,
    并且获取视频的帧率fps,具体的实现代码如下:
    '''
    images = []#定义一个列表,用于存放视频中的每一帧图像
    cap = cv2.VideoCapture(mp4_path)#读取已有的视频
    fps = cap.get(cv2.CAP_PROP_FPS)#获取视频的帧率fps,fps=9.538461538461538
    '''
    第二步:
    通过while循环读取视频中的每一帧图像,并将图片信息保存到images列表当中,
    最后释放视频对象空间,具体的实现代码如下:
    '''
    while cap.isOpened():#判断视频对象是否成功读取,成功读取视频对象返回True
        #按帧读取视频,返回值ret是布尔型,正确读取则返回True,
        #读取失败或读取视频结尾则会返回False。
        #frame为每一帧的图像,这里图像是三维矩阵,即frame.shape = (640,480,3),
        #读取的图像为BGR格式。
        ret, frame = cap.read() 
        if frame is None:#当读取到空图像时,循环终止
            break
        images.append(frame)#将读取到的每一张图像添加到images列表中
    cap.release()#释放视频对象
    '''
    第三步:
    对每一张图像进行人体关键骨骼点检测,并将结果保存到results中,通过for循环,
    获取每张图像的头部关键点的纵坐标信息,将每张图像的头部关键点的纵坐标信息存储
    到heads列表中,具体实现代码如下:
    '''
    results = point_detection(images)#进行人体关键骨骼点检测
    #获取每张图像的头顶关键点的纵坐标
    heads = [result['data']['head_top'][1] for result in results]
    '''
    第四步:
    定义is_up_list列表,用于记录视频中的每一帧的位置是否完成一次引体向上,通过for循环遍历视频中的图像,以每七张图像为一个单位进行,
    比较头部关键点的纵坐标大小,判断第四张图像的纵坐标是否为这七张图像中的最小值,并且保证前三张图像不是计数点,
    如果满足以上要求is_up_list添加1,如果不满足则添加0,直到循环结束,is_up_list中存储了每一帧图像是否完成一次引体向上,
    最后判断是否将计数过程可视化,如果实现可视化,则调用visualizationtomp4()函数,具体实现代码如下:
    '''
    is_up_list = [0] * compare_window #视频每一帧的位置是否为引体向上完成一次
    #从3到57依次循环遍历
    for idx in range(compare_window, len(heads) - compare_window - 1):
        front_idx = idx - compare_window #定义front_idx第一个图像的索引
        #heads中索引为0到3之间的数转化为数组,定义为front
        front = np.array(heads[front_idx:idx])
        #获取真正的索引3+3+1=7,定义为rear_idx
        rear_idx = idx + compare_window + 1
        #heads中索引为4到7之间的数转化为数组,定义为rear
        rear = np.array(heads[idx+1:rear_idx])
        #将前四张图像的头部关键点纵坐标减去第四张纵坐标,
        # 将大于1的数记为1,小于-1的记为-1,
        #将得到的四个数组求和定义为is_greater_than_the_front
        is_greater_than_the_front = np.sum(np.clip(front - heads[idx], 
                                                   a_min=-1, 
                                                   a_max=1))
        #将第四张图像到第七张图像的头部关键点纵坐标减去第四张纵坐标,
        # 将大于1的数记为1,小于-1的记为-1,将得到的四个数组求和定义为is_greater_than_the_real
        is_greater_than_the_rear = np.sum(np.clip(rear - heads[idx], a_min=-1, a_max=1))
        #判断是否同时满足以下三个要求:以下条件为是否满足一次引体向上
        if is_greater_than_the_front > 0 and is_greater_than_the_rear > 0 and sum(is_up_list[-compare_window:]) == 0:
            is_up_list.append(1)#满足以上条件is_up_list列表末尾添加1
        else:
            is_up_list.append(0)#如果不满足以上条件is_up_list列表末尾添加0
    is_up_list.extend([0] * (compare_window + 1))#在is_up_list中添加4个0,用于补足视频的帧数
    if visualizationtomp4:#是否将计数过程保存成视频
        imagestovideo(images, is_up_list, video_name, fps)#将计数过程保存成视频
    return results, is_up_list

第5步:运行主函数

In [7]

results, is_up_list = countbyhead_with_mp4(pull_up_path,
                                           video_name, 
                                           compare_window=3,
                                           visualizationtomp4=visualizationtomp4)
Download https://bj.bcebos.com/paddlehub/paddlehub_dev/human_pose_estimation_resnet50_mpii_1_2_0.zip
[##################################################] 100.00%
Decompress /home/aistudio/.paddlehub/tmp/tmphzw2nbgn/human_pose_estimation_resnet50_mpii_1_2_0.zip
[##################################################] 100.00%
[2023-07-21 17:32:55,564] [    INFO] - Successfully installed human_pose_estimation_resnet50_mpii-1.2.0
---    Fused 0 subgraphs into layer_norm op.
image saved in output_pose/ndarray_time=1689931976012325.jpg
image saved in output_pose/ndarray_time=1689931976012369.jpg
image saved in output_pose/ndarray_time=1689931976012375.jpg
image saved in output_pose/ndarray_time=1689931976012380.jpg
image saved in output_pose/ndarray_time=1689931976012384.jpg
image saved in output_pose/ndarray_time=1689931976012389.jpg
image saved in output_pose/ndarray_time=1689931976012394.jpg
image saved in output_pose/ndarray_time=1689931976012400.jpg
image saved in output_pose/ndarray_time=1689931976012405.jpg
image saved in output_pose/ndarray_time=1689931976012411.jpg
image saved in output_pose/ndarray_time=1689931976012416.jpg
image saved in output_pose/ndarray_time=1689931976012421.jpg
image saved in output_pose/ndarray_time=1689931976012436.jpg
image saved in output_pose/ndarray_time=1689931976012441.jpg
image saved in output_pose/ndarray_time=1689931976012446.jpg
image saved in output_pose/ndarray_time=1689931976012452.jpg
image saved in output_pose/ndarray_time=1689931976012456.jpg
image saved in output_pose/ndarray_time=1689931976012461.jpg
image saved in output_pose/ndarray_time=1689931976012466.jpg
image saved in output_pose/ndarray_time=1689931976012472.jpg
image saved in output_pose/ndarray_time=1689931976012476.jpg
image saved in output_pose/ndarray_time=1689931976012482.jpg
image saved in output_pose/ndarray_time=1689931976012487.jpg
image saved in output_pose/ndarray_time=1689931976012492.jpg
image saved in output_pose/ndarray_time=1689931976012498.jpg
image saved in output_pose/ndarray_time=1689931976012502.jpg
image saved in output_pose/ndarray_time=1689931976012507.jpg
image saved in output_pose/ndarray_time=1689931976012512.jpg
image saved in output_pose/ndarray_time=1689931976012517.jpg
image saved in output_pose/ndarray_time=1689931976012522.jpg
image saved in output_pose/ndarray_time=1689931976012527.jpg
image saved in output_pose/ndarray_time=1689931976012532.jpg
image saved in output_pose/ndarray_time=1689931976012536.jpg
image saved in output_pose/ndarray_time=1689931976012542.jpg
image saved in output_pose/ndarray_time=1689931976012546.jpg
image saved in output_pose/ndarray_time=1689931976012550.jpg
image saved in output_pose/ndarray_time=1689931976012556.jpg
image saved in output_pose/ndarray_time=1689931976012561.jpg
image saved in output_pose/ndarray_time=1689931976012565.jpg
image saved in output_pose/ndarray_time=1689931976012570.jpg
image saved in output_pose/ndarray_time=1689931976012575.jpg
image saved in output_pose/ndarray_time=1689931976012579.jpg
image saved in output_pose/ndarray_time=1689931976012584.jpg
image saved in output_pose/ndarray_time=1689931976012589.jpg
image saved in output_pose/ndarray_time=1689931976012594.jpg
image saved in output_pose/ndarray_time=1689931976012599.jpg
image saved in output_pose/ndarray_time=1689931976012604.jpg
image saved in output_pose/ndarray_time=1689931976012609.jpg
image saved in output_pose/ndarray_time=1689931976012614.jpg
image saved in output_pose/ndarray_time=1689931976012619.jpg
image saved in output_pose/ndarray_time=1689931976012624.jpg
image saved in output_pose/ndarray_time=1689931976012629.jpg
image saved in output_pose/ndarray_time=1689931976012634.jpg
image saved in output_pose/ndarray_time=1689931976012640.jpg
image saved in output_pose/ndarray_time=1689931976012644.jpg
image saved in output_pose/ndarray_time=1689931976012648.jpg
image saved in output_pose/ndarray_time=1689931976012654.jpg
image saved in output_pose/ndarray_time=1689931976012658.jpg
image saved in output_pose/ndarray_time=1689931976012662.jpg
image saved in output_pose/ndarray_time=1689931976012667.jpg
image saved in output_pose/ndarray_time=1689931976012673.jpg
image saved in output_pose/ndarray_time=1689931976012678.jpg
100%|██████████| 62/62 [00:00<00:00, 975.11it/s]

完整代码+模型+视频例子+运行结果视频下载地址:

https://download.csdn.net/download/FL1623863129/89760682

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

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

相关文章

【电机仿真】全速域观测器零速旋转方波高频注入+低速+高速滑模观测器三段式启动

【电机仿真】全速域观测器零速脉振方波高频注入低速高速滑模观测器三段式启动 文章目录 前言一、零速——HFI方波注入1.HFI观测器2.静止坐标系——旋转高频电压信号3.PLL1锁相环4.PLL2锁相环 二、零速到中高速——HFI切SMO1.函数定义2.函数内部 三、中高速——SMO观测器1.SMO观…

卸载完mathtype后,删除word加载项中的mathtype

请参考博客“卸载完mathtype后&#xff0c;word加载项中还是有mathtype的解决方法_怎么删除word加载项里的mathtype-CSDN博客”以及 “安装卸载MathType经验解决MathType DLL找不到的问题——超实用_mathtype dll cannot-CSDN博客” 如果在删除.dotm文件时&#xff0c;删不掉…

CenterPoint-KITTI:环境配置、模型训练、效果展示;KITTI 3D 目标检测数据集下载

目录 前言 Python虚拟环境创建以及使用 KITTI3D目标检测数据集 CenterPoint-KITTI编译遇到问题合集 ImportError: cannot import name VoxelGenerator from spconv.utils 失败案例 最终解决方案 对于可选参数&#xff0c;road plane的处理 E: Unable to locate packag…

supermap iclient3d for cesium中entity使用

目标将西南石油大学部分区域围起来&#xff0c;然后引个标签显示名称&#xff0c;最后弄个飞机绕学校飞&#xff08;这个时间有点晚了&#xff0c;明天弄) 围墙: wall:{positions:Cesium.Cartesian3.fromDegreesArrayHeights([104.173,30.822,500,104.178,30.837,500,104.19,3…

数据库之索引<保姆级文章>

目录&#xff1a; 一. 什么是索引 二. 索引应该选择哪种数据结构 三. MySQL中的页 四. 索引分类及使用 一. 什么是索引&#xff1a; 1. MySQL的索引是⼀种数据结构&#xff0c;它可以帮助数据库高效地查询、更新数据表中的数据。 索引通过 ⼀定的规则排列数据表中的记录&#x…

动态内存

动态内存分配函数&#xff1a;在程序运行时为变量或数据结构开辟的内存空间的函数。 有三个重要的动态分配函数&#xff1a;malloc、calloc、realloc。 动态内存分配函数 malloc 这个函数是向内存中申请一块连续的空间&#xff0c;返回一个指向这个块空间的指针。 如果开辟成…

【Elasticsearch系列七】索引 crud

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

测试ASP.NET Core的WebApi项目调用WebService

虚拟机中部署的匿名访问的WebService&#xff0c;支持简单的加减乘除操作。本文记录在WebApi中调用该WebService的方式。   VS2022创建WebApi项目&#xff0c;然后在解决方案资源管理器的Connected Services节点点右键&#xff0c;选择管理连接的服务菜单。 点击下图圈红处…

【STM32 HAL库】IIC通信与CubeMX配置

【STM32 HAL库】IIC通信与CubeMX配置 前言理论IIC总线时序图IIC写数据IIC读数据 轮询模式CubeMX配置应用示例AHT20初始化初始化函数读取说明读取函数 中断模式CubeMX配置状态机图fsm.caht20.c DMA模式CubeMX配置代码 前言 本文为笔者学习 IIC 通信的总结&#xff0c;基于keysk…

评价类——熵权法(Entropy Weight Method, EWM),完全客观评价

目录 一、 熵权法赋权代码说明1.1 介绍 二、 手把手教你运行代码2.1 数据示例2.2 可直接运行代码2.3 shangquanfa_eg_Sheet1.csv数据可视化2.4 代码运行过程截屏2.5 代码运行结果截屏2.6 对熵权法的结果分析 三、 提供的代码如何修改&#xff1f;四、 为什么确定极小化指标&…

算法:计算二叉树的最大深度(Java实现)

思路 定义问题&#xff1a; 最大深度&#xff08;或称为最大层数&#xff09;是从根节点到最远叶子节点的路径上的节点数。我们需要找到这个最长路径的节点数。 递归的基本思路&#xff1a; 对于每个节点&#xff0c;我们需要计算其左子树的最大深度和右子树的最大深度。节点的…

54.【C语言】 字符函数和字符串函数(strncpy,strncat,strncmp函数)

和strcpy,strcat,strcmp函数对应的是strncpy,strncat,strncmp函数 8.strncpy函数 *简单使用 cplusplus的介绍 点我跳转 翻译: 函数 strncpy char * strncpy ( char * destination, const char * source, size_t num ); 从字符串中复制一些字符 复制源(source)字符串的前num个…

Redis详细解析

Redis 什么是Redis?关系型与非关系型数据库Redis可以做什么Redis入门安装在Windows系统上安装在Linux系统上安装 Redis在Linux系统上启动运行如何设置redis-server后台运行与关闭如何设置redis客户端登录时需要验证密码**设置允许远程连接redis服务**Redis数据类型Redis常用命…

魔方财务迁移指南

本文将详细介绍如何将魔方财务系统迁移到新的服务器&#xff0c;确保您能够顺利地迁移数据和系统文件。 迁移前的准备 在开始迁移之前&#xff0c;请确保新服务器满足以下配置要求&#xff1a; 操作系统&#xff1a;CentOS/Debian/Ubuntu硬件配置&#xff1a;至少2H2G&#…

RP2040 C SDK ADC功能使用

RP2040 C SDK ADC功能使用 &#x1f33f;RP2040 ADC功能说明文档&#xff1a;https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#hardware_adc &#x1f4d7;RP2040 ADC介绍 SAR ADC500 kS/s (Using an independent 48MHz clock)12 bit (RP2040 8.7 ENOB, R…

建筑资质与劳务资质的区别

在建筑行业&#xff0c;资质就像是企业的“身份证”&#xff0c;它证明了企业具备承接相应工程的能力和条件。对于刚入行的小白来说&#xff0c;可能会对建筑资质和劳务资质的区别感到困惑。别担心&#xff0c;今天我们就来聊聊这两者之间的不同。 什么是建筑资质&#xff1f; …

git push : RPC failed; HTTP 400 curl 22 The requested URL returned error: 400

git push 出现RPC failed; HTTP 400 curl 22 The requested URL returned error: 400 问题 git push Enumerating objects: 11, done. Counting objects: 100% (11/11), done. Delta compression using up to 8 threads Compressing objects: 100% (10/10), done. error: RPC …

分布式训练:(Pytorch)

分布式训练是将机器学习模型的训练过程分散到多个计算节点或设备上&#xff0c;以提高训练速度和效率&#xff0c;尤其是在处理大规模数据和模型时。分布式训练主要分为数据并行和模型并行两种主要策略&#xff1a; 1. 数据并行 (Data Parallelism) 数据并行是最常见的分布式…

数据结构之树的常用术语

二叉树的常用术语 前言 由于数组在插入、删除上的缺点和链表在查询上的缺点&#xff0c;出现了树的数据结构&#xff0c;可以在增删改查中弥补数组和链表的缺陷。 常用数据 节点&#xff1a;每个节点根节点&#xff1a;最上层的节点&#xff0c;Root节点父节点&#xff1a;相…

基于SSM的宿舍管理系统的设计与实现 (含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的宿舍管理系统拥有两种角色&#xff0c;分别为管理员和宿管&#xff0c;具体功能如下&#xff1a; 管理员&#xff1a;学生管理、班级管理、宿舍管理、卫生管理、访客管理、用户…