Skip to content

Commit e3483ce

Browse files
author
yixu.cui
committed
format py file by black
1 parent 0bb799b commit e3483ce

File tree

2 files changed

+879
-385
lines changed

2 files changed

+879
-385
lines changed

tools/convert_VisDrone_to_yolov2.py

Lines changed: 158 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -13,113 +13,182 @@
1313
import cv2
1414
import glob
1515
import numpy as np
16+
from tqdm import tqdm
1617

17-
DATA_ROOT = '/data/wujiapeng/datasets/VisDrone2019/VisDrone2019'
18-
18+
# VisDrone2019, MOT20, MOT17
19+
DATA_ROOT = "/perception/yixu.cui/datas/tracking/VisDrone2019"
1920

2021
# 以下两个seqs只跟踪车的时候有用
21-
certain_seqs = ['uav0000071_03240_v', 'uav0000072_04488_v','uav0000072_05448_v', 'uav0000072_06432_v','uav0000124_00944_v','uav0000126_00001_v','uav0000138_00000_v','uav0000145_00000_v','uav0000150_02310_v','uav0000222_03150_v','uav0000239_12336_v','uav0000243_00001_v',
22-
'uav0000248_00001_v','uav0000263_03289_v','uav0000266_03598_v','uav0000273_00001_v','uav0000279_00001_v','uav0000281_00460_v','uav0000289_00001_v','uav0000289_06922_v','uav0000307_00000_v',
23-
'uav0000308_00000_v','uav0000308_01380_v','uav0000326_01035_v','uav0000329_04715_v','uav0000361_02323_v','uav0000366_00001_v']
24-
25-
ignored_seqs = ['uav0000013_00000_v', 'uav0000013_01073_v', 'uav0000013_01392_v',
26-
'uav0000020_00406_v', 'uav0000079_00480_v',
27-
'uav0000084_00000_v', 'uav0000099_02109_v', 'uav0000086_00000_v',
28-
'uav0000073_00600_v', 'uav0000073_04464_v', 'uav0000088_00290_v']
22+
certain_seqs = [
23+
"uav0000071_03240_v",
24+
"uav0000072_04488_v",
25+
"uav0000072_05448_v",
26+
"uav0000072_06432_v",
27+
"uav0000124_00944_v",
28+
"uav0000126_00001_v",
29+
"uav0000138_00000_v",
30+
"uav0000145_00000_v",
31+
"uav0000150_02310_v",
32+
"uav0000222_03150_v",
33+
"uav0000239_12336_v",
34+
"uav0000243_00001_v",
35+
"uav0000248_00001_v",
36+
"uav0000263_03289_v",
37+
"uav0000266_03598_v",
38+
"uav0000273_00001_v",
39+
"uav0000279_00001_v",
40+
"uav0000281_00460_v",
41+
"uav0000289_00001_v",
42+
"uav0000289_06922_v",
43+
"uav0000307_00000_v",
44+
"uav0000308_00000_v",
45+
"uav0000308_01380_v",
46+
"uav0000326_01035_v",
47+
"uav0000329_04715_v",
48+
"uav0000361_02323_v",
49+
"uav0000366_00001_v",
50+
]
51+
52+
ignored_seqs = [
53+
"uav0000013_00000_v",
54+
"uav0000013_01073_v",
55+
"uav0000013_01392_v",
56+
"uav0000020_00406_v",
57+
"uav0000079_00480_v",
58+
"uav0000084_00000_v",
59+
"uav0000099_02109_v",
60+
"uav0000086_00000_v",
61+
"uav0000073_00600_v",
62+
"uav0000073_04464_v",
63+
"uav0000088_00290_v",
64+
]
2965

3066
image_wh_dict = {} # seq->(w,h) 字典 用于归一化
3167

68+
3269
def generate_imgs_and_labels(opts):
3370
"""
3471
产生图片路径的txt文件以及yolo格式真值文件
3572
"""
3673
if not opts.certain_seqs:
37-
seq_list = os.listdir(osp.join(DATA_ROOT, opts.split_name, 'sequences')) # 所有序列名称
74+
seq_list = os.listdir(
75+
osp.join(DATA_ROOT, opts.split_name, "sequences")
76+
) # 所有序列名称
3877
else:
3978
seq_list = certain_seqs
40-
79+
4180
if opts.car_only: # 只跟踪车就忽略行人多的视频
4281
seq_list = [seq for seq in seq_list if seq not in ignored_seqs]
4382
category_list = [4, 5, 6, 9] # 感兴趣的类别编号 List[int]
4483
else:
4584
category_list = [i for i in range(1, 11)]
4685

47-
print(f'Total {len(seq_list)} seqs!!')
48-
if not osp.exists('./visdrone/'):
49-
os.makedirs('./visdrone/')
86+
print(f"Total {len(seq_list)} seqs!!")
87+
if not osp.exists("./visdrone/"):
88+
os.makedirs("./visdrone/")
5089

5190
# 类别ID 从0开始
5291
category_dict = {category_list[idx]: idx for idx in range(len(category_list))}
5392

