|
@@ -8,7 +8,7 @@ from typing import Any, Callable, List, Optional, Type, Union
|
|
|
from torchvision.models.detection.backbone_utils import BackboneWithFPN
|
|
from torchvision.models.detection.backbone_utils import BackboneWithFPN
|
|
|
|
|
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
-# 工具函数
|
|
|
|
|
|
|
+# å·¥å
·å½æ°
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
|
|
|
|
|
def conv3x3(in_planes: int, out_planes: int, stride: int = 1, groups: int = 1, dilation: int = 1) -> nn.Conv2d:
|
|
def conv3x3(in_planes: int, out_planes: int, stride: int = 1, groups: int = 1, dilation: int = 1) -> nn.Conv2d:
|
|
@@ -30,7 +30,7 @@ def conv1x1(in_planes: int, out_planes: int, stride: int = 1) -> nn.Conv2d:
|
|
|
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
|
|
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
|
|
|
|
|
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
-# Bottleneck Block(你提供的)
|
|
|
|
|
|
|
+# Bottleneck Blockï¼ä½ æä¾çï¼
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
|
|
|
|
|
class Bottleneck(nn.Module):
|
|
class Bottleneck(nn.Module):
|
|
@@ -85,22 +85,22 @@ class Bottleneck(nn.Module):
|
|
|
return out
|
|
return out
|
|
|
|
|
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
-# ResNet 主类
|
|
|
|
|
|
|
+# ResNet 主类
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
|
|
|
|
|
def resnet18fpn(out_channels=256):
|
|
def resnet18fpn(out_channels=256):
|
|
|
- backbone = ResNet(Bottleneck,[2,2,2])
|
|
|
|
|
|
|
+ backbone = ResNet(Bottleneck,[2,2,2,2])
|
|
|
return_layers = {
|
|
return_layers = {
|
|
|
'encoder0': '0',
|
|
'encoder0': '0',
|
|
|
'encoder1': '1',
|
|
'encoder1': '1',
|
|
|
'encoder2': '2',
|
|
'encoder2': '2',
|
|
|
'encoder3': '3',
|
|
'encoder3': '3',
|
|
|
- # 'encoder4': '5'
|
|
|
|
|
|
|
+ 'encoder4': '4'
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# in_channels_list = [self.inplanes, 64, 128, 256, 512]
|
|
# in_channels_list = [self.inplanes, 64, 128, 256, 512]
|
|
|
- # in_channels_list = [64, 256, 512, 1024, 2048]
|
|
|
|
|
- in_channels_list = [64, 256, 512, 1024]
|
|
|
|
|
|
|
+ in_channels_list = [64, 256, 512, 1024, 2048]
|
|
|
|
|
+ # in_channels_list = [64, 256, 512, 1024]
|
|
|
|
|
|
|
|
return BackboneWithFPN(
|
|
return BackboneWithFPN(
|
|
|
backbone,
|
|
backbone,
|
|
@@ -110,18 +110,18 @@ def resnet18fpn(out_channels=256):
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
def resnet50fpn(out_channels=256):
|
|
def resnet50fpn(out_channels=256):
|
|
|
- backbone = ResNet(Bottleneck,[3,4,6])
|
|
|
|
|
|
|
+ backbone = ResNet(Bottleneck,[3,4,6,3])
|
|
|
return_layers = {
|
|
return_layers = {
|
|
|
'encoder0': '0',
|
|
'encoder0': '0',
|
|
|
'encoder1': '1',
|
|
'encoder1': '1',
|
|
|
'encoder2': '2',
|
|
'encoder2': '2',
|
|
|
'encoder3': '3',
|
|
'encoder3': '3',
|
|
|
- # 'encoder4': '5'
|
|
|
|
|
|
|
+ 'encoder4': '4'
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# in_channels_list = [self.inplanes, 64, 128, 256, 512]
|
|
# in_channels_list = [self.inplanes, 64, 128, 256, 512]
|
|
|
- # in_channels_list = [64, 256, 512, 1024, 2048]
|
|
|
|
|
- in_channels_list = [64, 256, 512, 1024]
|
|
|
|
|
|
|
+ in_channels_list = [64, 256, 512, 1024, 2048]
|
|
|
|
|
+ # in_channels_list = [64, 256, 512, 1024]
|
|
|
|
|
|
|
|
return BackboneWithFPN(
|
|
return BackboneWithFPN(
|
|
|
backbone,
|
|
backbone,
|
|
@@ -150,6 +150,7 @@ class ResNet(nn.Module):
|
|
|
self.encoder1 = self._make_layer(block, 64, layers[0],stride=2)
|
|
self.encoder1 = self._make_layer(block, 64, layers[0],stride=2)
|
|
|
self.encoder2 = self._make_layer(block, 128, layers[1], stride=2)
|
|
self.encoder2 = self._make_layer(block, 128, layers[1], stride=2)
|
|
|
self.encoder3 = self._make_layer(block, 256, layers[2], stride=2)
|
|
self.encoder3 = self._make_layer(block, 256, layers[2], stride=2)
|
|
|
|
|
+ self.encoder4 = self._make_layer(block, 512, layers[3], stride=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -193,7 +194,7 @@ class ResNet(nn.Module):
|
|
|
def _make_decoder_layer(self, block: Type[Union[Bottleneck]], in_channels: int,
|
|
def _make_decoder_layer(self, block: Type[Union[Bottleneck]], in_channels: int,
|
|
|
out_channels: int, blocks: int = 1) -> nn.Sequential:
|
|
out_channels: int, blocks: int = 1) -> nn.Sequential:
|
|
|
"""
|
|
"""
|
|
|
- 构建解码器部分的残差块
|
|
|
|
|
|
|
+ æå»ºè§£ç å¨é¨åçæ®å·®å
|
|
|
"""
|
|
"""
|
|
|
assert in_channels == out_channels, "in_channels must equal out_channels"
|
|
assert in_channels == out_channels, "in_channels must equal out_channels"
|
|
|
layers = []
|
|
layers = []
|
|
@@ -212,7 +213,7 @@ class ResNet(nn.Module):
|
|
|
|
|
|
|
|
def _make_upsample_layer(self, in_channels: int, out_channels: int) -> nn.Module:
|
|
def _make_upsample_layer(self, in_channels: int, out_channels: int) -> nn.Module:
|
|
|
"""
|
|
"""
|
|
|
- 使用转置卷积进行上采样
|
|
|
|
|
|
|
+ 使ç¨è½¬ç½®å·ç§¯è¿è¡ä¸éæ ·
|
|
|
"""
|
|
"""
|
|
|
return nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2)
|
|
return nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2)
|
|
|
|
|
|
|
@@ -228,14 +229,14 @@ class ResNet(nn.Module):
|
|
|
print(f'x2:{x2.shape}')
|
|
print(f'x2:{x2.shape}')
|
|
|
x3= self.encoder3(x2)
|
|
x3= self.encoder3(x2)
|
|
|
print(f'x3:{x3.shape}')
|
|
print(f'x3:{x3.shape}')
|
|
|
- # x4= self.encoder4(x3)
|
|
|
|
|
- # print(f'x4:{x4.shape}')
|
|
|
|
|
|
|
+ x4= self.encoder4(x3)
|
|
|
|
|
+ print(f'x4:{x4.shape}')
|
|
|
out={
|
|
out={
|
|
|
'encoder0':x0,
|
|
'encoder0':x0,
|
|
|
'encoder1': x1,
|
|
'encoder1': x1,
|
|
|
'encoder2': x2,
|
|
'encoder2': x2,
|
|
|
'encoder3': x3,
|
|
'encoder3': x3,
|
|
|
- # 'encoder4': x4,
|
|
|
|
|
|
|
+ 'encoder4': x4,
|
|
|
}
|
|
}
|
|
|
return out
|
|
return out
|
|
|
|
|
|
|
@@ -245,20 +246,21 @@ class ResNet(nn.Module):
|
|
|
|
|
|
|
|
|
|
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
-# 测试代码
|
|
|
|
|
|
|
+# æµè¯ä»£ç
|
|
|
# ----------------------------
|
|
# ----------------------------
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if __name__ == "__main__":
|
|
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
|
|
# model = ResNet(Bottleneck, n_classes=5).to(device)
|
|
# model = ResNet(Bottleneck, n_classes=5).to(device)
|
|
|
# print(model)
|
|
# print(model)
|
|
|
- model=resnet50fpn().to(device)
|
|
|
|
|
|
|
+ # model=resnet50fpn().to(device)
|
|
|
|
|
+ model = resnet18fpn().to(device)
|
|
|
|
|
|
|
|
|
|
|
|
|
input_tensor = torch.randn(1, 3, 512, 512).to(device)
|
|
input_tensor = torch.randn(1, 3, 512, 512).to(device)
|
|
|
output_tensor = model(input_tensor)
|
|
output_tensor = model(input_tensor)
|
|
|
|
|
|
|
|
- backbone = ResNet(Bottleneck,[3,4,6]).to(device)
|
|
|
|
|
|
|
+ backbone = ResNet(Bottleneck,[3,4,6,3]).to(device)
|
|
|
features = backbone(input_tensor)
|
|
features = backbone(input_tensor)
|
|
|
print("Raw backbone output:", list(features.keys()))
|
|
print("Raw backbone output:", list(features.keys()))
|
|
|
print(f"Input shape: {input_tensor.shape}")
|
|
print(f"Input shape: {input_tensor.shape}")
|
|
@@ -267,5 +269,5 @@ if __name__ == "__main__":
|
|
|
print(f"Output shape1: {output_tensor['1'].shape}")
|
|
print(f"Output shape1: {output_tensor['1'].shape}")
|
|
|
print(f"Output shape2: {output_tensor['2'].shape}")
|
|
print(f"Output shape2: {output_tensor['2'].shape}")
|
|
|
print(f"Output shape3: {output_tensor['3'].shape}")
|
|
print(f"Output shape3: {output_tensor['3'].shape}")
|
|
|
- # print(f"Output shape4: {output_tensor['5'].shape}")
|
|
|
|
|
|
|
+ print(f"Output shape4: {output_tensor['4'].shape}")
|
|
|
print(f"Output shape5: {output_tensor['pool'].shape}")
|
|
print(f"Output shape5: {output_tensor['pool'].shape}")
|