R-CNN到Faster R-CNN:两阶段检测的演进之路
引言
在深度学习目标检测的发展历程中,R-CNN系列占据着举足轻重的地位。从2014年的R-CNN到2016年的Faster R-CNN,短短两年间,目标检测领域发生了翻天覆地的变化。
为什么需要了解R-CNN系列?
虽然YOLO系列后来居上,但R-CNN系列的两阶段检测思想至今仍有重要价值:
- ✅ 精度优势:两阶段检测在精度上仍有优势
- ✅ 理论基础:为理解目标检测提供重要理论基础
- ✅ 技术演进:展示了深度学习在目标检测中的演进过程
- ✅ YOLO铺垫:理解R-CNN的局限性,才能更好理解YOLO的革命性
本系列学习路径:
R-CNN系列(两阶段) → YOLO v1(一阶段革命) → YOLO进化 → 现代YOLO
目标检测基础回顾
什么是目标检测?
目标检测 = 目标定位 + 目标分类
输入:图像
输出:每个目标的边界框 + 类别标签
示例:
图像中有:人、汽车、狗
输出:
- 人:边界框(x1,y1,x2,y2) + 类别"person"
- 汽车:边界框(x1,y1,x2,y2) + 类别"car"
- 狗:边界框(x1,y1,x2,y2) + 类别"dog"
传统方法 vs 深度学习方法
传统方法(2014年前)
步骤1:特征提取
- HOG(方向梯度直方图)
- SIFT(尺度不变特征变换)
- LBP(局部二值模式)
步骤2:分类器
- SVM(支持向量机)
- AdaBoost
- 随机森林
问题:
✗ 特征表达能力有限
✗ 手工设计特征
✗ 精度不高
✗ 速度慢
深度学习方法(2014年后)
步骤1:CNN特征提取
- 自动学习特征
- 端到端训练
- 强大表达能力
步骤2:检测头
- 分类 + 回归
- 端到端优化
优势:
✅ 特征自动学习
✅ 端到端训练
✅ 精度大幅提升
✅ 可扩展性强
R-CNN:CNN特征提取的开创
核心思想
R-CNN = Region-based CNN
传统思路:
图像 → 特征提取 → 分类
R-CNN思路:
图像 → 候选区域 → CNN特征提取 → 分类
关键创新:
- Region Proposals:使用Selective Search生成候选区域
- CNN特征:用CNN替代手工特征
- 分类器:SVM分类器 + 边界框回归
R-CNN架构详解
Region Proposal生成
Selective Search算法:
def selective_search(image, scale=1.0, sigma=0.8, min_size=50):
"""
Selective Search算法生成候选区域
Args:
image: 输入图像
scale: 图像缩放因子
sigma: 高斯模糊参数
min_size: 最小区域大小
Returns:
regions: 候选区域列表 [(x, y, w, h), ...]
"""
import cv2
from skimage import segmentation, color
# 1. 图像预处理
img_lbl, regions = segmentation.slic(
image, compactness=30, n_segments=100, sigma=sigma
)
# 2. 计算区域特征
img_color = color.rgb2lab(image)
# 3. 层次聚类
regions = []
for region in img_lbl:
# 计算区域边界框
y, x = np.where(img_lbl == region)
if len(x) > min_size:
regions.append((x.min(), y.min(), x.max()-x.min(), y.max()-y.min()))
return regions
# 示例使用
image = cv2.imread('image.jpg')
regions = selective_search(image)
print(f"生成了 {len(regions)} 个候选区域")
Selective Search的优势:
- ✅ 多尺度检测
- ✅ 多样化区域形状
- ✅ 计算效率较高
- ✅ 召回率较高
CNN特征提取
AlexNet作为特征提取器:
import torch
import torch.nn as nn
import torchvision.models as models
class RCNNFeatureExtractor(nn.Module):
def __init__(self, num_classes=1000):
super(RCNNFeatureExtractor, self).__init__()
# 使用预训练的AlexNet
alexnet = models.alexnet(pretrained=True)
# 移除最后的分类层
self.features = alexnet.features
self.classifier = alexnet.classifier[:-1] # 移除最后一层
# 添加新的分类层
self.fc = nn.Linear(4096, num_classes)
def forward(self, x):
# 特征提取
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
# 使用示例
model = RCNNFeatureExtractor(num_classes=20) # VOC 20类
训练过程
R-CNN训练步骤:
def train_rcnn(model, regions, image, gt_boxes, gt_labels):
"""
R-CNN训练过程
Args:
model: CNN特征提取器
regions: 候选区域
image: 输入图像
gt_boxes: 真实边界框
gt_labels: 真实标签
"""
# 1. 为每个候选区域提取特征
features = []
labels = []
for region in regions:
# 裁剪区域
x, y, w, h = region
roi = image[y:y+h, x:x+w]
# 调整到固定尺寸 (227x227 for AlexNet)
roi_resized = cv2.resize(roi, (227, 227))
# 特征提取
with torch.no_grad():
feature = model(torch.tensor(roi_resized).unsqueeze(0))
features.append(feature)
# 标签分配(IoU > 0.5为正样本)
iou = calculate_iou(region, gt_boxes)
if iou.max() > 0.5:
labels.append(gt_labels[iou.argmax()])
else:
labels.append(0) # 背景类
return features, labels
def calculate_iou(box1, boxes2):
"""计算IoU"""
x1, y1, w1, h1 = box1
x2, y2, w2, h2 = boxes2[:, 0], boxes2[:, 1], boxes2[:, 2], boxes2[:, 3]
# 计算交集
x_left = np.maximum(x1, x2)
y_top = np.maximum(y1, y2)
x_right = np.minimum(x1 + w1, x2 + w2)
y_bottom = np.minimum(y1 + h1, y2 + h2)
intersection = np.maximum(0, x_right - x_left) * np.maximum(0, y_bottom - y_top)
# 计算并集
area1 = w1 * h1
area2 = w2 * h2
union = area1 + area2 - intersection
return intersection / union
边界框回归
Bounding Box Regression:
class BBoxRegressor(nn.Module):
def __init__(self, feature_dim=4096):
super(BBoxRegressor, self).__init__()
self.regressor = nn.Linear(feature_dim, 4) # 预测 (dx, dy, dw, dh)
def forward(self, features):
return self.regressor(features)
def encode_bbox(self, gt_bbox, anchor_bbox):
"""
编码边界框回归目标
Args:
gt_bbox: 真实边界框 (x, y, w, h)
anchor_bbox: 锚框 (x, y, w, h)
Returns:
targets: 回归目标 (dx, dy, dw, dh)
"""
gt_x, gt_y, gt_w, gt_h = gt_bbox
anchor_x, anchor_y, anchor_w, anchor_h = anchor_bbox
# 计算回归目标
dx = (gt_x - anchor_x) / anchor_w
dy = (gt_y - anchor_y) / anchor_h
dw = np.log(gt_w / anchor_w)
dh = np.log(gt_h / anchor_h)
return np.array([dx, dy, dw, dh])
def decode_bbox(self, predictions, anchor_bbox):
"""
解码边界框回归预测
Args:
predictions: 模型预测 (dx, dy, dw, dh)
anchor_bbox: 锚框 (x, y, w, h)
Returns:
bbox: 预测边界框 (x, y, w, h)
"""
dx, dy, dw, dh = predictions
anchor_x, anchor_y, anchor_w, anchor_h = anchor_bbox
# 解码预测
pred_x = dx * anchor_w + anchor_x
pred_y = dy * anchor_h + anchor_y
pred_w = anchor_w * np.exp(dw)
pred_h = anchor_h * np.exp(dh)
return np.array([pred_x, pred_y, pred_w, pred_h])
R-CNN的局限性
计算效率低
问题分析:
- 每个候选区域都要通过CNN
- 2000个候选区域 × CNN前向传播
- 大量重复计算
示例:
图像:500×500
候选区域:2000个
CNN:AlexNet (约1GFLOPs)
总计算量:2000 × 1GFLOPs = 2000GFLOPs
训练复杂
训练步骤:
1. 预训练CNN(ImageNet)
2. 微调CNN(VOC数据集)
3. 训练SVM分类器
4. 训练边界框回归器
问题:
- 多阶段训练
- 存储空间大
- 训练时间长
速度慢
推理时间:
- 特征提取:2000 × 0.5s = 1000s
- SVM分类:2000 × 0.01s = 20s
- 边界框回归:2000 × 0.01s = 20s
- 总计:约17分钟/图像
无法实时应用
[1]
Fast R-CNN:共享计算优化
核心创新
Fast R-CNN = 共享特征提取 + ROI Pooling
R-CNN问题:
图像 → 2000个候选区域 → 2000次CNN前向传播
Fast R-CNN解决方案:
图像 → 1次CNN前向传播 → ROI Pooling → 分类+回归
关键组件
ROI Pooling
ROI Pooling的作用:将不同尺寸的候选区域转换为固定尺寸的特征
import torch
import torch.nn as nn
import torch.nn.functional as F
class ROIPooling(nn.Module):
def __init__(self, output_size):
super(ROIPooling, self).__init__()
self.output_size = output_size
def forward(self, feature_map, rois):
"""
ROI Pooling前向传播
Args:
feature_map: 特征图 (B, C, H, W)
rois: 候选区域 (N, 5) [batch_idx, x1, y1, x2, y2]
Returns:
pooled_features: 池化后的特征 (N, C, output_h, output_w)
"""
batch_size, channels, height, width = feature_map.size()
num_rois = rois.size(0)
# 初始化输出
pooled_features = torch.zeros(num_rois, channels, self.output_size[0], self.output_size[1])
for i, roi in enumerate(rois):
batch_idx, x1, y1, x2, y2 = roi.int()
# 确保坐标在有效范围内
x1 = max(0, min(x1, width-1))
y1 = max(0, min(y1, height-1))
x2 = max(x1+1, min(x2, width))
y2 = max(y1+1, min(y2, height))
# 提取ROI特征
roi_feature = feature_map[batch_idx, :, y1:y2, x1:x2]
# 自适应池化到固定尺寸
pooled_roi = F.adaptive_avg_pool2d(roi_feature, self.output_size)
pooled_features[i] = pooled_roi
return pooled_features
# 使用示例
roi_pooling = ROIPooling(output_size=(7, 7))
feature_map = torch.randn(1, 256, 32, 32) # 特征图
rois = torch.tensor([[0, 10, 10, 20, 20], [0, 15, 15, 25, 25]]) # 候选区域
pooled_features = roi_pooling(feature_map, rois)
print(f"池化后特征尺寸: {pooled_features.shape}") # (2, 256, 7, 7)
端到端训练
Fast R-CNN网络架构:
class FastRCNN(nn.Module):
def __init__(self, num_classes=21):
super(FastRCNN, self).__init__()
# 特征提取网络(VGG16)
self.features = nn.Sequential(
# VGG16的卷积层
nn.Conv2d(3, 64, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, 3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2),
nn.Conv2d(64, 128, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, 3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2),
# ... 更多卷积层
)
# ROI Pooling
self.roi_pooling = ROIPooling(output_size=(7, 7))
# 分类头
self.classifier = nn.Sequential(
nn.Linear(256 * 7 * 7, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
)
# 分类分支
self.cls_score = nn.Linear(4096, num_classes)
# 回归分支
self.bbox_pred = nn.Linear(4096, num_classes * 4)
def forward(self, images, rois):
# 特征提取
feature_map = self.features(images)
# ROI Pooling
pooled_features = self.roi_pooling(feature_map, rois)
# 展平
pooled_features = pooled_features.view(pooled_features.size(0), -1)
# 分类器
features = self.classifier(pooled_features)
# 分类和回归
cls_scores = self.cls_score(features)
bbox_preds = self.bbox_pred(features)
return cls_scores, bbox_preds
多任务损失函数
Fast R-CNN损失函数:
class FastRCNNLoss(nn.Module):
def __init__(self, num_classes=21):
super(FastRCNNLoss, self).__init__()
self.num_classes = num_classes
self.cls_criterion = nn.CrossEntropyLoss()
self.bbox_criterion = nn.SmoothL1Loss()
def forward(self, cls_scores, bbox_preds, labels, bbox_targets):
"""
计算Fast R-CNN损失
Args:
cls_scores: 分类预测 (N, num_classes)
bbox_preds: 回归预测 (N, num_classes * 4)
labels: 真实标签 (N,)
bbox_targets: 回归目标 (N, 4)
"""
# 分类损失
cls_loss = self.cls_criterion(cls_scores, labels)
# 回归损失(仅对正样本计算)
pos_mask = labels > 0
if pos_mask.sum() > 0:
pos_bbox_preds = bbox_preds[pos_mask]
pos_bbox_targets = bbox_targets[pos_mask]
bbox_loss = self.bbox_criterion(pos_bbox_preds, pos_bbox_targets)
else:
bbox_loss = 0
# 总损失
total_loss = cls_loss + bbox_loss
return total_loss, cls_loss, bbox_loss
Fast R-CNN的优势
速度提升
计算对比:
R-CNN:
- 2000个候选区域 × CNN前向传播
- 总计算量:2000 × 1GFLOPs = 2000GFLOPs
Fast R-CNN:
- 1次CNN前向传播 + ROI Pooling
- 总计算量:1GFLOPs + ROI Pooling
- 加速比:约10-20倍
[2]
端到端训练
训练流程:
1. 预训练CNN(ImageNet)
2. 端到端微调(VOC数据集)
优势:
- 简化训练流程
- 更好的特征学习
- 端到端优化
精度提升
VOC 2007数据集结果:
- R-CNN: mAP = 58.5%
- Fast R-CNN: mAP = 66.9%
- 提升:+8.4%
[1][2]
Faster R-CNN:端到端检测
核心创新
Faster R-CNN = RPN + Fast R-CNN
Fast R-CNN问题:
图像 → Selective Search → 候选区域 → Fast R-CNN
Faster R-CNN解决方案:
图像 → RPN → 候选区域 → Fast R-CNN
关键组件
Region Proposal Network (RPN)
RPN的作用:用CNN替代Selective Search生成候选区域
class RPN(nn.Module):
def __init__(self, in_channels=256, num_anchors=9):
super(RPN, self).__init__()
self.num_anchors = num_anchors
# 共享卷积层
self.conv = nn.Conv2d(in_channels, 512, 3, padding=1)
self.relu = nn.ReLU(inplace=True)
# 分类头(前景/背景)
self.cls_head = nn.Conv2d(512, num_anchors * 2, 1)
# 回归头(边界框回归)
self.bbox_head = nn.Conv2d(512, num_anchors * 4, 1)
def forward(self, features):
"""
RPN前向传播
Args:
features: 特征图 (B, C, H, W)
Returns:
cls_scores: 分类分数 (B, num_anchors*2, H, W)
bbox_preds: 回归预测 (B, num_anchors*4, H, W)
"""
# 共享卷积
x = self.relu(self.conv(features))
# 分类和回归
cls_scores = self.cls_head(x)
bbox_preds = self.bbox_head(x)
return cls_scores, bbox_preds
Anchor机制
Anchor的作用:为每个位置预设多个尺度和宽高比的候选框
def generate_anchors(base_size=16, ratios=[0.5, 1, 2], scales=[8, 16, 32]):
"""
生成Anchor
Args:
base_size: 基础尺寸
ratios: 宽高比
scales: 尺度
Returns:
anchors: Anchor坐标 (num_anchors, 4)
"""
anchors = []
for scale in scales:
for ratio in ratios:
# 计算宽高
w = base_size * scale * np.sqrt(ratio)
h = base_size * scale / np.sqrt(ratio)
# 中心点坐标(以(0,0)为中心)
x1 = -w / 2
y1 = -h / 2
x2 = w / 2
y2 = h / 2
anchors.append([x1, y1, x2, y2])
return np.array(anchors)
# 使用示例
anchors = generate_anchors()
print(f"生成了 {len(anchors)} 个Anchor")
print(f"Anchor形状: {anchors.shape}") # (9, 4)
完整Faster R-CNN架构
class FasterRCNN(nn.Module):
def __init__(self, num_classes=21):
super(FasterRCNN, self).__init__()
# 共享特征提取网络
self.features = self._build_feature_extractor()
# RPN
self.rpn = RPN(in_channels=256, num_anchors=9)
# Fast R-CNN
self.roi_pooling = ROIPooling(output_size=(7, 7))
self.classifier = self._build_classifier(num_classes)
def _build_feature_extractor(self):
"""构建特征提取网络"""
return nn.Sequential(
# VGG16的卷积层
nn.Conv2d(3, 64, 3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, 3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2),
# ... 更多卷积层
nn.Conv2d(256, 256, 3, padding=1),
nn.ReLU(inplace=True),
)
def _build_classifier(self, num_classes):
"""构建分类器"""
return nn.Sequential(
nn.Linear(256 * 7 * 7, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, num_classes),
)
def forward(self, images):
# 特征提取
features = self.features(images)
# RPN预测
rpn_cls, rpn_bbox = self.rpn(features)
# 生成候选区域
rois = self._generate_rois(rpn_cls, rpn_bbox)
# ROI Pooling
pooled_features = self.roi_pooling(features, rois)
# 分类
pooled_features = pooled_features.view(pooled_features.size(0), -1)
cls_scores = self.classifier(pooled_features)
return cls_scores, rois
训练策略
交替训练(Alternating Training):
def train_faster_rcnn(model, dataloader, num_epochs=10):
"""
Faster R-CNN训练
训练策略:
1. 训练RPN
2. 用RPN生成候选区域训练Fast R-CNN
3. 微调RPN
4. 微调Fast R-CNN
"""
# 阶段1:训练RPN
print("阶段1:训练RPN")
for epoch in range(num_epochs // 4):
for images, gt_boxes, gt_labels in dataloader:
# RPN损失
rpn_loss = compute_rpn_loss(model, images, gt_boxes)
# 反向传播
rpn_loss.backward()
optimizer.step()
# 阶段2:训练Fast R-CNN
print("阶段2:训练Fast R-CNN")
for epoch in range(num_epochs // 4):
for images, gt_boxes, gt_labels in dataloader:
# 用RPN生成候选区域
with torch.no_grad():
rois = model.generate_rois(images)
# Fast R-CNN损失
fast_rcnn_loss = compute_fast_rcnn_loss(model, images, rois, gt_boxes, gt_labels)
# 反向传播
fast_rcnn_loss.backward()
optimizer.step()
# 阶段3:微调RPN
print("阶段3:微调RPN")
for epoch in range(num_epochs // 4):
# ... 微调RPN
# 阶段4:微调Fast R-CNN
print("阶段4:微调Fast R-CNN")
for epoch in range(num_epochs // 4):
# ... 微调Fast R-CNN
def compute_rpn_loss(model, images, gt_boxes):
"""计算RPN损失"""
features = model.features(images)
rpn_cls, rpn_bbox = model.rpn(features)
# 计算RPN分类损失
cls_loss = F.cross_entropy(rpn_cls, rpn_labels)
# 计算RPN回归损失
bbox_loss = F.smooth_l1_loss(rpn_bbox, rpn_targets)
return cls_loss + bbox_loss
Faster R-CNN的优势
端到端训练
训练流程:
1. 预训练CNN(ImageNet)
2. 端到端训练(VOC数据集)
优势:
- 统一优化目标
- 更好的特征学习
- 简化训练流程
速度大幅提升
速度对比:
- R-CNN: 17分钟/图像
- Fast R-CNN: 2.3秒/图像
- Faster R-CNN: 0.2秒/图像
提升:85倍加速
[3]
精度保持
VOC 2007数据集结果:
- R-CNN: mAP = 58.5%
- Fast R-CNN: mAP = 66.9%
- Faster R-CNN: mAP = 70.0%
精度:持续提升
[1][2][3]
性能对比
速度对比
| 方法 | 推理时间 | 加速比 | 说明 |
|---|---|---|---|
| R-CNN | 17分钟 | 1× | 基准 |
| Fast R-CNN | 2.3秒 | 440× | 共享计算 |
| Faster R-CNN | 0.2秒 | 5100× | 端到端 |
精度对比
| 方法 | VOC 2007 mAP | VOC 2012 mAP | 说明 |
|---|---|---|---|
| R-CNN | 58.5% | 53.7% | 基准 |
| Fast R-CNN | 66.9% | 65.7% | +8.4% |
| Faster R-CNN | 70.0% | 68.4% | +11.5% |
训练时间对比
| 方法 | 训练时间 | 存储需求 | 说明 |
|---|---|---|---|
| R-CNN | 84小时 | 200GB | 多阶段训练 |
| Fast R-CNN | 9小时 | 2.5GB | 端到端训练 |
| Faster R-CNN | 12小时 | 2.8GB | 端到端训练 |
[1][2][3]
R-CNN系列的贡献与局限
✅ 主要贡献
开创性工作
R-CNN系列的开创性:
- 首次将CNN应用于目标检测
- 证明了深度学习在目标检测中的有效性
- 为后续工作奠定了基础
技术演进
技术演进路径:
R-CNN → Fast R-CNN → Faster R-CNN
↓ ↓ ↓
CNN特征 共享计算 端到端训练
精度优势
两阶段检测的优势:
- 精度高:mAP > 70%
- 稳定性好:训练稳定
- 可解释性强:分阶段处理
❌ 主要局限
速度限制
速度瓶颈:
- 两阶段处理:候选区域生成 + 检测
- 无法实时应用:> 0.1秒
- 计算复杂度高:O(N²)
架构复杂
架构复杂性:
- 多组件:RPN + Fast R-CNN
- 训练复杂:交替训练
- 调参困难:超参数多
小目标检测差
小目标检测问题:
- 特征分辨率低
- 候选区域质量差
- 检测精度低
为YOLO革命做铺垫
R-CNN系列的启示
精度与速度的权衡
R-CNN系列启示:
- 精度高但速度慢
- 两阶段检测的局限性
- 需要新的检测范式
端到端训练的重要性
端到端训练优势:
- 统一优化目标
- 更好的特征学习
- 简化训练流程
实时检测的需求
实时检测需求:
- 自动驾驶:实时性要求
- 视频分析:实时处理
- 移动应用:资源受限
YOLO革命的前奏
YOLO革命的前奏:
- R-CNN系列证明了CNN的有效性
- 但速度无法满足实时需求
- 需要一阶段检测的新范式
- 为YOLO的诞生奠定了基础
R-CNN家族三代对比
graph LR
subgraph RCNN["R-CNN (2014)<br/>17 min/img · 58.5 mAP"]
R1[Input] --> R2[Selective Search<br/>2000 Regions]
R2 --> R3["CNN ×2000<br/>Very Slow"]
R3 --> R4["SVM + BBox Reg"]
end
subgraph FastRCNN["Fast R-CNN (2015)<br/>2.3s/img · 66.9 mAP"]
F1[Input] --> F2["CNN ×1<br/>Fast"]
F2 --> F3["ROI Pooling"]
F3 --> F4["FC + Softmax<br/>+ BBox Reg"]
end
subgraph FasterRCNN["Faster R-CNN (2015)<br/>0.2s/img · 70.0 mAP"]
G1[Input] --> G2["CNN + RPN<br/>Shared Features"]
G2 --> G3["ROI Pooling<br/>+ Detection"]
end
总结
R-CNN系列的核心贡献
- 开创性工作:首次将CNN应用于目标检测
- 技术演进:从R-CNN到Faster R-CNN的完整演进
- 精度提升:mAP从58.5%提升到70.0%
- 速度优化:从17分钟优化到0.2秒
技术演进总结
R-CNN (2014):
- CNN特征提取
- SVM分类器
- 精度:58.5%
Fast R-CNN (2015):
- 共享特征提取
- ROI Pooling
- 精度:66.9%
Faster R-CNN (2015):
- RPN + Fast R-CNN
- 端到端训练
- 精度:70.0%
为YOLO系列做铺垫
R-CNN系列虽然精度高,但速度慢,无法满足实时检测需求。这为YOLO系列的一阶段检测革命奠定了基础。
参考资料
- R-CNN: Girshick, R., et al. (2014). "Rich Feature Hierarchies for Accurate Object Detection and Semantic Segmentation." CVPR 2014. arXiv:1311.2524.
- Fast R-CNN: Girshick, R. (2015). "Fast R-CNN." ICCV 2015. arXiv:1504.08083.
- Faster R-CNN: Ren, S., et al. (2015). "Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks." NeurIPS 2015. arXiv:1506.01497.
- Mask R-CNN: He, K., et al. (2017). "Mask R-CNN." ICCV 2017. arXiv:1703.06870.
代码实现
- R-CNN官方 - 原始Caffe实现
- Fast R-CNN官方 - Caffe实现
- Faster R-CNN官方 - Caffe实现
- PyTorch实现 - 现代PyTorch实现
数据集
- PASCAL VOC - 目标检测基准数据集
- COCO - 大规模目标检测数据集