小目标检测利器:YOLOv8+SAHI使用教程

news2024/12/24 17:32:49

《博主简介》

小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。
更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~
👍感谢小伙伴们点赞、关注!

《------往期经典推荐------》

一、AI应用软件开发实战专栏【链接】

项目名称项目名称
1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】
3.【手势识别系统开发】4.【人脸面部活体检测系统开发】
5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】
7.【YOLOv8多目标识别与自动标注软件开发】8.【基于YOLOv8深度学习的行人跌倒检测系统】
9.【基于YOLOv8深度学习的PCB板缺陷检测系统】10.【基于YOLOv8深度学习的生活垃圾分类目标检测系统】
11.【基于YOLOv8深度学习的安全帽目标检测系统】12.【基于YOLOv8深度学习的120种犬类检测与识别系统】
13.【基于YOLOv8深度学习的路面坑洞检测系统】14.【基于YOLOv8深度学习的火焰烟雾检测系统】
15.【基于YOLOv8深度学习的钢材表面缺陷检测系统】16.【基于YOLOv8深度学习的舰船目标分类检测系统】
17.【基于YOLOv8深度学习的西红柿成熟度检测系统】18.【基于YOLOv8深度学习的血细胞检测与计数系统】
19.【基于YOLOv8深度学习的吸烟/抽烟行为检测系统】20.【基于YOLOv8深度学习的水稻害虫检测与识别系统】
21.【基于YOLOv8深度学习的高精度车辆行人检测与计数系统】22.【基于YOLOv8深度学习的路面标志线检测与识别系统】
23.【基于YOLOv8深度学习的智能小麦害虫检测识别系统】24.【基于YOLOv8深度学习的智能玉米害虫检测识别系统】
25.【基于YOLOv8深度学习的200种鸟类智能检测与识别系统】26.【基于YOLOv8深度学习的45种交通标志智能检测与识别系统】
27.【基于YOLOv8深度学习的人脸面部表情识别系统】28.【基于YOLOv8深度学习的苹果叶片病害智能诊断系统】
29.【基于YOLOv8深度学习的智能肺炎诊断系统】30.【基于YOLOv8深度学习的葡萄簇目标检测系统】
31.【基于YOLOv8深度学习的100种中草药智能识别系统】32.【基于YOLOv8深度学习的102种花卉智能识别系统】
33.【基于YOLOv8深度学习的100种蝴蝶智能识别系统】34.【基于YOLOv8深度学习的水稻叶片病害智能诊断系统】
35.【基于YOLOv8与ByteTrack的车辆行人多目标检测与追踪系统】36.【基于YOLOv8深度学习的智能草莓病害检测与分割系统】
37.【基于YOLOv8深度学习的复杂场景下船舶目标检测系统】38.【基于YOLOv8深度学习的农作物幼苗与杂草检测系统】
39.【基于YOLOv8深度学习的智能道路裂缝检测与分析系统】40.【基于YOLOv8深度学习的葡萄病害智能诊断与防治系统】
41.【基于YOLOv8深度学习的遥感地理空间物体检测系统】42.【基于YOLOv8深度学习的无人机视角地面物体检测系统】
43.【基于YOLOv8深度学习的木薯病害智能诊断与防治系统】44.【基于YOLOv8深度学习的野外火焰烟雾检测系统】
45.【基于YOLOv8深度学习的脑肿瘤智能检测系统】46.【基于YOLOv8深度学习的玉米叶片病害智能诊断与防治系统】
47.【基于YOLOv8深度学习的橙子病害智能诊断与防治系统】48.【基于深度学习的车辆检测追踪与流量计数系统】
49.【基于深度学习的行人检测追踪与双向流量计数系统】50.【基于深度学习的反光衣检测与预警系统】
51.【基于深度学习的危险区域人员闯入检测与报警系统】52.【基于深度学习的高密度人脸智能检测与统计系统】
53.【基于深度学习的CT扫描图像肾结石智能检测系统】54.【基于深度学习的水果智能检测系统】
55.【基于深度学习的水果质量好坏智能检测系统】56.【基于深度学习的蔬菜目标检测与识别系统】
57.【基于深度学习的非机动车驾驶员头盔检测系统】58.【基于深度学习的太阳能电池板检测与分析系统】
59.【基于深度学习的工业螺栓螺母检测】60.【基于深度学习的金属焊缝缺陷检测系统】
61.【基于深度学习的链条缺陷检测与识别系统】62.【基于深度学习的交通信号灯检测识别】
63.【基于深度学习的草莓成熟度检测与识别系统】64.【基于深度学习的水下海生物检测识别系统】
65.【基于深度学习的道路交通事故检测识别系统】

