当前位置:   article > 正文

扫盲:mmdetection安装以及训练自己的数据集_index put requires the source and destination dtyp

index put requires the source and destination dtypes match, got half for the

一、安装

  1. # 创建环境名为mmdet
  2. conda create -n mmdet python=3.7
  3. # 激活环境mmdet
  4. conda activate mmdet
  5. # 安装pytorch1.6
  6. # 安装torchvision0.7.0
  7. # 安装cuda,此处注意cuda版本要对应上或电脑已经安装了更高的版本,cuda版本向下兼容,电脑安装最新的cuda并把驱动升级到最新。
  8. conda install pytorch==1.6.0 torchvision==0.7.0 cudatoolkit=10.2 -c pytorch
  9. # 安装对应版本的mmcv-full,这个是官方已经给编译过的,安装时注意版本与上一步相同。cu102为cudatoolkit10.2,torch1.6.0为pytorch1.6.0。对应不上安装时看不出来,用的时候必报错,而且找不到原因。而且这是官方编译好的,意味着不能瞎改pytorch版本。
  10. pip install mmcv-full==1.4.6 -f https://download.openmmlab.com/mmcv/dist/cu102/torch1.6.0/index.html
  11. # 安装mmdet,安装检测模块的需要的包
  12. pip install mmdet
  13. # 安装mmrotate,安装旋转检测模块需要的包,这个不用mmrotate可不安
  14. pip install mmrotate
  15. # 也可以用另一种方法安装mmrotate
  16. git clone https://github.com/open-mmlab/mmrotate.git
  17. cd mmrotate
  18. pip install -r requirements/build.txt
  19. pip install -v -e .

1.报错不要慌,领悟每个命令行作用的同时,看看版本对没对上,csdn好多博文版本没对上或者用mim安装导致各种报错。

2.安装失败,这只是一种可能,看看是否安装了VS2019 C++buildtool,因为之前安装pycocotool的时候因为没安装这个工具导致安装不上。安装这个工具即使不需要,也没有任何害处,可能将来会用到。

二、demo演示文件测试效果

进入image_demo.py文件,读一读。

  1. # ....
  2. def parse_args():
  3. parser = ArgumentParser()
  4. parser.add_argument('img', help='Image file')
  5. parser.add_argument('config', help='Config file')
  6. parser.add_argument('checkpoint', help='Checkpoint file')
  7. # ....

 稍加修改,让配置参数时,更加规整而且配置时一一对应,更加严谨。

  1. # ....
  2. def parse_args():
  3. parser = ArgumentParser()
  4. parser.add_argument('--img', help='Image file')
  5. parser.add_argument('--config', help='Config file')
  6. parser.add_argument('--checkpoint', help='Checkpoint file')
  7. # ....

pycharm中配置参数:1.图片路径2.模型路径3.权重路径;此处的模型与权重最好时完全对应上。

  1. --img
  2. D:\\Project\\mmdetection-master\\demo\\demo.jpg
  3. --config
  4. D:\\Project\\mmdetection-master\\configs\\faster_rcnn\\faster_rcnn_r50_fpn_1x_coco.py
  5. --checkpoint
  6. D:\\Project\\mmdetection-master\\faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

报个小错,无伤大雅。小小警告,一般都是告诉我xx已经淘汰了;被xx替代了;建议替换等等。

 结果出来了,意味着你的环境配置已经问题不大了,后面如果缺组件,在现在的环境内pip install xxx即可。

三、简单的口罩检测——训练自己的数据集

1.首先准备好数据集——一些未标注的图片

 2.用labelme标注软件进行标注

labelme安装很简单,在本环境安装就行。

  1. # 安装pyqt5
  2. pip install pyqt5
  3. # 安装labelme
  4. pip install labelme
  5. # 运行labelme
  6. labelme

标注过程过于简单,不赘述。注意:

(1)不要乱改标注后的json文件名,要一一对应。

(2)矩形框标注从左上到右下符合图片坐标的规定。