54-
txt_name_dict = {'VisDrone2019-MOT-train': 'train',
55-
'VisDrone2019-MOT-val': 'val',
56-
'VisDrone2019-MOT-test-dev': 'test'} # 产生txt文件名称对应关系
93+
txt_name_dict = {
94+
"VisDrone2019-MOT-train": "train",
95+
"VisDrone2019-MOT-val": "val",
96+
"VisDrone2019-MOT-test-dev": "test",
97+
} # 产生txt文件名称对应关系
5798

5899
# 如果已经存在就不写了
59-
write_txt = False if os.path.isfile(os.path.join('./visdrone', txt_name_dict[opts.split_name] + '.txt')) else True
60-
print(f'write txt is {write_txt}')
61-
62-
frame_range = {'start': 0.0, 'end': 1.0}
100+
write_txt = (
101+
False
102+
if os.path.isfile(
103+
os.path.join("./visdrone", txt_name_dict[opts.split_name] + ".txt")
104+
)
105+
else True
106+
)
107+
print(f"write txt is {write_txt}")
108+
109+
frame_range = {"start": 0.0, "end": 1.0}
63110
if opts.half: # VisDrone-half 截取一半
64-
frame_range['end'] = 0.5
111+
frame_range["end"] = 0.5
65112

66113
# 以序列为单位进行处理
67-
for seq in seq_list:
68-
img_dir = osp.join(DATA_ROOT, opts.split_name, 'sequences', seq) # 该序列下所有图片路径
114+
for seq in tqdm(sorted(seq_list)):
115+
print(f"{'*' * 8} {seq} {'*' * 8}")
116+
img_dir = osp.join(DATA_ROOT, opts.split_name, "sequences", seq) # 该序列下所有图片路径
69117

70118
imgs = sorted(os.listdir(img_dir)) # 所有图片
71119
seq_length = len(imgs) # 序列长度
72120

73121
img_eg = cv2.imread(os.path.join(img_dir, imgs[0])) # 序列的第一张图 用以计算高宽
74122
w0, h0 = img_eg.shape[1], img_eg.shape[0] # 原始高宽
75123

76-
ann_of_seq_path = os.path.join(DATA_ROOT, opts.split_name, 'annotations', seq + '.txt') # GT文件路径
77-
ann_of_seq = np.loadtxt(ann_of_seq_path, dtype=np.float32, delimiter=',') # GT内容
124+
ann_of_seq_path = os.path.join(
125+
DATA_ROOT, opts.split_name, "annotations", seq + ".txt"
126+
) # GT文件路径
127+
ann_of_seq = np.loadtxt(
128+
ann_of_seq_path, dtype=np.float32, delimiter=","
129+
) # GT内容
78130

79-
gt_to_path = osp.join(DATA_ROOT, 'labels', opts.split_name, seq) # 要写入的真值文件夹
131+
gt_to_path = osp.join(DATA_ROOT, "labels", opts.split_name, seq) # 要写入的真值文件夹
80132
# 如果不存在就创建
81133
if not osp.exists(gt_to_path):
82134
os.makedirs(gt_to_path)
83135

84136
exist_gts = [] # 初始化该列表 每个元素对应该seq的frame中有无真值框
85137
# 如果没有 就在train.txt产生图片路径
86138

87-
for idx, img in enumerate(imgs):
139+
for idx, img in enumerate(tqdm(imgs)):
88140
# img: 相对路径 即 图片名称 0000001.jpg
89-
if idx < int(seq_length * frame_range['start']) or idx > int(seq_length * frame_range['end']):
141+
if idx < int(seq_length * frame_range["start"]) or idx > int(
142+
seq_length * frame_range["end"]
143+
):
90144
continue
91145

92146
# 第一步 产生图片软链接
93147
# print('step1, creating imgs symlink...')
94148
if opts.generate_imgs:
95-
img_to_path = osp.join(DATA_ROOT, 'images', opts.split_name, seq) # 该序列图片存储位置
149+
img_to_path = osp.join(
150+
DATA_ROOT, "images", opts.split_name, seq
151+
) # 该序列图片存储位置
96152

97153
if not osp.exists(img_to_path):
98154
os.makedirs(img_to_path)
99155

100-
os.symlink(osp.join(img_dir, img),
101-
osp.join(img_to_path, img)) # 创建软链接
156+
link_name = osp.join(img_to_path, img)
157+
if not osp.exists(link_name):
158+
os.symlink(
159+
osp.join(img_dir, img),
160+
link_name,
161+
) # 创建软链接
102162
# print('Done!\n')
103163

104164
# 第二步 产生真值文件
105165
# print('step2, generating gt files...')
106166

107167
# 根据本序列的真值文件读取
108168
# ann_idx = int(ann_of_seq[:, 0]) == idx + 1
109-
ann_of_current_frame = ann_of_seq[ann_of_seq[:, 0] == float(idx + 1), :] # 筛选真值文件里本帧的目标信息
169+
ann_of_current_frame = ann_of_seq[
170+
ann_of_seq[:, 0] == float(idx + 1), :
171+
] # 筛选真值文件里本帧的目标信息
110172
exist_gts.append(True if ann_of_current_frame.shape[0] != 0 else False)
111173

