Faster-RCNN网络
学习目标
- 熟悉FasterRCNN目标检测的思想
- 知道anchor(锚框)的思想
- 掌握RPN网络是如何进行候选区域的生成的
- 掌握ROIPooling的使用方法
- 知道fasterRCNN的训练方法
在R-CNN和Fast RCNN的基础上,在2016年提出了Faster RCNN网络模型,在结构上,Faster RCNN已经将候选区域的生成,特征提取,目标分类及目标框的回归都整合在了一个网络中,综合性能有较大提高,在检测速度方面尤为明显。接下来我们给大家详细介绍fasterRCNN网络模型。网络基本结构如下图所示:
Faster RCNN可以看成是区域生成网络(RPN)与Fast RCNN的组合,其中区域生成网络(RPN)替代选择性搜索来生成候选区域,Fast RCNN用来进行目标检测。
网络工作流程
FasterRCNN的工作流程是:
1、特征提取:将整个图像缩放至固定的大小输入到CNN网络中进行特征提取,得到特征图。
2、候选区域提取:输入特征图,使用区域生成网络RPN,产生一些列的候选区域
3、ROIPooling: 与Fast RCNN网络中一样,使用最大池化固定候选区域的尺寸,送入后续网络中进行处理
4、目标分类和回归:与Fast RCNN网络中一样,使用两个同级层:K+1个类别的SoftMax分类层和边框的回归层,来完成目标的分类和回归。
Faster R-CNN的流程与Fast R-CNN的区别不是很大,重要的改进是使用RPN网络来替代选择性搜索获取候选区域,所以我们可以将Faster R-CNN网络看做RPN和Fast R-CNN网络的结合。
接下来我们来看下该网络预训练模型的使用过程,模型源码位置:fasterRCNN中,如下图所示:
detection文件夹中是模型,数据的实现,weights中包含网络的预训练模型。接下来我们按照以下步骤进行目标检测:
1、获取数据和加载预训练网络
2、获取RPN网络生成的候选区域
3、获取网络的目标检测结果
首先导入相应的工具包:
# 获取VOC数据使用
from detection.datasets import pascal_voc
# 绘图
import matplotlib.pyplot as plt
import numpy as np
# 模型构建
from detection.models.detectors import faster_rcnn
import tensorflow as tf
# 图像展示
import visualize
遇到的问题1:ModuleNotFoundError: No module named ‘cv2’
解决方法:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
遇到问题2:ModuleNotFoundError: No module named ‘skimage’
解决办法:pip install scikit-image
另外每次pip install 都会特别慢,我找到一些办法可以参考:
https://blog.csdn.net/yang5915/article/details/83175804
https://waple.blog.csdn.net/article/details/104574277
确实下载快了许多!!!
数据加载
加载voc数据集中的一张图片进行网络预测:
# 实例化voc数据集的类,获取送入网络中的一张图片
pascal = pascal_voc.pascal_voc("train")
# image:送入网络中的数据,imagemeta:图像的yuan'x
image,imagemeta,bbox,label = pascal[218]
在将图像送入网络之前,我们对其进行了尺度的调整,标准化等处理,获取可展示的图像:
# 图像的均值和标准差
img_mean = (122.7717, 115.9465, 102.9801)
img_std = (1., 1., 1.)
# RGB图像
rgd_image= np.round(image+img_mean).astype(np.uint8)
获取原始图像,进行比较:
# 获取原始图像
from detection.datasets.utils import get_original_image
ori_img = get_original_image(image[0],imagemeta[0],img_mean)
将图像进行对比显示:
# 展示原图像和送入网络中图像
rgd_image= np.round(image+img_mean).astype(np.uint8)
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(ori_img.astype('uint8'))
axes[0].set_title("原图像")
axes[1].imshow(rgd_image[0])
axes[1].set_title("送入网络中的图像")
plt.show()
将原图像的长边缩放为1216,短边按相应比例进行调整后,并按照均值进行填充
# 原图像的大小
ori_img.shape
(375, 500, 3)
# 送入网络中图像的大小
image.shape
(1, 1216, 1216, 3)
imagemeta中的信息是:原图像大小,图像缩放后的大小,送入网络中图像的大小,图像缩放比例,图像是否翻转(未使用)。
# 原始图像和送入网络中图像的信息imagemeta
array([[ 375. , 500. , 3. , 912. , 1216. , 3. , 1216. , 1216. , 3. , 2.432, 0. ]], dtype=float32)
模型加载
加载使用coco数据集预训练的模型,对图像进行预测。
# coco数据集的class,共80个类别:人,自行车,火车,。。。
classes = ['bg', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
实例化faster-RCNN模型:
# 实例化模型
model = faster_rcnn.FasterRCNN(num_classes=len(classes))
加载预训练模型,由于fasterRCNN不是按照model的子类构建,所以无法通过h5文件直接加载模型结构,我们将结构实例化后,在加载权重获取整个预训练模型。
model((image,imagemeta,bbox,label),training=True)
# 加载训练好的weights
model.load_weights("weights/faster_rcnn.h5")
通过model.summary()查看网络架构,如下:
模型预测过程
模型的预测分为两部分:RPN生成候选区域和Fast RCNN进行目标的分类与回归
RPN获取候选区域
# RPN获取候选区域:输入图像和对应的元信息,输出是候选的位置信息proposals = model.simple_test_rpn(image[0],imagemeta[0])
候选区域的结果如下所示:对于上述图像共产生1533个候选区域,每个候选区域使用相对于输入网络中图像归一化后的左上角坐标和右下角坐标。
<tf.Tensor: shape=(1533, 4), dtype=float32, numpy=array([[0.20729761, 0.00852748, 0.748096 , 0.46975034], [0.42213044, 0.5887971 , 0.7810232 , 0.9806169 ], [0.40125194, 0.4384725 , 0.48458642, 0.47913405], ..., [0.25977597, 0.435113 , 0.27290097, 0.4483906 ], [0.38884488, 0.41798416, 0.41393432, 0.4339822 ], [