基于YOLO模型的目标检测与识别实现在ESP32-S3 EYE上全流程部署
前言
文章首发于 基于YOLO模型的目标检测与识别实现在ESP32-S3 EYE上全流程部署
文章目录
- 前言
- 项目环境安装
- ESP-IDF安装
- 开发环境
- 运行环境
- 训练数据集准备
- 添加自定义数据集
- 下载预训练模型
- 训练 YOLO 模型
- 模型量化和格式转换
- 模型结果评估
- 训练损失
- 评估指标
- 模型推理
- 模型部署
- 部署环境
- 导入模型
- 烧录模型
- 结果展示
- Swift YOLO Tiny Nano
- Swift YOLO Tiny
- 总结
- References
项目环境安装
ESP-IDF安装
ESP-IDF 5.0+ 的版本有较大改动,在部署过程中会出现一些问题,建议使用 4.4 版本的进行安装。
基于 Windows 平台的软件安装,可以参考 https://dl.espressif.com/dl/esp-idf/. 按照流程完成安装即可。
开发环境
本项目整体开发环境主要基于训练框架,以及对应esp32的模型部署框架,具体如下:
- 训练、转换模型: Model Assistant
- 模型部署: sscma-example-esp32(1.0.0)
运行环境
python3.10 + CUDA11.7 + esp-idf 4.4
# 主要按照 ModelAssistant/requirements_cuda.txt 进行安装
torch 2.0.0+cu117
torchaudio 2.0.1+cu117
torchvision 0.15.1+cu117
yapf 0.40.2
typing_extensions 4.5.0
tensorboard 2.13.0
tensorboard-data-server 0.7.2
tensorflow 2.13.0
keras 2.13.1
tensorflow-estimator 2.13.0
tensorflow-intel 2.13.0
tensorflow-io-gcs-filesystem 0.31.0
sscma 2.0.0rc3
setuptools 60.2.0
rich 13.4.2
Pillow 9.4.0
mmcls 1.0.0rc6
mmcv 2.0.0
mmdet 3.0.0
mmengine 0.10.1
mmpose 1.2.0
mmyolo 0.5.0
conda 的环境依赖主要见上面各种库的版本,其中
mmcv
库安装
mmcv
库的安装需要对应cuda
版本、torch
版本以及python
版本,具体说明:cu117,torch2.0.0,python3.10可以参考
https://download.openmmlab.com/mmcv/dist/cu117/torch2.0.0/index.html,对应其中主要根据操作系统选择性安装,./mmcv-2.0.1-cp310-cp310-manylinux1_x86_64.whl
和./mmcv-2.0.1-cp310-cp310-win_amd64.whl
文件,具体如下,
训练数据集准备
添加自定义数据集
主要的数据集可以从开源的 Roboflow Universe 搜集,比如我们需要识别某些类别,可以在该网站上下载对应的数据集,下载格式选择 COCO 格式,如下图所示:
将下载的数据集压缩包放置在 data/collection
目录下面,对各个类别数据集加压并重命名为类别名称,例如 “face”, “phone”,即类别标签。
挑选多个类别数据集后(这里选取 “face, phone”),需要对其进行合并,利用下述代码进行合并(主要合并 json 文件,并拷贝各类别数据集的图像文件):
import os
import json
import shutil# Save paths
train_path = 'datasets/collection/train'
valid_path = 'datasets/collection/valid'# Create directories if not exist
if not os.path.exists(train_path):os.makedirs(train_path)
if not os.path.exists(valid_path):os.makedirs(valid_path)def Add_Class_COCO_Data(dataset_path, classname, dataset, dataset_info):with open(os.path.join(dataset_path, '_annotations.coco.json'), 'r') as file:class_data = json.load(file)# check if the class already exists in the train dataclass_exist, class_id = False, Nonefor item in dataset['categories']:if item['name'] == classname:class_exist, class_id = True, item['id']if class_exist is False:class_id = dataset_info['category_id']dataset['categories'].append({'id': class_id, 'name': classname})dataset_info['category_id'] += 1# add the class images for the train dataimage_id = dataset_info['img_id']for image in class_data['images']:image_info = {'id': dataset_info['img_id'], 'file_name': image['file_name'], 'width': image['width'], 'height': image['height']}dataset['images'].append(image_info)dataset_info['img_id'] += 1# add the class annotations for the train datafor ann in class_data['annotations']:ann_info = {'id': dataset_info['ann_id'], 'image_id': image_id+ann['image_id'], 'category_id': class_id, 'bbox': ann['bbox'],'area': ann['area'], 'iscrowd': ann['iscrowd']}dataset['annotations'].append(ann_info)dataset_info['ann_id'] += 1def Copy_Files(src_dir, dst_dir, skip_files=['_annotations.coco.json']):"""Copy the files from source directory to the destination directory."""os.makedirs(dst_dir, exist_ok=True)for file_name in os.listdir(src_dir):# skip some filesif file_name in skip_files:continuesrc_file = os.path.join(src_dir, file_name)dst_file = os.path.join(dst_dir, file_name)if os.path.isfile(src_file):shutil.copy(src_file, dst_file)print(f"Copied: {src_file} -> {dst_file}")else:print(f"Skipping directory: {src_file}")# training classes
classes = ["face", "phone"]# store the combined data
category_id = 0
train_data = {'categories': [], 'images': [], 'annotations': []}
train_info = {'category_id': 0, 'img_id': 0, 'ann_id': 0}valid_data = {'categories': [], 'images': [], 'annotations': []}
valid_info = {'category_id': 0, 'img_id': 0, 'ann_id': 0}class_data_root = './data/collection'
for cls_name in classes:class_train_path = os.path.join(class_data_root, cls_name, 'train')class_valid_path = os.path.join(class_data_root, cls_name, 'valid')Add_Class_COCO_Data(class_train_path, cls_name, train_data, train_info)Add_Class_COCO_Data(class_valid_path, cls_name, valid_data, valid_info)Copy_Files(class_train_path, train_path)Copy_Files(class_valid_path, valid_path)# Save data to file
with open(os.path.join(train_path, '_annotations.coco.json'), 'w') as f:json.dump(train_data, f, indent=4)with open(os.path.join(valid_path, '_annotations.coco.json'), 'w') as f:json.dump(valid_data, f, indent=4)print(f">>> length of categories: {len(train_data['categories'])}")
print(f">>> length of train_data: {len(train_data['images'])}")
print(f">>> length of valid_data: {len(valid_data['images'])}")
合并后的统一的训练和验证数据集全部放在了 datasets/collection
目录下面,以便于后续模型训练使用。
下载预训练模型
参考 Face Detection - Swift-YOLO 下载预训练模型权重文件 pretrain.pth,然后保存在 ModelAssistant/checkpoints
文件夹下。
训练 YOLO 模型
在 ModelAssistant 项目下,采用的是仓库提供的 Swift YOLO 模型,作者解释说明该模型具有优化的端侧运行性能:“We implemented a lightweight object detection algorithm called Swift YOLO, which is designed to run on low-cost hardware with limited computing power. The visualization tool, model training and export command-line interface has refactored now”.
采用 swift_yolo_tiny_1xb16_300e_coco 的配置文件进行训练,训练命令如下:
# training the yolo model
python tools/train.py configs/swift_yolo/swift_yolo_tiny_1xb16_300e_coco.py \
--cfg-options \work_dir=work_dirs/collection \num_classes=2 \epochs=300 \height=96 \width=96 \data_root=datasets/collection/ \load_from=checkpoints/pretrain.pth
模型量化和格式转换
训练完毕后,还需要对模型进行权重量化以及格式转换,这样才能够让模型成功在 ESP32S3 主板上运行。在工作目录 work_dirs/collection
下,找到最好的 bbox_mAP
的模型,例如这里是 best_coco_bbox_mAP_epoch_300.pth
,采用以下命令导出模型:
# export the model
python tools/export.py configs/swift_yolo/swift_yolo_tiny_1xb16_300e_coco.py ./work_dirs/collection/best_coco_bbox_mAP_epoch_300.pth --cfg-options \work_dir=work_dirs/collection \num_classes=2 \epochs=300 \height=96 \width=96 \data_root=datasets/collection/ \load_from=checkpoints/pretrain.pth
导出的模型会保存在 work_dirs/collection
文件夹下,生成 best_coco_bbox_mAP_epoch_300_int8.tflite
文件,这是量化到 Int8 格式的 tflite 文件,可以用于后续模型的部署。
模型结果评估
训练损失
在整个 300 epoches 的训练过程中,对应的类别损失以及目标检测损失的变化如下图所示:
评估指标
在该项目中,主要测定了 Swift YOLO Tiny 结构以及 Swift YOLO Tiny Nano 结构(一种高度紧凑的深卷积神经网络,用于使用人机协同设计策略设计的嵌入式目标检测),主要的评估指标如下所示:
考虑到部署到端侧设备上时,更关注于目标检测的置信度,因此下面主要从置信度、平均推理时间的角度进行评估。
Model | Precision | Class | Confidence | Infer_Time(ms) | Size(MB) |
---|---|---|---|---|---|
Swift YOLO Tiny | Float32 | Face | 69.57 % | 6.44 | 3.63 |
Swift YOLO Tiny | Float32 | Phone | 54.86 % | 6.44 | 3.63 |
Swift YOLO Tiny | Float32 | [Face, Phone] | 62.21 % | 6.44 | 3.63 |
Swift YOLO Tiny | Int8 | Face | 68.75 % | 6.69 | 1.05 |
Swift YOLO Tiny | Int8 | Phone | 55.18 % | 6.69 | 1.05 |
Swift YOLO Tiny | Int8 | [Face, Phone] | 61.97 % | 6.69 | 1.05 |
Swift YOLO Tiny Nano | Float32 | Face | 73.62 % | 8.02 | 9.13 |
Swift YOLO Tiny Nano | Float32 | Phone | 55.76 % | 8.02 | 9.13 |
Swift YOLO Tiny Nano | Float32 | [Face, Phone] | 64.69 % | 8.02 | 9.13 |
Swift YOLO Tiny Nano | Int8 | Face | 74.62 % | 12.86 | 2.49 |
Swift YOLO Tiny Nano | Int8 | Phone | 55.62 % | 12.86 | 2.49 |
Swift YOLO Tiny Nano | Int8 | [Face, Phone] | 65.12 % | 12.86 | 2.49 |
- 可以看到,模型量化压缩后在能够维持较高的精度的情况下,模型大小显著减小,但是推理时间并没有降低,甚至约有增加;
- Swift YOLO Tiny Nano 的精度更高,但是模型大小更大,推理时间更长,在 ESP32S3-EYE 设备上牺牲的代价就是帧率较低;
- 整体而言,模型的置信度都已经比较高以及推理速度能比较不错,能够满足实际应用需求。
此外,我还尝试了保持原图像尺寸,即对于Swift YOLO Tiny配置而言,设置模型处理的图像宽高都是640,具体如下:
# training the yolo model
python tools/train.py configs/swift_yolo/swift_yolo_tiny_1xb16_300e_coco.py \
--cfg-options \work_dir=work_dirs/collection_640 \num_classes=2 \epochs=300 \height=640 \width=640 \data_root=datasets/collection/ \load_from=checkpoints/pretrain.pth
训练后模型的评估指标如下所示:
Model | Precision | Class | Confidence | Infer_Time(ms) | Size(MB) |
---|---|---|---|---|---|
Swift YOLO Tiny WH640 | Float32 | Face | 74.83 % | 54.08 | 3.88 |
Swift YOLO Tiny WH640 | Float32 | Phone | 65.47 % | 54.08 | 3.88 |
Swift YOLO Tiny WH640 | Float32 | [Face, Phone] | 70.15 % | 54.08 | 3.88 |
Swift YOLO Tiny WH640 | Int8 | Face | 75.52 % | 71.87 | 1.20 |
Swift YOLO Tiny WH640 | Int8 | Phone | 65.46 % | 71.87 | 1.20 |
Swift YOLO Tiny WH640 | Int8 | [Face, Phone] | 70.49 % | 71.87 | 1.20 |
虽然整体的精度有所提升,但是推理时间显著增加,模型虽然大小基本维持不变,但是推理时间增大了将近10倍,处理图像的分辨率所带来的开销远远超过了模型识别的精度。事实上,Swift YOLO Tiny WH640 在 ESP32S3-EYE 设备上已经没办法运行,实际中会出现数据存储栈溢出的问题,摄像头采集的图像分辨率太高导致栈空间不足。
模型推理
主要是观测量化后模型对验证集的推理结果,具体如下:








