Demable-DETR部署及训练个人数据集

目录

1. 环境

1.1 运行环境

1.2 环境部署

2.csv转换coco数据集

3.进行训练

3.1训练自己数据集

3.2使用官方的权重文件对提供的coco数据进行预测

4.总结


前言

新手小白一个,摸索了几天,分享一下学习内容。以下内容具有不确定性,仅供参考。

源码:https://github.com/fundamentalvision/Deformable-DETR

1. 环境

1.1 运行环境

系统:Ubuntu 18.04

 工具:Pytorch(1.8.0)         CUDA(11.1)        显卡(NVIDIA GeForce RTX 3060)

               驱动版本(530.41.03)

1.2 环境部署

关于双系统安装Ubuntu和Ubuntu上安装Anaconda,网上相关的教程有大把,而且都很详细,我就不在进行赘述。

1). 首先在Anaconda上为Demable-DETR搭建虚拟环境

conda create -n Deformable-DETR python=3.8 pip

运行提示输入y并回车,等待创建成功

2).进入虚拟环境:

conda activate Deformable-DETR

因为我以前已经安装过环境,为了方便演示,我又新建了Deformable-DETR这个新环境。如果没有安装过其他虚拟环境,默认的是base。我们可以通过下面命令查看当前有哪些环境。

conda env list

3). 下载源码查看安装所需要的库

进入前面给的论文链接进行查看

因为这是又新安装的环境,不需要和比赛一样对版本有特定要求,所以直接去Pytorch官网查询安装命令。https://pytorch.org/

我的命令是:

conda install pytorch torchvision torchaudio pytorch-cuda=12.1 -c pytorch -c nvidia

等待安装,大概需要几分钟。

打开python检查是否安装成功:

import torch

print(torch.__version__)

print(torch.version.cuda)

显示出版本则安装成功。

如果安装其他版本只需要对其后面进行版本的书写就可以,但是要先查询Pytorch的版本支持的 CUDA版本,这里不再进行演示。比赛要求的Pytorch为1.8,网上查询对应的CUDA为11.1和10.2,不过我用11.1进行安装,会失败,具体什么情况我也不是很清楚。


4).安装显卡驱动
这个驱动安装就比较费事,我从网上搜了好多文章,大体有两种安装方式。第一种,有手动官网下载进行安装,显示安装成功,但查询不到驱动版本,等于安装失败。其中涉及到一些命令行的操作,不推荐新手使用这种方法。第二种就是使用系统自带渠道安装,先去英伟达官网进行查询驱动版本。https://www.nvidia.cn/Download/index.aspx?lang=cn

不要下载,这时打开Ubuntu自带的软件和更新,进行驱动的应用

安装成功使用以下命令进行查看:

nvidia-smi

5). 其他需求

进入工程的主目录使用命令:

pip install -r requirements.txt

2.csv转换coco数据集

因为比赛的训练集已经提供了标注的信息.csv文件,我们只需进行转换为coco数据类型,其中coco中最主要的.json文件,我们只需要其中的 "images","annotations","categories"这三个字段,其格式如下:

"images"

height为图像高度;width为图像宽度;id为图像id;file_name为图像文件名。

"annotations"

id为标注框的id,一张图片可以有多个标注框。

image_id为"images"中图片的id。

category_id为标签的类别,这里的数字对应"categories"中的相应类别id。

segmentation为检测目标的轮廓分割级标签。因为我这里的数据都是矩形标注框,所以设置为空。

"bbox" [x,y,width,height]为标注框的信息,x,y为标注框左上角坐标。

iscrowd为目标是否被遮盖,默认为0。

"categories"

id为对应以上annotations部分的category_id。

name为类别标签名称。

下面是我的csv转coco数据格式的代码,网上参考进行修改,非原创

import os
import json
import numpy as np
import pandas as pd
import os
import cv2
import shutil
from IPython import embed
from sklearn.model_selection import train_test_split
np.random.seed(41)

