当前位置: 首页 > news >正文

使用Python脚本转换YOLOv5配置文件到https://github.com/ultralytics/ultralytics:一个详细的指南

在深度学习领域,YOLO(You Only Look Once)系列模型因其高效和准确性而广受欢迎。然而,随着项目需求的变化,有时我们需要对预训练模型的配置文件进行调整。本文将详细介绍如何使用Python脚本自动转换YOLOv5的配置文件到https://github.com/ultralytics/ultralytics,并解释每个步骤的目的和实现方法。

准备工作

首先,确保安装了必要的库:

pip install pyyaml

代码详解

定义格式化和过滤函数

def format_and_filter_list(lst):
    formatted_items = []
    for item in lst:
        if isinstance(item, list):
            processed_item = format_and_filter_list(item)
            if processed_item:  # 只添加非空列表
                formatted_items.append(processed_item)
        elif isinstance(item, str):
            if item == 'nearest':
                formatted_items.append(f"'{item}'")
            elif item != 'anchors':  # 过滤掉 'anchors'
                formatted_items.append(item)
        else:
            formatted_items.append(str(item))
    return f"[{', '.join(formatted_items)}]"

定义转换配置函数

def transform_config(original_config):
    transformed = {
        'nc': original_config['nc'],  # number of classes
        'scales': {
            'n': [original_config['depth_multiple'], original_config['width_multiple'], 1024]
        },
        'backbone': [],
        'head': []
    }

    # Transform backbone
    for layer in original_config['backbone']:
        if not isinstance(layer, list):
            layer = [layer]
        transformed['backbone'].append(layer)

    # Adjust the head to match the desired format, also updating nc and anchors usage
    for i, layer in enumerate(original_config['head']):
        if not isinstance(layer, list):
            layer = [layer]

        if isinstance(layer[0], list) and len(layer[0]) > 3 and layer[0][3] == 'Detect':
            layer[0][3] = ['nc', 'anchors']
            transformed['head'].append([layer[0]])
        else:
            transformed['head'].append(layer)

    # Special case: update the final Detect layer configuration
    if transformed['head'] and isinstance(transformed['head'][-1], list) and transformed['head'][-1]:
        last_layer = transformed['head'][-1]
        if isinstance(last_layer[0], list) and len(last_layer[0]) > 3:
            last_layer[0][3] = ['nc']

    return transformed

定义主函数以更改YAML文件


def change_yaml(yolov5_config):
    # Check if input file exists
    if not os.path.exists(yolov5_config):
        print(f"Error: Input file '{yolov5_config}' does not exist.")
    else:
        old_path = os.path.dirname(yolov5_config)
        save_path = os.path.dirname(old_path)
        new_yaml_name_path = os.path.join(save_path, "yolov5_" + os.path.basename(yolov5_config))
        # Load your YAML file
        with open(yolov5_config, 'r') as file:
            try:
                original_config = yaml.safe_load(file)
            except yaml.YAMLError as exc:
                print(f"Error: Failed to parse YAML file. {exc}")
                exit(1)

        transformed_config = transform_config(original_config)

        # Ensure that each element in backbone and head is a list
        def ensure_list_format(config_part):
            new_config_part = []
            for item in config_part:
                if not isinstance(item, list):
                    item = [item]
                new_config_part.append(item)
            return new_config_part

        transformed_config['backbone'] = ensure_list_format(transformed_config['backbone'])
        transformed_config['head'] = ensure_list_format(transformed_config['head'])

        # Generate the formatted YAML content
        formatted_yaml_content = f"""# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license

# Ultralytics YOLOv5 object detection model with P3/8 - P5/32 outputs
# Model docs: https://docs.ultralytics.com/models/yolov5
# Task docs: https://docs.ultralytics.com/tasks/detect

# Parameters
nc: {transformed_config['nc']} # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov5n.yaml' will call yolov5.yaml with scale 'n'
  # [depth, width, max_channels]
  n: {transformed_config['scales']['n']}
# YOLOv5 v6.0 backbone
backbone:
"""

    for layer in transformed_config['backbone']:
        layer = format_and_filter_list(layer)
        print(layer)
        formatted_yaml_content += f"  - {layer}\n"

    formatted_yaml_content += """
# YOLOv5 v6.0 head with (P2, P3, P4, P5) outputs
head:
"""

    for layer in transformed_config['head']:

        print(layer)
        if isinstance(layer, list) and layer[2] == 'Conv':
            formatted_yaml_content += '\n'

        layer = format_and_filter_list(layer)
        print(layer)
        formatted_yaml_content += f"  - {layer}\n"

    # Save the transformed configuration to a new YAML file
    with open(new_yaml_name_path, 'w') as file:
        file.write(formatted_yaml_content)

    print(f"Configuration has been transformed and saved to '{new_yaml_name_path}'.")

