FasterRcnn-Resnet50-FPN对图像的处理过程

如题。感觉物体检测框架还是比较复杂的,在这里理一下,一张图像从输入到输出,究竟被做了哪些操作。

警告:可能存在大量不知道我在说啥的状况,这个博客针对自己的初步理解,还是不够细致和准确,我只是记录一下,防止自己忘记,并无科普目的。

那么首先肯定是图像的预处理和增强。这个不必多说。假设处理完之后,图像的大小为3*800*1216。

FasterRcnn-Resnet50-FPN由backbone,proposal_generator和roi_head三大部分组成。

backbone先介绍Resnet50。resnet50由一个预处理模块和4个卷积模块构成。4个卷积模块分别命名为res2, res3, res4, res5。预处理模块包括一个卷积层和一个池化层,分别会使图像的大小缩小两倍。3*800*1216的图像经过预处理模块之后,大小会变成64*200*304,然后再送入后续4个block。FPN需要resnet的4个模块输出的特征图,其大小分别是:[res2: 256*200*304, res3: 512*100*152, res4: 1024*50*76, res5: 2048*25*38]。

接下来是FPN部分。FPN取res2, res3, res4, res5的输出特征作为输入,然后对这些特征图进行不同尺度之间的交互。具体就是这样的:先对res5来个1*1卷积把channel数量降到256,然后再来个3*3卷积得到特征p5: 256*25*38;然后把p5上采样,得到256*50*76,这个p5上采样结果加上res4的1*1卷积结果,得到256*50*76,再来个3*3卷积得到p4。然后p4上采样,res3 1*1卷积,相加,3*3卷积得到p3,然后同理得到p2。最终p5被搞了一个MaxPooling得到p6。如此一来,FPN的输出即为:[p2: 256*200*304, p3: 256*100*152, p4: 256*50*76, p5: 256*25*38, p6: 256*13*19]。

图像经过了resnet50-FPN,变成了不同尺度的特征图p2--p6。接下来这些特征图送入到proposal-generator中来生成初步的proposal。这里的proposal_generator即为RPN。RPN的输入为image,特征图以及图像的label,如果是测试等不需要计算loss的时候,不输入label也可以。然后第一步:根据输入的特征图生成anchors。生成anchors的话,首先要确定每个特征图对应的anchor size(可以理解为正方形框的边长)以及anchor的长宽比。假设此时的anchor size为[32,64,128,256,512],长宽比为[0.5, 1, 2]。然后根据不同的size和不同长宽比的排列组合,可以得到15 组个base anchor,这15个base anchor都假设中心点为(0,0)。接下来根据size和stride(stride为每个特征图对应的缩小系数,如p2对应的缩小系数为4.)生成偏移,将这些偏移应用于base anchor,就得到了每个特征图对应的anchors。再具体一点,以特征图p2为例:p2对应的stride为4。首先根据[32,64,128,256,512]以及纵横比得到了15个base anchor,这15个base anchor的中心都是(0,0)。然后又根据特征图size (200,304)和stride 4,在原图[(200*4)*(304*4)]上以步长为4生成了200*304个中心点。这200*304个中心点与那3个base anchor组合,得到了200*304*15个anchor。然后p3上得到100*152*15个anchor,p4得到50*76*15个,依次类推。

生成了anchors之后,接下来是rpn_head。rpn_head将输入的特征图映射为每个anchor的正负类以及对应的4个顶点的offset。还是拿p2为例子。rpn_head首先用一个3*3卷积卷一下p2,输出的大小还是256*200*304。然后再分别用两个1*1卷积,分别输出p2对应的15*300*304的logits_score和60*300*304的offsets。p3--p6同理。

接下来就是计算loss和predict proposals。先来讲计算loss。首先,要对anchor_generator在各个特征图上生成的anchors做一个匹配,看看哪个anchor和gt(ground truth)对的上。这个匹配非常的消耗内存,需要计算每个anchor和每个gt之间的IoU。这里是通过IOU阈值来判断的,label有3种:-1:ignore,0:negative,1:positive。IOU的阈值需要两个,假设为[0.3, 0.7]。那么低于0.3的部分,label会被标注为0。高于0.7的部分,label会被标注为1。0.3--0.7之间的部分会被标注为-1。匹配完事之后会得到每个anchor的label以及每个anchor匹配的gt。得到了匹配结果之后,需要对匹配结果再进行采样。采样256个正负anchor,其中正anchor的数量要尽可能的多,但是不能超过256*1/4。采样正anchor和负anchor的过程是随机的。采样完了256个anchor之后,把剩下的所以的anchor的label变为-1。再然后需要得到每个正anchor所匹配的gt的bbox。在进行了anchor的匹配和采样之后,就可以计算loss了。之前计算的logits和offsets就派上用场了。

计算完了loss,rpn还要输出predict proposals。之前的loss都是直接在生成的anchor的基础上进行匹配和采样的。到了这一步,就需要把模型预测的offset给用上了。这里是在所有的anchor上选logits比较大的1000个anchor传递给roi_head。具体的选取过程为:对于每张特征图,select the `pre_nms_topk` highest scoring proposals, apply NMS, clip proposals, and remove small boxes. Return the `post_nms_topk` highest scoring proposals among all the feature maps for each image. 选除了post_nms_topk(1000)个proposal之后,把这1000个proposal送到roi_head那里去。rpn整体的输出为1000个proposals以及losses。

