当前位置:   article > 正文

【做法说明】Yolo训练行人车辆目标检测数据集储备与模型训练【KITTI】_yolo车辆行人检测数据集

yolo车辆行人检测数据集

一、数据集介绍

       KITTI数据集由德国卡尔斯鲁厄理工学院和丰田工业大学芝加哥分校联合赞助的用于自动驾驶领域研究的数据集。作者收集了长达6个小时的真实交通环境,数据集由经过校正和同步的图像、雷达扫描、高精度的GPS信息和IMU加速信息等多种模态的信息组成。作者还在数据集官网提供了光流、物体检测、深度估计等多种任务的Benchmark。

       数据集链接:http://www.cvlibs.net/datasets/kitti/

       论文链接:http://www.webmail.cvlibs.net/publications/Geiger2012CVPR.pdf

       精确的地面真相由Velodyne激光扫描仪和GPS定位系统提供。我们的数据集是通过在中型城市卡尔斯鲁厄(Karlsruhe)、乡村地区和高速公路上行驶来获取的。每张图像可看到多达15辆汽车和30个行人。除了以原始格式提供所有数据外,我们还为每个任务提取基准。对于我们的每一个基准,我们也提供了一个评估指标和这个评估网站。初步实验表明,在现有基准中排名靠前的方法,如Middlebury方法,在脱离实验室进入现实世界后,表现低于平均水平。我们的目标是减少这种偏见,并通过向社会提供具有新困难的现实基准来补充现有基准。

二、数据集下载

       KITTI的官网地址为:The KITTI Vision Benchmark Suite

       由于使用做行人车辆目标检测训练,仅寻找与行人,车辆有关的内容,该部分需要注册账号,链接如下:

Downloadicon-default.png?t=N7T8http://www.cvlibs.net/download.php?file=data_object_image_2.zip

Downloadicon-default.png?t=N7T8http://www.cvlibs.net/download.php?file=data_object_label_2.zip

       得到需要的图片和标签。

       也可以在官网上直接下载:

https://s3.eu-central-1.amazonaws.com/avg-kitti/data_object_image_2.zipicon-default.png?t=N7T8https://s3.eu-central-1.amazonaws.com/avg-kitti/data_object_image_2.zip

https://s3.eu-central-1.amazonaws.com/avg-kitti/data_object_label_2.zipicon-default.png?t=N7T8https://s3.eu-central-1.amazonaws.com/avg-kitti/data_object_label_2.zip

       文件需要科学上网,下载时注意网速问题。

       下载完成后,我们在yolov5/dataset下创建文件夹kitti,在kitti中放入我们的数据

  1. |——kitti
  2. ├── imgages
  3. │ └── origin
  4. │ ├── 000001.png
  5. │ └── .......
  6. └── labels
  7. ├── origin
  8. │ ├── 000001.txt
  9. │ └── .......
  10. └── xml

 三、KITTI数据集LABLE转换

 1. KITTI原数据格式介绍

       原先文件中,LABLE如下所示。

       官网上可以查询到其数据格式:

 2. 数据类别的整合

       该数据集的标注一共分为8个类别:

       ’Car’,’Van’,’Truck’,’Pedestrian’,’Person_sitting’,’Cyclist’,’Misc’和’DontCare’。

       在代码中,将’Pedestrian’, ’Person_sitting’合并为’Pedestrian’ ,删除’Misc’和’DontCare’

       首先我们把类别归一一下,因为我们需要用到6个类(代码中的路径需要修改)

  1. # modify_annotations_txt.py
  2. import glob
  3. import string
  4. txt_list = glob.glob('D:/File/yolov5-mobileone-master/dataset/kitti/labels/origin/*.txt') # 存储Labels文件夹所有txt文件路径
  5. print(txt_list)
  6. def show_category(txt_list):
  7. category_list= []
  8. for item in txt_list:
  9. try:
  10. with open(item) as tdf:
  11. for each_line in tdf:
  12. labeldata = each_line.strip().split(' ') # 去掉前后多余的字符并把其分开
  13. category_list.append(labeldata[0]) # 只要第一个字段,即类别
  14. except IOError as ioerr:
  15. print('File error:'+str(ioerr))
  16. print(set(category_list)) # 输出集合
  17. def merge(line):
  18. each_line=''
  19. for i in range(len(line)):
  20. if i!= (len(line)-1):
  21. each_line=each_line+line[i]+' '
  22. else:
  23. each_line=each_line+line[i] # 最后一条字段后面不加空格
  24. each_line=each_line+'\n'
  25. return (each_line)
  26. print('before modify categories are:\n')
  27. show_category(txt_list)
  28. for item in txt_list:
  29. new_txt=[]
  30. try:
  31. with open(item, 'r') as r_tdf:
  32. for each_line in r_tdf:
  33. labeldata = each_line.strip().split(' ')
  34. # if labeldata[0] in ['Truck','Van','Tram']: # 合并汽车类
  35. # labeldata[0] = labeldata[0].replace(labeldata[0],'Car')
  36. if labeldata[0] == 'Person_sitting': # 合并行人类
  37. labeldata[0] = labeldata[0].replace(labeldata[0],'Pedestrian')
  38. if labeldata[0] == 'DontCare': # 忽略Dontcare类
  39. continue
  40. if labeldata[0] == 'Misc': # 忽略Misc类
  41. continue
  42. new_txt.append(merge(labeldata)) # 重新写入新的txt文件
  43. with open(item,'w+') as w_tdf: # w+是打开原文件将内容删除,另写新内容进去
  44. for temp in new_txt:
  45. w_tdf.write(temp)
  46. except IOError as ioerr:
  47. print('File error:'+str(ioerr))
  48. print('\nafter modify categories are:\n')
  49. show_category(txt_list)

       输出结果为:

