BDD100K数据集制作的流程(1)

第一步:json=>csv

利用json_to_csv.ipynb把路径"G:/Data/bdd100k_info/bdd100k/info/100k/val""G:/Data/bdd100k_info/bdd100k/info/100k/train"下面的json数据,全部转为csv数据。得到的文件是存储在路径G:\Data\bdd100k_info\bdd100k\info\100k\train_csv\each_train_csv和G:\Data\bdd100k_info\bdd100k\info\100k\val_csv下面。
数据转换的程序如下:

# data_dir = "G:/Data/bdd100k_info/bdd100k/info/100k/val"
data_dir = "G:/Data/bdd100k_info/bdd100k/info/100k/train"
data_path = os.listdir(data_dir)
data_path.sort()

# m = 4501
# json_path = os.path.join(data_dir,data_path[h])#将路径与文件名结合起来就是每个文件的完整路径
# json_content=json.load(open(json_path))
# print(len(json_content.keys()))
# print(data_path[h])

m = 0
h = 0
k = 0
DataResult = pd.DataFrame(columns=['imgid', 'rideid', 'latitude', 'longitude', 'startTime', 'endTime', 'speed'])
for num in range(0,len(data_path)):
    
    if m >20:
        break
    json_path = os.path.join(data_dir,data_path[m])#将路径与文件名结合起来就是每个文件的完整路径

#     json_path = os.path.join(data_dir,json_name)#将路径与文件名结合起来就是每个文件的完整路径
    json_content=json.load(open(json_path))   
    print("The number of variable m is %d" % (m))
    m = m + 1

    # Delete damaged files of json, the number of the key of json_content is 10
    if len(json_content.keys())==10:      
        #     print(json_content['gps'])
        #     print(json.dumps(json_content['gps'], sort_keys=True, indent=4))    
        # 重复从imgid,重复存rideID,一个json里面只有一个起始和结束时间(所以得到的时间都是相同的),因为bdd100k\info\100k\val是40秒视频里面的1帧
        for location in json_content['gps']:
            NewData = pd.DataFrame({'imgid':[data_path[m]],
                                    'rideid':[json_content['rideID']],
                                    'latitude':[location['latitude'] ],
                                    'longitude':[location['longitude'] ],
                                    'startTime': [timeStamp( json_content['startTime'] )],
                                    'endTime': [timeStamp( json_content['endTime'] )],
                                    'speed': [location['speed']]
                                    })    
            DataResult = DataResult.append(NewData, ignore_index=True)   
        
        print("The number of variable h is %d" % (h))
        print("The number of variable k is %d" % (k))
        k = k + 1
        h = h + 1
        if k==10:
#             DataResult.to_csv("G:/Data/bdd100k_info/bdd100k/info/100k/val_csv/%d.csv"%(h), index=None)
            DataResult=[]
            DataResult = pd.DataFrame(columns=['imgid', 'rideid', 'latitude', 'longitude', 'startTime', 'endTime', 'speed'])
            k = 1
            

第二步:csv=>csv

把文件下each_train_csv和each_val_csv下面的数据合并为train_info.csv或val_info.csv文件(用all_csv_to_train_val_info.ipynb),程序如下:

import json
import numpy as np
import os
from pathlib import Path
import json
import pandas as pd
import time
from datetime import datetime
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

#filename可以直接从盘符开始,标明每一级的文件夹直到csv文件,header=None表示头部为空
k = 1
DataResult = pd.DataFrame(columns=['imgid', 'rideid', 'latitude', 'longitude', 'startTime', 'endTime', 'speed'])

for info in os.listdir('G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/each_train_csv/'):
#     if k > 5:
#         break
    print(k)
    domain = os.path.abspath(r'G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/each_train_csv/') #获取文件夹的路径
#     domain = os.path.abspath(r'G:/Data/bdd100k_info/bdd100k/info/100k/val_csv/each_val_csv/') #获取文件夹的路径
    info = os.path.join(domain, info) #将路径与文件名结合起来就是每个文件的完整路径  
    NewData = pd.read_csv(info)
    
    DataResult = DataResult.append(NewData, ignore_index=True)
    k = k + 1
print(DataResult.head(2))
# result.to_csv("G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/train_info.csv", index=None)  
# result.to_csv("G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/val_info.csv", index=None)   

第三步:统计每张图片里面类别出现的频次

统计每张图片里面类别出现的频次得到train_class_accumulate.csv和val_class_accumulate.csv(class_accumulate.ipynb)
程序如下:

import json
import numpy as np
import os
from pathlib import Path
import json
import pandas as pd
import time
from datetime import datetime
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

### 获得每张图片类别数量和对应的GPS数据

