马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

Windows10+YOLOv3实现检测自己的数据集(1)——制作自己的数据集

[复制链接]
查看2394 | 回复1 | 2019-10-12 10:22:38 | 显示全部楼层 |阅读模式

本文将从以下三个方面先容如何制作自己的数据集

  1. 数据标注
  2. 数据扩增
  3. 将数据转化为COCO的json格式
  4. 参考资料

一、数据标注

在深度学习的目标检测使掷中,起首要使用练习集举行模型练习。练习的数据集好坏决定了使命的上限。下面先容两种常用的图像目标检测标注工具:LabelmeLabelImg。

(1)Labelme

Labelme实用于图像分割使命和目标检测使命的数据集制作,它来自该项目:https://github.com/wkentaro/labelme 。

按照项目中的教程安装完毕后,应用界面如下图所示:

102238tacxk2r96aj2hxm9.png

它可以大概提供多边形、矩形、圆形、直线和点的图像标注,并将效果生存为 JSON 文件。

(2)LabelImg

LabelImg实用于目标检测使命的数据集制作。它来自该项目:https://github.com/tzutalin/labelImg

应用界面如下图所示:

102238lcn22dk06ngk7ynl.png

它可以大概提供矩形的图像标注,并将效果生存为txt(YOLO)或xml(PascalVOC)格式。如果须要修改标签的类别内容,则在主目录data文件夹中的predefined_classes.txt文件中修改。

我使用的就是这一个标注软件,标注效果生存为xml格式,后续还须要举行标注格式的转换。

操作快捷键:

Ctrl + u 加载目录中的全部图像,鼠标点击Open dir同功能 Ctrl + r 更改默认解释目标目录(xml文件生存的地址) Ctrl + s 生存 Ctrl + d 复制当前标签和矩形框 space 将当前图像标记为已验证 w 创建一个矩形框 d 下一张图片 a 上一张图片 del 删除选定的矩形框 Ctrl++ 放大 Ctrl-- 缩小 ↑→↓← 键盘箭头移动选定的矩形框

二、数据扩增

在某些场景下的目标检测中,样本数目较小,导致检测的效果比力差,这时就须要举行数据扩增。本文先容常用的6类数据扩增方式,包罗裁剪、平移、改变亮度、加入噪声、旋转角度以及镜像。

思量到篇幅标题,将这一部分单列出来,详细请参考本篇博客:https://www.cnblogs.com/lky-learning/p/11653861.html

三、将数据转换至COCO的json格式

起首让我们明确一下几种格式,参考自【点此处】:

3.1 csv

  • csv/
    • labels.csv
    • images/
      • image1.jpg
      • image2.jpg
      • ...

labels.csv 的形式:

  • /path/to/image,xmin,ymin,xmax,ymax,label

比方:

  • /mfs/dataset/face/image1.jpg,450,154,754,341,face
  • /mfs/dataset/face/image2.jpg,143,154,344,341,face

3.2 voc

标准的voc数据格式如下:

VOC2007/

  • Annotations/
    • 0d4c5e4f-fc3c-4d5a-906c-105.xml
    • 0ddfc5aea-fcdac-421-92dad-144/xml
    • ...
  • ImageSets/
    • Main/
      • train.txt
      • test.txt
      • val.txt
      • trainval.txt
  • JPEGImages/
    • 0d4c5e4f-fc3c-4d5a-906c-105.jpg
    • 0ddfc5aea-fcdac-421-92dad-144.jpg
    • ...

3.3 COCO

coco/

  • annotations/
    • instances_train2017.json
    • instances_val2017.json
  • images/
    • train2017/
      • 0d4c5e4f-fc3c-4d5a-906c-105.jpg
      • ...
    • val2017
      • 0ddfc5aea-fcdac-421-92dad-144.jpg
      • ...

