1. RoIAlign的产生背景
首先设想一个场景,假设从一个图像中锚定了一个人的边界框

图1 锚定一个目标人物的边界框
这个时候,要提取边界框中的人的特征,显然应该用 CNN 网络来做这个工作。CNN 处理之后会形成一个特征图。按照一般的处理方式,会使用 RoI Pooling 来缩小特征图的尺寸。但是在 Mask-RCNN 中提出了一个 RoIAlign 的方式,使得得到的小特征图可以更加的精确和信息完整。
2. RoI Pooling
举例来说,如果我们现在得到了一个特征图,特征图尺寸是 5×7,要求将此区域缩小为 2×2。此时,因为 5/2=2.5,是个非整数,所以此时系统会对其进行取整的分割,即将 “ 5 ”分割成 “ 3+2 ”,将 “ 7 ” 分割成 “ 3+4 ”,然后取每个区域的最大值作为本区域的值,整个过程如下所示:
图2 整个RoI Pooling 的过程
3. RoI Align
可以知道,使用 RoIPooling 存在一个很大的问题:
- 很粗糙地选用了一个值来代替一个区域的值,而且每个区域的尺寸还有很大的差距。
RoIAlign 的过程如下:

图3 整个RoI Align 的过程
- 因为最终要将这个 5×7 的特征图处理成 2×2 的特征图。所以先将要进行RoIAlign 的过程转换成 2×2 个相同规模的范围,这个过程中不做任何量化处理。
- 将这 4 个模块(①,②,③,④)内部同样进行这样的处理,再细分成 4 个规模相同的区域(图中虚线表示)。
- 然后对于每一个最小的区域(包含不止一个像素点)确定其中心点(图中的红色 × )然后使用双线性插值法得到这个 × 号所在位置的值作为 最小格子区域 的值。
- 对于每一个 小区域(①,②,③,④)都会有 4 个这样的值,把这 4 个值取他们的最大值作为每个 小区域(①,②,③,④) 的值。这样最终就可以得到 4 个小区域的 4 个值,作为最终的特征图输出结果。
RoIAlign 提出的这种方式可以避免过程中丢失原特征图的信息,中间过程全程不量化来保证最大的信息完整性。
4. 双线性插值
双线性插值,又称为双线性内插。在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。
首先确定几个量:
- 四个像素点 Q11,Q12,Q21,Q22
- 他们的坐标分别是 (x1,y1),(x1,y2),(x2,y1),(x2,y2)
- 他们的像素值分别是 f(Q11),f(Q12),f(Q21),f(Q22)
- 横向插值插入的两个点 R1,R2,其坐标分别为 (x,y1),(x,y2)
- 纵向插值插入的一个点 P,其坐标是 (x,y)

插值的目的:
图像扩展,由已知的像素点的值来计算出来原本不存在的像素点。当然你也可以把扩展的地方的像素全部用 0 来表示,但是看起来是一种不太聪明的做法,会让像素的质量下降的很厉害。所以为了尽可能的让扩展的像素不太过于偏离原图像,使用插值的方式。
插值的方法:
计算过程:
-
首先来计算横向的插值,由 Q22,Q12 得到 R2 的过程:
x2−x1f(Q22)−f(Q12)≈x2−xf(Q22)−f(R2)
交叉相乘:
(f(Q22)−f(Q12))×(x2−x)≈(f(Q22)−f(R2))×(x2−x1)
化简一下:
f(R2)≈x2−x1x2−xf(Q12)+x2−x1x−x1f(Q22)
-
同样地,计算横向插值,由Q11,Q21 得到 R1 的过程:
x2−x1f(Q21)−f(Q11)≈x2−xf(Q21)−f(R1)
计算步骤同上,化简结果:
f(R1)≈x2−x1x2−xf(Q11)+x2−x1x−x1f(Q21)
-
然后结合 R1,R2 在 y 方向插值得到 P
y2−y1f(R2)−f(R1)≈y2−yf(R2)−f(P)
经过化简:
f(P)≈y2−y1y2−yf(R1)+y2−y1y−y1f(R2)
将得到的 f(R1),f(R2) 的化简结果带入到 f(P) 的公式里面:
f(P)≈(x2−x1)(y2−y1)f(Q11)(x2−x)(y2−y)+(x2−x1)(y2−y1)f(Q21)(x−x1)(y2−y)+(x2−x1)(y2−y1)f(Q12)(x2−x)(y−y1)+(x2−x1)(y2−y1)f(Q22)(x−x1)(y−y1)
所以,最后可以得到 P 点的像素值,无论是先进行横向插值还是纵向插值,最后的出的 P 点的像素值是一样的。