def get_train_val_class_number():
    # train_data_dir = "bdd100k_labels_images_train.json"
#     train_data_dir = "bdd100k_labels_images_val.json"

    train_data=json.load(open(train_data_dir)) 
    className = {
        1: 'bus',
        2: 'traffic light',
        3: 'traffic sign',
        4: 'person',
        5: 'bike',
        6: 'truck',
        7: 'motor',
        8: 'car',
        9: 'train',
        10: 'rider',
    }   
    classNameDF = pd.DataFrame({
                            '1':[ className[1] ],
                            '2':[ className[2] ],
                            '3':[ className[3] ],
                            '4':[ className[4] ],
                            '5':[ className[5] ],
                            '6':[ className[6] ],
                            '7':[ className[7] ],
                            '8':[ className[8] ],
                            '9':[ className[9] ],
                            '10':[ className[10] ]
                            })


    # 初始化类别的个数全为0
    image_name = {}
    class_accumulate = np.zeros((len(train_data), classNameDF.shape[1]))
    for i in range(0,len(train_data)):
        each_class_accumulate = np.zeros((1, classNameDF.shape[1]))
        print(i)
    #     if i >10:
    #         break
        each_image_data = train_data[i]
        image_name[i] = each_image_data['name']
        each_image_labels = each_image_data['labels']
        for j in range(0,len(each_image_labels)):
            # 统计每个类别的个数
            each_class = each_image_labels[j]['category']
            each_class_index = classNameDF == each_class
            each_class_counter = np.array(each_class_index)+0
            each_class_accumulate = each_class_counter + each_class_accumulate
    #     print(each_image_data['name'])
    #     print(each_class_accumulate)
        class_accumulate[i] = each_class_accumulate    
    
    class_accumulate_df = pd.DataFrame(class_accumulate)

    image_name_df = pd.DataFrame([image_name]).T
    image_name_df.rename(columns={ image_name_df.columns[0]: "img_id" }, inplace=True)
    # print(image_name_df)
    result = pd.concat([image_name_df, class_accumulate_df], axis=1)
    print(result.head(5))
#     result.to_csv("G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/train_class_accumulate.csv", index=None)    
#     result.to_csv("G:/Data/bdd100k_info/bdd100k/info/100k/val_csv/val_class_accumulate.csv", index=None)    
    
get_train_val_class_number() 把类别统计数据存储为train_class_accumulate.csv和val_class_accumulate.csv

第四步: 筛选出不同区域的图片

#filename可以直接从盘符开始,标明每一级的文件夹直到csv文件,header=None表示头部为空
k = 1
DataResult = pd.DataFrame(columns=['imgid', 'rideid', 'latitude', 'longitude', 'startTime', 'endTime', 'speed'])

for info in os.listdir('G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/each_train_csv/'):
#     if k > 5:
#         break
    print(k)
    domain = os.path.abspath(r'G:/Data/bdd100k_info/bdd100k/info/100k/train_csv/each_train_csv/') #获取文件夹的路径
#     domain = os.path.abspath(r'G:/Data/bdd100k_info/bdd100k/info/100k/val_csv/each_val_csv/') #获取文件夹的路径
    info = os.path.join(domain, info) #将路径与文件名结合起来就是每个文件的完整路径  
    NewData = pd.read_csv(info)
    
    DataResult = DataResult.append(NewData, ignore_index=True)
    k = k + 1
print(DataResult.head(2))

SubDataResult = DataResult # train_info.csv和val_info.csv文件数据也可以

### 筛选出不同区域的图片
state_boundaries_path = "state_boundaries.json"
state_minmax_latlon=json.load(open(state_boundaries_path)) 

new_york_min_lat = state_minmax_latlon['NY']['min_lat']
new_york_max_lat = state_minmax_latlon['NY']['max_lat']
new_york_min_lng = state_minmax_latlon['NY']['min_lng']
new_york_max_lng = state_minmax_latlon['NY']['max_lng']

NewYorkData = SubDataResult[(SubDataResult['latitude'] >= new_york_min_lat) & (SubDataResult['latitude'] <= new_york_max_lat) & (SubDataResult['longitude'] >= new_york_min_lng) & (SubDataResult['longitude'] <= new_york_max_lng)]



print(NewYorkData.head(3))
NewYorkData.to_csv("NewYorkData.csv", index=None)

第五步:把全部数据转换为VOC2007的数据格式

程序的细节解释,可以参考json2xml.py和json_extract.py
5.1: json_extract.py把json提取出来,然后保存为outputval.json(train和val分别制作)

#coding=utf-8
import json
import io

