detectron2环境搭建及自定义coco数据集(voc转coco)训练

news2024/11/23 3:45:32

detectron2建议ubuntu进行环境搭建,Windows大概率报错

一 环境搭建

创建虚拟环境

conda create -n detectron2 python=3.8 -y
conda activate detectron2

后面下载源代码建议存到git中再git clone

git clone https://github.com/facebookresearch/detectron2.git
python -m pip install -e detectron2

二 数据集构建

首先有两个文件夹,一个为图像,一个为标注完的voc的xml文件夹
在这里插入图片描述
在这里插入图片描述
后先划分数据集,创建以下格式

-- imageSets
	---Main
		----test.txt
		----train.txt
		----trainval.txt
		----val.txt

运行以下代码进行划分

import os
import random
def main():
    trainval_percent = 0.2
    train_percent = 0.8
    xmlfilepath = 'D:\\lunwen\\data\\data\\xml' # xml文件位置
    txtsavepath = r'D:\\lunwen\\data\\data\\image'  # 图像位置
    total_xml = os.listdir(xmlfilepath)

    num = len(total_xml)
    list = range(num)
    tv = int(num * trainval_percent)
    tr = int(tv * train_percent)
    trainval = random.sample(list, tv)
    train = random.sample(trainval, tr)
## 以下为对应的txt文件进行修改
    ftrainval = open('D:\\lunwen\\data\data\\ImageSets\\Main\\trainval.txt', 'w')
    ftest = open('D:\\lunwen\\data\data\\ImageSets\\Main\\test.txt', 'w')
    ftrain = open('D:\\lunwen\\data\data\\ImageSets\\Main\\train.txt', 'w')
    fval = open('D:\\lunwen\\data\data\\ImageSets\\Main\\val.txt', 'w')

    for i in list:
        name = total_xml[i][:-4] + '\n'
        if i in trainval:
            ftrainval.write(name)
            if i in train:
                ftest.write(name)
            else:
                fval.write(name)
        else:
            ftrain.write(name)

    ftrainval.close()
    ftrain.close()
    fval.close()
    ftest.close()



if __name__=='__main__':
    main();

划分完后对应的txt文件都有数据,后面将进行文件提取,提取出对应的训练/测试数据集及其xml文件

源目录下创建以下文件夹

-train_JPEGImages
-train_annotations
-val_JPEGImages
-val_annotations
import os
import shutil


class CopyXml():
    def __init__(self):
        # 你的xml格式的annotation的路径
        self.xmlpath = r'D:\lunwen\data\data\xml'
        self.jpgpath = r'D:\lunwen\data\data\image'
        # 你训练集/测试集xml和jpg存放的路径
        self.newxmlpath = r'D:\lunwen\data\data\val_annotations'
        self.newjpgpath = r'D:\lunwen\data\data\val_JPEGImages'

    def startcopy(self):
        filelist = os.listdir(self.xmlpath)  # file list in this directory
        # print(len(filelist))
        test_list = loadFileList()
        # print(len(test_list))
        for f in filelist:
            xmldir = os.path.join(self.xmlpath, f)
            (shotname, extension) = os.path.splitext(f)
            jpgdir = os.path.join(self.jpgpath, shotname+'.jpg')
            if str(shotname) in test_list:
                # print('success')
                shutil.copyfile(str(xmldir), os.path.join(self.newxmlpath, f))
                shutil.copyfile(str(jpgdir), os.path.join(self.newjpgpath, shotname+'.jpg'))


# load the list of train/test file list
def loadFileList():
    filelist = []
    ## 选取你上一步弄好的txt文件进行提取
    f = open("D:\\lunwen\\data\\data\\ImageSets\\Main\\val.txt", "r")
    # f = open("VOC2007/ImageSets/Main/train.txt", "r")
    lines = f.readlines()
    for line in lines:
        # 去掉文件中每行的结尾字符
        line = line.strip('\r\n')  # to remove the '\n' for test.txt, '\r\n' for tainval.txt
        line = str(line)
        filelist.append(line)
    f.close()
    # print(filelist)
    return filelist


if __name__ == '__main__':
    demo = CopyXml()
    demo.startcopy()