3. 数据的储存(转化为xml文件)

       然后再把它转换为xml文件,在Labels目录创建一个xml文件夹用于存放xml。

  1. # kitti_txt_to_xml.py
  2. # encoding:utf-8
  3. # 根据一个给定的XML Schema,使用DOM树的形式从空白文件生成一个XML
  4. from xml.dom.minidom import Document
  5. import cv2
  6. import glob
  7. import os
  8. def generate_xml(name,split_lines,img_size,class_ind):
  9. doc = Document() # 创建DOM文档对象
  10. annotation = doc.createElement('annotation')
  11. doc.appendChild(annotation)
  12. title = doc.createElement('folder')
  13. title_text = doc.createTextNode('KITTI')
  14. title.appendChild(title_text)
  15. annotation.appendChild(title)
  16. img_name=name+'.jpg'
  17. title = doc.createElement('filename')
  18. title_text = doc.createTextNode(img_name)
  19. title.appendChild(title_text)
  20. annotation.appendChild(title)
  21. source = doc.createElement('source')
  22. annotation.appendChild(source)
  23. title = doc.createElement('database')
  24. title_text = doc.createTextNode('The KITTI Database')
  25. title.appendChild(title_text)
  26. source.appendChild(title)
  27. title = doc.createElement('annotation')
  28. title_text = doc.createTextNode('KITTI')
  29. title.appendChild(title_text)
  30. source.appendChild(title)
  31. size = doc.createElement('size')
  32. annotation.appendChild(size)
  33. title = doc.createElement('width')
  34. title_text = doc.createTextNode(str(img_size[1]))
  35. title.appendChild(title_text)
  36. size.appendChild(title)
  37. title = doc.createElement('height')
  38. title_text = doc.createTextNode(str(img_size[0]))
  39. title.appendChild(title_text)
  40. size.appendChild(title)
  41. title = doc.createElement('depth')
  42. title_text = doc.createTextNode(str(img_size[2]))
  43. title.appendChild(title_text)
  44. size.appendChild(title)
  45. for split_line in split_lines:
  46. line=split_line.strip().split()
  47. if line[0] in class_ind:
  48. object = doc.createElement('object')
  49. annotation.appendChild(object)
  50. title = doc.createElement('name')
  51. title_text = doc.createTextNode(line[0])
  52. title.appendChild(title_text)
  53. object.appendChild(title)
  54. bndbox = doc.createElement('bndbox')
  55. object.appendChild(bndbox)
  56. title = doc.createElement('xmin')
  57. title_text = doc.createTextNode(str(int(float(line[4]))))
  58. title.appendChild(title_text)
  59. bndbox.appendChild(title)
  60. title = doc.createElement('ymin')
  61. title_text = doc.createTextNode(str(int(float(line[5]))))
  62. title.appendChild(title_text)
  63. bndbox.appendChild(title)
  64. title = doc.createElement('xmax')
  65. title_text = doc.createTextNode(str(int(float(line[6]))))
  66. title.appendChild(title_text)
  67. bndbox.appendChild(title)
  68. title = doc.createElement('ymax')
  69. title_text = doc.createTextNode(str(int(float(line[7]))))
  70. title.appendChild(title_text)
  71. bndbox.appendChild(title)
  72. # 将DOM对象doc写入文件
  73. f = open('D:/File/yolov5-mobileone-master/dataset/kitti/labels/xml/'+name+'.xml','w')#xml
  74. f.write(doc.toprettyxml(indent = ''))
  75. f.close()
  76. if __name__ == '__main__':
  77. class_ind=('Car', 'Cyclist', 'Truck', 'Van', 'Pedestrian', 'Tram')
  78. # cur_dir=os.getcwd()
  79. labels_dir= "D:/File/yolov5-mobileone-master/dataset/kitti/labels/origin"
  80. # labels_dir=os.path.join(cur_dir,'label_2')
  81. for parent, dirnames, filenames in os.walk(labels_dir):# 分别得到根目录,子目录和根目录下文件
  82. for file_name in filenames:
  83. full_path=os.path.join(parent, file_name) # 获取文件全路径
  84. f=open(full_path)
  85. split_lines = f.readlines() #以行为单位读
  86. name= file_name[:-4] # 后四位是扩展名.txt,只取前面的文件名
  87. img_name=name+'.png'
  88. img_path=os.path.join('D:/File/yolov5-mobileone-master/dataset/kitti/images/origin',img_name) # 路径需要自行修改
  89. img_size=cv2.imread(img_path).shape
  90. generate_xml(name,split_lines,img_size,class_ind)
  91. print('txts has converted into xmls')

       这个时候我们已经将.txt转化为.xml并存放在设定的文件夹xml下了。

