YOLO11 目标检测 | 自动标注 | 预标注 | 标签格式转换 | 手动校正标签

news2024/10/27 15:17:37

本文分享使用YOLO11进行目标检测时,实现模型推理预标注自动标注标签格式转换、以及使用Labelme手动校正标签等功能。

目录

1、预训练权重

 2、生成预标注

3、分析YOLO11的目标检测格式

4、分析Labelme标注工具的格式

5、生成json标注文件

6、手动校正标签

7、Labelme的json转为YOLO的txt

8、迭代优化模型(可选)


1、预训练权重

首先我们去官网下载,YOLO11目标检测的预训练权重,如下表格式所示:

下载地址:https://github.com/ultralytics/ultralytics

Modelsize
(pixels)
mAPval
50-95
Speed
CPU ONNX
(ms)
Speed
T4 TensorRT10
(ms)
params
(M)
FLOPs
(B)
YOLO11n64039.556.1 ± 0.81.5 ± 0.02.66.5
YOLO11s64047.090.0 ± 1.22.5 ± 0.09.421.5
YOLO11m64051.5183.2 ± 2.04.7 ± 0.120.168.0
YOLO11l64053.4238.6 ± 1.46.2 ± 0.125.386.9
YOLO11x64054.7462.8 ± 6.711.3 ± 0.256.9194.9

然后基于预训练权重,准备自己的数据集,进行模型训练

最终,得到效果更好的模型权重(xxx.pt或xxx.onnx)

 2、生成预标注

前面得到了效果更好的模型权重,这里用它来对新的图片进行推理,同时生成目标检测的信息。

模型推理的代码,如下所示:

from ultralytics import YOLO
 
# 加载训练的模型
model = YOLO(r"runs/detect/train/weights/best.pt")
 
# 对指定的图像文件夹进行推理,并设置各种参数
results = model.predict(
    source="datasets/det_20241020/images/",   # 新的图片,待标注的图片
    conf=0.45,                      # 置信度阈值
    iou=0.6,                        # IoU 阈值
    imgsz=640,                      # 图像大小
    half=False,                     # 使用半精度推理
    device=None,                    # 使用设备,None 表示自动选择,比如'cpu','0'
    max_det=300,                    # 最大检测数量
    vid_stride=1,                   # 视频帧跳跃设置
    stream_buffer=False,            # 视频流缓冲
    visualize=False,                # 可视化模型特征
    augment=False,                  # 启用推理时增强
    agnostic_nms=False,             # 启用类无关的NMS
    classes=None,                   # 指定要检测的类别
    retina_masks=False,             # 使用高分辨率分割掩码
    embed=None,                     # 提取特征向量层
    show=False,                     # 是否显示推理图像
    save=True,                      # 保存推理结果
    save_frames=False,              # 保存视频的帧作为图像
    save_txt=True,                  # 保存检测结果到文本文件
    save_conf=False,                # 保存置信度到文本文件
    save_crop=False,                # 保存裁剪的检测对象图像
    show_labels=True,               # 显示检测的标签
    show_conf=True,                 # 显示检测置信度
    show_boxes=True,                # 显示检测框
    line_width=None                 # 设置边界框的线条宽度,比如2,4
)
  • 需要修改model = YOLO(r"runs/detect/train/weights/best.pt")中的权重路径,替换为自己训练的
  • 同时需要修改source="datasets/det_20241020/images/", 这里是指新的图片,即待标注的图片
  • 其他推理参数,根据任务情况,自行修改了;比如:置信度conf、iou、图像大小imgsz等等。

推理完成后,会保留目标检测的结果图像、标签信息文件夹(labels),它们是同一级文件夹的

- runs/detect/predict/

        - labels(这个文件夹是存放YOLO11推理结果,作为预标注的标签信息)

        - picture1.jpg

        - picture2.jpg

                .....

        - pictureN.jpg

3、分析YOLO11的目标检测格式

YOLO11的标签文件是一个包含每行一个标签的txt文件。

每一行的格式是:<object-class> <x_center> <y_center> <width> <height>。其中:

  • <object-class>是类别索引。
  • <x_center><y_center>是目标的中心点坐标(归一化到0-1)。
  • <width><height>是目标的宽度高度(归一化到0-1)。

txt标签示例数据,表示有两个物体:

