ROI Align的实现原理2_代码实现

该博客介绍了ROIAlign的实现原理,通过一个实例展示了如何在PyTorch中使用`torchvision.ops.roi_align`和`roi_pool`函数。作者通过输入张量和边界框坐标,输出了经过池化操作后的特征图,对比了ROIAlign与ROIPool的区别,ROIAlign的输出包含了浮点数,而ROIPool的输出则是量化到整数。

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


书接上文,上一次分析了一下ROI Align的原理是如何实现的,一直想知道具体细节是如何实现的,这里找了相关资料进行学习.

上一篇原理介绍博客:ROI Align的实现原理_dlvector的博客-CSDN博客

输入输出的官方文档

Arguments:
input (Tensor[N, C, H, W]): input tensor
boxes (Tensor[K, 5] or List[Tensor[L, 4]]): the box coordinates in (x1, y1, x2, y2)
format where the regions will be taken from. If a single Tensor is passed,
then the first column should contain the batch index. If a list of Tensors
is passed, then each Tensor will correspond to the boxes for an element i
in a batch
output_size (int or Tuple[int, int]): the size of the output after the cropping
is performed, as (height, width)

原来batch_id在第0维…且数值为绝对位置。其格式应为[batch_id, x1, y1, x2, y2]

,其中(x1, y1)为左上角,(x2, y2)为右下角。

from torchvision.ops import nms, roi_align, roi_pool
import torch

# fp = torch.randn([1, 1, 5, 5])
fp = torch.tensor(list(range(5 * 5))).float()
fp = fp.view(1, 1, 5, 5)
print(fp)
# [batch_id, x1, y1, x2, y2]
boxes = torch.tensor([[0, 0, 0, 1, 1]]).float()

pooled_features = roi_align(fp, boxes, [4, 4])
print(pooled_features)

pooled_features = roi_pool(fp, boxes, [4, 4])
print(pooled_features)