#0为背景
classname_to_id = {'E2': 1, 'J20': 2, 'B2': 3, 'F14': 4, 'Tornado': 5, 'F4': 6, 'B52': 7, 'JAS39': 8, 'Mirage2000': 9}
class Csv2CoCo:

    def __init__(self,image_dir,total_annos):
        self.images = []
        self.annotations = []
        self.categories = []
        self.img_id = 0
        self.ann_id = 0
        self.image_dir = image_dir
        self.total_annos = total_annos

    def save_coco_json(self, instance, save_path):
        json.dump(instance, open(save_path, 'w'), ensure_ascii=False, indent=2)  # indent=2 更加美观显示

    # 由txt文件构建COCO
    def to_coco(self, keys):
        self._init_categories()
        for key in keys:
            self.images.append(self._image(key))
            shapes = self.total_annos[key]
            for shape in shapes:
                bboxi = []
                # for cor in shape[:-1]:
                for cor in shape[1:]:
                    bboxi.append(int(cor))
                label = shape[0]
                annotation = self._annotation(bboxi, label)
                self.annotations.append(annotation)
                self.ann_id += 1
            self.img_id += 1
        instance = {}
        instance['images'] = self.images
        instance['annotations'] = self.annotations
        instance['categories'] = self.categories
        return instance

    # 构建类别
    def _init_categories(self):
        for k, v in classname_to_id.items():
            category = {}
            category['id'] = v
            category['name'] = k
            self.categories.append(category)

    # 构建COCO的image字段
    def _image(self , filename):
        image = {}
        img = cv2.imread(self.image_dir + filename + '.jpg')
        image['height'] = img.shape[0]
        image['width'] = img.shape[1]
        image['id'] = self.img_id
        image['file_name'] = filename + '.jpg'
        return image

    # 构建COCO的annotation字段
    def _annotation(self, shape,label):
        points = shape[0 : ]
        annotation = {}
        annotation['id'] = self.ann_id
        annotation['image_id'] = self.img_id
        annotation['category_id'] = int(classname_to_id[label])
        annotation['segmentation'] = [[]]
        annotation['bbox'] = self._get_box(points)
        annotation['iscrowd'] = 0
        annotation['area'] = self._get_area(points)
        return annotation

    # COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式
    def _get_box(self, points):
        min_x = points[0]
        min_y = points[1]
        max_x = points[2]
        max_y = points[3]
        return [min_x, max_y, max_x - min_x, max_y - min_y]
    # 计算面积
    def _get_area(self, points):
        min_x = points[0]
        min_y = points[1]
        max_x = points[2]
        max_y = points[3]
        return (max_x - min_x+1) * (max_y - min_y+1)
   

if __name__ == '__main__':
    csv_file = "./combined_file.csv"
    image_dir = "./train/"
    saved_coco_path = "./"
    # 整合csv格式标注文件
    total_csv_annotations = {}
    annotations = pd.read_csv(csv_file).values
    for annotation in annotations:
        filename = annotation[0]
        height = annotation[1]
        width = annotation[2]
        category_id = annotation[3]
        # key = annotation[0].split(os.sep)[-1]
        # value = np.array([annotation[1:]])
        # value1 = np.array([annotation[1: 4]])
        # print(value1)
        value = np.array([annotation[3:]])
        print(value)
        # print(value)
        if filename in total_csv_annotations.keys():
            total_csv_annotations[filename] = np.concatenate((total_csv_annotations[filename],value),axis=0)
        else:
            total_csv_annotations[filename] = value
    # 按照键值划分数据
    total_keys = list(total_csv_annotations.keys())
    train_keys, val_keys = train_test_split(total_keys, test_size=0.2)
    # print(train_keys)
    print("train_n:", len(train_keys), 'val_n:', len(val_keys))
    # 创建必须的文件夹
    if not os.path.exists('%scoco/annotations/'%saved_coco_path):
        os.makedirs('%scoco/annotations/'%saved_coco_path)
    if not os.path.exists('%scoco/images/train2017/'%saved_coco_path):
        os.makedirs('%scoco/images/train2017/'%saved_coco_path)
    if not os.path.exists('%scoco/images/val2017/'%saved_coco_path):
        os.makedirs('%scoco/images/val2017/'%saved_coco_path)
    # 把训练集转化为COCO的json格式
    l2c_train = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)
    train_instance = l2c_train.to_coco(train_keys)
    l2c_train.save_coco_json(train_instance, '%scoco/annotations/instances_train2017.json'%saved_coco_path)
    for file in train_keys:
        shutil.copy(image_dir+file + '.jpg',"%scoco/images/train2017/"%saved_coco_path)
    for file in val_keys:
        shutil.copy(image_dir+file + '.jpg',"%scoco/images/val2017/"%saved_coco_path)
    # 把验证集转化为COCO的json格式
    l2c_val = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)
    val_instance = l2c_val.to_coco(val_keys)
    l2c_val.save_coco_json(val_instance, '%scoco/annotations/instances_val2017.json'%saved_coco_path)