成功后对应文件夹下将会有对应txt下的图片及xml
后面便是voc转coco格式了,代码如下

# coding:utf-8
import sys
import os
import json
import xml.etree.ElementTree as ET

START_BOUNDING_BOX_ID = 1
# 注意下面的dict存储的是实际检测的类别,需要根据自己的实际数据进行修改
# 这里以自己的数据集person和hat两个类别为例,如果是VOC数据集那就是20个类别
# 注意类别名称和xml文件中的标注名称一致
PRE_DEFINE_CATEGORIES = {"Normal": 0, "No_wear": 1,"Playing_phone":2,"Smoking":3,"Sleeping":4,
                         "Playing_phone_smoking":5,"No_wear_playing_phone":6,"No_wear_smoking":7,"No_wear_sleeping":8,
                         "No_wear_playing_phone_smoking":9}

# 注意按照自己的数据集名称修改编号和名称
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 NotImplementedError('Can not find %s in %s.' % (name, root.tag))
    if length > 0 and len(vars) != length:
        raise NotImplementedError('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 = os.path.splitext(filename)[0]
        return (filename)
    except:
        raise NotImplementedError('Filename %s is supposed to be an integer.' % (filename))


def convert(xml_dir, json_file):
    xmlFiles = os.listdir(xml_dir)

    json_dict = {"images": [], "type": "instances", "annotations": [],
                 "categories": []}
    categories = PRE_DEFINE_CATEGORIES
    bnd_id = START_BOUNDING_BOX_ID
    num = 0
    for line in xmlFiles:
        #         print("Processing %s"%(line))
        num += 1
        if num % 50 == 0:
            print("processing ", num, "; file ", line)

        xml_f = os.path.join(xml_dir, line)
        tree = ET.parse(xml_f)
        root = tree.getroot()
        # The filename must be a number
        filename = line[:-4]
        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}
        image = {'file_name': (filename + '.jpg'), 'height': height, 'width': width,
                 'id': image_id}
        json_dict['images'].append(image)
        # Cruuently 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)
    json_fp = open(json_file, 'w')
    json_str = json.dumps(json_dict)
    json_fp.write(json_str)
    json_fp.close()

if __name__ == '__main__':
    folder_list = ["train_annotations"]
    # 注意更改base_dir为本地实际图像和标注文件路径
    base_dir = "D:\\lunwen\\data\\data\\"
    # 修改为自己的路径
    for i in range(1):
        folderName = folder_list[i]
        xml_dir = base_dir + folderName
        json_dir = base_dir + folderName + "/instances_" + folderName + ".json"
        print("deal: ", folderName)
        print("xml dir: ", xml_dir)
        print("json file: ", json_dir)
        convert(xml_dir, json_dir)


最后生成
在这里插入图片描述

在detectron2下datasets中创建coco文件夹,将对应数据放入

coco

----train2017 ####手动创建

----val2017 ####手动创建

----annotations ####手动创建

--------instances_train2017.json ####脚本生成

--------instances_val2017.json ####脚本生成

三 模型训练

因为pytorch训练自己的数据集,涉及到数据集的注册,元数据集注册和加载,过程比较麻烦,这里我参考官方样本,写了一个脚本trainsample.py放置于model_train文件夹下。

import os
import cv2
import logging
from collections import OrderedDict

import detectron2.utils.comm as comm
from detectron2.utils.visualizer import Visualizer
from detectron2.checkpoint import DetectionCheckpointer
from detectron2.config import get_cfg
from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.data.datasets.coco import load_coco_json
from detectron2.engine import DefaultTrainer, default_argument_parser, default_setup, launch
from detectron2.evaluation import COCOEvaluator, verify_results
from detectron2.modeling import GeneralizedRCNNWithTTA

# 数据集路径
DATASET_ROOT = './datasets/coco'
ANN_ROOT = os.path.join(DATASET_ROOT, 'annotations')

TRAIN_PATH = os.path.join(DATASET_ROOT, 'train2017')
VAL_PATH = os.path.join(DATASET_ROOT, 'val2017')

