PV-RCNN代码解读——数据初始化

PV-RCNN:papercode

(一)_prepare_data函数

_prepare_data函数的调用

# pcdet/datasets/kitti/kitti_object_eval_python/eval.py
# 准备数据
rets = _prepare_data(gt_annos, dt_annos, current_class, difficulty)
(gt_datas_list, dt_datas_list, ignored_gts, ignored_dets, dontcares, total_dc_num, total_num_valid_gt) = rets

_prepare_data函数的定义

# pcdet/datasets/kitti/kitti_object_eval_python/eval.py
# 准备数据
def _prepare_data(gt_annos, dt_annos, current_class, difficulty, extra_info=None):
	
	# 数据初始化
    gt_datas_list = []
    dt_datas_list = []
    total_dc_num = []
    ignored_gts, ignored_dets, dontcares = [], [], []
    total_num_valid_gt = 0

    gt_extra_info, dt_extra_info, general_extra_info = extra_info

    # 遍历每个图像
    for i in range(len(gt_annos)):
        if 'clean_data_function' not in general_extra_info.keys() or general_extra_info['clean_data_function'] == None:
            rets = clean_data(gt_annos[i], dt_annos[i], current_class, difficulty, \
                extra_info_single=(gt_extra_info[i], dt_extra_info[i], general_extra_info))
        else: #产生log日志
            rets = general_extra_info['clean_data_function'](
                gt_annos[i], dt_annos[i], current_class, difficulty, \
                extra_info_single=(gt_extra_info[i], dt_extra_info[i], general_extra_info)
            )

        num_valid_gt, ignored_gt, ignored_det, dc_bboxes = rets
        ignored_gts.append(np.array(ignored_gt, dtype=np.int64))
        ignored_dets.append(np.array(ignored_det, dtype=np.int64))
        #! 最终形成ignored_gts的List

        if len(dc_bboxes) == 0:
            dc_bboxes = np.zeros((0, 4)).astype(np.float64) 
            #! dc_boxes 是一个np array,形状(该图像中的don't care boxes 数量, 4)
        else:
            dc_bboxes = np.stack(dc_bboxes, 0).astype(np.float64) 
            #! 每一列是一个Don't Care bbox
        
        total_dc_num.append(dc_bboxes.shape[0])
        #! don't care boxes的数量. total_dc_num是该图像dc_boxes数量的list,每个图像对应一个total_dc_num
        dontcares.append(dc_bboxes)
        #! 该图像的dc_boxes list的list

        total_num_valid_gt += num_valid_gt
        #! 有效 gt boxes 总数的计数器

        gt_datas = np.concatenate(
            [gt_annos[i]["bbox"], #! bbox index 形状是 N x 4
             gt_annos[i]["alpha"]#! alpha index 形状是 N -> 当np.newaxis, 是 N x 1
             [..., np.newaxis]], 1)
         #! 所以合并后成为 N x 5 ,5表示 [x1, y1, x2, y2, alpha]

        dt_datas = np.concatenate([
            dt_annos[i]["bbox"], dt_annos[i]["alpha"][..., np.newaxis],
            dt_annos[i]["score"][..., np.newaxis]
        ], 1)
        #! 类似的, 形状为N x 6, 6是 [x1, y1, x2, y2, alpha, score]

        gt_datas_list.append(gt_datas)
        dt_datas_list.append(dt_datas)
        # boxes list 的 list
        # gt_datas只和gt_annos[i]有关,dt_datas只和dt_annos[i]有关
        # 因此每个图像对应一个gt_datas_list和dt_datas_list
        
    total_dc_num = np.stack(total_dc_num, axis=0)
 '''
此处的所有数组的长度 = 数据集中的图像数量
gt_datas_list:list(N x 5个数组)
dt_datas_list:list(N x 6个数组)
ignore_gts:list(长度为N的数组(值-1、0或1))
ignore_dets :list(长度为N的数组(值-1、0或1))
dontcares:list((图像x 4个数组中的无关框数量)
total_dc_num:list(图像值中的无关框数量)
total_num_valid_gt:有效gt的总数(int)
'''
    return (gt_datas_list, dt_datas_list, ignored_gts, ignored_dets, dontcares,
            total_dc_num, total_num_valid_gt)
(二)clean_data函数

clean_data函数的调用