className = {
    1: 'bus',
    2: 'traffic light',
    3: 'traffic sign',
    4: 'person',
    5: 'bike',
    6: 'truck',
    7: 'motor',
    8: 'car',
    9: 'train',
    10: 'rider',
}

classNum = [1, 2, 3, 4, 5, 6, 7, 9, 10]

inputfile = []
inner = {}

# PATH_TO_JSON = 'G:/Data/bdd100k_labels_release/bdd100k/labels/bdd100k_labels_images_train.json'
PATH_TO_JSON = 'G:/Data/bdd100k_labels_release/bdd100k/labels/bdd100k_labels_images_val.json'

with open(PATH_TO_JSON, "r+") as f:
    allData = json.load(f)
    print("read ready")

def writeNum(Num):
#     with open("train_outputval.json", "a+", encoding='utf-8') as f:
    with open("val_outputval.json", "a+", encoding='utf-8') as f:
        f.write(str(Num))

inputfile = []
inner = {}

    k = 1
    for data in allData:
#         print(data.keys())
        print(k)
#         if k >1:
#             break
            
        k = k + 1
        for item in data['labels']:
#             print(item.keys())
            if 'box2d' in item:
                inner = {
                    "filename": str(data["name"]).zfill(6),
                    "name": item['category'],
                    "box2d": item['box2d'],
                    "id": item['id'],
                    "truncated": item['attributes']['truncated'],
                    "occluded": item['attributes']['occluded']
                }
#                 print(item['attributes'])
                inputfile.append(inner)

    inputfile = json.dumps(inputfile,indent=4)
    writeNum(inputfile)# 把数据存为inputfile,调用自定义函数,输出数据为outputval

5.2 json2xml.py把outputval.json转化为.xml数据(train和val分别制作)

### 把json标签转为.xml标签
#https://blog.csdn.net/qq_17278169/article/details/82189776 

# https://github.com/YaoLing13/DL_Tools 程序主要来自于这个网站


# 把json文件转化为xml,便于后面的训练使用,同时把图片复制到对应的文件夹里面 
#coding=utf-8
import xml.etree.ElementTree as ET
import json
import os
from skimage import io, data
import shutil

x1 = []
y1 = []
x2 = []
y2 = []
classname = []
truncate = []
occlude = []
# 读取json里的内容,allData表示整个.json的内容,data表示遍历的当前元素
# with open("train_outputval.json", "r+") as f:
with open("val_outputval.json", "r+") as f:
    allData = json.load(f)
    # data = allData["annotations"]
    print("read ready")


#####################此步骤将每一个图片的全部信息读为img_all列表的一个元素
one_img = []
img_all = []
j = 0
for i in range(1, len(allData)):
#     if j > 1:
#         break            
    if allData[i]['filename']==allData[i-1]['filename']: # train_outputval.json文件,一个label+一个filename,所以是多个label有一个filename
        one_img.append(allData[i-1]) # 最终得到的是一个图片里面存在多个label的坐标信息
    else:
        one_img.append(allData[i-1])#处理图片中最后一个bbox
        j += 1
        img_all.append(one_img)
        one_img = []
# print(one_img[9999]['filename'])
img_all.append(one_img)

# 美化xml文件  prettyXml(annotation, '\t', '\n') # \t 表示空格  \n表示换行
def prettyXml(element, indent, newline, level = 0): # element为传进来的Elment类,参数indent用于缩进,newline用于换行
#     print(element.text)
    if element:  # 判断element是否有子元素
        if element.text == None or element.text.isspace(): # 如果element的text没有内容
            element.text = newline + indent * (level + 1) 
        else:
            element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1)
    #else:  # 此处两行如果把注释去掉,Element的text也会另起一行
        #element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * level
    temp = list(element) # 将elemnt转成list
#     print(temp)
    for subelement in temp:
        if temp.index(subelement) < (len(temp) - 1): # 如果不是list的最后一个元素,说明下一个行是同级别元素的起始,缩进应一致
            subelement.tail = newline + indent * (level + 1)
        else:  # 如果是list的最后一个元素, 说明下一行是母元素的结束,缩进应该少一个
            subelement.tail = newline + indent * level
        prettyXml(subelement, indent, newline, level = level + 1) # 对子元素进行递归操作


x1 = []
y1 = []
x2 = []
y2 = []
classname = []
truncate = []
occlude = []
# 开始对每一张图片生成xml文件
k = 1
for single in img_all:
    print(k)
#     if k > 1:
#         break
    k += 1
    data = single[0]  # 获取图像名字
    img_name = data['filename']  # 获取图像名字

    # 把原文件里面的图片复制到目标文件夹里面
#     source_file_path = 'G:/Data/bdd100k_images/bdd100k/images/100k/train/'
    source_file_path = 'G:/Data/bdd100k_images/bdd100k/images/100k/val/'
    source_img_path = os.path.join(source_file_path, img_name)  #得到图像绝对路径