3.json to coco,格式转换。

 运行一下脚本,注意输入文件位置与输出文件位置。

  1. import os
  2. import json
  3. import numpy as np
  4. import glob
  5. import shutil
  6. import cv2
  7. from sklearn.model_selection import train_test_split
  8. np.random.seed(41)
  9. classname_to_id = {
  10. "mask": 0, #改成自己的类别
  11. "person": 1
  12. }
  13. class Lableme2CoCo:
  14. def __init__(self):
  15. self.images = []
  16. self.annotations = []
  17. self.categories = []
  18. self.img_id = 0
  19. self.ann_id = 0
  20. def save_coco_json(self, instance, save_path):
  21. json.dump(instance, open(save_path, 'w', encoding='utf-8'), ensure_ascii=False, indent=1) # indent=2 更加美观显示
  22. # 由json文件构建COCO
  23. def to_coco(self, json_path_list):
  24. self._init_categories()
  25. for json_path in json_path_list:
  26. obj = self.read_jsonfile(json_path)
  27. self.images.append(self._image(obj, json_path))
  28. shapes = obj['shapes']
  29. for shape in shapes:
  30. annotation = self._annotation(shape)
  31. self.annotations.append(annotation)
  32. self.ann_id += 1
  33. self.img_id += 1
  34. instance = {}
  35. instance['info'] = 'spytensor created'
  36. instance['license'] = ['license']
  37. instance['images'] = self.images
  38. instance['annotations'] = self.annotations
  39. instance['categories'] = self.categories
  40. return instance
  41. # 构建类别
  42. def _init_categories(self):
  43. for k, v in classname_to_id.items():
  44. category = {}
  45. category['id'] = v
  46. category['name'] = k
  47. self.categories.append(category)
  48. # 构建COCO的image字段
  49. def _image(self, obj, path):
  50. image = {}
  51. from labelme import utils
  52. img_x = utils.img_b64_to_arr(obj['imageData'])
  53. h, w = img_x.shape[:-1]
  54. image['height'] = h
  55. image['width'] = w
  56. image['id'] = self.img_id
  57. image['file_name'] = os.path.basename(path).replace(".json", ".jpg")
  58. return image
  59. # 构建COCO的annotation字段
  60. def _annotation(self, shape):
  61. # print('shape', shape)
  62. label = shape['label']
  63. points = shape['points']
  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'] = [np.asarray(points).flatten().tolist()]
  69. annotation['bbox'] = self._get_box(points)
  70. annotation['iscrowd'] = 0
  71. annotation['area'] = 1.0
  72. return annotation
  73. # 读取json文件,返回一个json对象
  74. def read_jsonfile(self, path):
  75. with open(path, "r", encoding='utf-8') as f:
  76. return json.load(f)
  77. # COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式
  78. def _get_box(self, points):
  79. min_x = min_y = np.inf
  80. max_x = max_y = 0
  81. for x, y in points:
  82. min_x = min(min_x, x)
  83. min_y = min(min_y, y)
  84. max_x = max(max_x, x)
  85. max_y = max(max_y, y)
  86. return [min_x, min_y, max_x - min_x, max_y - min_y]
  87. #训练过程中,如果遇到Index put requires the source and destination dtypes match, got Long for the destination and Int for the source
  88. #参考:https://github.com/open-mmlab/mmdetection/issues/6706
  89. if __name__ == '__main__':
  90. labelme_path = "./labelme-data/maskdataset"
  91. saved_coco_path = "./labelme-data/coco-format"
  92. print('reading...')
  93. # 创建文件
  94. if not os.path.exists("%scoco/annotations/" % saved_coco_path):
  95. os.makedirs("%scoco/annotations/" % saved_coco_path)
  96. if not os.path.exists("%scoco/images/train2017/" % saved_coco_path):
  97. os.makedirs("%scoco/images/train2017" % saved_coco_path)
  98. if not os.path.exists("%scoco/images/val2017/" % saved_coco_path):
  99. os.makedirs("%scoco/images/val2017" % saved_coco_path)
  100. # 获取images目录下所有的joson文件列表
  101. print(labelme_path + "/*.json")
  102. json_list_path = glob.glob(labelme_path + "/*.json")
  103. print('json_list_path: ', len(json_list_path))
  104. # 数据划分,这里没有区分val2017和tran2017目录,所有图片都放在images目录下
  105. train_path, val_path = train_test_split(json_list_path, test_size=0.1, train_size=0.9)
  106. print("train_n:", len(train_path), 'val_n:', len(val_path))
  107. # 把训练集转化为COCO的json格式
  108. l2c_train = Lableme2CoCo()
  109. train_instance = l2c_train.to_coco(train_path)
  110. l2c_train.save_coco_json(train_instance, '%scoco/annotations/instances_train2017.json' % saved_coco_path)
  111. for file in train_path:
  112. # shutil.copy(file.replace("json", "jpg"), "%scoco/images/train2017/" % saved_coco_path)
  113. img_name = file.replace('json', 'jpg')
  114. temp_img = cv2.imread(img_name)
  115. try:
  116. cv2.imwrite("{}coco/images/train2017/{}".format(saved_coco_path, img_name.split('\\')[-1].replace('png', 'jpg')), temp_img)
  117. except Exception as e:
  118. print(e)
  119. print('Wrong Image:', img_name )
  120. continue
  121. print(img_name + '-->', img_name.replace('png', 'jpg'))
  122. for file in val_path:
  123. # shutil.copy(file.replace("json", "jpg"), "%scoco/images/val2017/" % saved_coco_path)
  124. img_name = file.replace('json', 'jpg')
  125. temp_img = cv2.imread(img_name)
  126. try:
  127. cv2.imwrite("{}coco/images/val2017/{}".format(saved_coco_path, img_name.split('\\')[-1].replace('png', 'jpg')), temp_img)
  128. except Exception as e:
  129. print(e)
  130. print('Wrong Image:', img_name)
  131. continue
  132. print(img_name + '-->', img_name.replace('png', 'jpg'))
  133. # 把验证集转化为COCO的json格式
  134. l2c_val = Lableme2CoCo()
  135. val_instance = l2c_val.to_coco(val_path)
  136. l2c_val.save_coco_json(val_instance, '%scoco/annotations/instances_val2017.json' % saved_coco_path)

