第一次看到R-CNN论文时,我正被传统目标检测方法的性能瓶颈困扰。2014年之前,我们还在用HOG、SIFT这些手工特征,检测准确率卡在30%左右难以突破。Ross Girshick团队的这项工作就像一剂强心针——直接将PASCAL VOC数据集的检测准确率拉升到50%以上。
R-CNN的核心创新在于将CNN特征引入检测流程。具体实现分为四个关键步骤:先用Selective Search算法生成约2000个候选区域(这个数量级后来成为行业惯例);然后对每个区域进行CNN特征提取;接着训练SVM分类器判断类别;最后用回归器微调边界框位置。我当时复现这个流程时,最耗时的部分就是特征提取——每个候选区域都要单独过一遍AlexNet,2000个区域意味着2000次前向计算。
Selective Search的候选生成原理很有意思。它先通过图像分割得到初始区域,再基于颜色、纹理等相似度合并区域,形成层次化结构。这种自底向上的方式能较好地覆盖各种尺寸的目标。不过在实际项目中,我发现它对细长物体(如旗杆)的召回率较低。
特征提取阶段有个工程细节值得注意:所有候选区域都要缩放到227×227固定尺寸。这个设计源于AlexNet的输入要求,但也带来两个问题:一是形变会影响小目标的识别,二是重复计算导致效率低下。我做过测试,VGG16处理一张图的2000个候选框,仅特征提取就要47秒。
分类器设计采用了"一对多"策略——每个类别单独训练SVM。以PASCAL VOC为例,需要训练20个二分类器。这种设计在样本不平衡时表现稳健,但存储20组分类器参数确实占用不少空间。记得当时实验室服务器因为存储特征文件差点爆盘,不得不临时加装硬盘。
边界框回归是提升定位精度的关键。通过训练回归器预测四个参数(中心点偏移+宽高缩放),能将Selective Search生成的粗糙建议框调整得更精确。我在调试时发现,当初始IoU>0.6时回归效果最好,这也解释了为什么后续算法都注重提高初始建议框质量。
2015年看到Fast R-CNN论文时,我立刻被它的设计智慧折服。相比R-CNN的53秒检测耗时,新方法仅需0.3秒,提速近200倍!这主要归功于两项关键创新:特征共享和ROI Pooling。
特征共享机制彻底改变了处理流程。不再对每个候选框单独提取特征,而是先将整图输入CNN得到特征图,再通过空间映射获取各区域对应的特征矩阵。这个改动消除了重复计算,我实测VGG16的特征提取时间从47秒骤降到0.15秒。不过这里有个实现细节:如何准确将原图坐标映射到特征图?需要记住特征图尺寸是原图的1/16(VGG16的stride=16),坐标转换时要特别注意取整误差。
ROI Pooling解决了变长输入问题。它将不同大小的候选区域特征统一采样到7×7固定尺寸,使后续全连接层能正常运作。我拆解过它的实现:先将ROI区域划分为7×7的bin,每个bin内做max pooling。这种操作虽然简单,但在处理极端长宽比的区域时会有信息损失——这也为后来Mask R-CNN的ROI Align埋下伏笔。
训练策略的改进同样令人称道。Fast R-CNN用多任务损失取代了繁琐的SVM训练,将分类和回归统一到单个网络。具体实现时,分类分支输出N+1类概率(含背景),回归分支输出4×(N+1)个坐标参数。我在自定义数据集训练时发现,正负样本比例对性能影响很大。论文建议的1:3比例在多数场景适用,但当目标较密集时需要调整采样策略。
数据采样是另一个工程重点。Fast R-CNN采用层次化采样:先采样N张图像,每张图像再采样64个ROI。这种设计既能保证批次多样性,又能控制GPU显存占用。我在处理高分辨率图像时,曾因ROI过多导致OOM(内存溢出),最后通过动态调整采样数量解决了问题。
Faster R-CNN的突破性在于用RPN(Region Proposal Network)替代了Selective Search,首次实现完全端到端的目标检测。我在2015年首次部署时,5FPS的检测速度已经能满足实时性要求不高的场景。
RPN的核心思想是"锚点机制"(Anchor)。在特征图的每个位置上设置9个不同比例/尺度的锚框(3种面积×3种长宽比),通过预测锚框的偏移量和前景概率来生成建议框。实际调试时,锚点设置需要根据数据集调整:对于行人检测这种长宽比固定的任务,可以减少锚点类型;而处理商品识别时,可能需要增加更多比例。
RPN的训练采样策略很有讲究。通常从约20k个锚点中采样256个进行训练,保持正负样本1:1比例。这里有个细节:正样本不仅包括IoU>0.7的锚点,还包括与每个真实框IoU最大的锚点(即使IoU<0.7)。这个设计确保了小目标不会被完全忽略。我在处理显微图像时,正是靠调整这个IoU阈值才提高了小细胞检测的召回率。
多任务损失设计体现了工程智慧。RPN同时优化分类损失(锚点是否为前景)和回归损失(边界框调整),通过λ参数(通常设为10)平衡两项。在自定义数据集上,我发现调整λ值能改善定位精度——当目标边界要求严格时,可以适当增大λ。
Faster R-CNN的训练流程比较复杂,需要分阶段进行:
这种交替训练虽然繁琐,但能稳定收敛。后来有研究提出端到端联合训练方案,不过我在工程实践中发现,分阶段训练更容易调试,尤其当数据集与预训练域差异较大时。
在实际项目中部署RCNN系列算法时,我积累了一些实用技巧。首先是骨干网络的选择:VGG16虽然经典,但ResNet50通常在精度和速度上更平衡。对于边缘设备,可以尝试MobileNetV3等轻量架构,不过要注意调整锚点尺寸匹配浅层特征。
数据增强策略直接影响模型鲁棒性。除了常规的翻转、旋转,我特别推荐使用多尺度训练——随机缩放图像短边到[400,600,800]中的某个值。这能让模型适应不同尺寸的输入,测试时只需单尺度就能获得不错效果。
处理小目标有个小技巧:适当减少骨干网络的下采样倍数。比如修改VGG16的conv5_3步长从2到1,配合空洞卷积保持感受野。我在无人机航拍项目中这样调整后,小车辆检测AP提升了8%。
对于类别不平衡问题,除了调整采样比例,还可以在损失函数上做文章。Focal Loss虽然原生于RetinaNet,但移植到Faster R-CNN的RPN阶段也能缓解正负样本失衡。我在缺陷检测项目中结合OHEM(在线难例挖掘),使罕见缺陷的召回率提高了15%。
部署时的内存优化也很关键。通过共享骨干网络特征,Faster R-CNN的显存占用可以控制在3GB以内(输入尺寸600×800)。如果还需压缩,可以量化ROI Pooling后的特征为FP16,这几乎不影响精度但能节省30%显存。