二、机器学习实战专栏【链接】,已更新31期,欢迎关注,持续更新中~~
三、深度学习【Pytorch】专栏【链接】
四、【Stable Diffusion绘画系列】专栏【链接】
五、YOLOv8改进专栏【链接】持续更新中~~
六、YOLO性能对比专栏【链接】,持续更新中~

《------正文------》

目录

  • 引言
  • 为什么探测小物体很难?
    • 目标太小
    • 训练数据
    • 固定输入尺寸
  • SAHI如何工作
  • 实际案例
  • 使用YOLOv8进行标准推理
  • 使用SAHI进行超推理
  • 评估SAHI预测结果
  • 后续优化

引言

img

目标检测是计算机视觉的基本任务之一。在高层次上,它涉及预测图像中对象的位置和类别。像You-Only-Look-Once(YOLO)家族中的那些最先进的(SOTA)深度学习模型已经达到了惊人的准确度。然而,目标检测中一个众所周知的挑战性前沿是小目标。

在这篇文章中,你将学习如何使用切片辅助超推理(Slicing Aided Hyper Inference --SAHI)检测数据集中的小对象。主要包括以下内容:

  • 为什么很难发现小物体
  • SAHI如何工作
  • 如何将SAHI应用于数据集
  • 如何评价这些预测的性能

为什么探测小物体很难?

目标太小

首先,检测小物体很难,因为小物体很。物体越小,检测模型必须处理的信息就越少。如果一辆汽车在远处,它可能只占用我们图像中的几个像素。就像人类很难辨认出远处的物体一样,我们的模型很难识别出没有车轮和车牌等视觉可识别特征的汽车!

训练数据

模型的好坏取决于它们所训练的数据。大多数标准对象检测数据集和基准测试都集中在大中型对象上,这意味着大多数现成的对象检测模型并未针对小对象检测进行优化。

固定输入尺寸

对象检测模型通常采用固定大小的输入。例如,YOLOv 8是在最大边长为640像素的图像上训练的。这意味着,当我们向它提供一个大小为1920 x1080的图像时,模型将在进行预测之前将图像降采样到640 x360,降低分辨率并丢弃小对象的重要信息。

SAHI如何工作

img

切片辅助超推理(Slicing Aided HyperInference)

从理论上讲,你可以在更大的图像上训练模型,以提高对小物体的检测。然而,实际上,这将需要更多的内存,更多的计算能力,以及更劳动密集型的数据集来创建。

另一种方法是利用现有的对象检测,将模型应用于图像中固定大小的补丁或切片,然后将结果拼接在一起。这就是切片辅助超推理背后的理念!

SAHI的工作原理是将图像划分为完全覆盖它的切片,并使用指定的检测模型对每个切片进行推理。然后将所有这些切片的预测合并在一起,以生成整个图像的检测列表。SAHI中的“hyper”来自于这样一个事实,即SAHI的输出不是模型推理的结果,而是涉及多个模型推理的计算结果。

💡允许SAHI切片重叠(如上面的GIF所示),这有助于确保至少有一个切片中有足够的物体被检测到。

