ROI Pooling 与ROI Align

本文深入探讨了Mask-RCNN中提出的ROIAlign技术,一种用于解决ROIPooling操作中量化问题的区域特征聚集方法。通过取消量化操作并采用双线性内插,ROIAlign实现了特征聚集的连续性,有效提升了检测模型的准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ROI Align 是在Mask-RCNN这篇论文里提出的一种区域特征聚集方式, 很好地解决了ROI Pooling操作中两次量化造成的区域不匹配(mis-alignment)的问题。实验显示,在检测测任务中将 ROI Pooling 替换为 ROI Align 可以提升检测模型的准确性。

ROI Pooling过程:

1、首先根据后面网络要求的输入尺寸求网格大小,如输入特征图尺寸为5*5,而网络输入尺寸为2*2,那么网格的划分结果为

 

2、对于每个小网格,求最大值作为该网格最大池化之后的值。

在这个过程中会有两次量化操作。对于一个region proposal,首先从原图经过全卷积网络到特征图,得到的候选框位置可能存在浮点数,进行取整操作从而出现第一次量化;其次,在ROI Pooling求取每个小网格的位置时也同样存在浮点数取整的情况。这两次量化的结果都使得候选框的位置会出现偏差,在论文里,作者把它总结为“不匹配问题(misalignment)。如下图所示,假设图片经过主干网络提取特征后,特征图缩放步长(stride)为32,则该层特征图上0.1个像素的偏差,缩放到原图就是3.2个像素。

 

ROI Align过程:

为了解决ROI Pooling的上述缺点,作者提出了ROI Align这一改进的方法。ROI Align的思路很简单:取消量化操作,使用双线性内插的方法获得坐标为浮点数的像素点上的图像数值,从而将整个特征聚集过程转化为一个连续的操作,。值得注意的是,在具体的算法操作上,ROI Align并不是简单地补充出候选区域边界上的坐标点,然后将这些坐标点进行池化,而是重新设计了一套比较优雅的流程,如图3所示:

遍历每一个候选区域,保持浮点数边界不做量化。

将候选区域分割成k x k个单元,每个单元的边界也不做量化。

在每个单元中计算固定四个坐标位置,用双线性内插的方法计算出这四个位置的值,然后进行最大池化操作。

这里对上述步骤的第三点作一些说明:这个固定位置是指在每一个矩形单元(bin)中按照固定规则确定的位置。比如,如果采样点数是1,那么就是这个单元的中心点。如果采样点数是4,那么就是把这个单元平均分割成四个小方块以后它们分别的中心点。显然这些采样点的坐标通常是浮点数,所以需要使用插值的方法得到它的像素值。在相关实验中,作者发现将采样点设为4会获得最佳性能,甚至直接设为1在性能上也相差无几。事实上,ROI Align 在遍历取样点的数量上没有ROIPooling那么多,但却可以获得更好的性能,这主要归功于解决了misalignment的问题。值得一提的是,我在实验时发现,ROI Align在VOC2007数据集上的提升效果并不如在COCO上明显。经过分析,造成这种区别的原因是COCO上小目标的数量更多,而小目标受misalignment问题的影响更大(比如,同样是0.5个像素点的偏差,对于较大的目标而言显得微不足道,但是对于小目标,误差的影响就要高很多)。

 

反向传播公式:

常规的ROI Pooling的反向传播公式如下:

 

这里,xi代表池化前特征图上的像素点;yrj代表池化后的第r个候选区域的第j个点;i*(r,j)代表点yrj像素值的来源(最大池化的时候选出的最大像素值所在点的坐标)。由上式可以看出,只有当池化后某一个点的像素值在池化过程中采用了当前点Xi的像素值(即满足i=i*(r,j)),才在xi处回传梯度。

类比于ROIPooling,ROIAlign的反向传播需要作出稍许修改:首先,在ROIAlign中,xi*(r,j)是一个浮点数的坐标位置(前向传播时计算出来的采样点),在池化前的特征图中,每一个与 xi*(r,j) 横纵坐标均小于1的点都应该接受与此对应的点yrj回传的梯度,故ROI Align 的反向传播公式如下:

 

上式中,d(.)表示两点之间的距离,Δh和Δw表示 xi 与 xi*(r,j) 横纵坐标的差值,这里作为双线性内插的系数乘在原始的梯度上。

 

 

