天天看点

yolov4训练nuscenes数据集/nuscenes数据集转coco格式1. nuscenes数据集下载2. nuscenes数据集转COCO格式3. yolov4训练

1. nuscenes数据集下载

1.1 nuscenes数据集简介

nuScenes数据集 是自动驾驶公司nuTonomy建立的大规模自动驾驶数据集,该数据集不仅包含了Camera和Lidar,还记录了雷达数据。这个数据集由1000个场景组成(即scenes,这就是该数据集名字的由来),每个scenes长度为20秒,包含了各种各样的情景。在每一个scenes中,有40个关键帧(key frames),也就是每秒钟有2个关键帧,其他的帧为sweeps。关键帧经过手工的标注,每一帧中都有了若干个annotation,标注的形式为bounding box。不仅标注了大小、范围、还有类别、可见程度等等。这个数据集不久前发布了一个teaser版本(包含100个scenes),正式版(1000个scenes)的数据要2019年发布。这个数据集在sample的数量上、标注的形式上都非常好,记录了车的自身运动轨迹(相对于全局坐标),包含了非常多的传感器,可以用来实现更加智慧的识别算法和感知融合算法。

我需要包含毫米波雷达/激光雷达/摄像头的数据集,所以需要在数据集的选择上选取包含这三类传感器的数据集,故选择了nuscenes数据集。

1.2 nuscenes数据类型选择

数据集下载地址https://www.nuscenes.org/download

yolov4训练nuscenes数据集/nuscenes数据集转coco格式1. nuscenes数据集下载2. nuscenes数据集转COCO格式3. yolov4训练

数据集类型一共有以上六种,从上到下分别是图片数据集/激光雷达数据集/CAN数据集/地图数据集/完整数据集/先前的作广告的数据集(已弃用)

yolov4训练nuscenes数据集/nuscenes数据集转coco格式1. nuscenes数据集下载2. nuscenes数据集转COCO格式3. yolov4训练

这里我们只能选择Full dataset,原因会在之后的章节详细说明,作者下载了Mini版本,图中高亮的部分,点击Asia即可下载,下载速度较慢,建议复制下载链接使用迅雷下载。

如果需要大量训练集,则使用Trainval,需要下载MetaData和Camera blobs only for part 1,后面的part也可以下载,下载方式相同,都是点击后面的Asia。

2. nuscenes数据集转COCO格式

2.1 3D标注框转2D

nuscenes数据集采用的是三维框标注的数据集,故需要将3D标注框转化为2D格式。

使用官方工具nuscenes-devkthttps://github.com/nutonomy/nuscenes-devkit

克隆下来

cd ~
git clone https://github.com/nutonomy/nuscenes-devkit
           

找到

export_2d_annotations_as_json.py

路径在

/nuscenes-devkit/python-sdk/nuscenes/scripts/export_2d_annotations_as_json.py

该文件有以下5种选项,分别是

--dataroot

/

--version

/

--filename

/

--visibilities

/

--image_limit

--dataroot

是我们下载的MetaData的路径

--version

是我们需要转化的json文件的存放文件夹名

--filename

是我们对生成的2D框的json文件的保存名称

parser.add_argument('--dataroot', type=str, default='/data/sets/nuscenes', help="Path where nuScenes is saved.")
    parser.add_argument('--version', type=str, default='v1.0-trainval', help='Dataset version.')
    parser.add_argument('--filename', type=str, default='image_annotations.json', help='Output filename.')
    parser.add_argument('--visibilities', type=str, default=['', '1', '2', '3', '4'],
                        help='Visibility bins, the higher the number the higher the visibility.', nargs='+')
    parser.add_argument('--image_limit', type=int, default=-1, help='Number of images to process or -1 to process all.')
           

运行该python文件即可获得2D-box型的json文件,例如,我下载了Mini的数据包,我的MetaData路径是

~/nuscenes

,该文件下有以下四个文件夹

yolov4训练nuscenes数据集/nuscenes数据集转coco格式1. nuscenes数据集下载2. nuscenes数据集转COCO格式3. yolov4训练

/nuscenes-devkit/python-sdk/nuscenes/scripts/

路径下打开终端,我的命令如下,大家自行修改自己的路径及文件夹名称

python3 export_2d_annotations_as_json.py --dataroot ~/nuscenes --version v1.0-mini --filename 2D-box.json
           

这样就会在v1.0-mini文件夹下生成一个2D-box.json的文件。

PS:在这里详细说一下为什么下载数据集的时候要选择full dataset而不是nuImages,因为

export_2d_annotations_as_json.py

程序需要的很多json文件在nuImages数据集中没有包含,所以无法转化成2D框,所以在下载数据集的时候务必下载Full dataset。

2.2 nuscenes 2D格式转为COCO

在github上找到一个nuscenes 2D框转为COCO格式的一个工程https://github.com/AlizadehAli/2D_label_parser

cd ~
git clone https://github.com/AlizadehAli/2D_label_parser
           

包含labels和target_labels两个文件夹,labels是存放刚刚上一步生成的json文件的,把我们上一步生成的文件放进去,并修改文件名为2D_nuscenes.json放入labels文件夹中

打开查看一下我们的json文件

gedit 2D_nuscenes.json
           
yolov4训练nuscenes数据集/nuscenes数据集转coco格式1. nuscenes数据集下载2. nuscenes数据集转COCO格式3. yolov4训练

这里可以看到box的数据结构,分别是四个角点的像素坐标,从上到下为x1,y1,x2,y2