其中我的cvs文件中的数据为格式如下:

执行完上面的代码,就可以生成所需要的coco数据格式了,格式如下:

这些文件名对应的是标准coco2017数据格式进行生成的,可根据实际需求进行修改。

3.进行训练

3.1训练自己数据集

这下面参数修改的步骤都是根据下面这篇文章进行修改的。

目标检测算法——deformable-detr源码调试_deformable detr的detect.py_lzh~的博客-CSDN博客

训练我自己的数据集,使用模型进行预测效果非常次,应该是我的数据集影响因素表较多,训练集数据比较少,猜测是这些原因。纯小白,没基础参加比赛,跑出来结果就已经可以了。

放几张用自己训练模型预测的图片,其中有的图片识别标签不对,还有背景干扰过多识别的标签很多,尝试改过num_queries进行训练,效果依旧不好。

3.2使用官方的权重文件对提供的coco数据进行预测

训练自己的数据集效果非常不好,所以我又去尝试使用官方提供的权重文件,对其提供验证集进行预测,权重文件下载。

下载完直接使用这个权重文件进行预测,预测代码为:

import cv2
from PIL import Image
import numpy as np
import os
import time
 
import torch
from torch import nn
import torchvision.transforms as T
from main import get_args_parser as get_main_args_parser
from models import build_model
 
torch.set_grad_enabled(False)
 
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("[INFO] 当前使用{}做推断".format(device))
 
