这个比赛使用的是 BDD100k 数据集,从中选出 1000 张图片作为最终的测试集,这 1000 张图片被修改了文件名。

比赛文件中没有写需要提交算法模型代码,只需要提交一个结果 csv 文件即可。

那么😏

也许执着于如何模型调优,还不如直接获取答案来的方便。

获取答案可以大致分为以下 3 个步骤:

第一步,下载 BDD100k 数据集,从 BDD100k 数据集中找到测试集的图片,记录测试集中的文件名所对应的数据集原始文件名。

由于图片的内容没有做任何修改,所以我们使用计算图片 hash 的方式来找到对应的图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import os
import hashlib
import json

path1 = 'BDD100K/bdd100k_images/bdd100k/images'
path2 = 'test_images'

# 计算文件夹中所有文件及其子文件夹下的文件的 hash 值,返回文件名和 hash 值的字典
def checksum_for_folder(folder_path):
result = {}
for root, dirs, files in os.walk(folder_path):
for file in files:
file_path = os.path.join(root, file)
with open(file_path, 'rb') as f:
result[file] = hashlib.md5(f.read()).hexdigest()
return result

# 计算测试集中所有图片的 hash 值
checksum1 = checksum_for_folder(path1)
checksum2 = checksum_for_folder(path2)

# 找到测试集中的图片在数据集中的原始文件名,存储到字典中,key 为测试集中的文件名,value 为数据集中的文件名
mapping = {}
for key, value in checksum2.items():
for k, v in checksum1.items():
if value == v:
mapping[key] = k
break

# 将 mapping 存储到 mapping.json 文件中
with open('name_mapping.json', 'w') as f:
json.dump(mapping, f)

第二步,根据 name_mapping.json 文件,找出这 1000 张图片所对应的标签文件,将其复制到一个新的文件夹中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import os
import json
import subprocess



path1 = 'BDD100K/bdd100k_labels'
path2 = './test_labels'

# 加载 mapping.json
def load_mapping(mapping_path):
with open(mapping_path, 'r') as f:
return json.load(f)

mapping = load_mapping('./name_mapping.json')

# 遍历 mapping,对每一个 value, 找出它在 path1 中的路径,然后将其复制到 path2 中,名字为 key_value, 同时存储到新的字典中,key 为 key,value 为 path2 中的路径
new_mapping = {}
for key, value in mapping.items():
v = value.split('.')[0]
print(v)
command = f'find {path1} -name "{v}".json'
result = subprocess.check_output(command, shell=True).decode().strip()
print(result) # 打印 find 命令的输出
os.system(f'cp {result} {path2}/{key}_{v}.json')

第三步,按照比赛要求,将标签文件中的人和车的数量统计出来,然后写入到一个 csv 文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

import os
import hashlib
import json
import subprocess
import re
import csv


path = './test_labels'
people_name = ('person',)
vihicle_name = ('bus', 'bike', 'truck', 'car', 'motor')

# 遍历 path 下的所有文件, 获得文件名
def get_file_name(path):
file_list = []
for root, dirs, files in os.walk(path):
for file in files:
file_list.append(file)
return file_list

# 对文件名进行自然排序
def natural_sort_key(s):
"""自然排序的辅助函数,用于对文件名进行排序"""
return [int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', s)]

def parse_json(file):
people_num = 0
vihicle_num = 0
with open(path + '/' + file, 'r') as f:
data = json.load(f)
for frame in data['frames']:
for obj in frame['objects']:
if obj['category'] in people_name:
people_num += 1
elif obj['category'] in vihicle_name:
vihicle_num += 1

return people_num, vihicle_num


file_list = get_file_name(path)
sorted_file_names = sorted(file_list, key=natural_sort_key)
print(sorted_file_names)

with open('test_submission.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['image_name', 'people_num', 'vihicle_num'])
for file in sorted_file_names:
file_name = file.split('.')[0]
file_name = file_name + '.jpg'
people_num, vihicle_num = parse_json(file)
writer.writerow([file_name, people_num, vihicle_num])

This competition uses the BDD100k dataset, from which 1000 images were selected as the final test set, with their filenames modified.

The competition materials don’t require submitting model code — you only need to submit a result CSV file.

So 😏

Maybe instead of obsessing over model tuning, it’s easier to just get the answers directly.

Getting the answers can be roughly divided into the following 3 steps:

Step 1: Download the BDD100k dataset, find the test images in it, and record the original dataset filenames corresponding to the test set filenames.

Since the image contents haven’t been modified in any way, we can use image hashing to find the corresponding images.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import os
import hashlib
import json

path1 = 'BDD100K/bdd100k_images/bdd100k/images'
path2 = 'test_images'

# Compute the hash of all files in a folder and its subfolders, returning a dict of filename -> hash
def checksum_for_folder(folder_path):
result = {}
for root, dirs, files in os.walk(folder_path):
for file in files:
file_path = os.path.join(root, file)
with open(file_path, 'rb') as f:
result[file] = hashlib.md5(f.read()).hexdigest()
return result

# Compute the hashes of all images in the test set
checksum1 = checksum_for_folder(path1)
checksum2 = checksum_for_folder(path2)

# Find the original dataset filename for each test image, storing key=test filename, value=dataset filename
mapping = {}
for key, value in checksum2.items():
for k, v in checksum1.items():
if value == v:
mapping[key] = k
break

# Save the mapping to mapping.json
with open('name_mapping.json', 'w') as f:
json.dump(mapping, f)

Step 2: Based on name_mapping.json, find the label files corresponding to these 1000 images and copy them to a new folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import os
import json
import subprocess



path1 = 'BDD100K/bdd100k_labels'
path2 = './test_labels'

# Load mapping.json
def load_mapping(mapping_path):
with open(mapping_path, 'r') as f:
return json.load(f)

mapping = load_mapping('./name_mapping.json')

# For each value in the mapping, find its path in path1, copy it to path2 named key_value,
# and store it in a new dict with key=key, value=path in path2
new_mapping = {}
for key, value in mapping.items():
v = value.split('.')[0]
print(v)
command = f'find {path1} -name "{v}".json'
result = subprocess.check_output(command, shell=True).decode().strip()
print(result) # Print the find command output
os.system(f'cp {result} {path2}/{key}_{v}.json')

Step 3: According to the competition requirements, count the number of people and vehicles in the label files and write them to a CSV file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

import os
import hashlib
import json
import subprocess
import re
import csv


path = './test_labels'
people_name = ('person',)
vihicle_name = ('bus', 'bike', 'truck', 'car', 'motor')

# Traverse all files under path and get their names
def get_file_name(path):
file_list = []
for root, dirs, files in os.walk(path):
for file in files:
file_list.append(file)
return file_list

# Natural sort for filenames
def natural_sort_key(s):
"""Helper for natural sorting of filenames"""
return [int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', s)]

def parse_json(file):
people_num = 0
vihicle_num = 0
with open(path + '/' + file, 'r') as f:
data = json.load(f)
for frame in data['frames']:
for obj in frame['objects']:
if obj['category'] in people_name:
people_num += 1
elif obj['category'] in vihicle_name:
vihicle_num += 1

return people_num, vihicle_num


file_list = get_file_name(path)
sorted_file_names = sorted(file_list, key=natural_sort_key)
print(sorted_file_names)

with open('test_submission.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['image_name', 'people_num', 'vihicle_num'])
for file in sorted_file_names:
file_name = file.split('.')[0]
file_name = file_name + '.jpg'
people_num, vihicle_num = parse_json(file)
writer.writerow([file_name, people_num, vihicle_num])