输出打印,差异点在于roi_align输出的是带有小数的(宽,高

tensor([[[[ 0.,  1.,  2.,  3.,  4.],
          [ 5.,  6.,  7.,  8.,  9.],
          [10., 11., 12., 13., 14.],
          [15., 16., 17., 18., 19.],
          [20., 21., 22., 23., 24.]]]])
tensor([[[[0.7500, 1.0000, 1.2500, 1.5000],
          [2.0000, 2.2500, 2.5000, 2.7500],
          [3.2500, 3.5000, 3.7500, 4.0000],
          [4.5000, 4.7500, 5.0000, 5.2500]]]])
tensor([[[[0., 0., 1., 1.],
          [0., 0., 1., 1.],
          [5., 5., 6., 6.],
          [5., 5., 6., 6.]]]])

参考:

https://phabricator.mitk.org/file/data/oh4aj4voo5ldehmaf6aj/PHID-FILE-yudyawc6exqxmt7f2qby/fil​​​​​​e

https://medium.com/@andrewjong/how-to-use-roi-pool-and-roi-align-in-your-neural-networks-pytorch-1-0-b43e3d22d073

faster-rcnn.pytorch/roi_align.py at master · jwyang/faster-rcnn.pytorch · GitHub

Region of interest pooling explained

https://tjmachinelearning.com/lectures/1718/instance/instance.pdf

【torchvision】roi_align、roi_pool使用说明_StevenGerrad的博客-CSDN博客

c++代码实现

<think>嗯,用户遇到了一个编译错误,提示在CUDA内核代码中,std::min的参数类型不匹配,具体是long和int之间的类型冲突。用户之前已经给出了相关的代码片段和错误信息,我需要仔细分析这个问题。 首先,用户提供的代码中,这一行出错了: ```cpp dim3 grid(std::min( (num_rois + 512 - 1) / 512, 4096 )); ``` 错误信息指出参数类型是long和int。这里需要检查num_rois的类型。num_rois是从rois.size(0)获得的,而PyTorch中的Tensor的size()返回的是int64_t,也就是long类型。因此,(num_rois + 512 - 1)/512的结果是long类型,而4096是int类型,导致std::min的参数类型不匹配。 之前的建议是使用std::min<int>来显式指定模板参数,但用户仍然遇到错误,可能因为强制转换不完全。这时候需要更明确的类型转换,将两个参数都转为相同的类型,比如int,或者使用static_cast来确保类型一致。 另外,用户可能在之前的建议中没有正确应用所有步骤,或者在代码的其他部分还存在其他问题。例如,num_rois是否真的应该是输出大小?或者是否存在其他变量名错误,比如output_size未被定义的问题已经被修复,但类型问题依然存在? 可能用户参考了之前的建议,但问题仍然存在,所以需要更详细的解决方案。这时候需要分步骤说明如何解决类型不匹配的问题,包括显式转换两个参数的类型,或者使用模板参数指定std::min的类型。 另外,可能用户的环境中的CUDA编译器对类型检查更严格,所以必须确保两个参数类型完全一致。这时候使用static_cast<int>将num_rois转换为int可能更可靠,但需要注意num_rois是否可能超过int的范围,这时候可能会需要更大的类型,但通常ROI数量不会超过int的最大值。 最后,建议用户检查整个函数的上下文,确保所有变量都已正确声明,并且包括必要的头文件,比如<algorithm>以使用std::min。同时,参考官方实现或其他可靠来源的代码,确保CUDA核函数的配置正确。</think>--- ### 🔍 **错误原因深度解析** 在以下代码段中: ```cpp dim3 grid(std::min( (num_rois + 512 - 1) / 512, 4096 )); // 错误行 ``` 编译器报错的核心原因是: 1. **类型不匹配**:`num_rois`的类型为`long`(来自`rois.size(0)`),而`4096`是`int`类型 2. **std::min模板推导失败**:编译器无法自动推导两个不同类型参数的公共类型 --- ### 🔨 **精准修复方案** #### 步骤1:强制统一参数类型 ```cpp // 原错误行 dim3 grid(std::min( (num_rois + 512 - 1) / 512, 4096 )); // 修正方案1:显式类型转换 dim3 grid(std::min( static_cast<int>((num_rois + 512 - 1) / 512), // 将整个计算结果转为int 4096 // 保持原int类型 )); // 修正方案2:模板参数显式指定(推荐) dim3 grid(std::min<long>( // 指定模板参数为long (num_rois + 512 - 1) / 512, // 原long类型 4096L // 显式声明为long类型 )); ``` #### 步骤2:验证数值范围(重要!) ```cpp // 添加数值范围检查 AT_ASSERTM(num_rois <= std::numeric_limits<int>::max(), "num_rois exceeds int maximum value"); ``` --- ### 📝 **完整修复代码示例** ```cpp auto num_rois = rois.size(0); // 类型为long // 方案1:统一转为int dim3 grid(std::min( static_cast<int>((num_rois + 512 - 1) / 512), 4096 )); // 方案2:统一保持long(需要4096显式转为long) dim3 grid(std::min<long>( (num_rois + 512 - 1) / 512, 4096L // 注意结尾的L表示long字面量 )); // 方案3:使用模板参数强制匹配 dim3 grid(std::min<long>( (num_rois + 512 - 1) / 512, static_cast<long>(4096) )); ``` --- ### ⚙️ **技术原理详解** 1. **`dim3`类型要求**:CUDA的`dim3`构造函数实际接收`unsigned int`参数,但编译器允许隐式转换 2. **类型推导冲突**: - `rois.size(0)`返回`int64_t`(即`long`类型) - `4096`默认是`int`类型 - `std::min(a, b)`要求`a`和`b`类型严格一致 3. **解决方案选择**: - **方案1**:适用于`num_rois < 2^31-1`(约21亿)的常见场景 - **方案2**:更安全但需要显式处理`4096L` - **方案3**:最明确的类型控制方式 --- ### 🔍 **关联问题排查清单** | 检查项 | 验证方法 | |--------|----------| | CUDA头文件包含 | 检查是否包含`<algorithm>` | | 编译器标准 | 确认使用`-std=c++14`或更高 | | ROI数量限制 | 验证`num_rois <= 2,147,483,647` | | GPU架构兼容性 | 检查`block(512)`是否符合设备限制 | --- ### 📌 **最佳实践建议** 1. **统一类型声明**:建议在项目中使用`using int64 = int64_t;`等类型别名 2. **防御性编程**:在GPU核函数调用前添加范围检查: ```cpp AT_ASSERTM(num_rois <= (4096 * 512), "Exceeded maximum supported ROIs"); ``` 3. **跨平台兼容性**:使用`static_cast`代替C风格强制转换 --- 若问题仍未解决,请提供以下信息: 1. 完整的函数实现 2. 编译时使用的CUDA版本 3. `rois`张量的实际维度信息 这将有助于进一步定位潜在的类型传播问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值