路径分布

instances_train2017.json节取

  1. {
  2. "info": "spytensor created",
  3. "license": [
  4. "license"
  5. ],
  6. "images": [
  7. {
  8. "height": 737,
  9. "width": 1024,
  10. "id": 0,
  11. "file_name": "19.jpg"
  12. },
  13. ...
  14. ],
  15. "annotations": [
  16. {
  17. "id": 0,
  18. "image_id": 0,
  19. "category_id": 0,
  20. "segmentation": [
  21. [
  22. 52.74809160305344,
  23. 350.9083969465649,
  24. 191.6793893129771,
  25. 457.0152671755725
  26. ]
  27. ],
  28. "bbox": [
  29. 52.74809160305344,
  30. 350.9083969465649,
  31. 138.93129770992365,
  32. 106.1068702290076
  33. ],
  34. "iscrowd": 0,
  35. "area": 1.0
  36. },
  37. ...
  38. ],
  39. "categories": [
  40. {
  41. "id": 0,
  42. "name": "mask"
  43. },
  44. {
  45. "id": 1,
  46. "name": "person"
  47. }
  48. ]
  49. }

在 json 文件中有三个必要的键:

  • images: 包含多个图片以及它们的信息的数组,例如 file_nameheightwidth 和 id

  • annotations: 包含多个实例标注信息的数组。

  • categories: 包含多个类别名字和 ID 的数组。

4.对应自己的数据集去修改源码的类别

因为采用的时coco格式,故去修改源码中coco(80个类别)的类别,改成自己数据集的两个类别。

1.修改第一处