TRAIN_JSON = os.path.join(ANN_ROOT, 'instances_train2017.json')
# VAL_JSON = os.path.join(ANN_ROOT, 'val.json')
VAL_JSON = os.path.join(ANN_ROOT, 'instances_val2017.json')

CLASS_NAMES = ['Normal','No_wear','Playing_phone','Smoking','Sleeping','Playing_phone_smoking','No_wear_playing_phone'
    ,'No_wear_smoking','No_wear_sleeping','No_wear_playing_phone_smoking']
# 数据集类别元数据
DATASET_CATEGORIES = [
    # {"name": "background", "id": 0, "isthing": 1, "color": [220, 20, 60]},
    {"name": "Normal", "id": 0, "isthing": 1, "color": [255, 0, 0]},  # 红色
    {"name": "No_wear", "id": 1, "isthing": 1, "color": [0, 255, 0]},  # 绿色
    {"name": "Playing_phone", "id": 2, "isthing": 1, "color": [0, 0, 255]},  # 蓝色
    {"name": "Smoking", "id": 3, "isthing": 1, "color": [255, 255, 0]},  # 黄色
    {"name": "Sleeping", "id": 4, "isthing": 1, "color": [255, 0, 255]},  # 紫色
    {"name": "Playing_phone_smoking", "id": 5, "isthing": 1, "color": [0, 255, 255]},  # 青色
    {"name": "No_wear_playing_phone", "id": 6, "isthing": 1, "color": [128, 0, 128]},  # 深紫色
    {"name": "No_wear_smoking", "id": 7, "isthing": 1, "color": [128, 128, 0]},  # 深黄色
    {"name": "No_wear_sleeping", "id": 8, "isthing": 1, "color": [0, 128, 128]},  # 深青色
    {"name": "No_wear_playing_phone_smoking", "id": 9, "isthing": 1, "color": [128, 128, 128]}
]

# 数据集的子集
PREDEFINED_SPLITS_DATASET = {
    "train_2019": (TRAIN_PATH, TRAIN_JSON),
    "val_2019": (VAL_PATH, VAL_JSON),
}


def register_dataset():
    """
    purpose: register all splits of dataset with PREDEFINED_SPLITS_DATASET
    """
    for key, (image_root, json_file) in PREDEFINED_SPLITS_DATASET.items():
        register_dataset_instances(name=key,
                                   metadate=get_dataset_instances_meta(),
                                   json_file=json_file,
                                   image_root=image_root)


