UAVDT目标检测数据集格式转化以及训练集验证集划分教程(原格式转化为Json(COCO)格式)

UAVDT目标检测数据集格式转化教程(原格式转化为Json(COCO)格式)

无人机目标检测数据集目前主要有两个,一个是VisDrone19/18,还有一个就是UAVDT。
UAVDT数据集不是COCO格式的,但是目标检测一般使用COCO或者VOC格式的。
我找了一圈,博客和Github上都没有相关的转化数据集代码。(以前转数据集网上一搜都有别人提供的,但是这个数据集可能用的人少吧,我没找到)。所以只能自己来写了。以后其他人用这个数据集需要转化格式的时候就可以参考了。

1、下载数据集,了解数据集格式。
官网是这个:UAVDT官网
里面的图片类似这样。
在这里插入图片描述
UAVDT还包括了目标跟踪。其实它主要是目标跟踪。里面的目标检测也只是把视频里的东西逐帧提取,然后打上相应的标签。

下载下来后我们主要用这两个文件。
在这里插入图片描述
第一个就是图片,里面有子文件夹,子文件夹中就是那一段视频的每一帧的图片。
第二个文件夹就是GT标签,其中有README文件,里面有详细的格式说明。
README文件
标签是这样的
在这里插入图片描述
也就是类似yolo的txt格式。每一列它都有说明了。

2、先处理图片,把图片重命名放入到一个文件夹中。
COCO格式中图片都是放入到单独一个文件夹中的。
这个数据集一个文件夹下又有好多文件夹,这样不太好,我们可以把图片重命名后放入一个文件夹。

这里可以写一个简单的Python脚本。就叫imagescopy2onedir.py吧

import os
import shutil


multidirpath = 'D:/07_codeD/datasets/UAV/UAV-benchmark-M'
outdir = 'D:/07_codeD/datasets/UAV/uavdtallimages_rename'
# os.mkdir((outdir))

filenames = os.listdir(multidirpath)
# print(filenames)
for file in filenames:
    wholefile = multidirpath + '/' + file
    filenextname = os.listdir(wholefile)
    # print(filenextname)
    for filenext in filenextname:
        pathall = multidirpath + '/' + file + '/' + filenext
        # print(pathall)
        str1 = str(file)
        outpath = outdir + '/' + str1 + '_' + filenext[-10:]
        # print(outpath)
        shutil.copyfile(pathall,outpath)

改变路径就可以在你自己的电脑上运行了。
这是我们重新命名的图片。
在这里插入图片描述
3、接下来就是写一个txt2json的python脚本了。

import json
import pandas as pd
import os



classList = ["car", "truck", "bus"]
# By default, coco dataset starts index of categories from 1
PRE_DEFINE_CATEGORIES = {key: idx + 1 for idx, key in enumerate(classList)}
# print(PRE_DEFINE_CATEGORIES)


txtdir = 'D:/07_codeD/datasets/UAV/UAV-benchmark-MOTD_v1.0/GT'
out_json_file = "out.json"

json_dict = {"images": [], "type": "instances", "annotations": [],
             "categories": []}
# json格式如下,我们要写这总的4个部分,先把最简单的categories写了吧
# {"images": [], "type": "instances", "annotations": [], "categories": []}

# 先把categories部分写完
for cate, cid in PRE_DEFINE_CATEGORIES.items():
    cat = {'supercategory': cate, 'id': cid, 'name': cate}
    json_dict['categories'].append(cat)

def get_annot_data(txt_file):
    '''Read annotation into a Pandas dataframe'''
    annot_data =  pd.read_csv(txt_file, delimiter=',', names=['<frame_index>','<target_id>','<bbox_left>','<bbox_top>','<bbox_width>','<bbox_height>','<out-of-view>','<occlusion>','<object_category>'])
    return annot_data



# 记录键值对为后面id进行使用
dict_imagename2id = {}

# 先实现images部分
# begin
imageid= 0
imagesdir = 'D:/07_codeD/datasets/UAV/uavdtallimages_rename'
for image_name in os.listdir(imagesdir):
    file_name = image_name
    width = 540
    height = 1024
    id = imageid
    imageid += 1
    dict_imagename2id[file_name[:-4]] = id
    image = {'file_name': file_name, 'height': height, 'width': width, 'id': id}
    json_dict['images'].append(image)
# end


# images部分写好了

