Faster-RCNN简易复现

Faster-RCNN复现

数据准备

主要目标是利用pytorch框架简易复现Faster-RCNN,我选了一个比较简单的数据集VOC2012,这个数据集标注用的xml格式。

数据读取如下:

 def loadXml(path):
     '''
     读取原始的XMLlabel文件
     :return:
     '''
     dom = xml.dom.minidom.parse(path)
 ​
     root = dom.documentElement
     #获取图片上所有的目标
     objs = root.getElementsByTagName("object")
     #获取这张图片的长宽
     w, h = root.getElementsByTagName("width")[0].childNodes[0].data, root.getElementsByTagName("height")[0].childNodes[0].data
     infos = []
     #把所有目标的信息放到infos中返回
     for item in objs:
         c = item.getElementsByTagName("name")[0].childNodes[0].data
         xmin = item.getElementsByTagName("xmin")[0].childNodes[0].data
         ymin = item.getElementsByTagName("ymin")[0].childNodes[0].data
         xmax = item.getElementsByTagName("xmax")[0].childNodes[0].data
         ymax = item.getElementsByTagName("ymax")[0].childNodes[0].data
         infos.append((c, int(xmin), int(ymin), int(xmax), int(ymax)))
     return int(w), int(h), infos

模型配置

关于训练的参数,anchor的size比论文上多两个,提高小目标的检测能力,长宽比还是三个。初始学习率为0.0001,每2轮后乘以0.1。 训练的相关参数配置如下:

 class Config():
     # anchor的size和长宽比,这里的格式是由pytorch中自带的基础faster_rcnn的输入决定的,参考  
     # torchvision.models.detection.faster_rcnn
     anchor_size = ((32, 64, 128, 256, 512),)
     aspect_ratios = ((0.5, 1, 2),)
     # 特征网络
     backbone = "mobilenet_V2"
     # 目标类型,0是背景,同样是torchvision.models.detection.faster_rcnn的要求
     cls_label = ['__background__', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car',
                  'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike',
                  'person', 'pottedplant', 'sheep', 'sofa', 'train',
                  'tvmonitor', 'cat'] #VOC所有标签
     class_num = 20
     lr = 0.0001
     epoch = 6
     batch_size = 2
     # 模型保存位置
     FasterRCNN_checkpoints = './checkpoints/FasterRCNN/model.pth'

torchvision中自带的faster_rcnn模块

 from torchvision.models.detection import faster_rcnn
 from torchvision.models.detection.rpn import AnchorGenerator
 from torchvision.ops import MultiScaleRoIAlign
 ​
 ​
 # 生成anchor
 anchor_generator = AnchorGenerator(sizes=cfg.anchor_size, aspect_ratios=cfg.aspect_ratios)
 ​
 # 设置roipooling,采用ROIAlign
 roi_pooler = MultiScaleRoIAlign(featmap_names=['0'], output_size=7, sampling_ratio=2)
 ​
 # 建立FasterRCNN模型
 net = faster_rcnn.FasterRCNN(backbone,
                              num_classes=cfg.class_num+1,
                              rpn_anchor_generator=anchor_generator,
                              box_roi_pool=roi_pooler)

faster_rcnn创建主要需要三块,一个是anchor的生成器,一个是roipooling方式,还有一个是用于提取特征的backbone。

backbone可以用torch中提供的,也可以自己写的,但是,如果是自己写的,最好先进行预训练,我用没有预训练的自定义的backbone去试了下,效果不佳。

关于MultiScaleRoIAlign的第一个参数为啥是['0'],torchvision.models.detection.faster_rcnn.py中有说明。。说是如果backbone返回多个特征图层时,写入需要计算的图层名字,比如['feat1', 'feat3'],但如果只返回一个tensor,也就是只有一个图层返回,就['0']。

faster_rcnn中提供很多参数,可以在建立模型时传入。

 def __init__(self, backbone, num_classes=None,
              # transform parameters
              min_size=800, max_size=1333,
              image_mean=None, image_std=None,
              # RPN parameters
              rpn_anchor_generator=None, rpn_head=None,
              rpn_pre_nms_top_n_train=2000, rpn_pre_nms_top_n_test=1000,
              rpn_post_nms_top_n_train=2000, rpn_post_nms_top_n_test=1000,
              rpn_nms_thresh=0.7,
              rpn_fg_iou_thresh=0.7, rpn_bg_iou_thresh=0.3,
              rpn_batch_size_per_image=256, rpn_positive_fraction=0.5,
              # Box parameters
              box_roi_pool=None, box_head=None, box_predictor=None,
              box_score_thresh=0.05, box_nms_thresh=0.5, box_detections_per_img=100,
              box_fg_iou_thresh=0.5, box_bg_iou_thresh=0.5,
              box_batch_size_per_image=512, box_positive_fraction=0.25,
              bbox_reg_weights=None):