112-
gt_to_file = osp.join(gt_to_path, img[:-4] + '.txt')
174+
gt_to_file = osp.join(gt_to_path, img[:-4] + ".txt")
113175

114-
with open(gt_to_file, 'a') as f_gt:
176+
with open(gt_to_file, "w") as f_gt:
115177
for i in range(ann_of_current_frame.shape[0]):
116-
117-
category = int(ann_of_current_frame[i][7])
118-
if int(ann_of_current_frame[i][6]) == 1 and category in category_list:
119178

120-
# bbox xywh
121-
x0, y0 = int(ann_of_current_frame[i][2]), int(ann_of_current_frame[i][3])
122-
w, h = int(ann_of_current_frame[i][4]), int(ann_of_current_frame[i][5])
179+
category = int(ann_of_current_frame[i][7])
180+
if (
181+
int(ann_of_current_frame[i][6]) == 1
182+
and category in category_list
183+
):
184+
185+
# bbox xywh
186+
x0, y0 = int(ann_of_current_frame[i][2]), int(
187+
ann_of_current_frame[i][3]
188+
)
189+
w, h = int(ann_of_current_frame[i][4]), int(
190+
ann_of_current_frame[i][5]
191+
)
123192

124193
xc, yc = x0 + w // 2, y0 + h // 2 # 中心点 x y
125194

@@ -129,40 +198,69 @@ def generate_imgs_and_labels(opts):
129198

130199
category_id = category_dict[category]
131200

132-
write_line = '{:d} {:.6f} {:.6f} {:.6f} {:.6f}\n'.format(
133-
category_id, xc, yc, w, h)
201+
write_line = "{:d} {:.6f} {:.6f} {:.6f} {:.6f}\n".format(
202+
category_id, xc, yc, w, h
203+
)
134204

135205
f_gt.write(write_line)
136206

137207
f_gt.close()
138208
# print('Done!\n')
139-
print(f'img symlink and gt files of seq {seq} Done!')
209+
print(f"img symlink and gt files of seq {seq} Done!")
210+
140211
# 第三步 产生图片索引train.txt等
141-
print(f'generating img index file of {seq}')
142212
if write_txt:
143-
to_file = os.path.join('./visdrone', txt_name_dict[opts.split_name] + '.txt')
144-
with open(to_file, 'a') as f:
213+
print(f"generating img index file of {seq}")
214+
to_file = os.path.join(
215+
"./visdrone", txt_name_dict[opts.split_name] + ".txt"
216+
)
217+
with open(to_file, "a") as f:
145218
for idx, img in enumerate(imgs):
146-
if idx < int(seq_length * frame_range['start']) or idx > int(seq_length * frame_range['end']):
219+
if idx < int(seq_length * frame_range["start"]) or idx > int(
220+
seq_length * frame_range["end"]
221+
):
147222
continue
148-
223+
149224
if exist_gts[idx]:
150-
f.write('VisDrone2019/' + 'VisDrone2019/' + 'images/' + opts.split_name + '/' \
151-
+ seq + '/' + img + '\n')
225+
f.write(
226+
f"VisDrone2019/VisDrone2019/images/{opts.split_name}/{seq}/{img}\n"
227+
)
152228

153229
f.close()
154230

155-
print('All done!!')
231+
print("All done!!")
232+
156233

157-
if __name__ == '__main__':
234+
if __name__ == "__main__":
158235
parser = argparse.ArgumentParser()
159-
parser.add_argument('--split_name', type=str, default='VisDrone2019-MOT-train', help='train or test')
160-
parser.add_argument('--generate_imgs', action='store_true', help='whether generate soft link of imgs')
161-
parser.add_argument('--car_only', action='store_true', help='only cars')
162-
parser.add_argument('--certain_seqs', action='store_true', help='for debug')
163-
parser.add_argument('--half', action='store_true', help='half frames')
236+
parser.add_argument(
237+
"--split_name",
238+
type=str,
239+
default="VisDrone2019-MOT-train",
240+
help="train or test",
241+
)
242+
parser.add_argument(
243+
"--generate_imgs",
244+
action="store_true",
245+
help="whether generate soft link of imgs",
246+
)
247+
parser.add_argument(
248+
"--car_only",
249+
action="store_true",
250+
help="only cars",
251+
)
252+
parser.add_argument(
253+
"--certain_seqs",
254+
action="store_true",
255+
help="for debug",
256+
)
257+
parser.add_argument(
258+
"--half",
259+
action="store_true",
260+
help="half frames",
261+
)
164262

165263
opts = parser.parse_args()
166264

167265
generate_imgs_and_labels(opts)
168-
# python tools/convert_VisDrone_to_yolov2.py --split_name VisDrone2019-MOT-train --generate_imgs --car_only --half
266+
# python tools/convert_VisDrone_to_yolov2.py --split_name VisDrone2019-MOT-train --generate_imgs --car_only --half

0 commit comments

Comments
 (0)