提交 c29707a6 编写于 作者: A Aston Zhang

till iou in anchor

上级 4397377a
# 锚框
目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域是否有我们感兴趣的目标,以及进一步调整区域边缘来更准确预测目标的真实边界框。不同的模型使用不同的区域采样方法,这里我们介绍其中的一种:它以每个像素为中心生成数个大小和比例不同的被称之为锚框(anchor box)的边界框
目标检测算法通常会在输入图像中采样大量的区域,然后判断这些区域中是否包含我们感兴趣的目标,并调整区域边缘从而更准确预测目标的真实边界框。不同的模型所使用的区域采样方法可能不同。这里我们介绍其中的一种方法:它以每个像素为中心生成数个大小和宽高比(aspect ratio)不同的边界框。这些边界框被称为锚框(anchor box)。我们将在后面的小节中基于锚框实践目标检测
导入本小节需要的包。注意我们新引入了`contrib`这个模块,以及使用NumPy修改了打印精度,这是因为NDArray的打印实际上调用了NumPy的打印函数
首先,导入本小节需要的包或模块。这里我们新引入了`contrib`包,并修改了NumPy的打印精度。由于NDArray的打印实际调用NumPy的打印函数,本节打印出的NDArray中的浮点数更简洁一些
```{.python .input n=1}
import sys
......@@ -15,34 +15,34 @@ import numpy as np
np.set_printoptions(2)
```
## 锚框的生成
## 生成锚框
假设输入图像高为$h$,宽为$w$,那么大小为$s\in (0,1]$和比例为$r > 0$的锚框形状是
假设输入图像高为$h$,宽为$w$。我们分别以图像的每个像素为中心生成不同形状的锚框。设大小为$s\in (0,1]$且宽高比为$r > 0$,锚框的宽和高分别为$ws\sqrt{r}$和$hs/\sqrt{r}$。当中心位置给定时,已知宽和高的锚框是确定的。
$$\left( ws\sqrt{r}, \ \frac{hs}{\sqrt{r}}\right),$$
下面我们分别设定好一组大小$s_1,\ldots,s_n$和一组宽高比$r_1,\ldots,r_m$。如果以每个像素为中心时使用所有的大小与宽高比的组合,输入图像将一共得到$whnm$个锚框。虽然这些锚框可能覆盖了所有的真实边界框,但计算复杂度容易过高。因此,我们通常只对包含$s_1$或$r_1$的大小与宽高比的组合感兴趣,即
确定其中心点位置便可以固定一个锚框。
$$(s_1, r_1), (s_1, r_2), \ldots, (s_1, r_m), (s_2, r_1), (s_3, r_1), \ldots, (s_n, r_1).$$
当然我们可以通过使用不同的$s$和$r$,以及改变中心位置,来遍历所有可能的区域。虽然这样可以覆盖真实边界框,但会使得计算很复杂。通常我们进行采样,使得锚框尽量贴近真实边界框。 例如我们可以首先固定一个比例$r_1$,然后采样$n$个不同的大小$s_1,\ldots,s_n$。然后固定一个大小$s_1$,采样$m$个不同的比例$r_1,\ldots,r_m$。这样对每个像素我们一共生成$n+m-1$个锚框。对于整个输入图像,我们将一共生成$wh(n+m-1)$个锚框。
也就是说,以相同像素为中心的锚框数量为$n+m-1$。对于整个输入图像,我们将一共生成$wh(n+m-1)$个锚框。
上述的采样方法实现在`contrib.ndarray`中的`MultiBoxPrior`函数。通过指定输入数据(我们只需要访问其形状),锚框的采样大小和比例,这个函数将返回所有采样到的锚框。
以上生成锚框的方法已实现在`MultiBoxPrior`函数中。指定输入、一组大小和一组宽高比,该函数将返回输入的所有锚框。
```{.python .input n=52}
img = image.imread('../img/catdog.jpg').asnumpy()
h, w = img.shape[0:2]
x = nd.random.uniform(shape=(1, 3, h, w)) # 构造一个输入数据。
x = nd.random.uniform(shape=(1, 3, h, w)) # 构造输入数据。
y = contrib.nd.MultiBoxPrior(x, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
y.shape
```
其返回结果格式为(批量大小,锚框个数,4)。可以看到我们生成了2百万以上个锚框。将其变形成(高,宽,$n+m-1$,4)后,我们可以方便的访问以任何一个像素为中心的所有锚框。下面例子里我们访问以(250,250)为中心的第一个锚框。它有四个元素,同之前一样是左上和右下的x、y轴坐标,但被分别除以了高和宽使得数值在0和1之间。
我们看到,返回锚框变量`y`的形状为(批量大小,锚框个数,4)。将锚框变量`y`的形状变为(图像高,图像宽,以相同像素为中心的锚框个数,4)后,我们就可以通过指定像素位置来获取所有以该像素为中心的锚框了。下面例子里我们访问以(250,250)为中心的第一个锚框。它有四个元素,分别是锚框左上角和右下角的$x$和$y$轴坐标。其中$x$和$y$轴的坐标值分别已除以图像的宽和高,因此值域均为0和1之间。
```{.python .input n=10}
boxes = y.reshape((h, w, 5, 4))
boxes[250, 250, 0, :]
```
在画出这些锚框的具体样子前,我们需要定义`show_bboxes`函数在图上画出多个边界框。
为了描绘图像中以某个像素为中心的所有锚框,我们先定义`show_bboxes`函数以便在图像上画出多个边界框。
```{.python .input n=11}
# 本函数已保存在 gluonbook 包中方便以后使用。
......@@ -67,28 +67,26 @@ def show_bboxes(axes, bboxes, labels=None, colors=None):
bbox=dict(facecolor=color, lw=0))
```
然后我们画出以(250,250)为中心的所有锚框
刚刚我们看到,变量`boxes`中$x$和$y$轴的坐标值分别已除以图像的宽和高。在绘图时,我们需要恢复锚框的原始坐标值,并因此定义了变量`bbox_scale`。现在,我们可以画出图像中以(250,250)为中心的所有锚框了。可以看到,大小为0.75且宽高比为1的蓝色锚框较好地覆盖了图像中的狗
```{.python .input n=12}
gb.set_figsize()
bbox_scale = nd.array((w, h, w, h)) # 需要乘以高和宽使得符合我们的画图格式。
bbox_scale = nd.array((w, h, w, h))
fig = gb.plt.imshow(img)
show_bboxes(fig.axes, boxes[250, 250, :, :] * bbox_scale,
['s=0.75, r=1', 's=0.5, r=1', 's=0.25, r=1', 's=0.75, r=2',
's=0.75, r=0.5'])
```
可以看到大小为0.75比例为1的蓝色锚框比较好的覆盖了图像中的小狗。
## IoU:交集除并集
## IoU:交并比
在介绍如何使用锚框参与训练和预测前,我们先介绍如何判断两个边界框的距离。我们知道集合相似度的最常用衡量标准叫做Jaccard距离。给定集合$A$和$B$,它的定义是集合的交集除以集合的并集:
$$J(A,B) = \frac{|A\cap B|}{| A \cup B|}.$$
边界框指定了一块像素区域,其可以看成是像素点的集合。因此我们可以定义类似的距离,即我们使用两个边界框的相交面积除以相并面积来衡量它们的相似度。这被称之为交集除并集(Intersection over Union,简称IoU),如图9.2所示。它的取值范围在0和1之间。0表示边界框不相关,1则表示完全重合。
边界框指定了一块像素区域,其可以看成是像素点的集合。因此我们可以定义类似的距离,即我们使用两个边界框的相交面积除以相并面积来衡量它们的相似度。这被称之为交并比(Intersection over Union,简称IoU),如图9.2所示。它的取值范围在0和1之间。0表示边界框不相关,1则表示完全重合。
![集除并集](../img/iou.svg)
![并比](../img/iou.svg)
## 训练
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册