# 图像数据处理
transform = T.Compose([
    T.Resize(800),
    T.ToTensor(),
    T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
 
# plot box by opencv
def plot_result(pil_img, prob, boxes, save_name=None, imshow=False, imwrite=False):
    opencvImage = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
    LABEL =['N/A', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
            'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'N/A',
            'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse',
            'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'N/A', 'backpack',
            'umbrella', 'N/A', 'N/A', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis',
            'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove',
            'skateboard', 'surfboard', 'tennis racket', 'bottle', 'N/A', 'wine glass',
            'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich',
            'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake',
            'chair', 'couch', 'potted plant', 'bed', 'N/A', 'dining table', 'N/A',
            'N/A', 'toilet', 'N/A', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',
            'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'N/A',
            'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
    for p, (xmin, ymin, xmax, ymax) in zip(prob, boxes):
        cl = p.argmax()
        label_text = '{}: {}%'.format(LABEL[cl], round(p[cl] * 100, 2))
 
        cv2.rectangle(opencvImage, (int(xmin), int(ymin)), (int(xmax), int(ymax)), (255, 255, 0), 2)
        cv2.putText(opencvImage, label_text, (int(xmin) + 10, int(ymin) + 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
                    (255, 255, 0), 2)
    
    if imshow:
        cv2.imshow('detect', opencvImage)
        cv2.waitKey(0)
 
    if imwrite:
        if not os.path.exists("./result/pred"):
            os.makedirs('./result/pred')
        cv2.imwrite('./result/pred/{}'.format(save_name), opencvImage)
 
# 将xywh转xyxy
def box_cxcywh_to_xyxy(x):
    x_c, y_c, w, h = x.unbind(1)
    b = [(x_c - 0.5 * w), (y_c - 0.5 * h),
         (x_c + 0.5 * w), (y_c + 0.5 * h)]
    return torch.stack(b, dim=1)
 
def rescale_bboxes(out_bbox, size):
    img_w, img_h = size
    b = box_cxcywh_to_xyxy(out_bbox)
    b = b.cpu().numpy()
    b = b * np.array([img_w, img_h, img_w, img_h], dtype=np.float32)
    return b
 
def load_model(model_path , args):
    model, _, _ = build_model(args)
    model.cuda()
    model.eval()
    state_dict = torch.load(model_path) # <-----------修改加载模型的路径
    model.load_state_dict(state_dict["model"])
    model.to(device)
    print("load model sucess")
    return model
 
# 图像的推断
def detect(im, model, transform, prob_threshold=0.7):
    # mean-std normalize the input image (batch-size: 1)
    img = transform(im).unsqueeze(0)
 
 
    # propagate through the model
    img = img.to(device)
    start = time.time()
    outputs = model(img)
   
    # keep only predictions with 0.7+ confidence
    print(outputs['pred_logits'].softmax(-1)[0, :, :-1])
    probas = outputs['pred_logits'].softmax(-1)[0, :, :-1]
    keep = probas.max(-1).values > prob_threshold
 
    probas = probas.cpu().detach().numpy()
    keep = keep.cpu().detach().numpy()
 
    # convert boxes from [0; 1] to image scales
    bboxes_scaled = rescale_bboxes(outputs['pred_boxes'][0, keep], im.size)
    end = time.time()
    return probas[keep], bboxes_scaled, end - start
 
 
if __name__ == "__main__":
    
    main_args = get_main_args_parser().parse_args()
    # 加载模型
    dfdetr = load_model('./r50_deformable_detr-checkpoint.pth',main_args) # <--修改为自己加载模型的路径
 
    files = os.listdir("./val2017") # <--修改为待预测图片所在文件夹路径
 
    cn = 0
    waste=0
    for file in files:
        img_path = os.path.join("./val2017", file) # <--修改为待预测图片所在文件夹路径
        im = Image.open(img_path)
 
        scores, boxes, waste_time = detect(im, dfdetr, transform)
        plot_result(im, scores, boxes, save_name=file, imshow=False, imwrite=True)
        print("{} [INFO] {} time: {} done!!!".format(cn,file, waste_time))
 
        cn+=1
        waste+=waste_time
        waste_avg = waste/cn
        print(waste_avg)

查看预测结果

4.总结

使用defoemable-detr训练自己的模型,我的数据集是对飞机类别进行目标检测分类,虽然跑的通,但是效果很不好。因为是初学者具体什么原因我也不太清楚,自己摸索了几天还是比较棘手的,只会用,里面的原理,代码部分基本看不懂。观察训练日志文件,损失值是在下降,但是train_class_error错误率还是很高,个人感觉数据集过少的原因。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Transformer在许多NLP(自然语言处理)任务中取得了最先进的成果。 DETR(Detection Transformer)是Facebook提出的基于Transformer的端到端目标检测方法。DETR使用CNN+Transformer进行图像目标检测,该方法没有NMS后处理步骤、没有anchor。DETR总体思路是把目标检测看成一个set prediction的问题,并且使用Transformer来预测物体边界框的集合。本课程对DETR的原理与PyTorch实现代码进行精讲,来帮助大家掌握其详细原理和具体实现。 原理精讲部分包括:Transformer的架构概述、Transformer的Encoder 、Transformer的Decoder、DETR网络架构、DETR损失函数、DETR实验结果和分析。  代码精讲部分使用Jupyter Notebook对DETR的PyTorch代码进行逐行解读,包括:安装PyTorch、 DETR官方Demo,DETR的hands-on tutorial,DETR的代码精讲(数据准备、Backbone和位置编码、Transformer架构的实现)。相关课程: 《Transformer原理与代码精讲(PyTorch)》https://edu.csdn.net/course/detail/36697《Transformer原理与代码精讲(TensorFlow)》https://edu.csdn.net/course/detail/36699《ViT(Vision Transformer)原理与代码精讲》https://edu.csdn.net/course/detail/36719《DETR原理与代码精讲》https://edu.csdn.net/course/detail/36768《Swin Transformer实战目标检测:训练自己的数据集》https://edu.csdn.net/course/detail/36585《Swin Transformer实战实例分割:训练自己的数据集》https://edu.csdn.net/course/detail/36586《Swin Transformer原理与代码精讲》 https://download.csdn.net/course/detail/37045

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值