# 接下来写annotations部分
bndid_change = 1
for txt_file in os.listdir(txtdir):
    if 'gt_whole' in txt_file:
        # print(txt_file)
        txtwholepath = txtdir + '/'+ txt_file
        # print(txtwholepath)
        with open(txtwholepath) as f:
            annot_data = get_annot_data(txtwholepath)
            # print(annot_data)
            # print(annot_data.loc[0])
            # for index in annot_data:
            #     print(index)
            # pandas按行输出
            for index, row in annot_data.iterrows():
                # print(index)  # 输出每行的索引值
                # 要加int不然会出现int64错误
                o_width = int(row['<bbox_width>'])
                o_height = int(row['<bbox_height>'])
                xmin = int(row['<bbox_left>'])
                ymin = int(row['<bbox_top>'])
                category_id = int(row['<object_category>'])
                bnd_id = int(bndid_change)
                # image_id需要建立一个map或者叫dict
                # 转化成000001
                imageindx = row['<frame_index>']
                k = str(imageindx)
                str1 = txt_file[0:5]
                str2 = k.zfill(6)
                dictfilename = str1 + '_' + str2
                image_id = int(dict_imagename2id[dictfilename])
                print(image_id)
                ann = {'area': o_width * o_height, 'iscrowd': 0, 'image_id':image_id, 'bbox': [xmin, ymin, o_width, o_height],'category_id': category_id, 'id': bnd_id, 'ignore': 0,'segmentation': []}
                bndid_change += 1
                json_dict['annotations'].append(ann)

            # break

# about json
json_fp = open(out_json_file, 'w')
json_str = json.dumps(json_dict)
json_fp.write(json_str)
json_fp.close()

运行就可以在当前文件夹下生成对应的json标签文件了。

4、将标签映射回原图片查看是否转化正确。
这里网上找了一个,改了下。
我们可以找几张图片出来放到一个文件夹中。
在这里插入图片描述

画框的代码如下


# coding:utf-8
# 检查json格式转换的是否正确(即,将转换的数据画回原图中)
# 可以img show简单查看。
from pycocotools.coco import COCO
import cv2
import pandas as pd
import json


def select(json_path, outpath, image_path):
    json_file = open(json_path)
    infos = json.load(json_file)
    images = infos["images"]
    annos = infos["annotations"]
    assert len(images) == len(images)
    for i in range(len(images)):
        im_id = images[i]["id"]
        im_path = image_path + images[i]["file_name"]
        print(im_path)
        img = cv2.imread(im_path)
        for j in range(len(annos)):
            # import pdb
            # pdb.set_trace()
            if annos[j]["image_id"] == im_id:
                # import pdb
                # pdb.set_trace()
                x, y, w, h = annos[j]["bbox"]
                x, y, w, h = int(x), int(y), int(w), int(h)
                x2, y2 = x + w, y + h
                # object_name = annos[j][""]
                img = cv2.rectangle(img, (x, y), (x2, y2), (255, 0, 0), thickness=2)
                img_name = outpath + images[i]["file_name"]
                # cv2.imshow('uavdt',img)
                # cv2.waitKey(0)
                cv2.imwrite(img_name, img)
                # continue
        cv2.imshow('uavdt',img)
        cv2.waitKey(0)

        # print(i)

if __name__ == "__main__":
    # imageidFile = ''
    json_path = 'D:/07_codeD/github/DMNet-master/myDir/out.json'
    image_path = 'D:/07_codeD/datasets/UAV/testjsonimage/'
    outpath = 'D:/07_codeD/datasets/UAV/outtestjsonimage/'
    select(json_path, outpath, image_path)


在这里插入图片描述

可以正常显示了!!!!

接下来就可以训练了,看看效果。
训练的话得划分数据集,分出一部分训练一部分测试。

更新!!
接下来写下如何划分训练集和验证集。

首先,之前我们把所有图片都放到一个目录下了,一共是40735张图片,我们把3/5部分拿来训练,剩下的做验证,计算一下,也就是24441张做训练,16294做验证。

我们选的时候要注意是随机的。

简单写个脚本就可以把我们的图片部分先划分出来了。

import os
import numpy as np
import shutil


rootdir = 'D:/07_codeD/datasets/UAV/uavdtallimages_rename'  # 源数据集图像的文件夹的路径
traindir = 'D:/07_codeD/datasets/UAV/train24441'
valdir = 'D:/07_codeD/datasets/UAV/val16294'

path = os.listdir(rootdir)
np.random.shuffle(path)  # 将数据集打乱顺序

d = 24441  # 将数据集分为两部分,在这里可以根据自己的需要修改
train = path[:d]  # 数据集的前半部分
val = path[d:]  # 数据集的后半部分

for i in train:
    ori_path = rootdir + '/' + str(i)
    train_path = traindir + '/' + str(i)
    shutil.copyfile(ori_path,train_path)
    # print(ori_path)


for i in val:
    ori_path = rootdir + '/' + str(i)
    val_path = valdir + '/' + str(i)
    shutil.copyfile(ori_path,val_path)
    # print(ori_path)
# print(train)
# print(val)
#

注意这里要先建文件夹,我没有写建文件夹的命令。

运行完,我们就得到了两个文件夹,文件夹里图片的格式和刚刚提到的一样。