批量处理多个配置文件

input_path = "/media/lindsay/data/ultralytics-main/ultralytics/cfg/models/v5/yolov5"
input_path_list = [os.path.join(input_path, i) for i in os.listdir(input_path)]
for i in input_path_list:
    change_yaml(i)

总结

通过上述步骤,您可以轻松地将YOLOv5的配置文件转换为ultralytics-yolov8所需的格式,并且可以批量处理多个配置文件。这个脚本不仅可以帮助您节省时间,还能减少手动操作带来的错误。希望这篇博客能为您提供有价值的指导,让您更高效地管理深度学习项目的配置文件。

完整代码

import yaml
import os

# 函数用于格式化列表为所需形式
def format_and_filter_list(lst):
    formatted_items = []
    for item in lst:
        if isinstance(item, list):
            # 如果是列表类型,则递归调用此函数进行格式化和过滤
            processed_item = format_and_filter_list(item)
            if processed_item:  # 只添加非空列表
                formatted_items.append(processed_item)
        elif isinstance(item, str):
            # 特殊处理需要保留引号的字符串
            if item == 'nearest':
                formatted_items.append(f"'{item}'")
            elif item != 'anchors':  # 过滤掉 'anchors'
                formatted_items.append(item)
        else:
            # 其他类型直接转换成字符串表示
            formatted_items.append(str(item))

    # 返回格式化后的列表字符串表示
    return f"[{', '.join(formatted_items)}]"


def transform_config(original_config):
    transformed = {
        'nc': original_config['nc'],  # number of classes
        'scales': {
            'n': [original_config['depth_multiple'], original_config['width_multiple'], 1024]
        },
        'backbone': [],
        'head': []
    }

    # Transform backbone
    for layer in original_config['backbone']:
        if not isinstance(layer, list):
            layer = [layer]
        transformed['backbone'].append(layer)

    # Adjust the head to match the desired format, also updating nc and anchors usage
    for i, layer in enumerate(original_config['head']):
        if not isinstance(layer, list):
            layer = [layer]

        if isinstance(layer[0], list) and len(layer[0]) > 3 and layer[0][3] == 'Detect':
            # Update Detect layer to use 'nc' instead of specific numbers for classes
            layer[0][3] = ['nc', 'anchors']
            transformed['head'].append([layer[0]])
        else:
            transformed['head'].append(layer)

    # Special case: update the final Detect layer configuration
    if transformed['head'] and isinstance(transformed['head'][-1], list) and transformed['head'][-1]:
        last_layer = transformed['head'][-1]
        if isinstance(last_layer[0], list) and len(last_layer[0]) > 3:
            last_layer[0][3] = ['nc']

    return transformed


