【DETR】DETR训练VOC数据集/自定义数据集

news2024/9/23 14:31:31

训练DETR

  • 一、数据准备
  • 二、配置DETR
  • References

一、数据准备

DETR用的是COCO格式的数据集。
如果要用DETR训练自己的数据集,直接利用Labelimg标注成COCO格式。
如果是VOC数据集的话,要做一个格式转换。网上一大堆格式转换的代码都很乱,所以自己写了一个针对VOC数据集的转换。


COCO数据集的格式类似这样,annotations文件夹里面有对应的train、val数据集的json文件。train2017则是训练集图片,其他同理。
在这里插入图片描述
VOC数据集的存放方式是这样的,转换格式就是找出Main文件夹下用于目标检测的图片。
在这里插入图片描述
Main文件夹下有train.txt文件,记录了训练集的图片。val.txt记录了验证集的图片
在这里插入图片描述
只需要修改注释中的两个路径即可(创建文件夹时没有加判断语句严谨一点应该加上)。

import os
import shutil
import sys
import json
import glob
import xml.etree.ElementTree as ET


START_BOUNDING_BOX_ID = 1
# PRE_DEFINE_CATEGORIES = None
# If necessary, pre-define category and its id
PRE_DEFINE_CATEGORIES = {"aeroplane": 1, "bicycle": 2, "bird": 3, "boat": 4,
                         "bottle": 5, "bus": 6, "car": 7, "cat": 8, "chair": 9,
                         "cow": 10, "diningtable": 11, "dog": 12, "horse": 13,
                         "motorbike": 14, "person": 15, "pottedplant": 16,
                         "sheep": 17, "sofa": 18, "train": 19, "tvmonitor": 20}


def get(root, name):
    vars = root.findall(name)
    return vars


def get_and_check(root, name, length):
    vars = root.findall(name)
    if len(vars) == 0:
        raise ValueError("Can not find %s in %s." % (name, root.tag))
    if length > 0 and len(vars) != length:
        raise ValueError(
            "The size of %s is supposed to be %d, but is %d."
            % (name, length, len(vars))
        )
    if length == 1:
        vars = vars[0]
    return vars


def get_filename_as_int(filename):
    try:
        filename = filename.replace("\\", "/")
        filename = os.path.splitext(os.path.basename(filename))[0]
        return int(filename)
    except:
        raise ValueError(
            "Filename %s is supposed to be an integer." % (filename))


def get_categories(xml_files):
    """Generate category name to id mapping from a list of xml files.

    Arguments:
        xml_files {list} -- A list of xml file paths.

    Returns:
        dict -- category name to id mapping.
    """
    classes_names = []
    for xml_file in xml_files:
        tree = ET.parse(xml_file)
        root = tree.getroot()
        for member in root.findall("object"):
            classes_names.append(member[0].text)
    classes_names = list(set(classes_names))
    classes_names.sort()
    return {name: i for i, name in enumerate(classes_names)}