#     target_file_path = 'G:/Data/bdd100k_images/bdd100k/images/100k/SubTrain/JPEGImages/'
    target_file_path = 'G:/Data/bdd100k_images/bdd100k/images/100k/SubVal/JPEGImages/'
    target_img_path = os.path.join(target_file_path, img_name)  #得到图像绝对路径
    shutil.copyfile(source_img_path,target_img_path)
    
    #get the coordinates of the bbox, name, truncated, occluded(object的子节点们,需要循环)
#     img = io.imread(source_img_path)
#     h = img.shape[0]
#     w = img.shape[1]
#     d = img.shape[2]
#     print(h)
#     print(w)
#     print(d)

    h = 720
    w = 1280
    d = 3    
    
    for element in single:
        if 'box2d' in element:
            x1.append(element['box2d']['x1'])
            x2.append(element['box2d']['x2'])
            y1.append(element['box2d']['y1'])
            y2.append(element['box2d']['y2'])
            classname.append(element['name'])
            if element['truncated']==True:
                truncate.append('1')
            else:
                truncate.append('0')
            if element['occluded']==True:
                occlude.append('1')
            else:
                occlude.append('0')


    annotation = ET.Element("annotation")
    #创建annotation的子节点folder,并添加数据
    folder = ET.SubElement(annotation,"folder")
    folder.text = 'BDD 100K'
    #创建annotation的子节点filename,并添加属性
    filename = ET.SubElement(annotation,"filename")
    filename.text = img_name
    #创建annotation的子节点source,并添加属性
    source = ET.SubElement(annotation,"source")
    #
    size = ET.SubElement(annotation, "size")
    #
    segmented = ET.SubElement(annotation, "segmented")
    segmented.text = '0'


    #object
    for i in range(0, len(x1)):
        object = ET.SubElement(annotation, "object")
        #object的六个子节点
        name = ET.SubElement(object, 'name')
        name.text = classname[i]
        #
        pose = ET.SubElement(object, 'pose')
        pose.text = "Unspecified"
        #
        truncated = ET.SubElement(object, 'truncated')
        truncated.text = truncate[i]
        #
        occluded = ET.SubElement(object, 'occluded')
        occluded.text = occlude[i]
        #
        bndbox = ET.SubElement(object, 'bndbox')

        #
        difficult = ET.SubElement(object, 'difficult')
        difficult.text = "0"
        #

        #子节点bndbox下的四个子节点
        xmin = ET.SubElement(bndbox, 'xmin')
        xmin.text = str(x1[i])
        #
        ymin = ET.SubElement(bndbox, 'ymin')
        ymin.text = str(y1[i])
        #
        xmax = ET.SubElement(bndbox, 'xmax')
        xmax.text = str(x2[i])
        #
        ymax = ET.SubElement(bndbox, 'ymax')
        ymax.text = str(y2[i])
    #####################################

    #source的三个子节点
    database = ET.SubElement(source,"database")
    database.text = "bdd_100k_database"
    #
    annotation_1 = ET.SubElement(source,"annotation")
    annotation_1.text = "bdd_100k_database"
    #
    image = ET.SubElement(source,"image")
    image.text = "flickr"
    #

    #size的三个子节点
    width = ET.SubElement(size,"width")
    width.text = str(w)
    #
    height = ET.SubElement(size,"height")
    height.text = str(h)
    #
    depth = ET.SubElement(size,"depth")
    depth.text = str(d)
    #



    prettyXml(annotation, '\t', '\n')            #执行美化方法
    tree = ET.ElementTree(annotation) # 全部合并起来
    # data['filename'][:-4]把0000f77c-6257be58.jpg的'.jpg'后四个字符串去掉
#     xml_name = 'G:/Data/bdd100k_images/bdd100k/images/100k/SubTrain/Annotations/'+data['filename'][:-4] + '.xml'
    xml_name = 'G:/Data/bdd100k_images/bdd100k/images/100k/SubVal/Annotations/'+data['filename'][:-4] + '.xml'
#     print(data['filename'][:-4])
    tree.write(xml_name)
    print(data['filename'], 'finished')

    x1 = []
    y1 = []
    x2 = []
    y2 = []
    classname = []
    truncate = []
    occlude = []



第六步:每个车辆ID的数据存储为txt

利用create_data_lists.py把存储的txt转为.json数据(TEST_images.json, TEST_objects.json, TRAIN_images.json和TRAIN_objects.json)

TRAIN_images.json存储的是图片的路径;TRAIN_objects.json存储的是每个框的坐标和对应的标签

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值