训练部分

 from dataset.MyDataset import MyDataset
 from models.FasterRCNN import FasterRCNN
 from torch.utils.data import DataLoader
 from Config import Config
 import torch.optim as optim
 import numpy as np
 from torch.autograd import Variable
 import torch
 from utils.DataProcess import bar
 from torch.utils.tensorboard import SummaryWriter
 ​
 ​
 def train():
     # 调用tensorboard监视训练过程
     writer = SummaryWriter("runs/summary")
     cfg = Config()
 ​
     net = FasterRCNN().net
 ​
     net.cuda()
 ​
     trainset = MyDataset('train')
 ​
     trainLoader = DataLoader(trainset, batch_size=cfg.batch_size, shuffle=True, drop_last=True)
 ​
     params = [p for p in net.parameters() if p.requires_grad]
 ​
     opt = optim.Adam(params, lr=cfg.lr)
 ​
     num_train = len(trainLoader)
 ​
     for epoch in range(1, cfg.epoch + 1):
         net.train()
         # 每2轮学习率下降一次
         if epoch % 2 == 0:
             for p in opt.param_groups:
                 p['lr'] *= 0.1
         for n, data in enumerate(trainLoader):
             imgs = []
             gtbox = []
             for i in range(cfg.batch_size):
                 img_path = data[0][i]
                 gtbox_path = data[1][i]
                 img = trainset.load_pic(img_path)
                 img = Variable(img)
                 gtbbox = np.load(gtbox_path)
                 gtbbox = torch.from_numpy(gtbbox)
                 gtbbox = Variable(gtbbox)
                 if torch.cuda.is_available():
                     gtbbox = gtbbox.cuda()
                     img = img.cuda()
                 imgs.append(img)
                 gtbox.append({"boxes": gtbbox[:, 1:], "labels": gtbbox[:, 0]})
             opt.zero_grad()
             data = net(imgs, gtbox)
             l_cls = data['loss_classifier']
             l_box = data['loss_box_reg']
             l_obj = data['loss_objectness']
             l_box_rpn = data['loss_rpn_box_reg']
             bar('正在第%d轮训练,loss_cls=%.5f,loss_box=%.5f,loss_obj=%.5f,loss_box_rpn=%.5f' %
                 (epoch, l_cls.data, l_box.data, l_obj.data, l_box_rpn.data), n, num_train)
             loss = l_cls + l_box + l_obj + l_box_rpn
             # 添加监视目标
             writer.add_scalar("loss_classifier", l_cls.data, (epoch - 1) * num_train + n)
             writer.add_scalar("loss_box_reg", l_box.data, (epoch - 1) * num_train + n)
             writer.add_scalar("loss_objectness", l_obj.data, (epoch - 1) * num_train + n)
             writer.add_scalar("loss_rpn_box_reg", l_box_rpn.data, (epoch - 1) * num_train + n)
             loss.backward()
             opt.step()
         torch.save(net, cfg.FasterRCNN_checkpoints)
 ​
 ​
 if __name__ == '__main__':
     train()

训练部分用tensorboard记录了一下训练过程。这里注意一下,torch提供的faster_rcnn输入包含两部分,一个是图片集,注意不需要resize,第二个是标注集,标注集是个list,里面元素是Map,包括坐标信息boxes和标签信息labels。至于具体怎么读取数据就看自己怎么设计数据了。训练返回结果包括四个损失,anchor的坐标损失、anchor前背景损失、目标框的坐标损失以及目标分类损失。

模型校验

 net = torch.load(cfg.FasterRCNN_checkpoints)
 net.eval()
 ***********
 ****省略****
 ***********
 img = Variable(img)
 if torch.cuda.is_available():
     img = img.cuda()
 res = net([img])
 res = res[0]
 boxes = res["boxes"]
 labels = res["labels"]
 scores = res["scores"]
 ***********
 ****省略****
 ***********

校验部分就省略写了,主要两点,第一点,不需要新建一个faster_rcnn再加载数据,就直接torch.load就完事了,一定要记得net.eval();第二点,输入只需要图片列表。校验时,返回结果为坐标、label和得分。最后根据得分进行一下nms即可。

测试效果

自己用的电脑,显卡比较垃圾,就大概练了练,batch_size最大就到2。大概效果如下

源码:https://github.com/Zou-CM/Faster-RCNN-pytorch

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Faster-RCNN是一种用于目标检测的深度学习网络模型。它是在R-CNN和Fast RCNN的基础上发展而来的,通过将特征抽取、proposal提取、bounding box regression和classification整合在一个网络中,提高了综合性能和检测速度。[2] Faster-RCNN的训练过程可以分为以下几个步骤: 1. 使用一个预训练的卷积神经网络(如VGG16)来提取图像的特征。 2. 在特征图上使用Region Proposal Network (RPN) 来生成候选目标框(proposals)。 3. 使用这些候选目标框和真实标签来计算损失函数,并通过反向传播来更新网络参数,以使网络能够更好地预测目标框的位置和类别。 4. 使用训练好的RPN来生成候选目标框,并将这些候选目标框输入到网络中进行分类和边界框回归。 5. 通过计算损失函数并反向传播来更新网络参数,以进一步提高检测性能。 6. 可以进行多次迭代的训练,每次迭代都使用之前训练好的网络来初始化网络参数,并继续训练网络。[3] Faster-RCNN的网络结构包括一个共享的卷积层(用于特征提取)和两个分支:一个用于生成候选目标框的RPN,另一个用于对这些候选目标框进行分类和边界框回归。通过共享卷积层,Faster-RCNN能够在不同尺度的特征图上进行目标检测,从而提高检测的准确性和效率。[2] 总结来说,Faster-RCNN是一种用于目标检测的深度学习网络模型,通过整合特征抽取、proposal提取、bounding box regression和classification,提高了综合性能和检测速度。它的训练过程包括特征提取、候选目标框生成、分类和边界框回归等步骤。[2][3]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值