使用SAHI的主要优点是它与模型无关。SAHI可以利用今天的SOTA对象检测模型未来的SOTA模型!

当然,天下没有免费的午餐。作为“超推理”的交换,除了将结果拼接在一起所需的处理之外,您还运行了检测模型的多次向前传递。

实际案例

为了说明SAHI如何应用于检测小物体,我们将使用来自中国天津大学机器学习与数据挖掘实验室的AISKYEYE团队的VisDrone检测数据集。该数据集由8629张图像组成,边长从360像素到2000像素不等,使其成为SAHI的理想测试场。Ultralytics的YOLOv8l将作为我们的基本对象检测模型。

我们将使用以下库:

  • fiftyone数据集管理和可视化
  • huggingface_hub用于从Hugging Face Hub加载VisDrone数据集
  • 使用YOLOv 8运行推理的ultralytics,以及
  • 用于在图像切片上运行推理的Sahi

如果您还没有安装这些库的最新版本,请安装。您需要fiftyone>=0.23.8从Hugging Face Hub加载VisDrone:

pip install -U fiftyone sahi ultralytics huggingface_hub --quiet

现在,在Python进程中,让我们导入FiftyOne模块,我们将使用这些模块来查询和管理数据:

import fiftyone as fo
import fiftyone.zoo as foz
import fiftyone.utils.huggingface as fouh
from fiftyone import ViewField as F

就这样,我们准备好加载数据了!我们将使用FiftyOne的Hugging Face utils中的load_from_hub()函数通过其repo_id直接从Hugging Face Hub加载VisDrone数据集的一部分。

为了演示并保持代码执行尽可能快,我们将只从数据集中获取前100张图像。我们还将为我们正在创建的这个新数据集命名为“sahi-test”

dataset = fouh.load_from_hub(
    "Voxel51/VisDrone2019-DET", 
    name="sahi-test", 
    max_samples=100
)

在添加任何预测之前,让我们看看我们在FiftyOne应用程序中的数据集:

session = fo.launch_app(dataset)

img

使用YOLOv8进行标准推理

在下一节中,我们将使用SAHI对我们的数据进行超推理。在引入SAHI之前,让我们使用Ultralytics的YOLOv8模型的大型变体对我们的数据运行标准对象检测推理。

首先,我们创建一个ultralytics.YOLO模型实例,必要时下载模型检查点。然后,我们将此模型应用于我们的数据集,并将结果存储在样本的“base_model”字段中:
python

from ultralytics import YOLO

ckpt_path = "yolov8l.pt"
model = YOLO(ckpt_path)

dataset.apply_model(model, label_field="base_model")
session.view = dataset.view()

img

我们可以通过查看地面真实标签旁边的模型预测来看到一些东西。首先,我们的YOLOv8l模型检测到的类与VisDrone数据集中的真实类不同。我们的YOLO模型是在COCO数据集上训练的,COCO数据集有80个类,而VisDrone数据集有12个类,包括一个ignore_regions类。

为了简化比较,我们只关注数据集中最常见的几个类,并将VisDrone类映射到COCO类,如下所示:

mapping = {"pedestrians": "person", "people": "person", "van": "car"}
mapped_view = dataset.map_labels("ground_truth", mapping)

然后过滤我们的标签,只包含我们感兴趣的类:

def get_label_fields(sample_collection):
    """Get the (detection) label fields of a Dataset or DatasetView."""
    label_fields = list(
        sample_collection.get_field_schema(embedded_doc_type=fo.Detections).keys()
    )
    return label_fields

def filter_all_labels(sample_collection):
    label_fields = get_label_fields(sample_collection)

    filtered_view = sample_collection

    for lf in label_fields:
        filtered_view = filtered_view.filter_labels(
            lf, F("label").is_in(["person", "car", "truck"]), only_matches=False
        )
    return filtered_view

filtered_view = filter_all_labels(mapped_view)
session.view = filtered_view.view()

