1. 物体检测概念
计算机视觉中的物体检测是指在图像中检测和定位特定目标对象,它是计算机视觉中一个基本而又重要的问题。
物体检测的目的就是在输入图像中检测所关心的目标对象,并给出其边界框和类别信息。典型的输出包括:
- 边界框:表示目标对象在图像中的位置和大小。常用的边界框有四点坐标形式(左上、右上、右下、左下)和中心宽高形式(中心点坐标、宽度、高度)。
- 类别信息:表示检测到的目标对象的类别,比如人、车、猫、椅子等。
- 置信度:表示检测结果的可信度,一般为0-1之间的数值。
物体检测在许多领域都有重要应用,比如:
- 自动驾驶:检测车辆、行人、交通灯等
- 视频监控:检测异常物体和可疑人员
- 图像搜索:根据检测到的物体进行图像索引和搜索
- 机器人视觉:导航和操控时对环境中物体进行检测
2. 物体检测方法
计算机视觉中的物体检测通常分为基于图像分类和基于置信度预测两种方法。
2.1. 基于图像分类的检测
先利用图像分类模型判断输入图像中是否包含某个物体,如果包含则进一步定位物体位置。典型的方法有RCNN系列,比如Fast RCNN, Faster RCNN等。这类方法先利用选取的区域提议(Region Proposals)生成可能包含物体的区域,然后利用CNN来分类这些区域并修正边界框。
2.1.1 图像分类方法步骤
基于图像分类的物体检测方法主要分为两步:
第一步、生成区域提议(Region Proposals)
首先在输入图像中提出可能包含物体的区域候选框,这一步通常使用一些ati区域提议方法完成,如Selective Search、Edge Boxes等。这些方法会生成上百至上千个候选框。
第二步、区域分类和边界框回归
然后利用CNN对每个候选框进行分类判断是否包含物体以及类别,同时也进行边界框的修正。
这类方法的代表工作有RCNN系列,包括:
- RCNN
将每个候选框调整到统一大小,输入CNN进行分类和边框回归。但是重複计算量太大。
- Fast RCNN
利用RoI Pooling层在特征图上进行区域整合,然后进入全连接层分类和回归,减少计算量。
- Faster RCNN
在Fast RCNN的基础上,使用RPN网络生成候选框,进一步减少计算量。这是基于分类的检测方法的经典工作。
具体的网络结构包括:
- 特征提取网络
通常使用预训练的CNN模型(如VGG16、ResNet等)来提取输入图像的特征图。
- RPN网络
对特征图使用小的卷积网络生成多个矩形候选框,并计算每个框属于前景或背景的概率。
- RoI Pooling层
将每个候选框在特征图上进行max pooling,得到固定大小的特征表示。
- 两系列全连接层
一系列用于分类每个候选框属于各个类别的概率;另一系列用于回归生成更精确的候选框坐标。
- 非极大值抑制
移除大量重叠的候选框,只保留类别概率最大的框。
这个方法通过一步步的优化,大大减少了RCNN中冗余的计算,使得物体检测变得非常高效。Faster RCNN至今仍是基于分类的检测方法的最佳基线,也是实际工业应用中最广泛的方法之一。
2.1.2. 图像分类检测示例
这里给出一个基于TensorFlow实现的Faster RCNN的代码示例。
python
# 输入图像
image = tf.read_file(...)
image = tf.image.decode_image(image)
# 特征提取
feature_extractor = ResNet101(...)
feature_maps = feature_extractor(image)
# RPN生成候选框
rpn = ...
anchors = rpn.generate_anchors()
proposal_boxes, proposal_scores = rpn.propose(feature_maps)
# RoI Pooling
roi_pooling = RoiPoolingLayer(7, 7)
pooled_feature_maps = roi_pooling(feature_maps, proposal_boxes)
# 分类和回归分支
classification = FullyConnected(n_classes)
class_predictions = classification(pooled_feature_maps)
regression = FullyConnected(4 * n_classes)
reg_predictions = regression(pooled_feature_maps)
# 非极大值抑制
selected_indices = NonMaximumSuppressionLayer(iou_threshold=0.5)([proposal_boxes, proposal_scores])
proposal_boxes = tf.gather(proposal_boxes, selected_indices)
class_predictions = tf.gather(class_predictions, selected_indices)
reg_predictions = tf.gather(reg_predictions, selected_indices)
# 最终检测框
detection_boxes = DecodeBoundingBoxesLayer()([proposal_boxes, reg_predictions])
- 输入图像和特征提取:使用ResNet-101提取特征图feature_maps,包含目标信息。
- RPN生成候选框:在feature_maps上生成9个anchor,计算类别概率和偏移量得到proposal_boxes和proposal_scores,使用NMS获得选定的候选框。
- RoI Pooling:选定的候选框在feature_maps进行max pooling,获得pooled_feature_maps。
- 分类和回归分支:pooled_feature_maps输入全连接,分别输出类别概率class_predictions和框坐标reg_predictions。
- 非极大值抑制:基于proposal_scores选择更优的候选框。
- 最终检测框:根据reg_predictions对proposal_boxes进行解码微调,获得精确的detection_boxes。
2.2. 基于置信度预测的检测
物体检测的输出通常不仅包含边界框和类别信息,还会给出一个置信度(confidence score)表示预测结果的可信度。它直接预测输入图像中每个像素属于某个物体类别的概率(称为类别置信度),以及属于某个边界框的概率(称为框置信度)。然后通过类别置信度图和框置信度来生成检测结果。典型的方法有YOLO,SSD等。这类方法可以一步到位地完成检测而不需要区域提议的过程。
2.2.1 基于分类的预测方法步骤
对于基于分类的检测方法如Faster RCNN,其置信度预测过程如下:
1. RPN网络生成候选框时,会同时给出每个框属于前景或背景的概率,这可以看作是初步的置信度预测。
2. RoI Pooling层将每个候选框表示成固定大小的特征,输入到类别分类分支。
3. 分类分支会输出每个候选框属于各个类别的概率,其中包含背景类别。
4. 通常会认为类别概率最大且不属于背景类别的那个类别,就是预测框的类别。同时,其类别概率可以作为预测框的置信度。
5. 非极大值抑制会基于每个预测框的置信度选择更优的框,剔除置信度较低的冗余框。
6. 最终保留下来的预测框及其对应的置信度,就是网络的预测结果。
以Faster RCNN为例,其置信度预测主要来源于RPN和分类分支的概率预测。RPN初步给出前景/背景预测,分类分支进一步输出各类别的精细预测,其中最有可能的类别对应的概率即为置信度。
2.2.2 基于回归的预测方法步骤
对于基于回归的检测方法如YOLO和SSD,其置信度预测过程稍有不同:
1. 直接在特征图上定义锚框或默认框,不需要RPN生成区域提议。
2. 通过堆叠多个卷积层提取特征,然后对每个锚框/默认框执行类别预测和边界框回归。
3. 在类别预测中同样会输出各个类别的概率,最有可能的类别对应的概率作为置信度。
4. 根据置信度和iou进行非极大值抑制,选择最终的预测框。
不管是基于分类的检测方法还是基于回归的检测方法,其置信度预测的核心都来自于对各类别概率的预测,选择最匹配的类别并使用其概率作为置信度。这一过程为最终的预测结果赋予了可信度,也为后续处理算法提供了判断依据。
2.2.3. 示例
这里给出一个基于TensorFlow实现的Faster RCNN的置信度预测代码示例。
python
# RPN生成候选框
anchors = rpn.generate_anchors()
proposal_scores = rpn.propose_scores(feature_maps) # 前景/背景概率
# 非极大值抑制选择高置信度的候选框
selected_indices = NonMaximumSuppressionLayer(iou_threshold=0.5)
([proposal_boxes, proposal_scores])
proposal_boxes = tf.gather(proposal_boxes, selected_indices)
# 分类分支输出类别概率
classification = FullyConnected(n_classes)
class_predictions = classification(pooled_feature_maps)
# 选择概率最大的类别
category = tf.argmax(class_predictions, axis=1)
# 取该类别对应的概率作为置信度
confidence = tf.gather(class_predictions, category)
# 使用置信度进行再次非极大值抑制
selected_boxes = NonMaximumSuppressionLayer(iou_threshold=0.5)
([detection_boxes, confidence])
final_boxes = tf.gather(detection_boxes, selected_boxes)
final_confidence = tf.gather(confidence, selected_boxes)
- RPN生成候选框proposal_boxes,并预测每个框属于前景或背景的proposal_scores,proposal_scores为初步置信度。
- 使用proposal_scores进行非极大值抑制,选择高置信度的候选框。
- 分类分支对每个候选框预测其属于各个类别的概率class_predictions。
- 选择class_predictions中概率最大的类别作为预测类别category。
- 取该category对应的概率值作为置信度confidence。
- 使用confidence再次进行非极大值抑制,选择高置信度的最终预测框final_boxes。
- 最终输出结果为final_boxes和对应的置信度final_confidence。
可以看出,Faster RCNN的置信度预测来源于:
1. RPN初步判断每个anchor属于前景或背景的概率prediction_scores。
2. 分类分支输出每个候选框属于各类别的概率class_predictions。
3. 选择class_predictions中概率最大的类别作为预测类别,其概率作为置信度confidence。
4. 使用confidence过滤掉低置信度的框,获得高置信度的最终预测结果。
该过程赋予了最终的预测结果一定的可信度,为模型输出的预测框判定准确性提供了依据。希望通过这个代码示例,可以进一步理解Faster RCNN是如何进行置信度预测的。如果您有任何疑问,欢迎提出,我将进行详细解释。
2.3. 总结
无论是哪一类方法,目标检测的评价主要指标都包含准确率、召回率和mAP。
1. 准确率(Precision)
检测结果中真正的物体框占全部检测框的比例。
2. 召回率(Recall)
检测结果中真正的物体框占全部物体的比例。
3. mAP(mean Average Precision)
在不同召回率条件下的平均准确率。是综合考量准确率和召回率最重要的指标。
物体检测是一个视觉任务中比较基础但也比较困难的问题,是许多高级视觉任务如行为识别,场景解析的基础。随着深度学习的发展,物体检测的精度也在快速提高。但对小物体,部分遮挡场景的检测依旧面临很大困难。