模型部署
部署环境
部署环境为 ESP32-S3 EYE 开发板,没判断错的话,它有 4MB Flash,我们烧录的模型也主要存储在这个区域,当然它也附带了 SD 卡功能,可以从 SD 卡中加载模型。4 MB 的 Flash 分配主要在 partitions.csv 文件中,具体如下:
# Name Type SubType Offset Size Flags
# Note: if you change the phy_init or app partition offset make sure to change the offset in Kconfig.projbuild
factory app factory 0x010000 2048K
nvs data nvs 0x3D0000 64K
fr data 0x3E0000 128K
默认 app 分区最多有 2048K 即 2MB 的大小,但是由于地址空间还很充裕,例如从 0x010000
到 0x3D0000
的大小,最多可以分配 3MB 的空间,足够上述量化后的模型存储。此外,分区表主要以 64KB 为单位分配的,所以偏移地址后四位都为0. 可以在项目中通过 idf.py build
查看输出信息,其中包含了对分区大小是否合适以及剩余空间的判断。
对于 Swift YOLO Tiny Nano 配置,需要将分区表中的 app 分区增大到 3MB 即 3072K.
导入模型
对于烧录程序而言,需要将 tflite 格式模型转换为 c 语言格式,具体在项目 sscma-example-esp32-1.0.0
中,通过 tools/tflite2c.py
文件进行转换,但是为了能够在显示屏上同步显示检测的类别名称,需要修改其中的代码,即将 classes 换成字符串,然后通过分词找到各个类别,并将其转换为字符串列表,其中每个字符串都是一个类别名称,具体如下:
import sys
import os
import binascii
import argparsedef parse_args():parser = argparse.ArgumentParser(description='Convert tflite to c or cpp file')parser.add_argument('--input', help='input tflite file')parser.add_argument('--output_dir', help='output directory')parser.add_argument('--name', help='model name')parser.add_argument('--cpp', action='store_true',default=True, help='output cpp file')parser.add_argument('--classes', type=str, help='classes name')args = parser.parse_args()return argsif __name__ == '__main__':args = parse_args()input = args.inputname = args.nameoutput_dir = args.output_dirclasses = args.classesif classes != None:classes = list(classes.split(','))if not os.path.exists(input):print('input file not exist')sys.exit(1)if name == None:name = input.split('/')[-1].split('.')[0]output_h = os.path.join(output_dir, name + '_model_data.h')if args.cpp:output_c = os.path.join(output_dir, name + '_model_data.cpp')else:output_c = os.path.join(output_dir, name + '_model_data.c')with open(input, 'rb') as f_input:data = f_input.read()if data[4:8] != b'TFL3':print('input file is not tflite')sys.exit(1)data = binascii.hexlify(data)data = data.decode('utf-8')with open(output_h, 'w') as f_output_h:f_output_h.write('#ifndef __%s_MODEL_DATA_H__\r\n' % name.upper())f_output_h.write('#define __%s_MODEL_DATA_H__\r\n' % name.upper())f_output_h.write('\r\n//this file is generated by tflite2c.py\r\n')f_output_h.write('\r\n#include <stdint.h>\r\n')f_output_h.write('extern const unsigned char g_%s_model_data[];\r\n' % name)f_output_h.write('extern const unsigned int g_%s_model_data_len;\r\n' % name)if classes != None:f_output_h.write('extern const char* g_%s_model_classes[];\r\n' % name)f_output_h.write('extern const unsigned int g_%s_model_classes_num;\r\n' % name)f_output_h.write('\r\n#endif\r\n')f_output_h.close()with open(output_c, 'w') as f_output_c:f_output_c.write('#include <stdint.h>\r\n')f_output_c.write('\r\n#include "%s_model_data.h"\r\n\r\n' % name)f_output_c.write('const unsigned char g_%s_model_data[] = {\r\n' % name)for i in range(0, len(data), 2):f_output_c.write('0x')f_output_c.write(data[i])f_output_c.write(data[i+1])f_output_c.write(', ')if i % 36 == 34:f_output_c.write('\r\n')f_output_c.write('};\r\n\r\n')f_output_c.write('const unsigned int g_%s_model_data_len = %d;\r\n' % (name, len(data) // 2))if classes != None:f_output_c.write('const char* g_%s_model_classes[] = {' % name)for i in range(len(classes)):f_output_c.write('"%s", ' % classes[i])f_output_c.write('};\r\n\r\n')f_output_c.write('const unsigned int g_%s_model_classes_num = %d;\r\n' % (name, len(classes)))else:f_output_c.write('const char* g_%s_model_classes[] = {};\r\n' % name)f_output_c.write('const unsigned int g_%s_model_classes_num = 0;\r\n' % name)f_output_c.close()f_input.close()
同时为了能够在显示屏上显示置信度,还需要在 components/modules/algorithm/algo_yolo.cpp
文件中修改相应的代码,具体如下所示:
if (std::distance(_yolo_list.begin(), _yolo_list.end()) > 0)
{int index = 0;found = true;printf(" Objects found: %d\n", std::distance(_yolo_list.begin(), _yolo_list.end()));printf(" Objects:\n");printf(" [\n");for (auto &yolo : _yolo_list){yolo.x = uint16_t(float(yolo.x) / float(w) * float(frame->width));yolo.y = uint16_t(float(yolo.y) / float(h) * float(frame->height));yolo.w = uint16_t(float(yolo.w) / float(w) * float(frame->width));yolo.h = uint16_t(float(yolo.h) / float(h) * float(frame->height));fb_gfx_drawRect2(frame, yolo.x - yolo.w / 2, yolo.y - yolo.h / 2, yolo.w, yolo.h, box_color[index % (sizeof(box_color) / sizeof(box_color[0]))], 4);// fb_gfx_printf(frame, yolo.x - yolo.w / 2, yolo.y - yolo.h/2 - 5, 0x1FE0, 0x0000, "%s", g_yolo_model_classes[yolo.target]);fb_gfx_printf(frame, yolo.x - yolo.w / 2, yolo.y - yolo.h/2 - 5, 0x1FE0, "%s:%d", g_yolo_model_classes[yolo.target], yolo.confidence);printf(" {\"class\": \"%d\", \"x\": %d, \"y\": %d, \"w\": %d, \"h\": %d, \"confidence\": %d},\n", yolo.target, yolo.x, yolo.y, yolo.w, yolo.h, yolo.confidence);index++;}printf(" ]\n");
}
然后具体的转换命令如下所示,这将会在文件夹 components/modules/model
中生成两个文件 yolo_model_data.h
和 yolo_model_data.cpp
,其中 yolo_model_data.h
中包含了模型数据的声明,yolo_model_data.cpp
中包含了模型数据的定义。
python tools/tflite2c.py --input ./model_zoo/facephone_96/best_coco_bbox_mAP_epoch_300_int8.tflite --name yolo --output_dir ./components/modules/model --classes "person,phone"
烧录模型
模型准备完毕后,就可以利用乐鑫的 IDF 开发工具链将模型烧录进开发板中,具体过程主要是:
- 使用
ESP-IDF 4.4 CMD
进入sscma-example-esp32-1.0.0
项目的examples/yolo
目录下; - 使用
idf.py set-target esp32s3
设置目标芯片为esp32s3
; - 使用
idf.py build
命令编译项目; - 使用
idf.py flash monitor
命令烧录项目。
结果展示
Swift YOLO Tiny Nano
在 ESP32S3 设备上平均每张图像的处理时间是 628 ms,在端侧设备上出现帧率较低,稍微偏卡顿的效果。但是准确度提高的也不是很多,因此首选还是 Swift YOLO Tiny。
Swift YOLO Tiny
在 ESP32S3 设备上平均每张图像的处理时间是 268 ms,实时监测的帧率非常不错,已经很流畅,准确性而言也是较为不错的,具体结果如下所示:
实际的开发板检测结果如下所示:
总结
本文主要介绍了如何利用 Model Assistant、sscma-example-esp32-1.0.0 项目将 YOLO 模型部署到 ESP32S3 EYE 设备上,并且通过自定义数据集实现训练、导出、转换、导入、部署模型整个流程,也对实际开发板进行了测试,最终得到了较为理想的结果。
本文主要选取了 “face, phone” 两个类别进行训练,如果需要训练更多的类别,可以添加更多的类别,但是会存在目标检测上限以及端侧设备计算性能的限制,需要进一步平衡。
References
- esp32-s3训练自己的数据进行目标检测、图像分类
- SenseCraft Model Assistant by Seeed Studio
- EdgeLab Deployment on Espressif Chipsets
- Explore the Roboflow Universe
相关文章:
基于YOLO模型的目标检测与识别实现在ESP32-S3 EYE上全流程部署
前言 文章首发于 基于YOLO模型的目标检测与识别实现在ESP32-S3 EYE上全流程部署 文章目录 前言项目环境安装ESP-IDF安装开发环境运行环境 训练数据集准备添加自定义数据集 下载预训练模型训练 YOLO 模型模型量化和格式转换模型结果评估训练损失评估指标模型推理 模型部署部署环…...
2411C++,CXImage简单使用
介绍 CxImage是一个可非常简单快速的加载,保存,显示和转换图像的C类. 文件格式和链接的C库 Cximage对象基本上是加了一些成员变量来保存有用信息的一个位图: class CxImage{...protected:void* pDib; //包含标题,调色板,像素BITMAPINFOHEADER head; //标准头文件CXIMAGEINFO…...
Java对象与XML互相转换(xstream)
依赖 <dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.18</version></dependency> 实体类 package com.itheima.util;import lombok.AllArgsConstructor; import lom…...
计算机视觉工程师紧张学习中!
在当今这个日新月异的科技时代,计算机视觉作为人工智能的重要分支,正以前所未有的速度改变着我们的生活和工作方式。为了紧跟时代步伐,提升自我技能,一群怀揣梦想与热情的计算机视觉设计开发工程师们聚集在了本次线下培训活动中。…...
网关整合sentinel无法读取nacos配置问题分析
sentinel无法读取nacos配置问题分析 1.spring-cloud-gateway整合sentinel2.问题现象3.原因猜测4.源码分析4. 结语 最近公司需要上线一个集约项目,虽然为内网项目,但曾经有过内网被攻破,导致内部系统被攻击的案例,且集约系统同时在…...
速盾:高防 CDN 中高级缓存有什么用?
在高防 CDN(Content Delivery Network,内容分发网络)的服务体系里,高级缓存功能犹如一颗强大的 “性能优化引擎”,对于提升网站或应用的运行效率、减轻源站压力以及改善用户体验等诸多方面都发挥着极为关键的作用。 一…...
大数据期末笔记
第一章、大数据概述 人类的行为及产生的事件的一种记录称之为数据。 1、大数据时代的特征,并结合生活实例谈谈带来的影响。 (一)特征 1、Volume 规模性:数据量大。 2、Velocity高速性:处理速度快。数据的生成和响…...
Qt详解QUiLoader 动态加载UI文件
文章目录 详解 QUiLoader 模块的使用1. QUiLoader 简介1.1 应用场景 2. 准备工作2.1 添加模块依赖2.2 引入头文件 3. 使用 QUiLoader 加载界面3.1 示例代码form.uimain.cpp 4. 常用方法详解4.1 load函数原型作用参数返回值示例代码 4.2 createWidget函数原型作用参数返回值示例…...
Android -- 简易音乐播放器
Android – 简易音乐播放器 播放器功能:* 1. 播放模式:单曲、列表循环、列表随机;* 2. 后台播放(单例模式);* 3. 多位置同步状态回调;处理模块:* 1. 提取文件信息:音频文…...
云平台与阿里云服务器使用
云平台 云就是一堆远程计算机组成的集群。 计算就是各种软件服务。 云平台就是远程计算机集群提供的的各种服务所组成的远程服务平台。 云平台提供的服务主要可以分为三个类别: I 服务 P服务 S服务 i就是基础设施服务infrastructure p就是平台服务platform …...
Dart 中 initializer lists
在 Dart 中,initializer lists 是构造函数的一种特性,允许你在进入构造函数体之前对某些字段进行初始化或进行检查。这些字段包括 final 字段,因为 final 字段必须在构造函数体运行之前被初始化。 以下是它的几个关键点和适用场景࿱…...
02.06、回文链表
02.06、[简单] 回文链表 1、题目描述 编写一个函数,检查输入的链表是否是回文的。 2、解题思路: 快慢指针找中点: 利用快慢指针的技巧来找到链表的中间节点。慢指针 slow 每次移动一步,而快指针 fast 每次移动两步。这样&…...
linux中限定特定用户使用crontab
在Linux中,crontab(cron table)是用来定时执行任务的工具。默认情况下,任何用户(包括普通用户)都可以为自己的账户创建和管理crontab条目,但前提是这个用户拥有对/var/spool/cron/crontabs目录的…...
Oracle Universal Unique Identifier (UUID)
本文介绍Oracle生成全局唯一ID的函数SYS_GUID,后续会对SYS_GUID和Sequence两种方法进行比较。 SYS_GUID 函数生成并返回一个由 16 个字节组成的全局唯一标识符(RAW 值)。在大多数平台上,生成的标识符由主机标识符、调用该函数的进…...
LangChain——加载知识库文本文档 PDF文档
文档加载 这涵盖了如何加载目录中的所有文档。 在底层,默认情况下使用 UnstructedLoader。需要安装依赖 pip install unstructuredpython导入方式 from langchain_community.document_loaders import DirectoryLoader我们可以使用 glob 参数来控制加载特定类型文…...
shell编程3,参数传递+算术运算
声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…...
Spring boot之BeanDefinition介绍
在spring框架中IOC容器进行bean的创建和管理。Bean的创建是一个比较复杂的过程,它并不像我们创建对象一样只是直接new一下就行,虽然有些bean确实就是New一下。但在Spring中可以通过一些途径对bean进行增强扩展。在这个过程中,BeanDefinition作…...
JAVA:Spring Boot 3 实现 Gzip 压缩优化的技术指南
1、简述 随着 Web 应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈。为了减少数据传输量,提高用户体验,我们可以使用 Gzip 压缩 HTTP 响应。本文将介绍如何在 Spring Boot 3 中实现 Gzip 压缩优化。 2、配置 Spring Boot 3 对…...
探索 IntelliJ IDEA 中 Spring Boot 运行配置
前言 IntelliJ IDEA 作为一款功能强大的集成开发环境(IDE),为 Spring Boot 应用提供了丰富的运行配置选项,定义了如何在 IntelliJ IDEA 中运行 Spring Boot 应用程序,当从主类文件运行应用程序时,IDE 将创建…...
Java学习,反射
Java反射是Java编程语言的一个重要特性,它允许程序在运行时查看任意对象所属的类,获取类的内部信息(包括构造器、字段和方法等),并能动态地调用对象的方法或构造器。 反射概念 反射(Reflection)…...
应急响应靶机——Windows挖矿事件
载入虚拟机,开启虚拟机: (账户密码:administrator/zgsf123) 发现登录进去就弹出终端界面,自动运行powshell命令,看来存在计划任务,自动下载了一些文件,之后就主动结束退…...
0017. shell命令--tac
目录 17. shell命令--tac 功能说明 语法格式 选项说明 实践操作 注意事项 17. shell命令--tac 功能说明 Linux 的 tac 命令用于按行反向输出文件内容,与 cat 命令的输出顺序相反。非常有趣,好记。也就是说,当我们使用tac命令查看文件内…...
富文本编辑器图片上传并回显
1.概述 在代码业务需求中,我们会经常涉及到文件上传的功能,通常来说,我们存储文件是不能直接存储到数 据库中的,而是以文件路径存储到数据库中;但是存储文件的路径到数据库中又会有一定的问题,就是 浏览…...
深入学习MapReduce:原理解析与基础实战
标题:深入学习MapReduce:原理解析与基础实战 MapReduce是一种分布式计算框架,用于大规模数据的处理和分析。作为Hadoop生态系统的核心组件,MapReduce凭借其简单的编程模型和强大的并行计算能力,广泛应用于大数据领域。…...
医院数据库优化:提升性能与响应时间的关键策略
一、引言 在当今数智化时代,医院信息系统不仅要追踪管理伴随人流、财流、物流所产生的管理信息,还应支持以病人医疗信息记录为中心的整个医疗、科学、科研活动,提高整个医院的运作效率。但随着信息化系统积累数据的增长,特别是病…...
OpenAI Whisper 语音识别 模型部署及接口封装
环境配置: 一、安装依赖: pip install -U openai-whisper 或者,以下命令会从这个存储库拉取并安装最新的提交,以及其Python依赖项: pip install githttps://github.com/openai/whisper.git 二、安装ffmpeg: cd …...
设计模式 外观模式 门面模式
结构性模式-外观模式 门面模式 适用场景:如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。 不用关心后面的查询具体操作 /*** 聚合查询接口*/ RestController RequestMapping("/search") Slf…...
AI智算-正式上架GPU资源监控概览 Grafana Dashboard
下载链接 https://grafana.com/grafana/dashboards/22424-ai-gpu-20241127/...
颜色分类
颜色分类 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地 对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 sort 函数…...
使用 pycharm 新建使用 conda 虚拟 python 环境的工程
1. conda 常见命令复习: conda env list // 查看 conda 环境列表 conda activate xxxenv // 进入指定 conda 环境2. 环境展示: 2.1. 我的物理环境的 Python 版本为 3.10.9: 2.2. 我的 conda 虚拟环境 env_yolov9_python_3_8 中的 pyth…...
图形渲染性能优化
variable rate shading conditional render 设置可见性等, 不需要重新build command buffer indirect draw glMultiDraw* - 直接支持多次绘制glMultiDrawIndirect - 间接多次绘制multithreading 多线程录制 实例化渲染 lod texture array 小对象剔除 投影到…...
14、保存与加载PyTorch训练的模型和超参数
文章目录 1. state_dict2. 模型保存3. check_point4. 详细保存5. Docker6. 机器学习常用库 1. state_dict nn.Module 类是所有神经网络构建的基类,即自己构建一个深度神经网络也是需要继承自nn.Module类才行,并且nn.Module中的state_dict包含神经网络中…...
简单获取json预览
data: JSON 数据。 collapsedNodeLength: 对象或数组的长度超过此阈值时会折叠 deep: json路径深度超过此值时会折叠 showLineNumber: 显示左侧行号 showIcon: 显示图标。 virtual: 使用虚拟滚动 height: 使用虚拟滚动时列表的高度 itemHeight: 使用虚拟滚动时节点的高…...
【C语言】连接陷阱探秘(5):头文件
目录 一、头文件的作用 1.1. 声明共享 1.2. 模块化 1.3. 实践中的注意事项 二、常见的头文件陷阱 2.1 重复包含(Include Guards) 2.1.1. Include Guard 工作原理 2.1.2. Pragma Once(某些编译器支持) 2.2 循环依赖(Circular Dependencies) 2.2.1. 前向声明 2.…...
burpsuite功能模块学习(2)
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
Vue 2.0->3.0学习笔记(Vue 3 (四)- Composition API 的优势)
Vue 2.0->3.0学习笔记(Vue 3 (四)- Composition API 的优势) Composition API 的优势1. Options API 存在的问题2. Composition API 的优势 Composition API 的优势 1. Options API 存在的问题 笔记 使用传统OptionsA…...
在 ASP.NET C# Web API 中实现 Serilog 以增强请求和响应的日志记录
介绍 日志记录是任何 Web 应用程序的关键方面。它有助于调试、性能监控和了解用户交互。在 ASP.NET C# 中,集成 Serilog 作为记录请求和响应(包括传入和传出的数据)的中间件可以显著提高 Web API 的可观察性和故障排除能力。 在过去的几周里&…...
MongoDB集群分片安装部署手册
文章目录 一、集群规划1.1 集群安装规划1.2 端口规划1.3 目录创建 二、mongodb安装(三台均需要操作)2.1 下载、解压2.2 配置环境变量 三、mongodb组件配置3.1 配置config server的副本集3.1.1 config配置文件3.1.2 config server启动3.1.3 初始化config …...
DimensionX 学习部署笔记
目录 依赖项: huggingface/DimensionX 是huggingface 下载后的目录; 报错处理参考网址: 测试代码 ok: 依赖项: pip install peft huggingface/DimensionX 是huggingface 下载后的目录; orbit_left_lora_weights.safetensors orbit_up_lora_weights.safetensors …...
设计模式:11、迭代器模式(游标)
目录 0、定义 1、迭代器模式的四种角色 2、迭代器模式的UML类图 3、示例代码 4、迭代器的next()方法与集合的get(int index)方法的效率对比(LinkedList为例) 0、定义 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象…...
【CameraPoseRefinement】以BARF为例介绍三维重建中的位姿优化
文章目录 IntroductionApproachPlanar Image Alignment(2D)Neural Radiance Fields (3D)Bundle-Adjusting Neural Radiance Fields Experiment平面图像对齐的定性实验合成场景上的定量实验 Introduction 在计算机视觉三维重建中,求解3D场景的表示和定位给定的相机帧…...
大语言模型压缩技术;推理优化技术;SparseGPT算法;GPTQ算法
目录 大语言模型落地的成本、效率与效果 模型压缩技术 推理优化技术 SparseGPT算法 GPTQ算法 大语言模型落地的成本、效率与效果 模型压缩技术 模型压缩技术是大语言模型轻量化的关键。介绍了多种模型压缩方法,其中权重量化和模型稀疏化是两种主要的技术。 权重量化:权重…...
ctrl键和大写键互换解决方法
电脑卡住之后突然发现Ctrl键和大小写键(CapsLock)互换了,后面试了几种方法都没解决这个问题,最后在万能的贴吧中找到解决方法——键位复位。 108和87键位复位操作: 1.先按住FN不放, 然后,再按住…...
spring boot mapper测试类优化
spring boot mapper测试类优化 有些时候我们只需要测试在 mybatis 写的mapper 是否正确,在注入mapper的时候, SpringBootTest 会启动整个容器,包括servlet容器和spring 容器,随着项目文件数逐渐增加,测试一个类会启动…...
k8s集成skywalking
如果能科学上网的话,安装应该不难,如果有问题可以给我留言 本篇文章我将给大家介绍“分布式链路追踪”的内容,对于目前大部分采用微服务架构的公司来说,分布式链路追踪都是必备的,无论它是传统微服务体系亦或是新一代…...
贪心算法理论
系列博客目录 文章目录 系列博客目录贪心算法 (Greedy Algorithm)贪心算法的特点贪心算法的适用条件常见的贪心算法问题贪心算法的步骤贪心算法示例:活动选择问题贪心算法的优缺点 贪心算法 (Greedy Algorithm) 贪心算法是一种在每一步选择中都采取当前状态下最优的…...
前端项目扫描漏洞整改的解决方案,附带部分漏洞的解决方法。
天崩开局 最近项目开始了漏洞扫描,于是乎 哎嘿嘿。。。 我直接彻底疯狂!!!! 我真的受不了了,这破班谁爱上谁上!依赖开发的锅,为什么要我来背。 在这里点名批评一下 inflight&#…...
brew安装NVM新手教程
首先确保macos下已安装好brew,搜索nvm资源代码: brew search nvm 演示效果图如下: 安装命令 brew install nvm 卸载命令 brew uninstall node 安装完成后提示如下: 直接命令行执行下代码的代码 export NVM_DIR"$HOME/.…...
Open3D (C++) 生成任意2D椭圆点云
目录 一、算法原理二、代码实现三、结果展示一、算法原理 椭圆标准参数方程为: x = a ∗ c o s ( t ) y = b ∗...
前端框架Vue3项目实战(基于Vue3实现一个小相册)
下面是是对Vue3操作的一个项目实战 下面代码是html的基本骨架(没有任何的功能): <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>相册</title> <style&…...