### ROI PoolingROI Align 的概念 #### ROI Pooling ROI (Region of Interest) Pooling 是一种用于将不同大小的输入转换成固定尺寸输出的技术。该方法通过将候选区域划分为相同数量的小块,然后对每一小块执行最大池化操作来获取固定维度的特征向量。这种方法确保了无论原始候选框的实际大小如何,最终得到的特征映射都具有相同的宽度和高度。 然而,在实际应用中发现,由于采用了量化的方式确定子区域边界,这可能会引入一些误差,因为这些边界的坐标通常是浮点数而被强制转成了整数值[^1]。 ```python def roi_pooling(feature_map, rois, pooled_height, pooled_width): """ 实现简单的ROI Pooling算法 参数: feature_map -- 特征图 rois -- 候选区域列表 pooled_height -- 输出的高度 pooled_width -- 输出的宽度 返回: pooled_rois -- 经过pool后的rois """ num_rois = len(rois) channels = feature_map.shape[-1] pooled_rois = np.zeros((num_rois, pooled_height, pooled_width, channels)) for i in range(num_rois): h_start, w_start, h_end, w_end = map(int, rois[i]) # 将roi划分成pooled_height * pooled_width个小格子 bin_size_h = (h_end - h_start) / float(pooled_height) bin_size_w = (w_end - w_start) / float(pooled_width) for ph in range(pooled_height): for pw in range(pooled_width): h1 = int(np.floor(ph * bin_size_h + h_start)) w1 = int(np.floor(pw * bin_size_w + w_start)) h2 = int(np.ceil((ph + 1) * bin_size_h + h_start)) w2 = int(np.ceil((pw + 1) * bin_size_w + w_start)) # 执行max pooling pooled_rois[i, ph, pw, :] = np.max( feature_map[h1:h2, w1:w2], axis=(0, 1)) return pooled_rois ``` #### ROI Align 为了克服上述提到的问题,ROI Align 被设计出来作为改进方案。传统的ROI Pooling不同的是,ROI Align 不会简单地取最接近的位置来进行采样,而是采用双线性插值的方法精确计算出对应位置上的像素值。具体来说,对于每一个bin内的四个最近邻点,根据它们之间的相对距离加权求得目标位置处的真实响应值。这样做的好处是可以更准确地保留物体的空间信息而不受网格化的负面影响。 ```python def bilinear_interpolate(im, y, x): """Bilinear interpolation function.""" height, width = im.shape[:2] if y < 0 or y > height - 1 or x < 0 or x > width - 1: return 0 y_low = int(math.floor(y)) x_low = int(math.floor(x)) y_high = min(height - 1, math.ceil(y)) x_high = min(width - 1, math.ceil(x)) ly = y - y_low lx = x - x_low hy = 1. - ly hx = 1. - lx v1 = im[y_low, x_low] v2 = im[y_low, x_high] v3 = im[y_high, x_low] v4 = im[y_high, x_high] w1 = hy * hx w2 = hy * lx w3 = ly * hx w4 = ly * lx val = w1*v1 + w2*v2 + w3*v3 + w4*v4 return val def roi_align(feature_map, rois, pooled_height=7, pooled_width=7, sampling_ratio=-1): """ 实现简单的ROI Align算法 参数: feature_map -- 输入特征图 rois -- 区域建议框 pooled_height -- 池化后高度,默认为7 pooled_width -- 池化后宽度,默认为7 sampling_ratio -- 抽样的比例因子,默认自适应调整(-1) 返回: aligned_features -- 对齐后的特征矩阵 """ batch_size, _, feat_height, feat_width = feature_map.size() num_rois = rois.size()[0] device = feature_map.device aligned_features = torch.zeros([num_rois, feature_map.size(1), pooled_height, pooled_width]).to(device=device) for n_roi in range(num_rois): start_y, start_x, end_y, end_x = rois[n_roi].tolist() roi_width = max(end_x - start_x, 1.) roi_height = max(end_y - start_y, 1.) bin_size_h = 1. * roi_height / pooled_height bin_size_w = 1. * roi_width / pooled_width sample_num_h = ( sampling_ratio if sampling_ratio > 0 else ceil(bin_size_h)) + 1 sample_num_w = ( sampling_ratio if sampling_ratio > 0 else ceil(bin_size_w)) + 1 for ph in range(pooled_height): for pw in range(pooled_width): # 计算当前bin中心点相对于原图的比例偏移 yc = (start_y + ph * bin_size_h + ((sample_num_h - 1.) / 2.) * (bin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值