4. 数据格式的转化与数据集划分

       最后我们再把.xml转化为适合于yolo训练的标签模式,将下面代码放置在数据集文件夹的根目录,注意不要将图片文件夹和要生成文件夹的名称重复。按照0.7:0.15:0.15构造数据集、测试集、验证集并分别分配到不同文件夹去。

  1. |——kitti
  2. ├── imgages
  3. │ ├── train
  4. │ │ ├── 00XXXA.png
  5. │ │ └── .......
  6. │ ├── val
  7. │ │ ├── 00XXXB.png
  8. │ │ └── .......
  9. │ └── test
  10. │ └── 00XXXC.png
  11. │ └── .......
  12. └── labels
  13. ├── train
  14. │ ├── 00XXXA.txt
  15. │ └── .......
  16. ├── val
  17. │ ├── 00XXXB.txt
  18. │ └── .......
  19. └── test
  20. ├── 00XXXC.txt
  21. └── .......

        分配代码如下:

  1. # xml_to_txt_yolo.py
  2. # 将此文件放置在你的数据集根目录下即可
  3. # 一定要放到根目录下
  4. import xml.etree.ElementTree as ET
  5. import os
  6. import shutil
  7. import random
  8. xml_file_path = 'D:/File/yolov5-mobileone-master/dataset/kitti/labels/xml/' # 检查和自己的xml文件夹名称是否一致
  9. images_file_path = 'images/origin/' # 检查和自己的图像文件夹名称是否一致
  10. # 改成自己的类别名称
  11. classes = ['Car', 'Cyclist', 'Truck', 'Van', 'Pedestrian', 'Tram']
  12. # 数据集划分比例,训练集75%,验证集15%,测试集15%
  13. train_percent = 0.7
  14. val_percent = 0.15
  15. test_percent = 0.15
  16. # 此处不要改动,只是创一个临时文件夹
  17. if not os.path.exists('temp_labels/'):
  18. os.makedirs('temp_labels/')
  19. txt_file_path = 'temp_labels/'
  20. def convert(size, box):
  21. dw = 1. / size[0]
  22. dh = 1. / size[1]
  23. x = (box[0] + box[1]) / 2.0
  24. y = (box[2] + box[3]) / 2.0
  25. w = box[1] - box[0]
  26. h = box[3] - box[2]
  27. x = x * dw
  28. w = w * dw
  29. y = y * dh
  30. h = h * dh
  31. return x, y, w, h
  32. def convert_annotations(image_name):
  33. in_file = open(xml_file_path + image_name + '.xml')
  34. out_file = open(txt_file_path + image_name + '.txt', 'w')
  35. tree = ET.parse(in_file)
  36. root = tree.getroot()
  37. size = root.find('size')
  38. w = int(size.find('width').text)
  39. h = int(size.find('height').text)
  40. for obj in root.iter('object'):
  41. # difficult = obj.find('difficult').text
  42. cls = obj.find('name').text
  43. # if cls not in classes or int(difficult) == 1:
  44. # continue
  45. if cls not in classes == 1:
  46. continue
  47. cls_id = classes.index(cls)
  48. xmlbox = obj.find('bndbox')
  49. b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text),
  50. float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
  51. bb = convert((w, h), b)
  52. out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
  53. total_xml = os.listdir(xml_file_path)
  54. num_xml = len(total_xml) # XML文件总数
  55. for i in range(num_xml):
  56. name = total_xml[i][:-4]
  57. convert_annotations(name)
  58. # *********************************************** #
  59. # parent folder
  60. # --data
  61. # ----images
  62. # ----train
  63. # ----val
  64. # ----test
  65. # ----labels
  66. # ----train
  67. # ----val
  68. # ----test
  69. def create_dir():
  70. if not os.path.exists('images/'):
  71. os.makedirs('images/')
  72. if not os.path.exists('labels/'):
  73. os.makedirs('labels/')
  74. if not os.path.exists('images/train'):
  75. os.makedirs('images/train')
  76. if not os.path.exists('images/val'):
  77. os.makedirs('images/val')
  78. if not os.path.exists('images/test'):
  79. os.makedirs('images/test/')
  80. if not os.path.exists('labels/train'):
  81. os.makedirs('labels/train')
  82. if not os.path.exists('labels/val'):
  83. os.makedirs('labels/val')
  84. if not os.path.exists('labels/test'):
  85. os.makedirs('labels/test')
  86. return
  87. # *********************************************** #
  88. # 读取所有的txt文件
  89. create_dir()
  90. total_txt = os.listdir(txt_file_path)
  91. num_txt = len(total_txt)
  92. list_all_txt = range(num_txt) # 范围 range(0, num)
  93. num_train = int(num_txt * train_percent)
  94. num_val = int(num_txt * val_percent)
  95. num_test = num_txt - num_train - num_val
  96. train = random.sample(list_all_txt, num_train)
  97. # train从list_all_txt取出num_train个元素
  98. # 所以list_all_txt列表只剩下了这些元素:val_test
  99. val_test = [i for i in list_all_txt if not i in train]
  100. # 再从val_test取出num_val个元素,val_test剩下的元素就是test
  101. val = random.sample(val_test, num_val)
  102. # 检查两个列表元素是否有重合的元素
  103. # set_c = set(val_test) & set(val)
  104. # list_c = list(set_c)
  105. # print(list_c)
  106. # print(len(list_c))
  107. print("训练集数目:{}, 验证集数目:{},测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))
  108. for i in list_all_txt:
  109. name = total_txt[i][:-4]
  110. srcImage = images_file_path + name + '.png'
  111. srcLabel = txt_file_path + name + '.txt'
  112. if i in train:
  113. dst_train_Image = 'images/train/' + name + '.png'
  114. dst_train_Label = 'labels/train/' + name + '.txt'
  115. shutil.copyfile(srcImage, dst_train_Image)
  116. shutil.copyfile(srcLabel, dst_train_Label)
  117. elif i in val:
  118. dst_val_Image = 'images/val/' + name + '.png'
  119. dst_val_Label = 'labels/val/' + name + '.txt'
  120. shutil.copyfile(srcImage, dst_val_Image)
  121. shutil.copyfile(srcLabel, dst_val_Label)
  122. else:
  123. dst_test_Image = 'images/test/' + name + '.png'
  124. dst_test_Label = 'labels/test/' + name + '.txt'
  125. shutil.copyfile(srcImage, dst_test_Image)
  126. shutil.copyfile(srcLabel, dst_test_Label)
  127. print("complete")

        数据分配结果如下:

        数据集、验证集、测试集分配情况如下:

        可以看到,数据与标签对应,数据个数与标签一致。

        至此,数据准备已经全部完毕,可以载入yolo进行训练。在训练之前需要改变一些参数。

四、配置文件的修改

1. 修改数据集yaml文件

       修改yaml文件,将dat目录下的coco128.yaml复制一份修改为kitti.yaml。

       需要注意names部分应当与前述的一致,否则会出现错误。

  1. # kitti.yaml
  2. train: D:/File/yolov5-mobileone-master/dataset/kitti/images/train # train images (relative to 'path') 5236 images
  3. val: D:/File/yolov5-mobileone-master/dataset/kitti/images/val/ # val images (relative to 'path') 1122 images
  4. test: D:/File/yolov5-mobileone-master/dataset/kitti/images/test/ # test images (optional)
  5. nc: 6 # number of classes
  6. names: ['Car', 'Cyclist', 'Truck', 'Van', 'Pedestrian', 'Tram'] # class names

2. 修改models配置文件

       本次实验使用yolov5s,故修改yolov5s.yaml文件,在models目录下。

       修改nc(类别数量)即可。

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