def get_dataset_instances_meta():
    """
    purpose: get metadata of dataset from DATASET_CATEGORIES
    return: dict[metadata]
    """
    thing_ids = [k["id"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
    thing_colors = [k["color"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
    # assert len(thing_ids) == 2, len(thing_ids)
    thing_dataset_id_to_contiguous_id = {k: i for i, k in enumerate(thing_ids)}
    thing_classes = [k["name"] for k in DATASET_CATEGORIES if k["isthing"] == 1]
    ret = {
        "thing_dataset_id_to_contiguous_id": thing_dataset_id_to_contiguous_id,
        "thing_classes": thing_classes,
        "thing_colors": thing_colors,
    }
    return ret


def register_dataset_instances(name, metadate, json_file, image_root):
    """
    purpose: register dataset to DatasetCatalog,
             register metadata to MetadataCatalog and set attribute
    """
    DatasetCatalog.register(name, lambda: load_coco_json(json_file, image_root, name))
    MetadataCatalog.get(name).set(json_file=json_file,
                                  image_root=image_root,
                                  evaluator_type="coco",
                                  **metadate)


# 注册数据集和元数据
def plain_register_dataset():
    DatasetCatalog.register("train_2019", lambda: load_coco_json(TRAIN_JSON, TRAIN_PATH, "train_2019"))
    MetadataCatalog.get("train_2019").set(thing_classes=CLASS_NAMES,
                                          json_file=TRAIN_JSON,
                                          image_root=TRAIN_PATH)
    DatasetCatalog.register("val_2019", lambda: load_coco_json(VAL_JSON, VAL_PATH, "val_2019"))
    MetadataCatalog.get("val_2019").set(thing_classes=CLASS_NAMES,
                                        json_file=VAL_JSON,
                                        image_root=VAL_PATH)


# 查看数据集标注
def checkout_dataset_annotation(name="train_2019"):
    dataset_dicts = load_coco_json(TRAIN_JSON, TRAIN_PATH, name)
    for d in dataset_dicts:
        img = cv2.imread(d["file_name"])
        visualizer = Visualizer(img[:, :, ::-1], metadata=MetadataCatalog.get(name), scale=1.5)
        vis = visualizer.draw_dataset_dict(d)
        cv2.imshow('show', vis.get_image()[:, :, ::-1])
        cv2.waitKey(0)


register_dataset()

checkout_dataset_annotation()

slowfast源码中采取的模型架构为
在这里插入图片描述
在config中找到对应的yaml文件,并在trainsample.py进行设定

后运行

$ python3 model_train/trainsample.py

四 问题

1.缺少cv2模块

pip install opencv-python

2.PIL中缺少模块

`LINEAR` is deprecated and will be removed in Pillow 10 (2023-07-01). Use BILINEAR or Resampling.BILINEAR instead. 

版本更新

pip install pillow==9.5.0

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

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

相关文章

王道p40 1.设计一个递归算法,递归删除单链表L中所有值为x的结点(c语言)

视频讲解在这里:👇 p40 第1题 王道数据结构课后代码题c语言代码实现_哔哩哔哩_bilibili 本题代码如下 void delete(linklist* L,int x)//递归删除x {if((*L)->next! NULL){if ((*L)->next->data x)//找到x{lnode* p (*L)->next;(*L)-&…

【第2章 Node.js基础】2.2 Node.js回调函数

学习目标 (1)理解Node.js的回调函数; (2)掌握回调函数的使用。 什么是回调函数 回调函数是一种特殊的函数,它作为参数传递给另一个函数,并在特定的事件或条件发生时被调用。回调函数通常用于异…

FreeRTOS学习笔记——SysTick中断

FreeRTOS学习笔记——SysTick中断_freertos tick中断-CSDN博客 FreeRTOS 之六 任务调度原理解析(Systick、PendSV、SVC)_freertos m0-CSDN博客 FreeRTOS中关于时间的管理分为两部分:一部分是任务的延时管理;前面叙述过一些,还有…

找不到d3dx9_43.dll怎么办?解决d3dx9_43.dll丢失的5个方法

在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是“找不到d3dx9_43.dll”。这个错误通常出现在运行某些游戏或应用程序时,它是由于缺少DirectX组件中的d3dx9_43.dll文件所引起的。那么,当我们遇到这个问题时&#xff…

JWT 使用入门(三)请求流程

文章目录 1、前后端使用JWT详细步骤2、前后端使用JWT详情图3、从流程中看优点与缺点3.1 优点3.2 缺点 之前在第一篇中提到过其使用流程,以下讲的是第二种:https://blog.csdn.net/qq_37534947/article/details/132066909 但是JWT主要作用应该应用于以下&a…

Android sqlite 使用简介

进行Android应用开发时经常会用到数据库。Android系统支持sqlite数据库,在app开发过程中很容易通过SQLiteOpenHelper使用数据库,SQLiteOpenHelper依赖于Context对象,但是基于uiatomator1.0和Java程序等无法获取Context的应用如何使用数据库呢…

SAP实现文本框多行输入(类cl_gui_textedit)

先看效果,在输入框先来一段《赤壁赋》 然后点击 ‘保存输出’按钮,就能把输入内容从表里读取并输出来 源代码: *&---------------------------------------------------------------------* *& Report ZCYCLE060 *&---------…

如何避免JavaScript中的内存泄漏?

前言 过去,我们浏览静态网站时无须过多关注内存管理,因为加载新页面时,之前的页面信息会从内存中删除。 然而,随着单页Web应用(SPA)的兴起,应用程序消耗的内存越来越多,这不仅会降低…

13 套接字Socket

1、Socket 编程 socket编程基于 TCP 和 UDP 协议的tcp和udp是区分客户端和服务端的,所以我们的socket编程也是区分的。 2、socket是端到端的通信 1.Socket 这个名字很有意思,可以作插口或者插槽讲 2.一头插在客户端,一头插在服务端&#x…

阿里云双11优惠活动:2核2G3M云服务器1年99元,新老用户均可购买!

阿里云双11优惠活动正在火热进行中,阿里云推出了一款特价云服务器ECS,2核2G3M的配置1年仅需99元,新老用户均可购买,新购、续费同价! 活动入口:传送门>>> 活动详情: 云服务器ECS&#…

Bitget Wallet:使用 Base 链购买 ETH 的简明教程

Base 链是一种 Layer 2(L2)公链,它可以为用户提供以太坊(ETH)代币,而 Bitget Wallet 是一款多功能加密货币钱包,支持 Base 链以及其他主要区块链。

三天打鱼两天晒网

文章目录 前言一、题目描述 二、题目分析 三、解题 程序运行代码 前言 本系列为选择结构编程题&#xff0c;点滴成长&#xff0c;一起逆袭。 一、题目描述 二、题目分析 三、解题 程序运行代码 #include<stdio.h> int main(){int n;scanf("%d",&n);i…

MySQL进阶_1.逻辑架构和SQL执行流程

文章目录 第一节、逻辑架构剖析1.1、服务器处理客户端请求1.2、Connectors1.3、第1层&#xff1a;连接层1.4、第2层&#xff1a;服务层1.5、 第3层&#xff1a;引擎层1.6、 存储层1.7、小结 第二节、SQL执行流程2.1、查询缓存2.2、解析器2.3、优化器2.4、执行器 第三节、数据库…

MySQL的安装使用(入学篇)

目录 1 MySQL安装 1.1 安装epel源 1.2 安装MySQL Repository 1.3 安装MySQL官方yum源 1.4 安装服务端、客户端 1.5 启动MySQL服务 2 MySQL 使用 2.1 获取初始登录密码 2.2 登录MySQL数据库 2.3 修改密码 2.4 退出数据库 2.5 使用新密码登录数据库 2.6 重启数据库 2.7 创建数据…

美国出台新规对全球芯片业产生深远影响 | 百能云芯

2023年10月18日&#xff0c;美国宣布了一项新版半导体出口管制规则&#xff0c;旨在限制对中国等特定市场出口尖端人工智能&#xff08;AI&#xff09;芯片的企业。该法规于当月16日生效&#xff0c;引发了广泛的关注。据日本经济新闻报道&#xff0c;这一举措将显着提高中国发…

Docker安装Elasticsearch和Kibana

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Leetcode—2578.最小和分割【简单】

2023每日刷题&#xff08;二十三&#xff09; Leetcode—2578.最小和分割 实现代码 class Solution { public:int splitNum(int num) {vector<int> a;while(num) {a.push_back(num % 10);num / 10;}int n a.size();sort(a.begin(), a.begin() n);int num1 0;int num…

商业保险/补充医疗,打工人不可忽略的额外福利

关于看病如何花钱这回事&#xff0c;我之前的认知仅仅停留在可以使用医保报销的层次。 虽然工作这十年来公司一直有提供商业保险的福利&#xff0c;但是之前一直没有关注过它&#xff0c;直到去年偶然尝试了通过商业保险申请理赔&#xff0c;从而实现医保报销后的二次报销。在二…

node 第十六天 模板引擎handlebars

handlebars handlebars文档 Handlebars 是一种简单的 模板语言。 它使用模板和输入对象来生成 HTML 或其他文本格式。Handlebars 模板看起来像常规的文本&#xff0c;但是它带有嵌入式的 Handlebars 表达式 。 这里我们要注意模板引擎的定义 模板引擎是对一串字符串 结合数据 编…

Python GUI标准库tkinter实现与记事本相同菜单的文本编辑器(一)

介绍&#xff1a; Windows操作系统中自带了一款记事本应用程序&#xff0c;通常用于记录文字信息&#xff0c;具有简单文本编辑功能。Windows的记事本可以新建、打开、保存文件&#xff0c;有复制、粘贴、删除等功能&#xff0c;还可以设置字体类型、格式和查看日期时间等。 …