接下来,我们需要改动之前写的标签的代码,其实想一想,前面Json标签换个路径就可以了,而且我们有建立一个字典来储存信息,后面我们可以利用这个字典来做循环的continue部分。

代码如下:

import json
import pandas as pd
import os
import random


classList = ["car", "truck", "bus"]
# By default, coco dataset starts index of categories from 1
PRE_DEFINE_CATEGORIES = {key: idx + 1 for idx, key in enumerate(classList)}
# print(PRE_DEFINE_CATEGORIES)


txtdir = 'D:/07_codeD/datasets/UAV/UAV-benchmark-MOTD_v1.0/GT'
# out_json_file = "outtrain.json"
out_json_file = "outval.json"

json_dict = {"images": [], "type": "instances", "annotations": [],
             "categories": []}
# json格式如下,我们要写这总的4个部分,先把最简单的categories写了吧
# {"images": [], "type": "instances", "annotations": [], "categories": []}

# 先把categories部分写完
for cate, cid in PRE_DEFINE_CATEGORIES.items():
    cat = {'supercategory': cate, 'id': cid, 'name': cate}
    json_dict['categories'].append(cat)

def get_annot_data(txt_file):
    '''Read annotation into a Pandas dataframe'''
    annot_data =  pd.read_csv(txt_file, delimiter=',', names=['<frame_index>','<target_id>','<bbox_left>','<bbox_top>','<bbox_width>','<bbox_height>','<out-of-view>','<occlusion>','<object_category>'])
    return annot_data



# 记录键值对为后面id进行使用
dict_imagename2id = {}

# 先实现images部分
# begin
imageid= 0
# imagesdir = 'D:/07_codeD/datasets/UAV/uavdtallimages_rename'

# 修改成train,val dir
# imagesdir = 'D:/07_codeD/datasets/UAV/train24441'
imagesdir = 'D:/07_codeD/datasets/UAV/val16294'


# 修改成train,val dir


# 添加训练和验证部分




for image_name in os.listdir(imagesdir):
    file_name = image_name
    width = 540
    height = 1024
    id = imageid
    imageid += 1
    dict_imagename2id[file_name[:-4]] = id
    image = {'file_name': file_name, 'height': height, 'width': width, 'id': id}
    json_dict['images'].append(image)
# end
# print(dict_imagename2id)



# images部分写好了

# 接下来写annotations部分
bndid_change = 1
for txt_file in os.listdir(txtdir):
    if 'gt_whole' in txt_file:
        # print(txt_file)
        txtwholepath = txtdir + '/'+ txt_file
        # print(txtwholepath)
        with open(txtwholepath) as f:
            annot_data = get_annot_data(txtwholepath)
            # print(annot_data)
            # print(annot_data.loc[0])
            # for index in annot_data:
            #     print(index)
            # pandas按行输出
            for index, row in annot_data.iterrows():
                # print(index)  # 输出每行的索引值
                # 要加int不然会出现int64错误
                o_width = int(row['<bbox_width>'])
                o_height = int(row['<bbox_height>'])
                xmin = int(row['<bbox_left>'])
                ymin = int(row['<bbox_top>'])
                category_id = int(row['<object_category>'])
                bnd_id = int(bndid_change)
                # image_id需要建立一个map或者叫dict
                # 转化成000001
                imageindx = row['<frame_index>']
                k = str(imageindx)
                str1 = txt_file[0:5]
                str2 = k.zfill(6)
                dictfilename = str1 + '_' + str2

                # 做一判断,看下是否有这个file name
                if dictfilename not in dict_imagename2id:
                    continue

                image_id = int(dict_imagename2id[dictfilename])
                print(image_id)
                ann = {'area': o_width * o_height, 'iscrowd': 0, 'image_id':image_id, 'bbox': [xmin, ymin, o_width, o_height],'category_id': category_id, 'id': bnd_id, 'ignore': 0,'segmentation': []}
                bndid_change += 1
                json_dict['annotations'].append(ann)

            # break

# about json
json_fp = open(out_json_file, 'w')
json_str = json.dumps(json_dict)
json_fp.write(json_str)
json_fp.close()





这里使用的时候,一个是改写输出的json文件名,然后是我们刚刚划分好的Image的路径。只需要改写这两部分就可以了。

这样我们的数据集划分就完成了。

接下来就是训练,这一部分之后我跑出结果再说吧。

版权声明:本文为CSDN博主「慕慕的木木」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42597373/article/details/119004668

慕慕的木木

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

目标检测之非极大值抑制(NMS)

1.NMS(非极大值抑制)介绍 在目标检测算法中,对于一个真实物体的往往会有多个候选框输出,而我们只需一个最好的检测框,多余的候选框会影响检测的精度,因此需要利用NMS(非极大值抑制)来