one stage方法就是在特征图的每个位置上,使用不同尺度、长宽比密集采样生成anchor,直接进行分类和回归。主要优点是计算效率高,但检测精度稍差(主要是没有删除负样本的anchor,导致类别不均衡,RetinaNet采用focal loss),对小物体检测效果差(two stage中的roi polling对目标做resize,小目标的特征被放大,其轮廓也更为清晰,解决方法最简单的是增大输入尺寸,但会丧失速度快的优势,还可以采用FPN融合底层特征、空洞卷积增加感受野)
# 计算precision recall fp = np.cumsum(fp) tp = np.cumsum(tp) rec = tp / float(npos) # avoid divide by zero in case the first detection matches a difficult # ground truth prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
defvoc_ap(rec, prec, use_07_metric=False): """Compute VOC AP given precision and recall. If use_07_metric is true, uses the VOC 07 11-point method (default:False). """ if use_07_metric: # 使用07年方法 # 11 个点 ap = 0. for t in np.arange(0., 1.1, 0.1): if np.sum(rec >= t) == 0: p = 0 else: p = np.max(prec[rec >= t]) # 插值 ap = ap + p / 11. else: # 新方式,计算所有点 # correct AP calculation # first append sentinel values at the end mrec = np.concatenate(([0.], rec, [1.])) mpre = np.concatenate(([0.], prec, [0.]))
# compute the precision 曲线值(也用了插值) for i inrange(mpre.size - 1, 0, -1): mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
# to calculate area under PR curve, look for points # where X axis (recall) changes value i = np.where(mrec[1:] != mrec[:-1])[0]
# and sum (\Delta recall) * prec ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) return ap