0 0.5192 0.4512 0.3985 0.7572
3 0.5061 0.5921 0.2631 0.4561

  • 第一行表示物体1,类别为0,0.5192是中心点x坐标,0.4512是中心点y坐标,0.3985是宽度, 0.7572是高度。
  • 第二行表示物体2,类别为3,0.5061是中心点x坐标,0.5921是中心点y坐标,0.2631是宽度, 0.4561是高度。

4、分析Labelme标注工具的格式

在目标检测中,我们使用Labelme工具进行标注,选择“创建矩形”,对物体进行标注。

  • 标注后点击保存,会生成JSON标注文件;
  • 这样能使用Labelme,可视化检查预标注的结果,方便人工手动修正标签

LabelMe使用的是JSON格式,每个标签是一个形状(shape)对象,包含以下信息: 

  • label: 标签的名称。
  • points: 多边形的点列表(包含多边形顶点的坐标)。
  • group_id: (可选)用于将不同形状分组的ID。
  • shape_type: 形状类型(例如rectangle, circle等)。
  • flags: (可选)一些额外的标记信息。

5、生成json标注文件

编写程序,遍历该文件夹中的所有txt文件,然后将生成的Labelme的JSON文件保存到指定的输出文件夹中

  • 定义类别映射:创建一个字典,将YOLO11类别ID映射到相应的类名。

  • 转换函数:定义yolo_to_labelme函数,接收YOLO11格式的txt文件路径和图像尺寸,读取标注数据,计算绝对坐标,并格式化为LabelMe的JSON结构。

  • 主函数实现

    • 指定输入图像和标签文件夹路径,以及输出JSON文件的路径。
    • 检查输出目录是否存在,如不存在则创建。
    • 遍历标签文件夹中的所有.txt文件,读取相应的图像文件。
    • 使用OpenCV读取图像以获取其高度和宽度。
    • 调用转换函数生成标注数据。
    • 将生成的LabelMe格式数据写入新的JSON文件。

这里会提供源代码,需要根据我们的数据修改以下部分:

import os
import json
import cv2

# 自定义类别映射
class_map = {
    0: 'class_name1',   # 类别 0 对应的名称
    1: 'class_name2',   # 类别 1 对应的名称
    2: 'class_name3'    # 类别 2 对应的名称
}

# YOLO11的txt标签,转为Labelme的json文件
def yolo_to_labelme(txt_path, img_width, img_height):
    with open(txt_path, 'r') as file:
        lines = file.readlines()

    shapes = []
    for line in lines:
        parts = line.strip().split()
        class_id = int(parts[0])
        x_center = float(parts[1])
        y_center = float(parts[2])
        width = float(parts[3])
        height = float(parts[4])

        # 转换为绝对坐标
        x_center *= img_width
        y_center *= img_height
        width *= img_width
        height *= img_height

        # 计算矩形的四个顶点
        x1 = x_center - width / 2
        y1 = y_center - height / 2
        x2 = x_center + width / 2
        y2 = y_center + height / 2

        shapes.append({
            'label': class_map[class_id],
            'points': [[x1, y1], [x2, y2]],
            'group_id': None,
            'shape_type': 'rectangle',
            'flags': {}
        })

    return shapes

def main():
    # 文件夹路径
    image_folder_path = r"./datasets/seg-datasetsv2/images"     # 这里指定图片的文件夹路径
    txt_folder_path = r"./datasets/seg-datasetsv2/labels"       # 这里指定YOLO的txt_labels的文件夹路径
    json_output_path = r"./datasets/seg-datasetsv2/json_labels" # 这里指定待会生成Labelme的json_labels的文件夹路径

    # 检查输出文件夹是否存在,不存在则创建
    if not os.path.exists(json_output_path):
        os.makedirs(json_output_path)

    # 遍历所有txt文件并转换
    for txt_file in os.listdir(txt_folder_path):
        if txt_file.endswith('.txt'):
            txt_path = os.path.join(txt_folder_path, txt_file)

            # 获取与txt文件同名的图片路径
            img_file = txt_file.replace('.txt', '.jpg')  # 假设图片是jpg格式
            img_path = os.path.join(image_folder_path, img_file)

            try:
                # 使用OpenCV读取图片分辨率
                img = cv2.imread(img_path)
                if img is None:
                    raise FileNotFoundError(f"Image file not found: {img_path}")

                img_height, img_width, _ = img.shape

                shapes = yolo_to_labelme(txt_path, img_width, img_height)

                # 创建LabelMe格式的json文件
                labelme_data = {
                    'version': '4.5.6',
                    'flags': {},
                    'shapes': shapes,
                    'imagePath': img_file,
                    'imageData': None,
                    'imageHeight': img_height,
                    'imageWidth': img_width
                }

                json_path = os.path.join(json_output_path, txt_file.replace('.txt', '.json'))
                with open(json_path, 'w') as json_file:
                    json.dump(labelme_data, json_file, indent=2)

            except Exception as e:
                print(f"Error processing {img_file}: {e}")