我们打开label_parser.py,如下可以看到convert这个函数,对应上面box的数据结构可以明显看出xywh的计算是有问题的

def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0
    y = (box[2] + box[3])/2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)
           

将convert函数改为下面的:

def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[2])/2.0
    y = (box[1] + box[3])/2.0
    w = box[2] - box[0]
    h = box[3] - box[1]
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)
           

保存

查看代码中的nuscenes_parser函数这里表示了未来yolo训练的类别名称有以下10类,可以根据自己的需要进行修改。

for idx, name in enumerate(data):
                    if unique_img_names[i] == name['filename']:
                        x, y, w, h = convert((1600, 900), name['bbox_corners'])
                        if 'pedestrian' in name['category_name']:
                            obj_class = 0
                        elif 'bicycle' in name['category_name']:
                            obj_class = 1
                        elif 'motorcycle' in name['category_name']:
                            obj_class = 2
                        elif 'car' in name['category_name']:
                            obj_class = 3
                        elif 'bus' in name['category_name']:
                            obj_class = 4
                        elif 'truck' in name['category_name']:
                            obj_class = 5
                        elif 'emergency' in name['category_name']:
                            obj_class = 6
                        elif 'construction' in name['category_name']:
                            obj_class = 7
                        elif 'movable_object' in name['category_name']:
                            obj_class = 8
                        elif 'bicycle_rack' in name['category_name']:
                            obj_class = 9

                        temp = [str(obj_class), str(x), str(y), str(w), str(h), '\n']
                        L = " "
                        L = L.join(temp)
                        f.writelines(L)
           

然后查看代码可以看到有以下选项

parser.add_argument("-dt", "--data_type",
                        default="yolo",
                        help="data type of interest; yolo, bdd, nuscenes")
    parser.add_argument("-l", "--label_dir", default="./labels/",
                        help="root directory of the labels for YOLO json file, Berkeley Deep Drive (BDD) json-file, nuscenes")
    parser.add_argument("-s", "--save_dir", default="./target_labels/",
                        help="path directory to save the the converted label files")
    parser.add_argument("-i", "--image_dir",
                        default=None, required=False,
                        help="path where the images are located to BDD100K, nescenes, etc.")
    parser.add_argument("-o", "--output_dir",
                        default=None, required=False,
                        help="output directory to save the manipulated image files")
           

然后就是运行该程序,我们数据格式是nuscenes我的运行命令如下,注意save_dir必须包含以下六个文件夹,否则程序会报找不到文件之类的的错误

yolov4训练nuscenes数据集/nuscenes数据集转coco格式1. nuscenes数据集下载2. nuscenes数据集转COCO格式3. yolov4训练
python3 label_parser.py -dt nuscenes -s ~/nuscenes/samples/
           

等待程序运行结束,可能有些会报os之类的一些错误,只要txt成功生成了就没有问题。

2.3 数据集文件名对齐

首先将所有txt文件放在一个新文件夹TXT/中,将所有图片放在一个新文件夹CAM_ALL/中

使用如下程序data.py,比对两个文件夹下的文件名,删除没有标签的图片或者没有图片的标签。

data.py

import xml.dom.minidom
import os
root_path = '/home/hit/nuscenes/'
annotation_path = root_path + 'TXT/'
img_path = root_path + 'CAM_ALL/'
annotation_list = os.listdir(annotation_path)
img_list = os.listdir(img_path)
if len(img_list) != len(annotation_list):
    print("图片和标签数目不匹配")
    if len(img_list) < len(annotation_list):
        print("标签比图片多")
        error_xml = []
        for _ in annotation_list:
            xml_name = _.split('.')[0]
            img_name = xml_name + '.jpg'
            if img_name not in img_list:
                error_xml.append(_)
				os.remove(_)
        print("error xml:", error_xml)
    else:
        print("图片比标签多")
        error_img = []
        for _ in img_list:
            img_name = _.split('.')[0]
            xml_name = img_name + '.txt'
            if xml_name not in annotation_list:
                error_img.append(_)
                os.remove(_)
        print("缺少标签的图片:", error_img)
           

使用如下命令运行该程序

python3 data.py
           

运行后查看txt总数与图片总数是否一致,一致就可以放入darknet训练了

3. yolov4训练

首先需要darknet源码https://github.com/AlexeyAB/darknet

git clone https://github.com/AlexeyAB/darknet
           

然后就是源码的编译,建议查看官方文档或其他博客,此部分不再赘述

然后就是将上述第二步的txt和jpg分别放入训练的指定文件夹,由于我们没有voc格式的xml标签格式,所以无法使用程序自动分配数据集,我们在图片/你的darknet路径/你的训练图片路径/下运行以下命令

ls -R /你的darknet路径/你的训练图片路径/*.jpg > file.txt
           

这样会生成一个file.txt,将该文件的内容复制到/你的darknet路径/scripts/,将file.txt的文件内容复制到该文件夹下的所有txt文件,如果没有就新建2007_test.txt,2007_train.txt,2007_val.txt,train.all.txt,train.txt这五个文件,并把file.txt文件内容放进去

修改cfg/voc.data中的类别改为10类,修改data/voc.name为上述10类的类名

修改cfg/yolov4.cfg,建议跟随官网修改方式修改https://github.com/AlexeyAB/darknet

启动训练

./darknet detector train cfg/voc.data cfg/yolov4.cfg yolov4.conv.137
           

至此,yolo训练nuscenes数据集结束

继续阅读