def convert(xml_files, json_file):
    json_dict = {"images": [], "type": "instances",
                 "annotations": [], "categories": []}
    if PRE_DEFINE_CATEGORIES is not None:
        categories = PRE_DEFINE_CATEGORIES
    else:
        categories = get_categories(xml_files)
    bnd_id = START_BOUNDING_BOX_ID
    for xml_file in xml_files:
        tree = ET.parse(xml_file)
        root = tree.getroot()
        path = get(root, "path")
        if len(path) == 1:
            filename = os.path.basename(path[0].text)
        elif len(path) == 0:
            filename = get_and_check(root, "filename", 1).text
        else:
            raise ValueError("%d paths found in %s" % (len(path), xml_file))
        # The filename must be a number
        image_id = get_filename_as_int(filename)
        size = get_and_check(root, "size", 1)
        width = int(get_and_check(size, "width", 1).text)
        height = int(get_and_check(size, "height", 1).text)
        image = {
            "file_name": filename,
            "height": height,
            "width": width,
            "id": image_id,
        }
        json_dict["images"].append(image)
        # Currently we do not support segmentation.
        #  segmented = get_and_check(root, 'segmented', 1).text
        #  assert segmented == '0'
        for obj in get(root, "object"):
            category = get_and_check(obj, "name", 1).text
            if category not in categories:
                new_id = len(categories)
                categories[category] = new_id
            category_id = categories[category]
            bndbox = get_and_check(obj, "bndbox", 1)
            xmin = int(get_and_check(bndbox, "xmin", 1).text) - 1
            ymin = int(get_and_check(bndbox, "ymin", 1).text) - 1
            xmax = int(get_and_check(bndbox, "xmax", 1).text)
            ymax = int(get_and_check(bndbox, "ymax", 1).text)
            assert xmax > xmin
            assert ymax > ymin
            o_width = abs(xmax - xmin)
            o_height = abs(ymax - ymin)
            ann = {
                "area": o_width * o_height,
                "iscrowd": 0,
                "image_id": image_id,
                "bbox": [xmin, ymin, o_width, o_height],
                "category_id": category_id,
                "id": bnd_id,
                "ignore": 0,
                "segmentation": [],
            }
            json_dict["annotations"].append(ann)
            bnd_id = bnd_id + 1

    for cate, cid in categories.items():
        cat = {"supercategory": "none", "id": cid, "name": cate}
        json_dict["categories"].append(cat)

    os.makedirs(os.path.dirname(json_file), exist_ok=True)
    json_fp = open(json_file, "w")
    json_str = json.dumps(json_dict)
    json_fp.write(json_str)
    json_fp.close()


if __name__ == "__main__":
    #  只需修改以下两个路径
    #  VOC数据集根目录
    voc_path = "VOC2012"
    
    #  保存coco格式数据集根目录
    save_coco_path = "VOC2COCO"
    
    #  VOC只分了训练集和验证集即train.txt和val.txt
    data_type_list = ["train", "val"]
    for data_type in data_type_list:
        os.makedirs(os.path.join(save_coco_path, data_type+"2017"))
        os.makedirs(os.path.join(save_coco_path, data_type+"_xml"))
        with open(os.path.join(voc_path, "ImageSets\Main", data_type+".txt"), "r") as f:
            txt_ls = f.readlines()
        txt_ls = [i.strip() for i in txt_ls]
        for i in os.listdir(os.path.join(voc_path, "JPEGImages")):
            if os.path.splitext(i)[0] in txt_ls:
                shutil.copy(os.path.join(voc_path, "JPEGImages", i),
                            os.path.join(save_coco_path, data_type+"2017", i))
                shutil.copy(os.path.join(voc_path, "Annotations", i[:-4]+".xml"), os.path.join(
                    save_coco_path, data_type+"_xml", i[:-4]+".xml"))
        xml_path = os.path.join(save_coco_path, data_type+"_xml")
        xml_files = glob.glob(os.path.join(xml_path, "*.xml"))
        convert(xml_files, os.path.join(save_coco_path,
                "annotations", "instances_"+data_type+"2017.json"))
        shutil.rmtree(xml_path)


结果如图所示,在voc2coco文件夹下有三个文件:
在这里插入图片描述

二、配置DETR

修改main.py文件中的参数、超参数:
在这里插入图片描述
这个最好不改,就设为coco。去修改models/detr.py 文件的num_classes(大概在三百多行)。这里作者也解释了num_classes其实并不是类别数,因为coco只有80类,因为coco的id是不连续的,coco数据集最大的ID是90,所以原论文时写的MAX ID +1 即91。对于我们自定义的和转化的VOC数据集num_classes就是类别数。
在这里插入图片描述