# 主函数入口
if __name__ == "__main__":
    main()

 首先修改类别映射,比如:

# 定义类别标签映射
class_map = {
    0: 'person',    # 类别 0 对应的名称是person
    1: 'bicycle',   # 类别 1 对应的名称是bicycle
    2: 'car'        # 类别 2 对应的名称是car
}

然后修改一下代码中的参数:

    image_folder_path = r"./datasets/seg-datasetsv2/images"     # 这里指定图片的文件夹路径
    txt_folder_path = r"./datasets/seg-datasetsv2/labels"       # 这里指定YOLO的txt_labels的文件夹路径
    json_output_path = r"./datasets/seg-datasetsv2/json_labels" # 这里指定待会生成Labelme的json_labels的文件夹路径

运行代码,会生成用于YOLO11目标检测的JSON标签文件。

6、手动校正标签

生成了JSON文件后,把图像JSON文件放在同一个文件夹中

然后打开Labelme工具,选择“编辑多边形”,对物体进行标注信息修改

修改完成后,点击“Save"保存修正后的标注信息

7、Labelme的json转为YOLO的txt

这里把Labelme的json转为YOLO的txt,是因为用修正后数据,作为新的数据,加入旧数据中;

重新训练之前的模型权重,这样模型会学得更好,迭代优化模型。

通过下面代码,把Labelme的json转为YOLO的txt

 方案1——单个文件转换

该代码用于将LabelMe格式的JSON标注文件,转换为YOLO11格式的标注文件,函数解析:

convert_labelme_to_yolo(json_path, output_dir):

  • 功能: 将单个LabelMe格式的JSON文件转换为YOLO11格式。
  • 参数:
    • json_path (str): 输入的LabelMe格式JSON文件路径。
    • output_dir (str): 输出的YOLO11格式标注文件夹路径。
  • 操作:
    • 读取JSON文件,获取图像宽度和高度。
    • 遍历所有标注形状,提取标签和坐标,计算YOLO11所需的中心点和宽高。
    • 将结果写入以相同文件名命名的TXT文件中。

示例代码如下所示:

import json
import os

# 定义标签映射,将类别名称映射为ID
label_map = {
    "car": 0,  # 汽车
    "bus": 1   # 公交车
}

def convert_labelme_to_yolo(json_path, output_dir):
    """
    将LabelMe格式的JSON文件转换为YOLO11格式的标注文件。

    参数:
    json_path (str): 输入的LabelMe格式JSON文件路径。
    output_dir (str): 输出的YOLO11格式标注文件夹路径。
    """
    # 打开LabelMe格式的JSON文件
    with open(json_path, 'r') as f:
        labelme_data = json.load(f)  # 读取JSON数据

    # 获取图像的宽度和高度
    image_width = labelme_data['imageWidth']
    image_height = labelme_data['imageHeight']

    yolo_annotations = []  # 存储YOLO11格式的标注

    # 遍历所有的标注形状
    for shape in labelme_data['shapes']:
        label = shape['label']  # 获取标签名称
        if label not in label_map:
            continue  # 如果标签未定义,则忽略

        class_id = label_map[label]  # 获取对应的类别ID

        points = shape['points']  # 获取标注的坐标点
        if shape['shape_type'] == 'rectangle':  # 如果是矩形
            (x1, y1), (x2, y2) = points  # 获取矩形的两个顶点
        elif shape['shape_type'] == 'polygon':  # 如果是多边形
            x1, y1 = min(point[0] for point in points), min(point[1] for point in points)  # 计算多边形的左上角
            x2, y2 = max(point[0] for point in points), max(point[1] for point in points)  # 计算多边形的右下角
        else:
            continue  # 其他类型不处理

        # 计算YOLO11格式所需的中心点和宽高
        x_center = (x1 + x2) / 2.0 / image_width  # 计算中心点x坐标
        y_center = (y1 + y2) / 2.0 / image_height  # 计算中心点y坐标
        width = (x2 - x1) / image_width  # 计算宽度
        height = (y2 - y1) / image_height  # 计算高度

        # 添加YOLO11格式的标注到列表中
        yolo_annotations.append(f"{class_id} {x_center} {y_center} {width} {height}")

    # 构建输出文件的路径
    output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(json_path))[0] + '.txt')
    # 将YOLO11格式的标注写入输出文件
    with open(output_file, 'w') as f:
        f.write('\n'.join(yolo_annotations))

