转自:Zhreshold
目标检测通俗的来说是为了找到图像或者视频里的所有目标物体。在下面这张图中,两狗一猫的位置,包括它们所属的类(狗/猫),需要被正确的检测到。
所以和图像分类不同的地方在于,目标检测需要找到尽量多的目标物体,而且要准确的定位物体的位置,一般用矩形框来表示。
在接下来的章节里,我们先介绍一个流行的目标检测算法,SSD (Single-Shot MultiBox Object Detection).
友情提示:本章节特别长,千万不要在蹲坑的时候点开。
本文中涉及MXNet 0.11最新的发布的gluon接口,参考MXNet 0.11发布,加入动态图接口Gluon,还有两位CMU教授的亲笔教程
顾名思义,算法的核心是用卷积神经网络一次前向推导求出大量多尺度(几百到几千)的方框来表示目标检测的结果。网络的结构用下图表示。
跟所有的图像相关的网络一样,我们需要一个主干网络来提取特征,同时也是作为第一个预测特征层。网络在当前层产生大量的预设框,和与之对应的每个方框的分类概率(背景,猫,狗等等)以及真正的物体和预设框的偏移量。在完成当前层的预测后,我们会下采样当前特征层,作为新的预测层,重新产生新的预设框,分类概率,偏移量。这个过程往往会重复好几次,直到预测特征层到达全局尺度( )。
接下来我们用例子解释每个细节实现。
预设框 Default anchor boxes
预设框的形状和大小可以由参数控制,我们往往设置一堆预设框,以期望任意图像上的物体都能有一个预设框能大致重合,由于每个预设框需要对应的预测网络预测值,所以希望对于每个物体都有100%重合的预设框是不现实的,可能会需要几十万甚至几百万的预设框,但是采样的预设框越多,重合概率越好,用几千到上万个预设框基本能实现略大于70%的最好重合率,同时保证了检测的速度。
为了保证重合覆盖率,对于每个特征层上的像素点,我们用不同的大小和长宽比来采样预设框。 假设在某个特定的特征层( ),每个预设框的中心点就是特征像素点的中心,然后我们用如下的公式采样预设框:
预设框的中心为特征像素点的中心
对于长宽比 , 尺寸 , 生成的预设框大小 。
对于长宽比 同时 , 生成的预设框大小 , 其中 是第一个预设的尺寸。
这里例子里,我们用事先实现的层MultiBoxPrior产生预设框,输入 个预设尺寸,和 个预设的长宽比,输出为 个方框而不是 个。 当然我们完全可以使用其他的算法产生不同的预设框,但是实践中我们发现上述的方法覆盖率和相应需要的预设框数量比较合适。
import mxnet as mxfrom mxnet import ndfrom mxnet.contrib.ndarray import MultiBoxPriorn = 40# 输入形状: batch x channel x height x weightx = nd.random_uniform(shape=(1, 3, n, n)) y = MultiBoxPrior(x, sizes=[.5, .25, .1], ratios=[1, 2, .5])# 取位于 (20,20) 像素点的第一个预设框# 格式为 (x_min, y_min, x_max, y_max)boxes = y.reshape((n, n, -1, 4))print('The first anchor box at row 21, column 21:', boxes[20, 20, 0, :])
The first anchor box at row 21, column 21:
[ 0.26249999 0.26249999 0.76249999 0.76249999]
<NDArray 4 @cpu(0)>
看着数字不够直观的话,我们把框框画出来。取最中心像素的所有预设框,画在图上的话,我们看到已经可以覆盖几种尺寸和位置的物体了。把所有位置的组合起来,就是相当可观的预设框集合了。
import matplotlib.pyplot as pltdef box_to_rect(box, color, linewidth=3):
"""convert an anchor box to a matplotlib rectangle"""
box = box.asnumpy()
return plt.Rectangle(
(box[0], box[1]), (box[2]-box[0]), (box[3]-box[1]),
fill=False, edgecolor=color, linewidth=linewidth)colors = ['blue', 'green', 'red', 'black', 'magenta']plt.imshow(nd.ones((n, n, 3)).asnumpy())anchors = boxes[20, 20, :, :]for i in range(anchors.shape[0]):
plt.gca().add_patch(box_to_rect(anchors[i,:]*n, colors[i]))plt.show()
请点击“阅读原文”查看全文
原文链接:
https://zhuanlan.zhihu.com/p/28867241