mmdet\core\evaluation\class_names.py
  1. # ...
  2. def coco_classes():
  3. # return [
  4. # 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train',
  5. # 'truck', 'boat', 'traffic_light', 'fire_hydrant', 'stop_sign',
  6. # 'parking_meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep',
  7. # 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella',
  8. # 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
  9. # 'sports_ball', 'kite', 'baseball_bat', 'baseball_glove', 'skateboard',
  10. # 'surfboard', 'tennis_racket', 'bottle', 'wine_glass', 'cup', 'fork',
  11. # 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
  12. # 'broccoli', 'carrot', 'hot_dog', 'pizza', 'donut', 'cake', 'chair',
  13. # 'couch', 'potted_plant', 'bed', 'dining_table', 'toilet', 'tv',
  14. # 'laptop', 'mouse', 'remote', 'keyboard', 'cell_phone', 'microwave',
  15. # 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase',
  16. # 'scissors', 'teddy_bear', 'hair_drier', 'toothbrush'
  17. # ]
  18. return [
  19. 'mask', 'person',
  20. ]
  21. # ...

把80类注释掉,改成自己的类别,不改就会出现类别的检测错误,mask检测成person,person检测成bicycle。

2.修改第二处

mmdet\datasets\coco.py
  1. class CocoDataset(CustomDataset):
  2. # CLASSES = ('person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
  3. # 'train', 'truck', 'boat', 'traffic light', 'fire hydrant',
  4. # 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',
  5. # 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe',
  6. # 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
  7. # 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat',
  8. # 'baseball glove', 'skateboard', 'surfboard', 'tennis racket',
  9. # 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl',
  10. # 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot',
  11. # 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
  12. # 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop',
  13. # 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave',
  14. # 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock',
  15. # 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush')
  16. #
  17. # PALETTE = [(220, 20, 60), (119, 11, 32), (0, 0, 142), (0, 0, 230),
  18. # (106, 0, 228), (0, 60, 100), (0, 80, 100), (0, 0, 70),
  19. # (0, 0, 192), (250, 170, 30), (100, 170, 30), (220, 220, 0),
  20. # (175, 116, 175), (250, 0, 30), (165, 42, 42), (255, 77, 255),
  21. # (0, 226, 252), (182, 182, 255), (0, 82, 0), (120, 166, 157),
  22. # (110, 76, 0), (174, 57, 255), (199, 100, 0), (72, 0, 118),
  23. # (255, 179, 240), (0, 125, 92), (209, 0, 151), (188, 208, 182),
  24. # (0, 220, 176), (255, 99, 164), (92, 0, 73), (133, 129, 255),
  25. # (78, 180, 255), (0, 228, 0), (174, 255, 243), (45, 89, 255),
  26. # (134, 134, 103), (145, 148, 174), (255, 208, 186),
  27. # (197, 226, 255), (171, 134, 1), (109, 63, 54), (207, 138, 255),
  28. # (151, 0, 95), (9, 80, 61), (84, 105, 51), (74, 65, 105),
  29. # (166, 196, 102), (208, 195, 210), (255, 109, 65), (0, 143, 149),
  30. # (179, 0, 194), (209, 99, 106), (5, 121, 0), (227, 255, 205),
  31. # (147, 186, 208), (153, 69, 1), (3, 95, 161), (163, 255, 0),
  32. # (119, 0, 170), (0, 182, 199), (0, 165, 120), (183, 130, 88),
  33. # (95, 32, 0), (130, 114, 135), (110, 129, 133), (166, 74, 118),
  34. # (219, 142, 185), (79, 210, 114), (178, 90, 62), (65, 70, 15),
  35. # (127, 167, 115), (59, 105, 106), (142, 108, 45), (196, 172, 0),
  36. # (95, 54, 80), (128, 76, 255), (201, 57, 1), (246, 0, 122),
  37. # (191, 162, 208)]
  38. CLASSES = ('mask', 'person')
  39. PALETTE = [(220, 20, 60), (119, 11, 32)]

类别和颜色做一下修改。

3.配置文件修改