# pcdet/datasets/kitti/kitti_object_eval_python/eval.py
    # 遍历每个图像
    for i in range(len(gt_annos)):
        if 'clean_data_function' not in general_extra_info.keys() or general_extra_info['clean_data_function'] == None:
            rets = clean_data(gt_annos[i], dt_annos[i], current_class, difficulty, \
                extra_info_single=(gt_extra_info[i], dt_extra_info[i], general_extra_info))
        else: #产生log日志
            rets = general_extra_info['clean_data_function'](
                gt_annos[i], dt_annos[i], current_class, difficulty, \
                extra_info_single=(gt_extra_info[i], dt_extra_info[i], general_extra_info)
            )

clean_data函数的定义

def clean_data(gt_anno, dt_anno, current_class, difficulty):
    CLASS_NAMES = ['car', 'pedestrian', 'cyclist', 'van', 'person_sitting', 'truck'] #类别
    # difficultys = [0, 1, 2] 
    #检测难度从易到难,为了检测到同样数目的gt,使最小值减小,最大值增大
    MIN_HEIGHT = [40, 25, 25] #高度
    MAX_OCCLUSION = [0, 1, 2] #遮挡
    MAX_TRUNCATION = [0.15, 0.3, 0.5] #截断
    dc_bboxes, ignored_gt, ignored_dt = [], [], []
    current_cls_name = CLASS_NAMES[current_class].lower()
    num_gt = len(gt_anno["name"]) #gt数量
    num_dt = len(dt_anno["name"]) #dt数量
    num_valid_gt = 0
    for i in range(num_gt): #遍历所有的gt框
        bbox = gt_anno["bbox"][i]
        gt_name = gt_anno["name"][i].lower() #lower()函数是返回str所有小写字母
        height = bbox[3] - bbox[1] #高度
        valid_class = -1
        if (gt_name == current_cls_name): #gt_name为当前检验的类别名称时为有效类别
            valid_class = 1
        elif (current_cls_name == "Pedestrian".lower()
              and "Pedestrian".lower() == gt_name):# Pedestrian和Pedestrian的有效值为0
            valid_class = 0
        elif (current_cls_name == "Car".lower() and "Van".lower() == gt_name): # Car和Van的有效值为0
            valid_class = 0
        else:
            valid_class = -1
        ignore = False
        if ((gt_anno["occluded"][i] > MAX_OCCLUSION[difficulty]) #如果遮挡得太厉害
                or (gt_anno["truncated"][i] > MAX_TRUNCATION[difficulty]) #如果截断得太厉害
                or (height <= MIN_HEIGHT[difficulty])): #如果太小了
            ignore = True #就忽略
        if valid_class == 1 and not ignore:
            ignored_gt.append(0) #0表示有效
            num_valid_gt += 1 #有效框数量+1
        elif (valid_class == 0 or (ignore and (valid_class == 1))):
            ignored_gt.append(1) # 1表示忽略
        else:
            ignored_gt.append(-1) # -1表示其他
        if gt_anno["name"][i] == "DontCare":
            dc_bboxes.append(gt_anno["bbox"][i])
    for i in range(num_dt):
        if (dt_anno["name"][i].lower() == current_cls_name): #如果dt的类别名称等于当前检验的类别名称
            valid_class = 1 #有效值为1
        else:
            valid_class = -1
        height = abs(dt_anno["bbox"][i, 3] - dt_anno["bbox"][i, 1]) #计算高度
        if height < MIN_HEIGHT[difficulty]: #如果高度太低
            ignored_dt.append(1) #忽略
        elif valid_class == 1:
            ignored_dt.append(0) #有效
        else:
            ignored_dt.append(-1) #其他

    return num_valid_gt, ignored_gt, ignored_dt, dc_bboxes

致谢:detection-toolbox的作者将代码中的注释写的太清晰了,对我理解代码起到了很大帮助。有需要的读者可以看英文原版

我的其他PV-RCNN代码解读系列文章,如果对你有帮助的话,请给我点赞哦~
PV-RCNN代码解读——输入参数介绍
PV-RCNN代码解读——TP,FP,TN,FN的计算
PV-RCNN代码解读——eval.py
PV-RCNN代码解读——计算iou
PV-RCNN代码解读——数据初始化
PV-RCNN代码解读——从点云到输入神经网络的数据处理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值