img

现在我们已经有了基本模型预测,让我们使用SAHI来切片和切割我们的图像。💪

使用SAHI进行超推理

SAHI技术在我们之前安装的sahiPython包中实现。SAHI是一个与许多对象检测模型兼容的框架,包括YOLOv 8。我们可以选择我们想要使用的检测模型,并创建sahi.models.DetectionModel子类的任何类的实例,包括YOLOv8、YOLOv5,甚至拥抱脸变形金刚模型。

我们将使用SAHI的AutoDetectionModel类创建模型对象,指定模型类型和检查点文件的路径:

from sahi import AutoDetectionModel
from sahi.predict import get_prediction, get_sliced_prediction

detection_model = AutoDetectionModel.from_pretrained(
    model_type='yolov8',
    model_path=ckpt_path,
    confidence_threshold=0.25, ## same as the default value for our base model
    image_size=640,
    device="cpu", # or 'cuda' if you have access to GPU
)

在我们生成切片预测之前,让我们使用SAHI的get_prediction()函数检查模型对试验图像的预测:

result = get_prediction(dataset.first().filepath, detection_model)
print(result)
<sahi.prediction.PredictionResult object at 0x2b0e9c250>

幸运的是,SAHI结果对象有一个to_fiftyone_detections()方法,它将结果转换为FiftyOneDetection对象的列表:

