《使用 YOLOV8 和 KerasCV 进行高效目标检测》

《使用 YOLOV8 和 KerasCV 进行高效目标检测》

作者:Gitesh Chawda
创建日期:2023/06/26
最后修改时间:2023/06/26
描述:使用 KerasCV 训练自定义 YOLOV8 对象检测模型。

(i) 此示例使用 Keras 2

 在 Colab 中查看 •

 GitHub 源


介绍

KerasCV 是 Keras 的扩展,用于计算机视觉任务。在此示例中,我们将看到 如何使用 KerasCV 训练 YOLOV8 对象检测模型。

KerasCV 包括适用于常用计算机视觉数据集的预训练模型,例如 ImageNet、COCO 和 Pascal VOC,可用于迁移学习。KerasCV 还 提供了一系列用于检查中间表示的可视化工具 由模型学习,用于可视化对象检测和分割的结果 任务。

如果您有兴趣了解使用 KerasCV 进行对象检测,我强烈建议您 看看 Lukewood 创建的指南。此资源可在使用 KerasCV 进行对象检测中获得。 全面概述了基本概念和技术 使用 KerasCV 构建对象检测模型时需要。

!pip install --upgrade git+https://github.com/keras-team/keras-cv -q
[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv[0m[33m [0m 

设置

import os
from tqdm.auto import tqdm
import xml.etree.ElementTree as ETimport tensorflow as tf
from tensorflow import kerasimport keras_cv
from keras_cv import bounding_box
from keras_cv import visualization
/opt/conda/lib/python3.10/site-packages/tensorflow_io/python/ops/__init__.py:98: UserWarning: unable to load libtensorflow_io_plugins.so: unable to open file: libtensorflow_io_plugins.so, from paths: ['/opt/conda/lib/python3.10/site-packages/tensorflow_io/python/ops/libtensorflow_io_plugins.so'] caused by: ['/opt/conda/lib/python3.10/site-packages/tensorflow_io/python/ops/libtensorflow_io_plugins.so: undefined symbol: _ZN3tsl6StatusC1EN10tensorflow5error4CodeESt17basic_string_viewIcSt11char_traitsIcEENS_14SourceLocationE'] warnings.warn(f"unable to load libtensorflow_io_plugins.so: {e}") /opt/conda/lib/python3.10/site-packages/tensorflow_io/python/ops/__init__.py:104: UserWarning: file system plugins are not loaded: unable to open file: libtensorflow_io.so, from paths: ['/opt/conda/lib/python3.10/site-packages/tensorflow_io/python/ops/libtensorflow_io.so'] caused by: ['/opt/conda/lib/python3.10/site-packages/tensorflow_io/python/ops/libtensorflow_io.so: undefined symbol: _ZTVN10tensorflow13GcsFileSystemE'] warnings.warn(f"file system plugins are not loaded: {e}") 

加载数据

在本指南中,我们将使用从 roboflow 获取的自动驾驶汽车数据集。为了 使数据集更易于管理,我提取了较大数据集的子集,该子集 最初由 15,000 个数据样本组成。从这个子集中,我选择了 7,316 个 模型训练示例。

为了简化手头的任务并集中精力,我们将与减少的 对象类的数量。具体来说,我们将考虑 5 个主要类别 检测和分类:汽车、行人、红绿灯、骑自行车的人和卡车。这些 类表示 自动驾驶汽车的背景。

通过将数据集缩小到这些特定类,我们可以专注于构建 强大的对象检测模型,可以准确识别和分类这些重要 对象。

TensorFlow Datasets 库提供了一种下载和使用各种 数据集,包括对象检测数据集。对于那些人来说,这可能是一个不错的选择 想要快速开始处理数据而无需手动下载和 预处理它。

您可以在此处查看各种对象检测数据集 TensorFlow 数据集

但是,在此代码示例中,我们将演示如何从头开始加载数据集 使用 TensorFlow 的 tf.data 流水线。这种方法提供了更大的灵活性,并允许 您可以根据需要自定义预处理步骤。

加载 TensorFlow 数据集库中不可用的自定义数据集就是其中之一 使用 tf.data 管道的主要优势。此方法允许您 创建针对特定需求量身定制的自定义数据预处理管道,以及 要求。


超参数

SPLIT_RATIO = 0.2
BATCH_SIZE = 4
LEARNING_RATE = 0.001
EPOCH = 5
GLOBAL_CLIPNORM = 10.0

创建一个字典以将每个类名映射到唯一的数字标识符。这 mapping 用于在训练和推理期间对类标签进行编码和解码 对象检测任务。

class_ids = ["car","pedestrian","trafficLight","biker","truck",
]
class_mapping = dict(zip(range(len(class_ids)), class_ids))# Path to images and annotations
path_images = "/kaggle/input/dataset/data/images/"
path_annot = "/kaggle/input/dataset/data/annotations/"# Get all XML file paths in path_annot and sort them
xml_files = sorted([os.path.join(path_annot, file_name)for file_name in os.listdir(path_annot)if file_name.endswith(".xml")]
)# Get all JPEG image file paths in path_images and sort them
jpg_files = sorted([os.path.join(path_images, file_name)for file_name in os.listdir(path_images)if file_name.endswith(".jpg")]
)

下面的函数读取 XML 文件并查找图像名称和路径,然后 迭代 XML 文件中的每个对象以提取边界框坐标,并且 class 标签。

该函数返回三个值:图像路径、边界框列表(每个 表示为四个浮点数的列表:xmin、ymin、xmax、ymax)和类 ID 列表 (以整数表示)对应于每个边界框。获取类 ID 通过使用名为 的字典将类标签映射到整数值。class_mapping

def parse_annotation(xml_file):tree = ET.parse(xml_file)root = tree.getroot()image_name = root.find("filename").textimage_path = os.path.join(path_images, image_name)boxes = []classes = []for obj in root.iter("object"):cls = obj.find("name").textclasses.append(cls)bbox = obj.find("bndbox")xmin = float(bbox.find("xmin").text)ymin = float(bbox.find("ymin").text)xmax = float(bbox.find("xmax").text)ymax = float(bbox.find("ymax").text)boxes.append([xmin, ymin, xmax, ymax])class_ids = [list(class_mapping.keys())[list(class_mapping.values()).index(cls)]for cls in classes]return image_path, boxes, class_idsimage_paths = []
bbox = []
classes = []
for xml_file in tqdm(xml_files):image_path, boxes, class_ids = parse_annotation(xml_file)image_paths.append(image_path)bbox.append(boxes)classes.append(class_ids)
 0%| | 0/7316 [00:00<?, ?it/s] 

在这里,我们使用 tf.ragged.constant 从 和 列表创建不规则张量。参差不齐的张量是一种可以处理不同长度的 数据。这在处理具有 可变长度序列,例如文本或时间序列数据。bboxclasses

classes = [[8, 8, 8, 8, 8],      # 5 classes[12, 14, 14, 14],     # 4 classes[1],                  # 1 class[7, 7],               # 2 classes...]
bbox = [[[199.0, 19.0, 390.0, 401.0],[217.0, 15.0, 270.0, 157.0],[393.0, 18.0, 432.0, 162.0],[1.0, 15.0, 226.0, 276.0],[19.0, 95.0, 458.0, 443.0]],     #image 1 has 4 objects[[52.0, 117.0, 109.0, 177.0]],   #image 2 has 1 object[[88.0, 87.0, 235.0, 322.0],[113.0, 117.0, 218.0, 471.0]],   #image 3 has 2 objects...]

在这种情况下,每个图像的 and 列表具有不同的长度, 取决于图像中的对象数量和相应的边界框,以及 类。为了处理这种可变性,使用参差不齐的张量而不是常规张量。bboxclasses

稍后,这些参差不齐的张量用于使用该方法创建 tf.data.Dataset 。该方法通过以下方式从输入张量创建数据集 沿第一维度对它们进行切片。通过使用不规则张量,数据集可以处理 每张图像的数据长度不同,并提供灵活的输入管道以进一步 加工。from_tensor_slices

bbox = tf.ragged.constant(bbox)
classes = tf.ragged.constant(classes)
image_paths = tf.ragged.constant(image_paths)data = tf.data.Dataset.from_tensor_slices((image_paths, classes, bbox))

在训练和验证数据中拆分数据

# Determine the number of validation samples
num_val = int(len(xml_files) * SPLIT_RATIO)# Split the dataset into train and validation sets
val_data = data.take(num_val)
train_data = data.skip(num_val)

让我们看看数据加载和边界框格式化以使事情顺利进行。边界 KerasCV 中的框具有预先确定的格式。为此,您必须捆绑边界 框添加到符合下列要求的词典中:

bounding_boxes = {# num_boxes may be a Ragged dimension'boxes': Tensor(shape=[batch, num_boxes, 4]),'classes': Tensor(shape=[batch, num_boxes])
}

字典有两个键 和 ,每个键都映射到 TensorFlow RaggedTensor 或 Tensor 对象。Tensor 的形状为 ,其中 batch 是 batch 中的图像数,num_boxes 是 任何图像中的最大边界框数。4 表示 定义边界框:xmin、ymin、xmax、ymax。'boxes''classes''boxes'[batch, num_boxes, 4]

Tensor 的形状为 ,其中每个元素表示 Tensor 中相应边界框的类标签。num_boxes 尺寸可能参差不齐,这意味着 批次。'classes'[batch, num_boxes]'boxes'

最终 dict 应该是:

{"images": images, "bounding_boxes": bounding_boxes}
def load_image(image_path):image = tf.io.read_file(image_path)image = tf.image.decode_jpeg(image, channels=3)return imagedef load_dataset(image_path, classes, bbox):# Read Imageimage = load_image(image_path)bounding_boxes = {"classes": tf.cast(classes, dtype=tf.float32),"boxes": bbox,}return {"images": tf.cast(image, tf.float32), "bounding_boxes": bounding_boxes}

在这里,我们创建一个图层,将图像大小调整为 640x640 像素,同时保持 原始纵横比。与图像关联的边界框以格式指定。如有必要,调整大小后的图像将用零填充,以保持 原始纵横比。xyxy

KerasCV 支持的边界框格式: 1. CENTER_XYWH 2. XYWH 3. XYXY 4. REL_XYXY 5. REL_XYWH 6. YXYX 7. REL_YXYX

你可以在 docs 中关于 KerasCV 边界框格式的信息。

此外,还可以在任意两对之间执行格式转换:

boxes = keras_cv.bounding_box.convert_format(bounding_box,images=image,source="xyxy",  # Original Formattarget="xywh",  # Target Format (to which we want to convert))

数据增强

构建对象检测管道时最具挑战性的任务之一是数据 增大。它涉及对输入图像应用各种转换,以 增加训练数据的多样性,提高模型的能力 概括。但是,在处理对象检测任务时,它变得更加 复杂,因为这些转换需要了解底层边界框和 相应地更新它们。

KerasCV 为边界框增强提供原生支持。KerasCV 提供了一个 大量专为处理边界而设计的数据增强层 盒。这些图层会根据图像的原样智能地调整边界框坐标 transformed,确保边界框保持准确并与 增强图像。

通过利用 KerasCV 的功能,开发人员可以方便地集成边界 将 Box 友好的数据增强到他们的对象检测管道中。通过执行 在 tf.data 流水线中进行动态增强,该过程变得无缝且 高效,从而实现更好的训练和更准确的对象检测结果。

augmenter = keras.Sequential(layers=[keras_cv.layers.RandomFlip(mode="horizontal", bounding_box_format="xyxy"),keras_cv.layers.RandomShear(x_factor=0.2, y_factor=0.2, bounding_box_format="xyxy"),keras_cv.layers.JitteredResize(target_size=(640, 640), scale_factor=(0.75, 1.3), bounding_box_format="xyxy"),]
)

创建训练数据集

train_ds = train_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.shuffle(BATCH_SIZE * 4)
train_ds = train_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
train_ds = train_ds.map(augmenter, num_parallel_calls=tf.data.AUTOTUNE)

创建验证数据集

resizing = keras_cv.layers.JitteredResize(target_size=(640, 640),scale_factor=(0.75, 1.3),bounding_box_format="xyxy",
)val_ds = val_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.shuffle(BATCH_SIZE * 4)
val_ds = val_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
val_ds = val_ds.map(resizing, num_parallel_calls=tf.data.AUTOTUNE)

可视化

def visualize_dataset(inputs, value_range, rows, cols, bounding_box_format):inputs = next(iter(inputs.take(1)))images, bounding_boxes = inputs["images"], inputs["bounding_boxes"]visualization.plot_bounding_box_gallery(images,value_range=value_range,rows=rows,cols=cols,y_true=bounding_boxes,scale=5,font_scale=0.7,bounding_box_format=bounding_box_format,class_mapping=class_mapping,)visualize_dataset(train_ds, bounding_box_format="xyxy", value_range=(0, 255), rows=2, cols=2
)visualize_dataset(val_ds, bounding_box_format="xyxy", value_range=(0, 255), rows=2, cols=2
)

PNG 格式

PNG 格式

我们需要从 preprocessing 字典中提取输入并准备好它们 馈送到模型中。

def dict_to_tuple(inputs):return inputs["images"], inputs["bounding_boxes"]train_ds = train_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)val_ds = val_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.prefetch(tf.data.AUTOTUNE)

创建模型

YOLOv8 是一款尖端的 YOLO 模型,用于各种计算机视觉任务, 例如对象检测、图像分类和实例分割。Ultralytics, YOLOv5 的创建者还开发了 YOLOv8,其中包含许多改进和 与前代产品相比,架构和开发人员体验发生了变化。YOLOv8 是 在业内受到高度评价的最新最新型号。

下表比较了 5 种不同 YOLOv8 模型的性能指标与 不同大小(以像素为单位):YOLOv8n、YOLOv8s、YOLOv8m、YOLOv8l 和 YOLOv8x。 这些指标包括不同 验证数据的交并比 (IoU) 阈值,CPU 上的推理速度 ONNX 格式和 A100 TensorRT 、参数数量和浮点数 操作 (FLOP)(分别以百万和数十亿为单位)。由于 model 增加时,mAP、参数和 FLOPs 通常增加,而速度 减少。YOLOv8x 的 mAP、参数和 FLOP 最高,但也是最慢的 推理速度,而 YOLOv8n 具有最小的尺寸、最快的推理速度和最低的推理速度 mAP、参数和 FLOPs。

您可以在此 RoboFlow 博客中阅读有关 YOLOV8 及其架构的更多信息

首先,我们将创建一个 backbone 实例,供我们的 yolov8 检测器使用 类。

KerasCV 中提供的 YOLOV8 Backbones:

  1. 无权重:
1. yolo_v8_xs_backbone 2. yolo_v8_s_backbone 3. yolo_v8_m_backbone 4. yolo_v8_l_backbone 5. yolo_v8_xl_backbone 
  1. 使用预先训练的 coco 重量:
backbone = keras_cv.models.YOLOV8Backbone.from_preset("yolo_v8_s_backbone_coco"  # We will use yolov8 small backbone with coco weights
)
1. yolo_v8_xs_backbone_coco 2. yolo_v8_s_backbone_coco 2. yolo_v8_m_backbone_coco 2. yolo_v8_l_backbone_coco 2. yolo_v8_xl_backbone_coco Downloading data from https://storage.googleapis.com/keras-cv/models/yolov8/coco/yolov8_s_backbone.h5 20596968/20596968 [==============================] - 0s 0us/step 

接下来,让我们使用 构建一个 YOLOV8 模型,它接受一个特征 extractor 作为参数,则指定数字 of 对象类来根据列表的大小进行检测,该参数通知模型 数据集,最后,特征金字塔网络 (FPN) 深度由参数指定。YOLOV8Detectorbackbonenum_classesclass_mappingbounding_box_formatfpn_depth

使用上述任何 backbone 构建 YOLOV8 都很简单,这要归功于 KerasCV 的

yolo = keras_cv.models.YOLOV8Detector(num_classes=len(class_mapping),bounding_box_format="xyxy",backbone=backbone,fpn_depth=1,
)

编译模型

用于 YOLOV8 的损失

  1. 分类损失:此损失函数计算预期 类概率和实际类概率。在这种情况下,二进制分类问题的一个突出解决方案是 利用。我们利用了二进制交叉熵,因为每个被识别的事物都是 被归类为属于或不属于某个对象类(例如,一个人、一个 汽车等)。binary_crossentropy

  2. Box Loss:是用于衡量 预测边界框和地面实况。在这种情况下,完整 IoU (CIoU) 指标,它不仅衡量预测值和真实值之间的重叠 边界框,但还要考虑纵横比、中心距和 盒子大小。这些损失函数共同帮助优化对象检测模型,方法是 最小化 Predicted 和 Ground Truth 类概率之间的差异,以及 边界框。box_loss

optimizer = tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE,global_clipnorm=GLOBAL_CLIPNORM,
)yolo.compile(optimizer=optimizer, classification_loss="binary_crossentropy", box_loss="ciou"
)

COCO 指标回调

我们将使用 KerasCV 来评估模型并计算 Map(Mean Average Precision) 分数、Recall 和 Precision。我们还会在 mAP 评分提高。BoxCOCOMetrics

class EvaluateCOCOMetricsCallback(keras.callbacks.Callback):def __init__(self, data, save_path):super().__init__()self.data = dataself.metrics = keras_cv.metrics.BoxCOCOMetrics(bounding_box_format="xyxy",evaluate_freq=1e9,)self.save_path = save_pathself.best_map = -1.0def on_epoch_end(self, epoch, logs):self.metrics.reset_state()for batch in self.data:images, y_true = batch[0], batch[1]y_pred = self.model.predict(images, verbose=0)self.metrics.update_state(y_true, y_pred)metrics = self.metrics.result(force=True)logs.update(metrics)current_map = metrics["MaP"]if current_map > self.best_map:self.best_map = current_mapself.model.save(self.save_path)  # Save the model when mAP improvesreturn logs

训练模型

yolo.fit(train_ds,validation_data=val_ds,epochs=3,callbacks=[EvaluateCOCOMetricsCallback(val_ds, "model.h5")],
)
Epoch 1/3 1463/1463 [==============================] - 633s 390ms/step - loss: 10.1535 - box_loss: 2.5659 - class_loss: 7.5876 - val_loss: 3.9852 - val_box_loss: 3.1973 - val_class_loss: 0.7879 - MaP: 0.0095 - MaP@[IoU=50]: 0.0193 - MaP@[IoU=75]: 0.0074 - MaP@[area=small]: 0.0021 - MaP@[area=medium]: 0.0164 - MaP@[area=large]: 0.0010 - Recall@[max_detections=1]: 0.0096 - Recall@[max_detections=10]: 0.0160 - Recall@[max_detections=100]: 0.0160 - Recall@[area=small]: 0.0034 - Recall@[area=medium]: 0.0283 - Recall@[area=large]: 0.0010 Epoch 2/3 1463/1463 [==============================] - 554s 378ms/step - loss: 2.6961 - box_loss: 2.2861 - class_loss: 0.4100 - val_loss: 3.8292 - val_box_loss: 3.0052 - val_class_loss: 0.8240 - MaP: 0.0077 - MaP@[IoU=50]: 0.0197 - MaP@[IoU=75]: 0.0043 - MaP@[area=small]: 0.0075 - MaP@[area=medium]: 0.0126 - MaP@[area=large]: 0.0050 - Recall@[max_detections=1]: 0.0088 - Recall@[max_detections=10]: 0.0154 - Recall@[max_detections=100]: 0.0154 - Recall@[area=small]: 0.0075 - Recall@[area=medium]: 0.0191 - Recall@[area=large]: 0.0280 Epoch 3/3 1463/1463 [==============================] - 558s 381ms/step - loss: 2.5930 - box_loss: 2.2018 - class_loss: 0.3912 - val_loss: 3.4796 - val_box_loss: 2.8472 - val_class_loss: 0.6323 - MaP: 0.0145 - MaP@[IoU=50]: 0.0398 - MaP@[IoU=75]: 0.0072 - MaP@[area=small]: 0.0077 - MaP@[area=medium]: 0.0227 - MaP@[area=large]: 0.0079 - Recall@[max_detections=1]: 0.0120 - Recall@[max_detections=10]: 0.0257 - Recall@[max_detections=100]: 0.0258 - Recall@[area=small]: 0.0093 - Recall@[area=medium]: 0.0396 - Recall@[area=large]: 0.0226 <keras.callbacks.History at 0x7f3e01ca6d70> 

可视化预测

def visualize_detections(model, dataset, bounding_box_format):images, y_true = next(iter(dataset.take(1)))y_pred = model.predict(images)y_pred = bounding_box.to_ragged(y_pred)visualization.plot_bounding_box_gallery(images,value_range=(0, 255),bounding_box_format=bounding_box_format,y_true=y_true,y_pred=y_pred,scale=4,rows=2,cols=2,show=True,font_scale=0.7,class_mapping=class_mapping,)visualize_detections(yolo, dataset=val_ds, bounding_box_format="xyxy")
1/1 [==============================] - 0s 115ms/step 

PNG 格式

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

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

相关文章

vue3+ts+element-plus 对话框el-dialog设置圆角

对话框el-dialog设置圆角&#xff0c;实现的需求效果&#xff1a; 目前只能通过行内样式&#xff08;style"border-radius: 20px"&#xff09;来实现圆角效果&#xff1a;

pycharm-pyspark 环境安装

1、环境准备&#xff1a;java、scala、pyspark、python-anaconda、pycharm vi ~/.bash_profile export SCALA_HOME/Users/xunyongsun/Documents/scala-2.13.0 export PATH P A T H : PATH: PATH:SCALA_HOME/bin export SPARK_HOME/Users/xunyongsun/Documents/spark-3.5.4-bin…

UnityXR Interaction Toolkit 如何检测HandGestures

前言 随着VR设备的不断发展,从最初的手柄操作,逐渐演变出了手部交互,即头显可以直接识别玩家的手部动作,来完成手柄的交互功能。我们今天就来介绍下如何使用Unity的XR Interaction Toolkit 来检测手势Hand Gesture。 环境配置 1.使用Unity 2021或者更高版本,创建一个项…

thinkphp 5.0 结合redis 做延迟队列,队列无法被消费

目录 一、Linux 环境下 二、如何验证消息队列被正确监听 一、Linux 环境下 项目部署在Linux 环境下&#xff0c;首先找到项目的部署路径&#xff0c;接着输入命令,这个命令是以守护进程方式进行监听你的队列&#xff0c;只要redis 不关闭 就可以一直监听这个队列 nohup php …

E10.【C语言】练习:编写一个猜数字游戏

目录 1.规则 2.准备 3.游戏代码 1.规则 1.程序生成1-100间的随机数 2.用户猜数字 猜对了&#xff1a;游戏结束 猜错了&#xff1a;程序会告知猜大了或猜小了&#xff0c;继续进行游戏&#xff0c;直到猜对 3.游戏可以一直玩除非退出游戏 2.准备 1.框架&#xff1a;循…

【HTML+CSS+JS+VUE】web前端教程-31-css3新特性

圆角 div{width: 100px;height: 100px;background-color: saddlebrown;border-radius: 5px;}阴影 div{width: 200px;height: 100px;background-color: saddlebrown;margin: 0 auto;box-shadow: 10px 10px 20px rgba(0, 0, 0, 0.5);}

【高阶数据结构】位图

位图 一.位图相关面试题二.位图的设计及实现三.C库中的位图bitset四.位图的优缺点五.位图相关考察题目 一.位图相关面试题 问题&#xff1a;给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff08;本…

解决Qt打印中文字符出现乱码

在 Windows 平台上&#xff0c;默认的控制台编码可能不是 UTF-8&#xff0c;这可能会导致中文字符的显示问题。 下面是在 Qt 应用程序中设置中文字体&#xff0c;并确保控制台输出为 UTF-8 编码&#xff1a; 1. Qt 应用程序代码 在 Qt 中&#xff0c;我们可以使用 QApplic…

hutool糊涂工具通过注解设置excel宽度

import java.lang.annotation.*;Documented Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) public interface ExcelStyle {int width() default 0; }/*** 聊天记录*/ Data public class DialogContentInfo {/**…

【算法学习】——整数划分问题详解(动态规划)

&#x1f9ee;整数划分问题是一个较为常见的算法题&#xff0c;很多问题从整数划分这里出发&#xff0c;进行包装&#xff0c;形成新的题目&#xff0c;所以完全理解整数划分的解决思路对于之后的进一步学习算法是很有帮助的。 「整数划分」通常使用「动态规划」解决&#xff0…

【Elasticsearch7.11】postman批量导入少量数据

JSON 文件内的数据格式&#xff0c;json文件数据条数不要过多&#xff0c;会请求参数过大&#xff0c;最好控制再10000以内。 {"index":{"_id":"baec07466732902d22a24ba01ff09751"}} {"uuid":"baec07466732902d22a24ba01ff0975…

Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)

MySQL是一种广泛使用的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;其体系结构设计旨在提供高效的数据存储、查询处理和事务管理。MySQL的体系结构可以分为多个层次&#xff0c;每个层次负责不同的功能模块。 MySQL的体系结构主要由以下几个部分组成&#…

ue5 蒙太奇,即上半身动画和下半身组合在一起,并使用。学习b站库得科技

本文核心 正常跑步动画端枪动画跑起来也端枪 正常跑步动画 端枪动画的上半身 跑起来也端枪 三步走&#xff1a; 第一步制作动画蒙太奇和插槽 第二步动画蓝图选择使用上半身动画还是全身动画&#xff0c;将上半身端枪和下半身走路结合 第三步使用动画蒙太奇 1.开始把&a…

Linux下部署Redis(本地部署超详细)

非docker 1、下载Redis 历史版本&#xff1a; http://download.redis.io/releases 我的&#xff1a; http://download.redis.io/releases/redis-7.0.5.tar.gz 2.安装教程 1.Redis是基于c语言编写的需要安装依赖&#xff0c;需要安装gcc yum install gcc-c 2.查看gcc版…

java -jar启动项目报错:XXX.jar中没有主清单属性

XXX.jar中没有主清单属性 1、错误复现2、错误原因3、解决方案 java -jar启动项目报错&#xff1a;XXX.jar中没有主清单属性 1、错误复现 今天使用springboot给项目打了jar包&#xff0c;使用命令启动时报错&#xff0c;截图如下&#xff1a; 2、错误原因 项目的pom文件配置如…

贪心算法详细讲解(沉淀中)

文章目录 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09;经典例题1.1.1 找零问题1.1.2最小路径和1.1.3 背包问题 2.贪心算法的特点2.1 证明例1 3.学习贪心的方向心得体会 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09; 贪心策略&a…

【Logstash03】企业级日志分析系统ELK之Logstash 过滤 Filter 插件

Logstash 过滤 Filter 插件 数据从源传输到存储库的过程中&#xff0c;Logstash 过滤器能够解析各个事件&#xff0c;识别已命名的字段以构建结构&#xff0c; 并将它们转换成通用格式&#xff0c;以便进行更强大的分析和实现商业价值。 Logstash 能够动态地转换和解析数据&a…

unity打包sdk热更新笔记

基础打包需要知识&#xff1a; 安装包大小不要超过2G&#xff0c;AB包数量过多会影响加载和构建&#xff0c;多次IO&#xff0c;用Gradle打包&#xff0c;要支持64位系统&#xff0c;不同的渠道包&#xff1a;让做sdk的人支持&#xff0c;提供渠道包的打包工具 配置系统环境变量…

论文笔记(六十一)Implicit Behavioral Cloning

Implicit Behavioral Cloning 文章概括摘要1 引言2 背景&#xff1a;隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解&#xff1a;隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用&#xff1a; inproceedings{florence2022implicit,titl…

【Rust自学】12.3. 重构 Pt.1:改善模块化

12.3.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print)&#xff0c;是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步&#xff1a; 接收命令行参数读取…