yaoppeng / U-Net_v2

215 stars 20 forks source link

模型推理时,图片尺寸的疑问 #15

Open 1819707238 opened 10 months ago

1819707238 commented 10 months ago
  1. 项目中SDI模块的forward函数,传入了xs和anchor,在for循环中,仅仅考虑了x元素的最后一个维度(w),也就是说默认H=W,但实际情况中很容易输入的H与W并不相等,因此直接如果输入没有resize可能就会引起报错。 我的疑问是,如果将模型用于推理,此时H与W不相等,将无法使用。所以是先对图片进行填充,再对图片进行区域裁剪吗?

2.顺便指出一下,network中的演示示例resunet似乎仍有bug,按


`class SDI(nn.Module):
def __init__(self, channel):
super().__init__()
    self.convs = nn.ModuleList(
        [nn.Conv2d(channel, channel, kernel_size=3, stride=1, padding=1) for _ in range(4)])

def forward(self, xs, anchor):
    ans = torch.ones_like(anchor)
    target_size = anchor.shape[-1]

    for i, x in enumerate(xs):
        if x.shape[-1] > target_size:
            x = F.adaptive_avg_pool2d(x, (target_size, target_size))
        elif x.shape[-1] < target_size:
            x = F.interpolate(x, size=(target_size, target_size),
                                  mode='bilinear', align_corners=True)

        ans = ans * self.convs[i](x)

RuntimeError: Given groups=1, weight of size [32, 64, 3, 3], expected input[2, 96, 112, 112] to have 64 channels, but got 96 channels instead

    return ans

`



`RuntimeError: Given groups=1, weight of size [32, 64, 3, 3], expected input[2, 96, 112, 112] to have 64 channels, but got 96 channels instead`
yaoppeng commented 9 months ago
  1. 这个没有大的影响。按照比例缩放即可。
  2. 使用BasicConv2d(in_planes, out_planes)将输出的channel调整到一致即可。
1819707238 commented 9 months ago

您能针对第一点详细介绍一下吗,我还是不能get到。。 针对第二点,应该是decoder中您直接对每个conv块的输出通道减半,但resnet34中conv1和layer1的通道都是64,这可能才是问题所在

yaoppeng commented 9 months ago
  1. 如果heigh和width不相等,需要简单修改代码

    def forward(self, xs, anchor):
    ans = torch.ones_like(anchor)
    target_size = anchor.shape[-1]
    
    for i, x in enumerate(xs):
        if x.shape[-1] > anchor.shape[-1]:
            x = F.adaptive_avg_pool2d(x, anchor.shape[-2:])
        elif x.shape[-1] < target_size:
            x = F.interpolate(x, size= anchor.shape[-2:],
                                  mode='bilinear', align_corners=True)
    
        ans = ans * self.convs[i](x)

也就是(H, W)rescale成(2H, 2W)或者(H/2, W/2)。图像不必以正方形的形式输入。

  1. 不同的Backbone的每个stage的输出通道数都不一定一样。我是用一个(3, 3)的conv统一到一个相同的channel数然后再操作。抱歉最近忙于其他的东西,demo的代码我会再检查下。
1819707238 commented 9 months ago

第一点我按照您给的代码进行了修改,可惜依然不行

1819707238 commented 9 months ago

如果输入图片尺寸长宽不相等的话,似乎仅调整那里是不行的,还需要对网络的多个上采样和跳连接进行处理,这样是很麻烦的。。 是否可以在输入的时候将图片resize为长宽一致的?但这样似乎也存在一些问题。

1819707238 commented 9 months ago

您能介绍一下您在开展实验时,比如训练阶段和模型测试阶段,是如何对输入图片进行处理的吗,我想这能解决我的疑惑

yaoppeng commented 8 months ago

可以将图片resize成2的幂, 这样down-sample和up-sample时能保证不会由于图像H或W不能被2整除导致cat或者add时相差1的问题。

在Polyp分割时,先把图像resize到(352, 352)。做evaluation时,将predication再resize回去。ISIC数据集图像大小就是(256, 256)

长宽不等时,下采样和上采样也是H和W各自按照2倍的比例,不会产生影响。