Json file 格式: (imageData那一块太长了,不展示了)

  1. {
  2. "version": "3.6.16",
  3. "flags": {},
  4. "shapes": [
  5. {
  6. "label": "helmet",
  7. "line_color": null,
  8. "fill_color": null,
  9. "points": [
  10. [
  11. 131,
  12. 269
  13. ],
  14. [
  15. 388,
  16. 457
  17. ]
  18. ],
  19. "shape_type": "rectangle"
  20. }
  21. ],
  22. "lineColor": [
  23. 0,
  24. 255,
  25. 0,
  26. 128
  27. ],
  28. "fillColor": [
  29. 255,
  30. 0,
  31. 0,
  32. 128
  33. ],
  34. "imagePath": "004ffe6f-c3e2-3602-84a1-ecd5f437b113.jpg",
  35. "imageData": "" # too long ,so not show here
  36. "imageHeight": 1080,
  37. "imageWidth": 1920
  38. }
复制代码

在上一节中提到,经过标注后的效果生存为xml格式,我们起首要把这些xml标注文件整合成一个csv文件。

整合代码如下:

  1. import os
  2. import glob
  3. import pandas as pd
  4. import xml.etree.ElementTree as ET
  5. ## xml文件的路径
  6. os.chdir('./data/annotations/scratches')
  7. path = 'C:/Users/Admin/Desktop/data/annotations/scratches' # 绝对路径
  8. img_path = 'C:/Users/Admin/Desktop/data/images'
  9. def xml_to_csv(path):
  10. xml_list = []
  11. for xml_file in glob.glob(path + '/*.xml'): #返回全部匹配的文件路径列表。
  12. tree = ET.parse(xml_file)
  13. root = tree.getroot()
  14. for member in root.findall('object'):
  15. # value = (root.find('filename').text,
  16. # int(root.find('size')[0].text),
  17. # int(root.find('size')[1].text),
  18. # member[0].text,
  19. # int(member[4][0].text),
  20. # int(member[4][1].text),
  21. # int(member[4][2].text),
  22. # int(member[4][3].text)
  23. # )
  24. value = (img_path +'/' + root.find('filename').text,
  25. int(member[4][0].text),
  26. int(member[4][1].text),
  27. int(member[4][2].text),
  28. int(member[4][3].text),
  29. member[0].text
  30. )
  31. xml_list.append(value)
  32. #column_name = ['filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax']
  33. column_name = ['filename', 'xmin', 'ymin', 'xmax', 'ymax', 'class']
  34. xml_df = pd.DataFrame(xml_list, columns=column_name)
  35. return xml_df
  36. if __name__ == '__main__':
  37. image_path = path
  38. xml_df = xml_to_csv(image_path)
  39. ## 修改文件名称
  40. xml_df.to_csv('scratches.csv', index=None)
  41. print('Successfully converted xml to csv.')
复制代码

当显示 Successfully converted xml to csv 后,我们就得到了整理后的标记文件。

在有些模型下,有了图像数据和csv格式的标注文件后,就可以举行练习了。但是在YOLOv3中,标记文件的类型为COCO的json格式,因此我们还得将其转换至json格式。