接下来终于进入到了roi_head的部分。roi_head取images,feature maps,proposals,gt作为输入,输出预测结果和loss。如果gt不输入的话,那就不算loss了。roi_head又分为3个子模块,分别为ROIPooler,box_head和box_predictor。

在训练过程中,首先要对rpn送来的1000个proposals进行gt匹配和采样。rpn中有个batchsize_per_image,在roi_head这里,也有一个batchsize_per_image,其值为512。采样过程中,首先把gt添加进了proposals。然后计算图像中的gt和(1000+num(gt))个proposals之间的IOU,根据阈值0.5进行匹配。大于0.5的proposal标记为1,否则标记为0。然后就可以得到这(1000+num(gt))个proposals所匹配的gt和实际的标签。然后从这些里面采样512个样本,其中正样本的数量越多越好,但是不要超过512*1/4。采样完之后,记录下这512个proposal以及他们对应的物体类别。

采样出512个proposals之后,需要进一步对这些proposal进行类别预测和边界框回归。过程分3步:首先对输入的特征图进行ROIPooling,然后将pooling得到的结果送入box_head进行编码,最后将编码得到的特征送入box_predictor输出物体的类别和框框的offset。

首先来看POIPooling。这里只对p2--p5进行了pooling,因为到了p6特征图就太小了。pooler的输入是特征图list和proposal list。特征图list装着4套特征图,每套的大小为B*C*H*W。这里我们只考虑输入了一张图像,所以这里的B为1。那么输出的特征图list就是这样图像的不同尺度的特征图p2--p5。然后需要对512个proposal进行转化,变成512*5的形式,第一列代表着这个proposal是在那个特征图上的。proposal可以经过一个level mapper的东西,根据proposal的面积来决定这个proposal来自于哪层特征。再接下里,就是把proposal面积缩小(1/stride),然后在对应的特征图上把proposal框住的部分抠出来,再将抠出来的部分平均分成7*7的网格,每个channel上的每个网格内进行max pooling。完事之后,一个proposal的特征就会变成256*7*7。ROIPooling最终的输出为512*256*7*7.

pooling完之后就是box_head进行编码。这个简单,直接flatten,变成512*12544,然后两个全连接,变成512*1024。然后再送入最后的box_predictor。

box_predictor的输入即为proposal特征:N*1024,输出为类别:N*(K+1),offset:N*4。这两个结果都是分别再N*1024上添加1个全连接得到的。如果是训练的话,拿着这些最终结果,去和每个proposal匹配的gt去计算loss就可以了。

如果不是训练的话,那还需要对这些proposal进行进一步的处理。首先,如果不是在train的话,那么就不需要对RPN送来的1000个proposal进行采样。经过同样的处理之后,会得到的这1000个proposal的类别logits和offset。然后再进行inference:这里的inference需要roi_head对这1000个proposal的处理结果,以及1000个proposal本身作为输入。首先将offset应用于proposal,得到1000个框框。然后再将1000proposal的类别logits进行softmax得到score。最后,clip proposals,移除背景类,然后根据阈值进行筛选,先将score的前K列取出来,然后选取分值大于0.05的部分,再移除空的proposal,最后对选出的proposal进行逐类别NMS,得到最终的输出。

  • 8
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 PyTorch 中使用 `faster_rcnn_resnet50_fpn` 模型,可以按照以下步骤进行: 1. 安装 PyTorch 和 TorchVision 库(如果未安装的话)。 2. 导入必要的库和模块: ```python import torch import torchvision from torchvision.models.detection.faster_rcnn import FastRCNNPredictor ``` 3. 加载预训练模型 `faster_rcnn_resnet50_fpn`: ```python model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) ``` 4. 修改模型的分类器,将其调整为适合你的任务。由于 `faster_rcnn_resnet50_fpn` 是一个目标检测模型,它的分类器通常是用来检测物体类别的。如果你的任务不需要检测物体类别,可以将分类器替换为一个只有一个输出的线性层: ```python num_classes = 1 # 只检测一个类别 in_features = model.roi_heads.box_predictor.cls_score.in_features model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes) ``` 5. 将模型转换为训练模式,并将其移动到所选设备(如GPU)上: ```python device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') model.to(device) model.train() # 转换为训练模式 ``` 6. 训练模型,可以使用自己的数据集来训练模型,或者使用 TorchVision 中的数据集,如 Coco 或 Pascal VOC 数据集。 7. 在测试阶段,可以使用以下代码来检测图像中的物体: ```python # 定义图像 image = Image.open('test.jpg') # 转换为Tensor,并将其移动到设备上 image_tensor = torchvision.transforms.functional.to_tensor(image) image_tensor = image_tensor.to(device) # 执行推理 model.eval() with torch.no_grad(): outputs = model([image_tensor]) # 处理输出 boxes = outputs[0]['boxes'].cpu().numpy() # 物体框 scores = outputs[0]['scores'].cpu().numpy() # 物体分数 ``` 需要注意的是,`faster_rcnn_resnet50_fpn` 是一个较大的模型,需要较高的计算资源和训练时间。在训练和测试时,建议使用GPU来加速计算。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值