# 示例使用
convert_labelme_to_yolo('/path/to/labelme_file.json', '/path/to/output_dir')

方案2——多个标签文件转换

读取一个文件夹下所有json文件,然后转为YOLO11的txt标签格

process_folder(input_folder, output_folder):

  • 功能: 处理输入文件夹中的所有JSON文件,转换为YOLO11格式。
  • 参数:
    • input_folder (str): 包含LabelMe格式JSON文件的输入文件夹路径。
    • output_folder (str): 用于保存YOLO11格式标注文件的输出文件夹路径。
  • 操作:
    • 创建输出文件夹(如果不存在)。
    • 遍历输入文件夹,调用转换函数处理每个以.json结尾的文件。

 示例代码如下所示:

import json
import os

# 定义标签映射,将类别名称映射为ID
label_map = {
    "car": 0,  # 汽车
    "bus": 1   # 公交车
}

def convert_labelme_to_yolo(json_path, output_dir):
    """
    将LabelMe格式的JSON文件转换为YOLO11格式的标注文件。

    参数:
    json_path (str): 输入的LabelMe格式JSON文件路径。
    output_dir (str): 输出的YOLO11格式标注文件夹路径。
    """
    # 打开LabelMe格式的JSON文件
    with open(json_path, 'r') as f:
        labelme_data = json.load(f)  # 读取JSON数据

    # 获取图像的宽度和高度
    image_width = labelme_data['imageWidth']
    image_height = labelme_data['imageHeight']

    yolo_annotations = []  # 存储YOLO11格式的标注

    # 遍历所有的标注形状
    for shape in labelme_data['shapes']:
        label = shape['label']  # 获取标签名称
        if label not in label_map:
            continue  # 如果标签未定义,则忽略

        class_id = label_map[label]  # 获取对应的类别ID

        points = shape['points']  # 获取标注的坐标点
        if shape['shape_type'] == 'rectangle':  # 如果是矩形
            (x1, y1), (x2, y2) = points  # 获取矩形的两个顶点
        elif shape['shape_type'] == 'polygon':  # 如果是多边形
            x1, y1 = min(point[0] for point in points), min(point[1] for point in points)  # 计算多边形的左上角
            x2, y2 = max(point[0] for point in points), max(point[1] for point in points)  # 计算多边形的右下角
        else:
            continue  # 其他类型不处理

        # 计算YOLO11格式所需的中心点和宽高
        x_center = (x1 + x2) / 2.0 / image_width  # 计算中心点x坐标
        y_center = (y1 + y2) / 2.0 / image_height  # 计算中心点y坐标
        width = (x2 - x1) / image_width  # 计算宽度
        height = (y2 - y1) / image_height  # 计算高度

        # 添加YOLO11格式的标注到列表中
        yolo_annotations.append(f"{class_id} {x_center} {y_center} {width} {height}")

    # 构建输出文件的路径
    output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(json_path))[0] + '.txt')
    # 将YOLO11格式的标注写入输出文件
    with open(output_file, 'w') as f:
        f.write('\n'.join(yolo_annotations))

def process_folder(input_folder, output_folder):
    """
    处理输入文件夹中的所有JSON文件,并将其转换为YOLO11格式的标注文件。

    参数:
    input_folder (str): 输入文件夹路径,包含LabelMe格式的JSON文件。
    output_folder (str): 输出文件夹路径,用于保存YOLO11格式的标注文件。
    """
    # 创建输出文件夹(如果不存在)
    os.makedirs(output_folder, exist_ok=True)
    
    # 处理输入文件夹中的每个 JSON 文件
    for filename in os.listdir(input_folder):
        if filename.endswith(".json"):  # 只处理以 .json 结尾的文件
            json_path = os.path.join(input_folder, filename)  # 获取完整的JSON文件路径
            convert_labelme_to_yolo(json_path, output_folder)  # 调用转换函数

# 示例使用
input_folder = "/mnt/data/json_labels"  # 输入json_labels文件夹路径
output_folder = "/mnt/data/yolo11_txt_labels"  # 输出txt_labels文件夹路径