生成自己的配置文件:因为项目自带的配置文件由于模块化设计,有继承关系,参数不能在一个文件上修改,配置参数很麻烦。采用一种方法:先把要用的模型的配置文件在train中作为配置参数运行一遍,会在work_dir文件中找到一个完整的配置文件。

1.复制想要的模型的配置文件绝对路径。

2.将绝对路径复制放进pycharm配置参数

3.运行后在work_dir中找到并改名

 4.修改输出类别数量,coco数据集80类,自己数据集2类。num_classes

  1. # ...
  2. bbox_head=dict(
  3. type='DeformableDETRHead',
  4. num_query=300,
  5. num_classes=80,
  6. in_channels=2048,
  7. sync_cls_avg_factor=True,
  8. as_two_stage=False,
  9. # ...
  1. # ...
  2. bbox_head=dict(
  3. type='DeformableDETRHead',
  4. num_query=300,
  5. num_classes=2,
  6. in_channels=2048,
  7. sync_cls_avg_factor=True,
  8. as_two_stage=False,
  9. # ...

5.修改训练集和验证集路径

  1. # ...
  2. train=dict(
  3. type='CocoDataset',
  4. ann_file='D:\\Project\\mmdetection-master\\mmdet\\data\\labelme-data\\coco-formatcoco\\annotations\\instances_train2017.json',
  5. img_prefix='D:\\Project\\mmdetection-master\\mmdet\\data\\labelme-data\\coco-formatcoco\\images\\train2017',
  6. # ...
  7. # ...
  8. val=dict(
  9. type='CocoDataset',
  10. ann_file='D:\\Project\\mmdetection-master\\mmdet\\data\\labelme-data\\coco-formatcoco\\annotations\\instances_val2017.json',
  11. img_prefix='D:\\Project\\mmdetection-master\\mmdet\\data\\labelme-data\\coco-formatcoco\\images\\val2017',
  12. # ...

6.加上预训练模型

load_from = 'D:\\Project\\mmdetection-master\\deformable_detr_r50_16x2_50e_coco_20210419_220030-a12b9512.pth'

7.修改训练的配置

batch size和num_workers,这个算法很吃内存,batch size=1

  1. # ...
  2. data = dict(
  3. samples_per_gpu=1,
  4. workers_per_gpu=1,
  5. # ...

修改这一块,50个epoch

  1. evaluation = dict(interval=10, metric='bbox')
  2. checkpoint_config = dict(interval=50)
  3. log_config = dict(interval=10, hooks=[dict(type='TextLoggerHook')])
  4. custom_hooks = [dict(type='NumClassCheckHook')]
  5. dist_params = dict(backend='nccl')
  6. log_level = 'INFO'
  7. load_from = 'D:\Project\mmdetection-master\deformable_detr_r50_16x2_50e_coco_20210419_220030-a12b9512.pth'
  8. resume_from = None
  9. workflow = [('train', 1)]
  10. opencv_num_threads = 0
  11. mp_start_method = 'fork'
  12. auto_scale_lr = dict(enable=False, base_batch_size=32)

8.重新编译文件,修改完 class_names.py 和 voc.py 之后一定要重新编译代码(运行python setup.py install,要不报错AssertionError: The `num_classes` (80) in Shared2FCBBoxHead of MMDataParallel does not matche。

9.开始训练

 电脑配置不够,内存爆了,一顿操作猛如虎,一看结果250,以后拿个简单的模型试一试,但是过程是可以借鉴的。

换Faster r-cnn,同样的思路,再用demo检测一下。

  1. --img
  2. D:\\Project\\mmdetection-master\\demo\\mask.jpg
  3. --config
  4. D:\\Project\\mmdetection-master\\configs\\faster_rcnn\\my_faster_rcnn_r50_fpn_1x_coco.py
  5. --checkpoint
  6. D:\\Project\\mmdetection-master\\tools\\work_dirs\\faster_rcnn_r50_fpn_1x_coco\\epoch_30.pth

 这么少的数据集,能有这个效果,已经不错了。

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

闽ICP备14008679号