在这里插入图片描述
coco_path改成自己的coco路径。
在这里插入图片描述
其中预训练权重需要修改一下,coco是80类,不能直接加载官方的模型。voc是20类。把num_classes改成21。传入得到的detr_r50_21.pth新的权重文件。

import torch
pretrained_weights=torch.load('detr-r50-e632da11.pth')
num_classes=21
pretrained_weights["model"]["class_embed.weight"].resize_(num_classes+1,256)
pretrained_weights["model"]["class_embed.bias"].resize_(num_classes+1)
torch.save(pretrained_weights,"detr_r50_%d.path"%num_classes)

运行日志(特别难训练):
在这里插入图片描述

References

VOC2COCO代码参考Github
DETR预训练模型

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

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

相关文章

java基于springboot外卖系统在线订餐系统app源码厨艺论坛APP

简介 本项目主要包括了外卖订餐系统(在线订餐和外卖配送)、厨艺论坛系统、管理员后台、用户中心等功能。用户注册后可以选择餐桌在线点餐支付,也可以选择外卖配送到家的方式。 演示视频 https://www.bilibili.com/video/BV1xv411t7JD/?sha…

Thinkphp5框架简单理解

说明 该文章来源于同事lu2ker转载至此处,更多文章可参考:https://github.com/lu2ker/ 目录说明TP5框架简单理解1. 架构总览1.1 控制器/操作1.2 MVC模式流程1.3 类库自动加载1.4 URL访问检测1.5 路由模式1.5.1 普通模式1.5.2 混合模式1.5.4 强制路由1.6 …

数据结构与算法学习——栈结构

在程序设计中,一定接触过“堆栈”的概念。其实,“栈 ” 和 “堆 ” 是两个不同的概念。这里,栈是一种特殊的数据结构,在中断处理特别是重要数据的现场保护有着重要意义。 什么是栈结构 从数据的逻辑结构来看,栈结构其…

59. 微调(fine-tuning)代码实现

1. 热狗识别 让我们通过具体案例演示微调:热狗识别。 我们将在一个小型数据集上微调ResNet模型。该模型已在ImageNet数据集上进行了预训练。 这个小型数据集包含数千张包含热狗和不包含热狗的图像,我们将使用微调模型来识别图像中是否包含热狗。 %matp…

专访中银金科:数字驱动成为新的增长引擎,未来业务转化是关键

大数据和信息科技正在逐步颠覆银行业过往的业务模式。建立以数据驱动为核心,以优化客户体验为目标的可持续营销理念,逐渐成为行业的共识。但是,伴随着银行业数字化转型进程加速发展,海量客户数据和低效营销之间的矛盾日益凸显。在…

Linux apt 命令

apt(Advanced Packaging Tool)是一个在 Debian 和 Ubuntu 中的 Shell 前端软件包管理器。 apt 命令提供了查找、安装、升级、删除某一个、一组甚至全部软件包的命令,而且命令简洁而又好记。 apt 命令执行需要超级管理员权限(root)。 apt 语…

23.2、Junit单元测试反射注解

Java代码执行的三个阶段 Junit单元测试: * 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。 2. 白盒测试:需要写代码的。关注程序具体的执行流程。 * Junit使用&#…

洛谷千题详解 | P1030 [NOIP2001 普及组] 求先序排列【C/C++、pascal语言】

博主主页:Yu仙笙 专栏地址:洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析: C源码: C源码2: pascal源码: C源码: --------------------------------------------------------…

P4Pi AP转wifi模式

调试时间:2022.11.07 树莓派在安装P4Pi后,会自动设置为AP热点模式。本文档通过配置将树莓派系统从ap模式转变为wifi模式。 1 调试环境 Raspberry 4B 4GB-SDcard 32GB Raspberry Pi Imager v1.7.3 Raspberry Pi OS – Raspberry PiFrom industries lar…

值得信赖的数据同步备份软件 -Allway Sync 安全又可靠,简单又易用!

