当前位置:   article > 正文

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

deformable-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数据格式的代码,网上参考进行修改,非原创

  1. import os
  2. import json
  3. import numpy as np
  4. import pandas as pd
  5. import os
  6. import cv2
  7. import shutil
  8. from IPython import embed
  9. from sklearn.model_selection import train_test_split
  10. np.random.seed(41)
  11. #0为背景
  12. classname_to_id = {'E2': 1, 'J20': 2, 'B2': 3, 'F14': 4, 'Tornado': 5, 'F4': 6, 'B52': 7, 'JAS39': 8, 'Mirage2000': 9}
  13. class Csv2CoCo:
  14. def __init__(self,image_dir,total_annos):
  15. self.images = []
  16. self.annotations = []
  17. self.categories = []
  18. self.img_id = 0
  19. self.ann_id = 0
  20. self.image_dir = image_dir
  21. self.total_annos = total_annos
  22. def save_coco_json(self, instance, save_path):
  23. json.dump(instance, open(save_path, 'w'), ensure_ascii=False, indent=2) # indent=2 更加美观显示
  24. # 由txt文件构建COCO
  25. def to_coco(self, keys):
  26. self._init_categories()
  27. for key in keys:
  28. self.images.append(self._image(key))
  29. shapes = self.total_annos[key]
  30. for shape in shapes:
  31. bboxi = []
  32. # for cor in shape[:-1]:
  33. for cor in shape[1:]:
  34. bboxi.append(int(cor))
  35. label = shape[0]
  36. annotation = self._annotation(bboxi, label)
  37. self.annotations.append(annotation)
  38. self.ann_id += 1
  39. self.img_id += 1
  40. instance = {}
  41. instance['images'] = self.images
  42. instance['annotations'] = self.annotations
  43. instance['categories'] = self.categories
  44. return instance
  45. # 构建类别
  46. def _init_categories(self):
  47. for k, v in classname_to_id.items():
  48. category = {}
  49. category['id'] = v
  50. category['name'] = k
  51. self.categories.append(category)
  52. # 构建COCO的image字段
  53. def _image(self , filename):
  54. image = {}
  55. img = cv2.imread(self.image_dir + filename + '.jpg')
  56. image['height'] = img.shape[0]
  57. image['width'] = img.shape[1]
  58. image['id'] = self.img_id
  59. image['file_name'] = filename + '.jpg'
  60. return image
  61. # 构建COCO的annotation字段
  62. def _annotation(self, shape,label):
  63. points = shape[0 : ]
  64. annotation = {}
  65. annotation['id'] = self.ann_id
  66. annotation['image_id'] = self.img_id
  67. annotation['category_id'] = int(classname_to_id[label])
  68. annotation['segmentation'] = [[]]
  69. annotation['bbox'] = self._get_box(points)
  70. annotation['iscrowd'] = 0
  71. annotation['area'] = self._get_area(points)
  72. return annotation
  73. # COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式
  74. def _get_box(self, points):
  75. min_x = points[0]
  76. min_y = points[1]
  77. max_x = points[2]
  78. max_y = points[3]
  79. return [min_x, max_y, max_x - min_x, max_y - min_y]
  80. # 计算面积
  81. def _get_area(self, points):
  82. min_x = points[0]
  83. min_y = points[1]
  84. max_x = points[2]
  85. max_y = points[3]
  86. return (max_x - min_x+1) * (max_y - min_y+1)
  87. if __name__ == '__main__':
  88. csv_file = "./combined_file.csv"
  89. image_dir = "./train/"
  90. saved_coco_path = "./"
  91. # 整合csv格式标注文件
  92. total_csv_annotations = {}
  93. annotations = pd.read_csv(csv_file).values
  94. for annotation in annotations:
  95. filename = annotation[0]
  96. height = annotation[1]
  97. width = annotation[2]
  98. category_id = annotation[3]
  99. # key = annotation[0].split(os.sep)[-1]
  100. # value = np.array([annotation[1:]])
  101. # value1 = np.array([annotation[1: 4]])
  102. # print(value1)
  103. value = np.array([annotation[3:]])
  104. print(value)
  105. # print(value)
  106. if filename in total_csv_annotations.keys():
  107. total_csv_annotations[filename] = np.concatenate((total_csv_annotations[filename],value),axis=0)
  108. else:
  109. total_csv_annotations[filename] = value
  110. # 按照键值划分数据
  111. total_keys = list(total_csv_annotations.keys())
  112. train_keys, val_keys = train_test_split(total_keys, test_size=0.2)
  113. # print(train_keys)
  114. print("train_n:", len(train_keys), 'val_n:', len(val_keys))
  115. # 创建必须的文件夹
  116. if not os.path.exists('%scoco/annotations/'%saved_coco_path):
  117. os.makedirs('%scoco/annotations/'%saved_coco_path)
  118. if not os.path.exists('%scoco/images/train2017/'%saved_coco_path):
  119. os.makedirs('%scoco/images/train2017/'%saved_coco_path)
  120. if not os.path.exists('%scoco/images/val2017/'%saved_coco_path):
  121. os.makedirs('%scoco/images/val2017/'%saved_coco_path)
  122. # 把训练集转化为COCO的json格式
  123. l2c_train = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)
  124. train_instance = l2c_train.to_coco(train_keys)
  125. l2c_train.save_coco_json(train_instance, '%scoco/annotations/instances_train2017.json'%saved_coco_path)
  126. for file in train_keys:
  127. shutil.copy(image_dir+file + '.jpg',"%scoco/images/train2017/"%saved_coco_path)
  128. for file in val_keys:
  129. shutil.copy(image_dir+file + '.jpg',"%scoco/images/val2017/"%saved_coco_path)
  130. # 把验证集转化为COCO的json格式
  131. l2c_val = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)
  132. val_instance = l2c_val.to_coco(val_keys)
  133. 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数据进行预测

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

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

  1. import cv2
  2. from PIL import Image
  3. import numpy as np
  4. import os
  5. import time
  6. import torch
  7. from torch import nn
  8. import torchvision.transforms as T
  9. from main import get_args_parser as get_main_args_parser
  10. from models import build_model
  11. torch.set_grad_enabled(False)
  12. device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  13. print("[INFO] 当前使用{}做推断".format(device))
  14. # 图像数据处理
  15. transform = T.Compose([
  16. T.Resize(800),
  17. T.ToTensor(),
  18. T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
  19. ])
  20. # plot box by opencv
  21. def plot_result(pil_img, prob, boxes, save_name=None, imshow=False, imwrite=False):
  22. opencvImage = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
  23. LABEL =['N/A', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
  24. 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'N/A',
  25. 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse',
  26. 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'N/A', 'backpack',
  27. 'umbrella', 'N/A', 'N/A', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis',
  28. 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove',
  29. 'skateboard', 'surfboard', 'tennis racket', 'bottle', 'N/A', 'wine glass',
  30. 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich',
  31. 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake',
  32. 'chair', 'couch', 'potted plant', 'bed', 'N/A', 'dining table', 'N/A',
  33. 'N/A', 'toilet', 'N/A', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',
  34. 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'N/A',
  35. 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
  36. for p, (xmin, ymin, xmax, ymax) in zip(prob, boxes):
  37. cl = p.argmax()
  38. label_text = '{}: {}%'.format(LABEL[cl], round(p[cl] * 100, 2))
  39. cv2.rectangle(opencvImage, (int(xmin), int(ymin)), (int(xmax), int(ymax)), (255, 255, 0), 2)
  40. cv2.putText(opencvImage, label_text, (int(xmin) + 10, int(ymin) + 30), cv2.FONT_HERSHEY_SIMPLEX, 1,
  41. (255, 255, 0), 2)
  42. if imshow:
  43. cv2.imshow('detect', opencvImage)
  44. cv2.waitKey(0)
  45. if imwrite:
  46. if not os.path.exists("./result/pred"):
  47. os.makedirs('./result/pred')
  48. cv2.imwrite('./result/pred/{}'.format(save_name), opencvImage)
  49. # 将xywh转xyxy
  50. def box_cxcywh_to_xyxy(x):
  51. x_c, y_c, w, h = x.unbind(1)
  52. b = [(x_c - 0.5 * w), (y_c - 0.5 * h),
  53. (x_c + 0.5 * w), (y_c + 0.5 * h)]
  54. return torch.stack(b, dim=1)
  55. def rescale_bboxes(out_bbox, size):
  56. img_w, img_h = size
  57. b = box_cxcywh_to_xyxy(out_bbox)
  58. b = b.cpu().numpy()
  59. b = b * np.array([img_w, img_h, img_w, img_h], dtype=np.float32)
  60. return b
  61. def load_model(model_path , args):
  62. model, _, _ = build_model(args)
  63. model.cuda()
  64. model.eval()
  65. state_dict = torch.load(model_path) # <-----------修改加载模型的路径
  66. model.load_state_dict(state_dict["model"])
  67. model.to(device)
  68. print("load model sucess")
  69. return model
  70. # 图像的推断
  71. def detect(im, model, transform, prob_threshold=0.7):
  72. # mean-std normalize the input image (batch-size: 1)
  73. img = transform(im).unsqueeze(0)
  74. # propagate through the model
  75. img = img.to(device)
  76. start = time.time()
  77. outputs = model(img)
  78. # keep only predictions with 0.7+ confidence
  79. print(outputs['pred_logits'].softmax(-1)[0, :, :-1])
  80. probas = outputs['pred_logits'].softmax(-1)[0, :, :-1]
  81. keep = probas.max(-1).values > prob_threshold
  82. probas = probas.cpu().detach().numpy()
  83. keep = keep.cpu().detach().numpy()
  84. # convert boxes from [0; 1] to image scales
  85. bboxes_scaled = rescale_bboxes(outputs['pred_boxes'][0, keep], im.size)
  86. end = time.time()
  87. return probas[keep], bboxes_scaled, end - start
  88. if __name__ == "__main__":
  89. main_args = get_main_args_parser().parse_args()
  90. # 加载模型
  91. dfdetr = load_model('./r50_deformable_detr-checkpoint.pth',main_args) # <--修改为自己加载模型的路径
  92. files = os.listdir("./val2017") # <--修改为待预测图片所在文件夹路径
  93. cn = 0
  94. waste=0
  95. for file in files:
  96. img_path = os.path.join("./val2017", file) # <--修改为待预测图片所在文件夹路径
  97. im = Image.open(img_path)
  98. scores, boxes, waste_time = detect(im, dfdetr, transform)
  99. plot_result(im, scores, boxes, save_name=file, imshow=False, imwrite=True)
  100. print("{} [INFO] {} time: {} done!!!".format(cn,file, waste_time))
  101. cn+=1
  102. waste+=waste_time
  103. waste_avg = waste/cn
  104. print(waste_avg)

查看预测结果

4.总结

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/337800
推荐阅读
  

闽ICP备14008679号