详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法

1. RoIAlign的产生背景

首先设想一个场景,假设从一个图像中锚定了一个人的边界框
详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
图1 锚定一个目标人物的边界框

这个时候,要提取边界框中的人的特征,显然应该用 CNN 网络来做这个工作。CNN 处理之后会形成一个特征图。按照一般的处理方式,会使用 RoI Pooling 来缩小特征图的尺寸。但是在 Mask-RCNN 中提出了一个 RoIAlign 的方式,使得得到的小特征图可以更加的精确和信息完整。

2. RoI Pooling

举例来说,如果我们现在得到了一个特征图,特征图尺寸是 5×75×7,要求将此区域缩小为 2×22×2。此时,因为 5/2=2.5{5}/{2}=2.5,是个非整数,所以此时系统会对其进行取整的分割,即将 “ 55 ”分割成 “ 3+23+2 ”,将 “ 77 ” 分割成 “ 3+43+4 ”,然后取每个区域的最大值作为本区域的值,整个过程如下所示:详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
图2 整个RoI Pooling 的过程

3. RoI Align

可以知道,使用 RoIPoolingRoI Pooling 存在一个很大的问题:

  • 很粗糙地选用了一个值来代替一个区域的值,而且每个区域的尺寸还有很大的差距。

RoIAlignRoI Align 的过程如下:
详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
图3 整个RoI Align 的过程

  • 因为最终要将这个 5×75×7 的特征图处理成 2×22×2 的特征图。所以先将要进行RoIAlignRoI Align 的过程转换成 2×22×2 个相同规模的范围,这个过程中不做任何量化处理。
    详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
  • 将这 44 个模块(①,②,③,④)内部同样进行这样的处理,再细分成 44 个规模相同的区域(图中虚线表示)。
    详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
  • 然后对于每一个最小的区域(包含不止一个像素点)确定其中心点(图中的红色 ×× )然后使用双线性插值法得到这个 ×× 号所在位置的值作为 最小格子区域 的值。
    详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
  • 对于每一个 小区域(①,②,③,④)都会有 44 个这样的值,把这 44 个值取他们的最大值作为每个 小区域(①,②,③,④) 的值。这样最终就可以得到 44 个小区域的 44 个值,作为最终的特征图输出结果。

RoIAlignRoI Align 提出的这种方式可以避免过程中丢失原特征图的信息,中间过程全程不量化来保证最大的信息完整性。

4. 双线性插值

双线性插值,又称为双线性内插。在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。

首先确定几个量:

  • 四个像素点 Q11,Q12,Q21,Q22Q_{11}, Q_{12},Q_{21},Q_{22}
  • 他们的坐标分别是 (x1,y1),(x1,y2),(x2,y1),(x2,y2)(x_1,y_1),(x_1,y_2),(x_2,y_1),(x_2,y_2)
  • 他们的像素值分别是 f(Q11),f(Q12),f(Q21),f(Q22)f(Q_{11}),f(Q_{12}),f(Q_{21}),f(Q_{22})
  • 横向插值插入的两个点 R1,R2R_1,R_2,其坐标分别为 (x,y1),(x,y2)(x,y_1),(x,y_2)
  • 纵向插值插入的一个点 PP,其坐标是 (x,y)(x,y)
    详解 Mask-RCNN 中的 “RoIAlign” 作用 / 双线性插值的方法
    插值的目的:

图像扩展,由已知的像素点的值来计算出来原本不存在的像素点。当然你也可以把扩展的地方的像素全部用 00 来表示,但是看起来是一种不太聪明的做法,会让像素的质量下降的很厉害。所以为了尽可能的让扩展的像素不太过于偏离原图像,使用插值的方式。

插值的方法:

  • 先横向插,再纵向插
  • 先纵向插,再横向插

计算过程:

  • 首先来计算横向的插值,由 Q22,Q12Q_{22},Q_{12} 得到 R2R_2 的过程:

    f(Q22)f(Q12)x2x1f(Q22)f(R2)x2x\frac{f(Q_{22})-f(Q_{12})}{x_2-x_1} \approx\frac{f(Q_{22})-f(R_2)}{x_2-x}

    交叉相乘:

    (f(Q22)f(Q12))×(x2x)(f(Q22)f(R2))×(x2x1)({f(Q_{22})-f(Q_{12})})×(x_2-x)\approx({f(Q_{22})-f(R_{2})})×(x_2-x_1)

    化简一下:

    f(R2)x2xx2x1f(Q12)+xx1x2x1f(Q22)f(R_{2}) \approx \frac{x_2-x}{x_2-x_1}f(Q_{12})+\frac{x-x_1}{x_2-x_1}f(Q_{22})

  • 同样地,计算横向插值,由Q11,Q21Q_{11},Q_{21} 得到 R1R_1 的过程:

    f(Q21)f(Q11)x2x1f(Q21)f(R1)x2x\frac{f(Q_{21})-f(Q_{11})}{x_2-x_1} \approx\frac{f(Q_{21})-f(R_1)}{x_2-x}

    计算步骤同上,化简结果:

    f(R1)x2xx2x1f(Q11)+xx1x2x1f(Q21)f(R_{1}) \approx \frac{x_2-x}{x_2-x_1}f(Q_{11})+\frac{x-x_1}{x_2-x_1}f(Q_{21})

  • 然后结合 R1,R2R_1,R_2yy 方向插值得到 PP

    f(R2)f(R1)y2y1f(R2)f(P)y2y\frac{f(R_{2})-f(R_{1})}{y_2-y_1} \approx\frac{f(R_{2})-f(P)}{y_2-y}

    经过化简:

    f(P)y2yy2y1f(R1)+yy1y2y1f(R2)f(P) \approx \frac{y_2-y}{y_2-y_1}f(R_{1})+\frac{y-y_1}{y_2-y_1}f(R_{2})

    将得到的 f(R1),f(R2)f(R_{1}),f(R_{2}) 的化简结果带入到 f(P)f(P) 的公式里面:

    f(P)f(Q11)(x2x1)(y2y1)(x2x)(y2y)+f(Q21)(x2x1)(y2y1)(xx1)(y2y)+f(Q12)(x2x1)(y2y1)(x2x)(yy1)+f(Q22)(x2x1)(y2y1)(xx1)(yy1)f(P) \approx \frac{f(Q_{11})}{(x_2-x_1)(y_2-y_1)}(x_2-x)(y_2-y)+\frac{f(Q_{21})}{(x_2-x_1)(y_2-y_1)}(x-x_1)(y_2-y)+\frac{f(Q_{12})}{(x_2-x_1)(y_2-y_1)}(x_2-x)(y-y_1)+\frac{f(Q_{22})}{(x_2-x_1)(y_2-y_1)}(x-x_1)(y-y_1)

所以,最后可以得到 PP 点的像素值,无论是先进行横向插值还是纵向插值,最后的出的 PP 点的像素值是一样的。