process_folder(input_folder, output_folder)  # 处理文件夹中的所有JSON文件

# 列出输出文件夹中的文件以确认
os.listdir(output_folder)  # 打印输出文件夹中的文件列表

我们使用上面代码时,需要设置输入的json_labels文件夹路径输出txt_labels文件夹路径

input_folder = "/mnt/data/json_labels"  # 输入json_labels文件夹路径
output_folder = "/mnt/data/yolo11_txt_labels"  # 输出txt_labels文件夹路径

8、迭代优化模型(可选)

然后,可以迭代优化模型。用修正后数据,作为新的数据,加入旧数据中;

重新训练之前的模型权重,这样模型会学得更好,迭代优化模型。

YOLO11目标检测-训练模型参考我这篇文章:

https://blog.csdn.net/qq_41204464/article/details/142826049?spm=1001.2014.3001.5501

  YOLO11相关文章推荐:

一篇文章快速认识YOLO11 | 关键改进点 | 安装使用 | 模型训练和推理-CSDN博客

一篇文章快速认识 YOLO11 | 实例分割 | 模型训练 | 自定义数据集-CSDN博客

YOLO11模型推理 | 目标检测与跟踪 | 实例分割 | 关键点估计 | OBB旋转目标检测-CSDN博客

YOLO11模型训练 | 目标检测与跟踪 | 实例分割 | 关键点姿态估计-CSDN博客

YOLO11 实例分割 | 自动标注 | 预标注 | 标签格式转换 | 手动校正标签-CSDN博客

YOLO11 实例分割 | 导出ONNX模型 | ONNX模型推理-CSDN博客

YOLO11 目标检测 | 导出ONNX模型 | ONNX模型推理-CSDN博客

分享完成,欢迎大家多多点赞收藏,谢谢~

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

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

相关文章

#渗透测试#SRC漏洞挖掘# 信息收集-Shodan进阶VNC

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

PHPOK 4.8.338 后台任意文件上传漏洞(CVE-2018-12941)复现