def change_yaml(yolov5_config):
    # Check if input file exists
    if not os.path.exists(yolov5_config):
        print(f"Error: Input file '{yolov5_config}' does not exist.")
    else:
        old_path = os.path.dirname(yolov5_config)
        save_path = os.path.dirname(old_path)
        new_yaml_name_path = os.path.join(save_path, "yolov5_" + os.path.basename(yolov5_config))
        # Load your YAML file
        with open(yolov5_config, 'r') as file:
            try:
                original_config = yaml.safe_load(file)
            except yaml.YAMLError as exc:
                print(f"Error: Failed to parse YAML file. {exc}")
                exit(1)

        transformed_config = transform_config(original_config)

        # Ensure that each element in backbone and head is a list
        def ensure_list_format(config_part):
            new_config_part = []
            for item in config_part:
                if not isinstance(item, list):
                    item = [item]
                new_config_part.append(item)
            return new_config_part

        transformed_config['backbone'] = ensure_list_format(transformed_config['backbone'])
        transformed_config['head'] = ensure_list_format(transformed_config['head'])

        # Generate the formatted YAML content
        formatted_yaml_content = f"""# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license

# Ultralytics YOLOv5 object detection model with P3/8 - P5/32 outputs
# Model docs: https://docs.ultralytics.com/models/yolov5
# Task docs: https://docs.ultralytics.com/tasks/detect

# Parameters
nc: {transformed_config['nc']} # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov5n.yaml' will call yolov5.yaml with scale 'n'
  # [depth, width, max_channels]
  n: {transformed_config['scales']['n']}
# YOLOv5 v6.0 backbone
backbone:
"""

    for layer in transformed_config['backbone']:
        layer = format_and_filter_list(layer)
        print(layer)
        formatted_yaml_content += f"  - {layer}\n"

    formatted_yaml_content += """
# YOLOv5 v6.0 head with (P2, P3, P4, P5) outputs
head:
"""

    for layer in transformed_config['head']:

        print(layer)
        if isinstance(layer, list) and layer[2] == 'Conv':
            formatted_yaml_content += '\n'

        layer = format_and_filter_list(layer)
        print(layer)
        formatted_yaml_content += f"  - {layer}\n"

    # Save the transformed configuration to a new YAML file
    with open(new_yaml_name_path, 'w') as file:
        file.write(formatted_yaml_content)

    print(f"Configuration has been transformed and saved to '{new_yaml_name_path}'.")


input_path = "/media/lindsay/data/ultralytics-main/ultralytics/cfg/models/v5/yolov5"
input_path_list = [os.path.join(input_path, i) for i in os.listdir(input_path)]
for i in input_path_list:
    change_yaml(i)

相关文章:

  • 《道德经的现代智慧:解码生活与商业的底层逻辑1》
  • escape SQL中用法
  • 9-1. MySQL 性能分析工具的使用——last_query_cost,慢查询日志
  • 修改/etc/hosts并生效
  • 蓝禾,oppo,游卡,汤臣倍健,康冠科技,作业帮,高途教育25届春招内推
  • jmeter 接入deepseek 或者chatgpt
  • qt.qpa.fonts: Unable to open default EUDC font: “EUDC.TTE“
  • MATLAB中isletter函数用法
  • 爬虫与反爬-Ja3指纹风控(Just a moment...)处理方案及参数说明
  • 软件架构设计:软件工程
  • 【学习资料】嵌入式人工智能Embedded AI
  • SCSS——CSS的扩展和进化
  • java 单例模式(Lazy Initialization)实现遍历文件夹下所有excel文件且返回其运行时间
  • 【Java从入门到起飞】数组
  • Pycharm下载|附安装包+详细安装教程
  • 网卡驱动架构以及源码分析
  • 炫影智能轻云盒(智慧小盒)移动版SY910_RK3528芯片_2+8G_安卓9.0_免拆固件包
  • 使用Java爬虫获取1688 item_search_factory 接口的工厂搜索数据
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_init_setproctitle函数
  • 49 set与map的模拟实现
  • 网站开发实训目的/搜索seo神器
  • web网站漏洞扫描/关键词排名优化网站
  • 网站开发维护招聘/可以入侵的网站
  • 上海交通大学文科建设处网站/网店代运营十大排名
  • 域名有没有被注册哪个网站最好/seo团队管理系统
  • 建筑工程管理系统平台/达州seo