在KITTI数据集上运行CenterNet
一、配置环境在Frustum Convnet和CenterNet环境下
- 将Frustum Convnet里的所有文件,和CenterNet的部分文件,拷贝到新建文件frustum下,目录组织如下图,其中centernet_models、src、cocoapi三个文件为CenterNet下的(centernet_models为CenterNet文件主目录下的models文件,因为要使用预训练模型ctdet_coco_dla_2x.pth),其余为Frustum Convnet下的。
此外,还需要将CenterNet/experiments/ctdet_coco_dla_2x.sh
拷贝到frustum/scripts
里面,并重命名为ctdet_kitti_dla_2x.sh。
- 安装一些包
pip install mayavi
pip install PyQt5
二、convert kitti to coco
从网上寻找代码,先将kitti的label_2里的.txt文件转为.xml文件,再转为.json文件,具体自行百度(应该有更好更便捷的方法)。
(本人参考的朋友代码,故不公开了)
以下为错误做法,运行main.py时会报错
1. 将frustum/kitti/image_sets
和frustum/kitti/rgb_detections
文件夹拷贝至frustum/data/kitti/
下,并将image_sets重命名为ImageSets_frustum,最后新建空文件夹annotations,如下图。
2. 打开frustum/src/tools/convert_kitti_to_coco.py
,修改:
Line 9 —— DATA_PATH = 'data/kitti/'
,
Line 13 —— SPLITS = ['frustum'] # ['3dop', 'subcnn']
。
3. 在frustum主目录下打开终端,运行python src/tools/convert_kitti_to_coco.py
,结果如下图。
重点:
用几类,转换几类!猜测上述错误做法的失败原因是将9类都转换了,而后续第三步的设定只用到了3类,因此也可以考虑修改python src/tools/convert_kitti_to_coco.py
文件(未尝试)。
三、kitti 2d object detection
参考:链接1、链接2、链接3
- 复制
frustum/src/lib/datasets/dataset/coco.py
文件并重命名为kitti2coco.py,修改kitti2coco.py(部分代码copy了frustum/src/lib/datasets/dataset/kitti.py
):
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import pycocotools.coco as coco
from pycocotools.cocoeval import COCOeval
import numpy as np
import json
import os
import torch.utils.data as data
class kitti2coco(data.Dataset):
num_classes = 3
default_resolution = [384, 1280]
mean = np.array([0.651932, 0.686103, 0.666008], np.float32).reshape(1, 1, 3)
std = np.array([0.565150, 0.582811, 0.580653], np.float32).reshape(1, 1, 3)
def __init__(self, opt, split):
super(kitti2coco, self).__init__()
self.data_dir = os.path.join(opt.data_dir, 'kitti')
self.img_dir = os.path.join(self.data_dir, 'training', 'image_2')
if split == 'val':
self.annot_path = os.path.join(
self.data_dir, 'annotations', 'kitti_frustum_{}.json').format(split)
else:
if opt.task == 'exdet':
self.annot_path = os.path.join(
self.data_dir, 'annotations', 'kitti_frustum_{}.json').format(split)
else:
self.annot_path = os.path.join(
self.data_dir, 'annotations', 'kitti_frustum_{}.json').format(split)
self.max_objs = 50
self.class_name = ['__background__', 'Pedestrian', 'Car', 'Cyclist']
self._valid_ids = [1, 2, 3, 4, 5, 6, 7, 8, 9]
self.cat_ids = {v: i for i, v in enumerate(self._valid_ids)}
self.voc_color = [(v // 32 * 64 + 64, (v // 8) % 4 * 64, v % 8 * 32) \
for v in range(1, self.num_classes + 1)]
self._data_rng = np.random.RandomState(123)
self._eig_val = np.array([0.2141788, 0.01817699, 0.00341571],
dtype=np.float32)
self._eig_vec = np.array([
[-0.58752847, -0.69563484, 0.41340352],
[-0.5832747, 0.00994535, -0.81221408],
[-0.56089297, 0.71832671, 0.41158938]
], dtype=np.float32)
# self.mean = np.array([0.485, 0.456, 0.406], np.float32).reshape(1, 1, 3)
# self.std = np.array([0.229, 0.224, 0.225], np.float32).reshape(1, 1, 3)
self.split = split
self.opt = opt
print('==> initializing kitti_trainval {} data.'.format(split))
self.coco = coco.COCO(self.annot_path)
self.images = self.coco.getImgIds()
self.num_samples = len(self.images)
print('Loaded {} {} samples'.format(split, self.num_samples))
def _to_float(self, x):
return float("{:.2f}".format(x))
def convert_eval_format(self, all_bboxes):
# import pdb; pdb.set_trace()
detections = []
for image_id in all_bboxes:
for cls_ind in all_bboxes[image_id]:
category_id = self._valid_ids[cls_ind - 1]
for bbox in all_bboxes[image_id][cls_ind]:
bbox[2] -= bbox[0]
bbox[3] -= bbox[1]
score = bbox[4]
bbox_out = list(map(self._to_float, bbox[0:4]))
detection = {
"image_id": int(image_id),
"category_id": int(category_id),
"bbox": bbox_out,
"score": float("{:.2f}".format(score))
}
if len(bbox) > 5:
extreme_points = list(map(self._to_float, bbox[5:13]))
detection["extreme_points"] = extreme_points
detections.append(detection)
return detections
def __len__(self):
return self.num_samples
def save_results(self, results, save_dir):
json.dump(self.convert_eval_format(results),
open('{}/results.json'.format(save_dir), 'w'))
def run_eval(self, results, save_dir):
# result_json = os.path.join(save_dir, "results.json")
# detections = self.convert_eval_format(results)
# json.dump(detections, open(result_json, "w"))
self.save_results(results, save_dir)
coco_dets = self.coco.loadRes('{}/results.json'.format(save_dir))
coco_eval = COCOeval(self.coco, coco_dets, "bbox")
coco_eval.evaluate()
coco_eval.accumulate()
coco_eval.summarize()
- 打开
frustum/src/lib/datasets/dataset_factory.py
,在dataset_facto字典里加入自己的数据集名字(注意格式要求):
from .dataset.kitti2coco import KITTI2COCO
dataset_factory = {
'coco': COCO,
'pascal': PascalVOC,
'kitti': KITTI,
'coco_hp': COCOHP,
'kitti2coco': KITTI2COCO,
}
-
打开
frustum/src/lib/ops.py
,修改:
Line 15 ——self.parser.add_argument('--dataset', default='kitti2coco', help='coco | kitti | coco_hp | pascal | kitti2coco')
Line 338 ——'ctdet': {'default_resolution': [384, 1280], 'num_classes': 3, 'mean': [0.485, 0.456, 0.406], 'std': [0.229, 0.224, 0.225], 'dataset': 'kitti2coco'},
-
打开
frustum/src/lib/utils/debugger.py
:
在Line 47 的下一行添加:elif num_classes == 3 or dataset == 'kitti2coco': self.names = kitti2coco_class_name
在Line 460 添加:kitti2coco_class_name = ['Pedestrian', 'Car', 'Cyclist']
-
将语句
python src/main.py ctdet --exp_id kitti_dla_2x --batch_size 8 --lr 1.25e-4 --gpus 0 --load_model centernet_models/ctdet_coco_dla_2x.pth
保存在frustum/scripts/ctdet_kitti_dla_2x.sh