目标检测之RCNN
1. RCNN:Regions with CNN features[2014 Ross]
- 图片输入
- 区域建议(region proposal)
- 特征提取(feature extraction)
- 分类+2次定位(classification(SVM) + detection(线性模型Linear 正则化项))
2. 区域建议
- 算法:selective search前景分割,将纹理、形状、颜色相似的合在一起,目前比较少人用,数学公式复杂,难用,效果还不太好,不建议看
- 大概2K多个候选框,包括很多感兴趣尽可能囊括到候选框,粗筛
- 2k个候选框的图片,每个做resize到固定大小,固定大小里有无物体,进入分类网络判断
3. 特征提取
- a.在数据集ILSVRC2012 dataset上预训练好的分类网络(AlexNet)直接拿来用,将大约2k个图片一个个送到分类网络(backbone),只拿了特征提取层,扔掉了最后的1*1000的分类层。
- b.在真实数据集上finetune微调,主要更新后两层全连接dense层
- c.训练样本正样本和负样本比例为1:3
- c.IOU小于0.5,给定比较宽松的限制条件,对应较为复杂的网络,样本才不会显得过于少
- 提取CNN特征前必须resize到统一大小,因为后面有FC层,参数是固定的
- 问题:resize后改变了图片本身信息——长方形的旗杆resize压缩成成正方形后,他还是旗杆吗?这个仍然需要改善
4. SVM分类器分类 + NMS算法筛选 + 边界框回归(BBox Regression)
4.1. SVM分类(少样本模型)
- 给每个样本做分类
- 正样本:Groud True
- 负样本:IOU < 0.3[others ignored]
- Q:和AlexNet网络训练相比,svm分类时IOU的阈值threshould为什么不一样?A:训练CNN需要更多数据样本,更多数据样本不一定质量高,svm分类时需要质量高数据样本
- Q:为什么用SVM,为什么不直接用AlexNet最后的softmax?A:AlexNet专注于分类, 不好用少数样本来做定位。数据多,质量差;数据少,质量高,数据少时用SVM相对好一些
4.2. NMS(Non-Maximum Suppression)非极大值抑制算法(很重要)
NMS广泛应用于目标检测算法中。其目的是为了消除多余的候选框,找到最佳的物体检测位置。
- 每个类别置信程度score越高,越能说明物体在框里面
- 取score值最高的一个框,将其他的框和他的iou越大,越可能是同一个物体,所以去掉其他和该框iou高于某一阀值候选框
- 代码实现
import numpy as np
def NMS(lists, thre):
if len(lists) == 0:
return {}
lists = np.array(lists)
res = []
#取得第i列,第0列为x1,第1列为y1...
x1, y1, x2, y2, score = [lists[:, i] for i in range(5)]
area = (x2 - x1 + 1) * (y2 - y1 + 1)
# get sorted index in ascending order
idxs = np.argsort(score)
while len(idxs) > 0:
last = len(idxs) - 1
i = idxs[last]
res.append(i)
xmin = np.maximum(x1[i], x1[idxs[:last]])
ymin = np.maximum(y1[i], y1[idxs[:last]])
xmax = np.minimum(x2[i], x2[idxs[:last]])
ymax = np.minimum(y2[i], y2[idxs[:last]])
w = xmax - xmin + 1
h = ymax - ymin + 1
inner_area = w * h
# 其他所有边界框bbox和得分score最高的bbox做iou计算
iou = inner_area / (area[i] + area[idxs[:last]] - inner_area)
# 去除iou计算阈值大于指定值的bbox
idxs = np.delete(idxs,
np.concatenate(([last],
np.where(iou > thre)[0])))
# here "where" will return us a tuple idxs==>[0 3]
# [0] means to extract array from a tuple
return lists[res]
if __name__ == '__main__':
boxes = np.array([[1, 2, 3, 4], [1, 3, 3, 4], [1, 3, 4, 4], [1, 1, 4, 4], [1, 1, 4, 4]], dtype=np.float32)
scores = np.array([0.4, 0.5, 0.72, 0.90, 45], dtype=np.float32)
thre = 0.5
scores1 = scores[:, np.newaxis]
lists = np.hstack((boxes, scores1))
result_boxes_scores = NMS(lists, thre)
print(result_boxes_scores)
- 问题:
- 当图片中物体比较密集的情况下,会出现新的问题
- 下图中,两个不一样的对象,在NMS算法中可能就输出一个对象,哪个score高输出哪个,去掉另外一个;很显然,和我们两个对象都要保存输出的真实结果是违背的
4.3. NMS发展历史/种类
1.Soft-NMS[2017]
- B表示原始没有经过过滤的BBox边界框,S表示每个边界框的分数score,Nt表示NMS的阈值
- 设置一个空集D={}表示我们要用NMS筛选后输出的检测框
- 取分数S最高的对应的边界框M,加入到集合D中,同时B集合中把边界框M去除(循环)
- NMS:做一个遍历,所有B中的边界框和M做IOU计算,当计算结果大于某一阈值时,把B集合中对应的边界框B和分数S都删除
- 其数学语言可以表达为:
- 如上图,相比于下图的Soft-NMS,NMS硬的地方体现在阈值高于某设定值时,score值简单粗暴地设置为0
- 其数学语言可以表达为:
-
IoU-Net[2018]
-
soft-NMS[2019]
-
NMS总结
- 算法复杂,用cpu计算,不能用gpu加速,影响运行速度
- 阈值的确认依赖经验,较难确认
- soft-NMS不需要设定IOU阈值,训练时不用,测试时用提升较为明显
4.4. Bbox Regression(Bbox回归)
- 回归的目标,偏移量(dx,dy,dw,dh)
- 坐标需要归一化
5. RCNN总结
- 慢:做了2k个区域建议,resize到固定尺寸,将固定尺寸的图输入到CNN网络中,在做分类和位置回归,每个区域建议的图都要做卷积
- SVM和回归方法不太合适,SVM和CNN混合较为奇怪,训练较为复杂,过程较为臃肿