转换代码:

  1. import os
  2. import json
  3. import numpy as np
  4. import pandas as pd
  5. import glob
  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 = {"scratches": 1,"inclusion": 2}
  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. bboxi.append(int(cor))
  34. label = shape[-1]
  35. annotation = self._annotation(bboxi,label)
  36. self.annotations.append(annotation)
  37. self.ann_id += 1
  38. self.img_id += 1
  39. instance = {}
  40. instance['info'] = 'spytensor created'
  41. instance['license'] = ['license']
  42. instance['images'] = self.images
  43. instance['annotations'] = self.annotations
  44. instance['categories'] = self.categories
  45. return instance
  46. # 构建类别
  47. def _init_categories(self):
  48. for k, v in classname_to_id.items():
  49. category = {}
  50. category['id'] = v
  51. category['name'] = k
  52. self.categories.append(category)
  53. # 构建COCO的image字段
  54. def _image(self, path):
  55. image = {}
  56. img = cv2.imread(self.image_dir + path)
  57. image['height'] = img.shape[0]
  58. image['width'] = img.shape[1]
  59. image['id'] = self.img_id
  60. image['file_name'] = path
  61. return image
  62. # 构建COCO的annotation字段
  63. def _annotation(self, shape,label):
  64. # label = shape[-1]
  65. points = shape[:4]
  66. annotation = {}
  67. annotation['id'] = self.ann_id
  68. annotation['image_id'] = self.img_id
  69. annotation['category_id'] = int(classname_to_id[label])
  70. annotation['segmentation'] = self._get_seg(points)
  71. annotation['bbox'] = self._get_box(points)
  72. annotation['iscrowd'] = 0
  73. annotation['area'] = 1.0
  74. return annotation
  75. # COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式
  76. def _get_box(self, points):
  77. min_x = points[0]
  78. min_y = points[1]
  79. max_x = points[2]
  80. max_y = points[3]
  81. return [min_x, min_y, max_x - min_x, max_y - min_y]
  82. # segmentation
  83. def _get_seg(self, points):
  84. min_x = points[0]
  85. min_y = points[1]
  86. max_x = points[2]
  87. max_y = points[3]
  88. h = max_y - min_y
  89. w = max_x - min_x
  90. a = []
  91. a.append([min_x,min_y, min_x,min_y+0.5*h, min_x,max_y, min_x+0.5*w,max_y, max_x,max_y, max_x,max_y-0.5*h, max_x,min_y, max_x-0.5*w,min_y])
  92. return a
  93. if __name__ == '__main__':
  94. ## 修改目录
  95. csv_file = "data/annotations/scratches/scratches.csv"
  96. image_dir = "data/images/"
  97. saved_coco_path = "./"
  98. # 整合csv格式标注文件
  99. total_csv_annotations = {}
  100. annotations = pd.read_csv(csv_file,header=None).values
  101. for annotation in annotations:
  102. key = annotation[0].split(os.sep)[-1]
  103. value = np.array([annotation[1:]])
  104. if key in total_csv_annotations.keys():
  105. total_csv_annotations[key] = np.concatenate((total_csv_annotations[key],value),axis=0)
  106. else:
  107. total_csv_annotations[key] = value
  108. # 按照键值划分数据
  109. total_keys = list(total_csv_annotations.keys())
  110. train_keys, val_keys = train_test_split(total_keys, test_size=0.2)
  111. print("train_n:", len(train_keys), 'val_n:', len(val_keys))
  112. ## 创建必须的文件夹
  113. if not os.path.exists('%ssteel/annotations/'%saved_coco_path):
  114. os.makedirs('%ssteel/annotations/'%saved_coco_path)
  115. if not os.path.exists('%ssteel/images/train/'%saved_coco_path):
  116. os.makedirs('%ssteel/images/train/'%saved_coco_path)
  117. if not os.path.exists('%ssteel/images/val/'%saved_coco_path):
  118. os.makedirs('%ssteel/images/val/'%saved_coco_path)
  119. ## 把练习集转化为COCO的json格式
  120. l2c_train = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)
  121. train_instance = l2c_train.to_coco(train_keys)
  122. l2c_train.save_coco_json(train_instance, '%ssteel/annotations/instances_train.json'%saved_coco_path)
  123. for file in train_keys:
  124. shutil.copy(image_dir+file,"%ssteel/images/train/"%saved_coco_path)
  125. for file in val_keys:
  126. shutil.copy(image_dir+file,"%ssteel/images/val/"%saved_coco_path)
  127. ## 把验证集转化为COCO的json格式
  128. l2c_val = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)
  129. val_instance = l2c_val.to_coco(val_keys)
  130. l2c_val.save_coco_json(val_instance, '%ssteel/annotations/instances_val.json'%saved_coco_path)
复制代码

至此,我们的数据预处理惩罚工作就做好了

四、参考资料

  • https://blog.csdn.net/sty945/article/details/79387054
  • https://blog.csdn.net/saltriver/article/details/79680189
  • https://www.ctolib.com/topics-44419.html
  • https://www.zhihu.com/question/20666664
  • https://github.com/spytensor/prepare_detection_dataset#22-voc
  • https://blog.csdn.net/chaipp0607/article/details/79036312







来源:https://www.cnblogs.com/lky-learning/p/11640180.html
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则