1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| import numpy as np import torch.nn as nn import torch.nn.functional as F import math import torch
class Bottleneck(nn.Module): expansion = 4 def __init__(self,in_planes, planes, stride=1, downsample = None): super(Bottleneck,self).__init__() self.bottleneck = nn.Sequential( nn.Conv3d(in_planes,planes,1, bias=False), nn.BatchNorm3d(planes), nn.ReLU(inplace= True), nn.Conv3d(planes, planes , (3,3,1), stride ,(1,1,0) ,bias=False), nn.BatchNorm3d(planes), nn.ReLU(inplace=True), nn.Conv3d(planes, self.expansion * planes, 1 , bias=False), nn.BatchNorm3d(self.expansion * planes),) self.relu = nn.ReLU(inplace=True) self.downsample = downsample def forward(self,x): identity = x out = self.bottleneck(x) if self.downsample is not None: identity = self.downsample(x) out += identity out = self.relu(out) return out
class FPN(nn.Module): def __init__(self,layers): super(FPN,self).__init__() self.inplanes = 16
self.conv1 = nn.Conv3d(8, 16, 1, 1, bias = False) self.bn1 = nn.BatchNorm3d(16) self.relu = nn.ReLU(inplace = True) self.maxpool = nn.MaxPool3d(1,1,0)
self.layer1 = self._make_layer(16,layers[0]) self.layer2 = self._make_layer(32,layers[1],(2,2,1)) self.layer3 = self._make_layer(64,layers[2],(2,2,1)) self.layer4 = self._make_layer(128,layers[3],(2,2,1))
self.toplayer = nn.Conv3d(512,64,1,1,0)
self.smooth1 = nn.Conv3d(64, 64, (3,3,1), 1, (1,1,0)) self.smooth2 = nn.Conv3d(64, 64, (3,3,1), 1, (1,1,0)) self.smooth3 = nn.Conv3d(64, 64, (3,3,1), 1, (1,1,0))
self.latlayer1 = nn.Conv3d(256,64,1,1,0) self.latlayer2 = nn.Conv3d(128, 64, 1, 1, 0) self.latlayer3 = nn.Conv3d(64, 64, 1, 1, 0)
def _make_layer(self,planes, blocks, stride = 1): downsample = None if stride != 1 or self.inplanes != Bottleneck.expansion * planes : downsample = nn.Sequential( nn.Conv3d(self.inplanes,Bottleneck.expansion * planes, 1 , stride , bias=False), nn.BatchNorm3d(Bottleneck.expansion * planes) ) layers = [] layers.append(Bottleneck(self.inplanes, planes, stride, downsample)) self.inplanes = planes * Bottleneck.expansion for i in range(1,blocks): layers.append(Bottleneck(self.inplanes, planes)) return nn.Sequential(*layers) def _upsample_add(self, x, y): _,_,H,W,Z = y.shape return F.interpolate(x,size=(H,W,Z),mode='trilinear',align_corners=False) + y def forward(self,x): c1 = self.maxpool(self.relu(self.bn1(self.conv1(x)))) c2 = self.layer1(c1) c3 = self.layer2(c2) c4 = self.layer3(c3) c5 = self.layer4(c4)
p5 = self.toplayer(c5) p4 = self._upsample_add(p5, self.latlayer1(c4)) p3 = self._upsample_add(p4, self.latlayer2(c3)) p2 = self._upsample_add(p3, self.latlayer3(c2))
p4 = self.smooth1(p4) p3 = self.smooth2(p3) p2 = self.smooth3(p2) return p2, p3, p4, p5
net_fpn = FPN([3,4,6,3]).cuda() input = torch.randn(16,8,16,16,52).cuda() output = net_fpn(input) print(output[0].shape)
|