PHPOK企业站(简称PHPOK&#xff09;建设系统是一套基于PHP和MySQL构建的高效企业网站建设方案之一&#xff0c;全面针对企业网&#xff08;以展示为中心&#xff09;进行合理的设计规划。 PHPOK是一套开源免费的建站系统&#xff0c;可以在遵守LGPL协议的基础上免费使用。系统具…

trueNas 24.10 docker配置文件daemon.json无法修改(重启被覆盖)解决方案

前言 最近听说truenas的24.10版本开放docker容器解决方案放弃了原来难用的k3s&#xff0c;感觉非常巴适&#xff0c;就研究了一下&#xff0c;首先遇到无法迁移老系统应用问题比较好解决&#xff0c;使用sudo登录ssh临时修改daemon.json重启docker后进行docker start 容器即可…

腾讯云视频文件上传云存储时自动将mp4格式转码成m3u8

针对问题&#xff1a; 弱网环境下或手机网络播放mp4格式视频卡顿。 存储环境&#xff1a;腾讯云对象存储。 处理流程&#xff1a; 1&#xff1a;登录腾讯云控制台&#xff0c;进入对象存储服务&#xff0c;找到对应的存储桶&#xff0c;点击进入。 在任务与工作流选项卡中找…

Linux复习-C++

参考博客&#xff1a; https://blog.csdn.net/qq_45254369/article/details/126023482?ops_request_misc%257B%2522request%255Fid%2522%253A%252277629891-A0F3-4EFC-B1AC-410093596085%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&req…

深入探索:AI模型在各行业的实际应用

深入探索&#xff1a;AI模型在各行业的实际应用 前言一、卷积神经网络&#xff08;CNN&#xff09;图像分类 二、循环神经网络&#xff08;RNN&#xff09;及其变体&#xff08;LSTM、GRU&#xff09;自然语言处理&#xff08;NLP&#xff09; 三、基于Transformer架构的模型&a…

基于树型结构实现顺序结构堆

目录 前言 一、树 1、树的概念与结构 2、树的相关术语 3、二叉树 4、满二叉树 ​ 5、完全二叉树 ​ 6、二叉树的存储 1、顺序结构 2、链式结构 二、堆 1、堆的结构 2、堆的初始化 3、入堆&#xff08;大根堆&#xff09; 4、出堆&#xff08;大根堆&#xf…

C++网络编程之C/S模型

C网络编程之C/S模型 引言 在网络编程中&#xff0c;C/S&#xff08;Client/Server&#xff0c;客户端/服务器&#xff09;模型是一种最基本且广泛应用的架构模式。这种模型将应用程序分为两个部分&#xff1a;服务器&#xff08;Server&#xff09;和客户端&#xff08;Clien…

Java审计对比工具JaVers使用

最近有个需求&#xff0c;需要将页面的内容生成excel或者word文档&#xff0c;而且每次的修改都需要生成新的版本&#xff0c;同时需要记录每次修改变化的内容。我们会把每次的修改的内容提交赋值给一个java对象&#xff0c;同时存储到数据库一条新数据&#xff0c;对应数据表一…

uniapp圆形波浪进度效果

uniapp圆形波浪进度效果 背景实现思路代码实现尾巴 背景 最近项目中有些统计的地方需要用到圆形的波浪进度效果&#xff0c;要求是根据百分比值然后在一个圆形内动态的展示一个波浪形的进度&#xff0c;看参考一下效果。 实现思路 这个效果看着挺复杂的&#xff0c;那么我们…

android——渐变色

1、xml的方式实现渐变色 效果图&#xff1a; xml的代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <shape xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools…

索引的使用和优化

索引就是一种快速查询和检索数据的数据结构&#xff0c;mysql中的索引结构有&#xff1a;B树和Hash。 索引的作用就相当于目录的作用&#xff0c;我么只需先去目录里面查找字的位置&#xff0c;然后回家诶翻到那一页就行了&#xff0c;这样查找非常快&#xff0c; 创建一个表结…

【数据结构】宜宾大学-计院-实验五

实验五 栈和队列&#xff08;队列的基本操作&#xff09; 实验目的&#xff1a;链表结点结构&#xff1a;实验结果&#xff1a;运行截图&#xff1a;代码实现&#xff1a; 实验目的&#xff1a; 1&#xff0e;掌握队列的顺序存储结构和链式存储结构 2&#xff0e;实现队列的基…

(北京政务服务满意度公司)满意度调查助力服务质量提升

在当今社会&#xff0c;&#xff08;政务服务满意度公司&#xff09;政务窗口服务的质量直接关系到市民的日常生活和城市的健康发展。为了解市民对政务窗口服务的满意度&#xff0c;提升服务质量&#xff0c;某市委托民安智库专业市场调查公司开展了政务窗口服务满意度调查&…

若依框架部署到服务器刷新或者是退出登录出现404

登出错误404 改成/登出的时候重定向到根路径&#xff0c;让nginx匹配去找dist目录下的index.html文件 或者是直接改为/index.html&#xff0c;少一步可能会快一点&#xff1f; 不过会变得很丑,算了还是根目录吧 原版是index&#xff0c;那玩意是 针对路由的&#xff0c;而打包…

【重生之我要苦学C语言】 函数递归

函数递归 什么是递归&#xff1f; 递归就是函数自己调用自己 递归一定是基于函数的 在任何一次函数调用中&#xff0c;都会申请资源&#xff0c;申请的是内存中栈区的资源 栈区的资源是有限的&#xff0c;因此函数不能无限次的递归 递归的思想 把一个大型复杂问题层层转化为…

解决docker拉取readeck镜像报Error response from daemon: toomanyrequests问题

readeck 是一个内容中心&#xff0c;目前已支持中文翻译 这是本地化部署后的效果&#xff1a; 原命令为&#xff1a; docker run --rm -ti -p 8000:8000 -v readeck-data:/readeck codeberg.org/readeck/readeck:latest Unable to find image codeberg.org/readeck/readeck:la…

数据库的诗篇:深入探索 MySQL 表操作的艺术与哲学

文章目录 前言&#x1f338;一、创建表——搭建数据存储的基础框架1.1 基本语法1.2 创建表的实际案例解释&#xff1a; 1.3 表设计的最佳实践 &#x1f338;二、查看表结构——快速了解数据库设计2.1 使用 DESC 命令解释&#xff1a; 2.2 使用 SHOW COLUMNS 命令2.3 使用 SHOW …

[MySQL#2] 库 | 表 | 详解CRUD命令 | 字符集 | 校验规则

目录 一. 库操作 1. 创建数据库 2. 字符集和校验规则 校验规则对数据库的影响 显示创建数据库时对应的命令 3. 修改数据库 4. 数据库删除 备份和恢复 还原 查看连接情况 二. 表操作 1. 创建表&#xff08;定义实例化格式 2. 创建表案例 &#xff08;实例化数据类型…