Allway Sync 是一款可靠的数据同步备份工具,最初的版本发布于 2004 年 4 月 19 号,距离今日大约有 19 年的更新历史了,足以说明软件绝对稳定,时间验证了软件的可靠性!而对于我们用户来说,数据同步备份最重要…

基于线性表的查找

目录 一、查找的基本概念 二、顺序查找 关键代码 完整代码 运行结果 增加哨兵 三、二分查找(折半查找) 关键代码 完整代码 运行结果 四、分块查找 图示 关键代码 完整代码 一、查找的基本概念 对查找表进行的操作 1.查找某个特定的数据元素是否存在 …

攻防世界-fakebook

题目 访问题目场景 我自己尝试了很久&#xff0c;发现怎么都找不到这道题的入手点&#xff0c;然后就去看了大佬们的文章&#xff0c;然后我发现这道题更趋近于真实的场景 解题过程 先使用目录扫描器扫一下发现存在robots.txt访问一下 这里发现存在一个备份文件 <?php…

html、css、js的小米商城

首页的展示 首页的功能 1、搜索栏模糊查询 在我在输入框输入关键字的时候&#xff0c;会匹配关键字&#xff0c;如果我的存放的数据里面包含这些关机键字就会显示出来。做到模糊查询的效果。 2、实现搜索功能 在首页的搜索框点击搜索的时候&#xff0c;就会对你输入的关键字进…

Redis 未授权访问的原理、危害及复现

原理介绍 Redis 未授权访问 准确的来说&#xff0c;其实并不是一个漏洞。而是由于开发人员配置不当&#xff0c;而产生的预料之外的危害。 具体原理&#xff1a; 可能由于部分业务要求&#xff0c;或者开发人员的配置不当&#xff0c;将 redis 服务器的 ip 和 port 暴露在公网…

基础数学(7)——常微分方程数值解法

文章目录期末考核方式基础知识解析解&#xff08;公式法&#xff09;解析解例题&#xff08;使用公式法&#xff0c;必考&#xff09;解析解的局限性数值解数值解的基本流程显示Euler法显示欧拉&#xff08;差值理解&#xff09;显示欧拉&#xff08;Taylor展开理解&#xff09…

ClickHouse表引擎详解看这篇就够了-基本讲解、处理逻辑、测试实例

表引擎是ClickHouse设计实现中的一大特色。表引擎在 ClickHouse 中的作用十分关键&#xff0c;直接决定了数据如何存储和读取、是否支持并发读写、是否支持 index、支持的 query 种类、是否支持主备复制等。1、表引擎概述1.1 介绍ClickHouse 提供了大约 28 种表引擎&#xff0c…

ArcGIS基础实验操作100例--实验43填充面要素空洞

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验43 填充面要素空洞 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&a…

JavaScript 条件语句

文章目录JavaScript If...Else 语句条件语句If 语句If...else 语句If...else if...else 语句JavaScript If…Else 语句 条件语句用于基于不同的条件来执行不同的动作。 条件语句 通常在写代码时&#xff0c;您总是需要为不同的决定来执行不同的动作。您可以在代码中使用条件语…

【学习笔记】Shell入门

Shell入门 https://www.bilibili.com/video/BV1WY4y1H7d3 资料&#xff1a;评论区取的 公众号的资料链接 https://pan.baidu.com/s/1_nBKUjE57MB2c96wmfSD5A 提取码&#xff1a;yyds 文章目录一、**Shell** 概述二、**Shell** 脚本入门三、变量1.系统预定义变量2.自定义变量**3…

自学软件测试该如何入门?

互联网行业发展很快技术更新也很快&#xff0c;软件测试技能要求在逐渐提高&#xff0c;自学软件测试要尽快而且入行后需要持续学习。保持好心态&#xff0c;找准教程&#xff0c;按照学习路线和自己的规划一步步学习下去~ 软件测试对代码的要求不像其他编程学科那么高&#x…