print(result.to_fiftyone_detections())
[<Detection: {
    'id': '661858c20ae3edf77139db7a',
    'attributes': {},
    'tags': [],
    'label': 'car',
    'bounding_box': [
        0.6646394729614258,
        0.7850866247106482,
        0.06464214324951172,
        0.09088355170355902,
    ],
    'mask': None,
    'confidence': 0.8933132290840149,
    'index': None,
}>, <Detection: {
    'id': '661858c20ae3edf77139db7b',
    'attributes': {},
    'tags': [],
    'label': 'car',
    'bounding_box': [
        0.6196376800537109,
        0.7399617513020833,
        0.06670347849527995,
        0.09494832356770834,
    ],
    'mask': None,
    'confidence': 0.8731599450111389,
    'index': None,
}>, <Detection: {
   ....
   ....
   ....

这使我们的数据处理变得简单,因此我们可以专注于数据,而不是格式转换的细节。SAHI的get_sliced_prediction()函数的工作方式与get_prediction()函数相同,但有一些额外的超参数让我们配置图像的切片方式。特别是,我们可以指定切片的高度和宽度,以及切片之间的重叠。下面是一个示例:

sliced_result = get_sliced_prediction(
    dataset.skip(40).first().filepath,
    detection_model,
    slice_height = 320,
    slice_width = 320,
    overlap_height_ratio = 0.2,
    overlap_width_ratio = 0.2,
)

作为初步检查,我们可以将切片预测中的检测数量与原始预测中的检测数量进行比较:

num_sliced_dets = len(sliced_result.to_fiftyone_detections())
num_orig_dets = len(result.to_fiftyone_detections())

print(f"Detections predicted without slicing: {num_orig_dets}")
print(f"Detections predicted with slicing: {num_sliced_dets}")

Detections predicted without slicing: 17
Detections predicted with slicing: 73

我们可以看到,预测的数量大幅增加!我们还没有确定额外的预测是否有效,或者我们只是有更多的误报。我们将很快使用FiftyOne的Evaluation API来实现这一点。我们还想为切片找到一组好的超参数。我们需要将SAHI应用于整个数据集来完成所有这些事情。

为了简化这个过程,我们将定义一个函数,它将预测添加到指定标签字段中的样本,然后我们将遍历数据集,将该函数应用于每个样本。该函数将样本的文件路径和切片超参数传递给get_sliced_prediction(),然后将预测添加到指定标签字段中的样本:

def predict_with_slicing(sample, label_field, **kwargs):
    result = get_sliced_prediction(
        sample.filepath, detection_model, verbose=0, **kwargs
    )
    sample[label_field] = fo.Detections(detections=result.to_fiftyone_detections())

我们将切片重叠固定为0.2,并查看切片高度和宽度如何影响预测的质量:

kwargs = {"overlap_height_ratio": 0.2, "overlap_width_ratio": 0.2}

for sample in dataset.iter_samples(progress=True, autosave=True):
    predict_with_slicing(sample, label_field="small_slices", slice_height=320, slice_width=320, **kwargs)
    predict_with_slicing(sample, label_field="large_slices", slice_height=480, slice_width=480, **kwargs)

请注意,这些推理时间比原始推理时间长得多。这是因为我们在每个图像的多个切片上运行模型,这增加了模型必须进行的向前传递的数量。我们正在做出权衡,以提高对小物体的检测。

现在,让我们再次过滤标签,仅包含我们感兴趣的类,并在FiftyOne应用程序中可视化结果:

filtered_view = filter_all_labels(mapped_view)
session = fo.launch_app(filtered_view, auto=False)

img

结果看起来很有希望!从一些视觉示例来看,切片似乎可以提高地面实况检测的覆盖率,特别是较小的切片似乎可以捕获更多的检测。但我们怎么能确定呢?让我们运行一个评估例程,将检测标记为真阳性、假阳性或假阴性,以将切片预测与地面实况进行比较。我们将使用过滤视图的evaluate_detections()方法。

评估SAHI预测结果

保持我们对数据集的过滤视图,让我们运行一个评估示例,将来自每个预测标签字段的预测与真实标签进行比较。在这里,我们使用默认的IoU阈值0.5,但您可以根据需要进行调整:

base_results = filtered_view.evaluate_detections("base_model", gt_field="ground_truth", eval_key="eval_base_model")
large_slice_results = filtered_view.evaluate_detections("large_slices", gt_field="ground_truth", eval_key="eval_large_slices")
small_slice_results = filtered_view.evaluate_detections("small_slices", gt_field="ground_truth", eval_key="eval_small_slices")

让我们为每个打印一个报告:

print("Base model results:")
base_results.print_report()

print("-" * 50)
print("Large slice results:")
large_slice_results.print_report()

print("-" * 50)
print("Small slice results:")
small_slice_results.print_report()
Base model results:
              precision    recall  f1-score   support

         car       0.81      0.55      0.66       692
      person       0.94      0.16      0.28      7475
       truck       0.66      0.34      0.45       265

   micro avg       0.89      0.20      0.33      8432
   macro avg       0.80      0.35      0.46      8432
weighted avg       0.92      0.20      0.31      8432

--------------------------------------------------
Large slice results:
              precision    recall  f1-score   support

         car       0.67      0.71      0.69       692
      person       0.89      0.34      0.49      7475
       truck       0.55      0.45      0.49       265

   micro avg       0.83      0.37      0.51      8432
   macro avg       0.70      0.50      0.56      8432
weighted avg       0.86      0.37      0.51      8432

--------------------------------------------------
Small slice results:
              precision    recall  f1-score   support

         car       0.66      0.75      0.70       692
      person       0.84      0.42      0.56      7475
       truck       0.49      0.46      0.47       265

   micro avg       0.80      0.45      0.57      8432
   macro avg       0.67      0.54      0.58      8432
weighted avg       0.82      0.45      0.57      8432

我们可以看到,随着我们引入更多的切片,假阳性的数量增加,而假阴性的数量减少。这是意料之中的,因为模型能够用更多的切片检测更多的对象,但也会犯更多的错误!您可以应用更积极的置信度阈值来对抗这种误报的增加,但即使不这样做,F1分数也会显着提高。

让我们更深入地研究这些结果。我们之前注意到,模型在处理小对象时会遇到困难,所以让我们看看这三种方法在处理小于32 x32像素的对象时的效果如何。我们可以使用FiftyOne的ViewField来执行此过滤:

## Filtering for only small boxes

box_width, box_height = F("bounding_box")[2], F("bounding_box")[3]
rel_bbox_area = box_width * box_height

im_width, im_height = F("$metadata.width"), F("$metadata.height")
abs_area = rel_bbox_area * im_width * im_height

small_boxes_view = filtered_view
for lf in get_label_fields(filtered_view):
    small_boxes_view = small_boxes_view.filter_labels(lf, abs_area < 32**2, only_matches=False)

session.view = small_boxes_view.view()

img

如果我们像以前一样根据这些视图评估我们的模型并打印报告,我们就可以清楚地看到SAHI提供的价值!使用SAHI时,对于小对象的召回率要高得多,而精度没有显著下降,从而提高了F1分数。这对于人员检测尤其明显,其中F1分数是三倍!

## Evaluating on only small boxes
small_boxes_base_results = small_boxes_view.evaluate_detections("base_model", gt_field="ground_truth", eval_key="eval_small_boxes_base_model")
small_boxes_large_slice_results = small_boxes_view.evaluate_detections("large_slices", gt_field="ground_truth", eval_key="eval_small_boxes_large_slices")
small_boxes_small_slice_results = small_boxes_view.evaluate_detections("small_slices", gt_field="ground_truth", eval_key="eval_small_boxes_small_slices")

## Printing reports
print("Small Box — Base model results:")
small_boxes_base_results.print_report()

print("-" * 50)
print("Small Box — Large slice results:")
small_boxes_large_slice_results.print_report()

print("-" * 50)
print("Small Box — Small slice results:")
small_boxes_small_slice_results.print_report()
Small Box — Base model results:
              precision    recall  f1-score   support

         car       0.71      0.25      0.37       147
      person       0.83      0.08      0.15      5710
       truck       0.00      0.00      0.00        28

   micro avg       0.82      0.08      0.15      5885
   macro avg       0.51      0.11      0.17      5885
weighted avg       0.82      0.08      0.15      5885

--------------------------------------------------
Small Box — Large slice results:
              precision    recall  f1-score   support

         car       0.46      0.48      0.47       147
      person       0.82      0.23      0.35      5710
       truck       0.20      0.07      0.11        28

   micro avg       0.78      0.23      0.36      5885
   macro avg       0.49      0.26      0.31      5885
weighted avg       0.80      0.23      0.36      5885

--------------------------------------------------
Small Box — Small slice results:
              precision    recall  f1-score   support

         car       0.42      0.53      0.47       147
      person       0.79      0.31      0.45      5710
       truck       0.21      0.18      0.19        28

   micro avg       0.75      0.32      0.45      5885
   macro avg       0.47      0.34      0.37      5885
weighted avg       0.77      0.32      0.45      5885

后续优化

在本示例中,我们介绍了如何将SAHI预测添加到数据中,然后严格评估切片对预测质量的影响。我们已经看到了切片辅助超推理(SAHI)如何提高检测的召回率和F1分数,特别是对于小对象,而不需要在较大的图像上训练模型。

为了最大限度地提高SAHI的有效性,您可能需要进行以下试验:

  • 切片超参数,如切片高度和宽度以及重叠
  • 基本对象检测模型,因为SAHI与许多模型兼容,包括YOLOv 5和拥抱脸变形器模型
  • 可能在逐个类别的基础上进行置信度阈值处理,以减少误报的数量
  • 后处理技术,如非最大抑制(NMS),以减少重叠检测的数量

无论你想调整什么参数,重要的是要获取更高的性能指标。在执行小物体检测任务时,图像中的小物体越多,丢失“地面实况”标签的可能性就越大。SAHI可以帮助您发现潜在的错误,您可以使用人在回路(HITL)工作流程纠正这些错误。


关注文末名片G-Z-H:【阿旭算法与机器学习】,发送【开源】可获取更多学习资源

在这里插入图片描述

好了,这篇文章就介绍到这里,喜欢的小伙伴感谢给点个赞和关注,更多精彩内容持续更新~~
关于本篇文章大家有任何建议或意见,欢迎在评论区留言交流!

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

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

相关文章

软考系统分析师知识点三:应用数学

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;34天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…

vSAN06:ESA与OSA对比、ESA安装、新架构、工作方式、自动策略管理、原生快照、数据压缩、故障处理

目录 vSAN ESAvSAN ESA 安装ESA新架构ESA工作方式ESA自动策略管理自适应RAID5策略 原生快照支持数据压缩的改进ESA故障处理 vSAN ESA vSAN ESA 安装 流程和OSA完全一致&#xff0c;但要注意要勾选启用vSAN ESA ESA和OSA的底层架构不一样&#xff0c;但是UI上是一致的。 生产环…

【C++】第二节:类与对象(上)

1、面向过程和面向对象初步认识 C 语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C 是面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间的交互完成。 …

【ESP32】Arduino开发 | Timer定时器+定时器闹钟例程

有关定时器外设的详细介绍在ESP-IDF的对应文章中&#xff0c;跳转栏目目录可以找到。 1. API 1.1 启动定时器 hw_timer_t * timerBegin(uint8_t timer, uint16_t divider, bool countUp); timer&#xff1a;定时器序号&#xff08;ESP32有4个硬件定时器&#xff0c;所以可填序…

您看这篇就够了:ComfyUI 新手指南!

前言 欢迎来到 ComfyUI 的神奇世界&#xff0c;这是 Stable Diffusion 的一个强大而灵活的图形用户界面。无论你是数字艺术的新手&#xff0c;还是希望将你的图像创作提升到新高度的老手&#xff0c;ComfyUI 都能满足你的需求。在这篇全面的指南中&#xff0c;我们将带你穿越 …

2003经典绝版100%仿盛大服务端火炬引擎原版

;中国游戏制作 本版本为中国游戏制作小组推出的第一个版本&#xff0c;有什么不完美的地方还请大家多多指教&#xff01;&#xff01;&#xff01; 与盛大逼真&#xff01;&#xff01;&#xff01; 本版本M2Server采用“梦幻风”以及“冰眼”M2Server修改器修改的 2004/1/…

vue项目配置cesium

vue中配置cesium ①打开目标文件夹的终端&#xff0c;输入 pnpm install cesium ②这时你的node_models文件夹下&#xff0c;会出现cesium文件夹&#xff1b;然后&#xff0c;其中Build/Cesium文件夹&#xff0c;复制到public文件夹下。 ③打开public/index.html文件&#xf…

Linux下载安装MySQL8.4

这里写目录标题 一、准备工作查看系统环境查看系统架构卸载已安装的版本 二、下载MySQL安装包官网地址 三、安装过程上传到服务器目录解压缩&#xff0c;设置目录及权限配置my.cnf文件初始化数据库配置MySQL开放端口 一、准备工作 查看系统环境 确认Linux系统的版本和架构&am…

[单master节点k8s部署]31.ceph分布式存储(二)

Ceph配置 Ceph集群通常是一个独立的存储集群&#xff0c;可以部署在 Kubernetes 集群之外。Ceph 提供分布式存储服务&#xff0c;能够通过 RADOS、CephFS、RBD&#xff08;块存储&#xff09;、和 RGW&#xff08;对象存储&#xff09;等方式与 Kubernetes 集成。即使 Ceph 部…

SumatraPDF一打开就无响应怎么办?

结论&#xff1a;当前安装版不论32位还是64位都会出现问题。使用portable免安装版未发现相关问题。——sumatrapdf可以用于pdf, epub, mobi 等格式文件的浏览。 点击看相关问题和讨论

如何使用 Python 的 logging 模块记录日志

如何使用 Python 的 logging 模块记录日志 在编写 Python 程序时&#xff0c;日志记录是一个非常重要的部分。日志不仅帮助你在开发过程中调试代码&#xff0c;还可以在程序正式运行时提供诊断信息&#xff0c;帮助定位问题。如果你正在构建一个复杂的系统或者开发大型应用程序…

【数据结构】【队列】算法汇总

一、顺序队列【相当于一维数组】 1.准备工作 #define MAXQSIZE 100 typedef struct{QElemType*base;int front;int rear; }SqQueue; 2.队满&#xff0c;队空。入队&#xff0c;出队 二、链式队列 1.准备工作 typedef struct Qnode{ElemType data;struct Qnode*next; }Qnod…

深入浅出解析大模型:探索智能体(Agent)

大语言模型 vs 人类 大语言模型很强大&#xff0c;就像人类的大脑一样拥有思考的能力。如果人类只有大脑&#xff0c;没有四肢&#xff0c;没有工具&#xff0c;是没办法与世界互动的。如果我们能给大模型配备上四肢和工具呢&#xff1f;大模型是不是就会打破次元壁&#xff0…

GD32F4xx USB MSC Host调试记录

本文记录GD32F4xx MCU的RTX系统工程内移植USB MSC Host的例程代码,适配自制的电路板,实现向USB内写入数据。有关USB的一些基础信息,可以参考本专栏的另一篇文章《GD32 MCU USB开发学习记录》。 目录 1. USB MSC host 例程1.1、硬件接口2.2、USB msc host 例程2.2.1 工程目录…

dz论坛可可积分商城插件价值399元

界面简洁美观大方&#xff0c;适合各类站点。支持多用户商城&#xff0c;可让商家入驻站点发布商品&#xff0c;亦可站长自己发布商品。支持向商家抽佣抽成功能&#xff0c;可设置商家在成交商品后按一定比例扣除抽成&#xff0c;达到网站盈利目的采用队列技术处理&#xff0c;…

【ubuntu22.04】 搭建自己的镜像站 【harbor】【docker compose】【超详细】

文章目录 什么是 harbor特点主要功能 部署配置 dns初始化下载 dns编辑 named.conf.local编辑 named.conf.options配置正向解析配置反向解析解析扩展 部署 harbor修改配置执行 prepare执行 install.sh查看镜像访问 自制镜像创建镜像仓库上传镜像开始推送拉取镜像 什么是 harbor …

宏队列和微队列

1、javascript是一个单线程语言。 javascript 语言的目的&#xff08;待补充&#xff09; 2、主线程执行完成之后&#xff0c;再执行微队列&#xff0c;微队列执行完成后再执行宏队列 3、promise的构造函数传入的回调函数是同步执行 4、promise的then函数会直接加入微队列&…

Java 中的 LinkedHashMap

让我们从一个简单的 Java 代码片段开始&#xff0c;演示如何在 Java 中创建和使用 LinkedHashMap。 import java.util.LinkedHashMap; public class LinkedHashMapCreation { public static void main(String[] args) { // Create a LinkedHashMap of S…

【AI知识点】批归一化(Batch Normalization)

批归一化&#xff08;Batch Normalization&#xff0c;BN&#xff09; 是一种用于加速神经网络训练并提高模型稳定性的方法&#xff0c;最早由 Sergey Ioffe 和 Christian Szegedy 在 2015 年提出。批归一化通过在每一层对神经网络中的激活值进行标准化&#xff0c;使得每一层的…

半路出家:如何转行成为软件开发者——之找到一份工作

一、前言 一个半路出家的软件开发者&#xff0c;尽管只有短短几年软件开发的相关经验&#xff0c;却可以凭借他在其他领域积累的丰厚经验&#xff0c;最终一举超过单纯拥有更多软件开发经验的同行【有时拥有不同的专业背景&#xff08;甚至是与软件完全不搭界的行业&#xff09…