前言
CornerNet-lite系列模型分Cornernet,Cornernet-Saccade,Cornernet-Squeese三个网络,后2个网络是Cornernet的改进版本,虽然说现在Anchor-free系列的FCOS、centerNet网络性能优于Cornernet,但是学习前者的源码还是很有必要的,况且Conernet的代码风格很清新。
论文地址:https://arxiv.org/abs/1904.08900
代码:https://github.com/princeton-vl/CornerNet-Lite
项目架构
CornerNet-Lite-master
-----configs #数据集参数配置文件
cornernet-saccade.json
-----core
------------dbs #数据预处理,COCO,voc格式
------------external #对检测的box处理 ,nms
------------models # 模型架构定义,loss,返回模型得到的 Out
------------nnet #py_factory.py 模型启动器 ,类似于solver
------------sample # ground truth 数据图像encode,汇总成Target
------------test #测试
------------utils # 部分组件单元
-----data #需要手动创建,放voc 和coco数据集
-----demo.py
-----evaluate.py #测试
-----train.py
训练
项目训练没有太多注意的地方,参考ReadME即可,注意一点当只有一个GPU时,需要将config下的json文件参数: batch_size=chunk_sizes=X ,X不要太大就可以,一般选15。
configs参数解析:
以 cornernet-saccade.json为例:
{
"system": {
"dataset": "VOC", #数据集格式
"batch_size": 15, #batch
"sampling_function": "cornernet_saccade",
"train_split": "trainval" #划分数据集
"val_split": "minival",
"learning_rate": 0.00025, #学习率
"decay_rate": 10, #学习率衰减的参数, 为了迭代次数越多,将学习率降低
# 参考train.py learning_rate /= (decay_rate ** (start_iter // stepsize))
"val_iter": 100,
"opt_algo": "adam",
"prefetch_size": 5, #作者采用多线程训练 5个为一个线程队列
"max_iter": 500000,
"stepsize": 450000,
"snapshot": 5000,
"chunk_sizes": [15] #一块gpu处理的图像数
},
"db": {
"rand_scale_min": 0.5, #数据预处理的参数
"rand_scale_max": 1.1,
"rand_scale_step": 0.1,
"rand_scales": null,
"rand_full_crop": true,
"gaussian_bump": true,
"gaussian_iou": 0.5,
"min_scale": 16,
"view_sizes": [],
"height_mult": 31, #代码里没用到
"width_mult": 31,
"input_size": [255, 255], #输入图像统一后尺寸
"output_sizes": [[64, 64]], #输出特征图尺寸
"att_max_crops": 30,
"att_scales": [[1, 2, 4]],
"att_thresholds": [0.3],
"top_k": 12, #对检测出的box(或dets)选取top_k个
"num_dets": 12,
"categories": 1, #类别
"ae_threshold": 0.3,
"nms_threshold": 0.5,
"max_per_image": 100
}
}
core 文件:
dbs:
dbs下只给出了COCO数据集的训练格式, voc的训练格式博主放到了github:https://github.com/huangzicheng/CornerNet-Lite,COCO文件主要返回detections, eval_ids,detection包含物体的category和box, eval_ids 保存每张图像的id,这个不细读了,如何修改参考博主给出的voc版本就可以加深理解。
import os
import json
import numpy as np
from .detection import DETECTION
from ..paths import get_file_path
# COCO bounding boxes are 0-indexed
class COCO(DETECTION):
def __init__(self, db_config, split=None, sys_config=None):
assert split is None or sys_config is not None
super(COCO, self).__init__(db_config)
self._mean = np.array([0.40789654, 0.44719302, 0.47026115], dtype=np.float32)
self._std = np.array([0.28863828, 0.27408164, 0.27809835], dtype=np.float32)
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._coco_cls_ids = [
1,
2, 3, 4, 5, 6, 7,