backbone_factory.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. from collections import OrderedDict
  2. import torchvision
  3. from torchvision.models import maxvit_t
  4. from torchvision.models.detection.backbone_utils import BackboneWithFPN
  5. from libs.vision_libs import models
  6. from libs.vision_libs.models import mobilenet_v3_large, EfficientNet_V2_S_Weights, efficientnet_v2_s, \
  7. EfficientNet_V2_M_Weights, efficientnet_v2_m, EfficientNet_V2_L_Weights, efficientnet_v2_l, ConvNeXt_Base_Weights
  8. from libs.vision_libs.models._utils import _ovewrite_value_param, handle_legacy_interface
  9. from libs.vision_libs.models.detection import FasterRCNN
  10. from libs.vision_libs.models.detection.anchor_utils import AnchorGenerator
  11. from libs.vision_libs.models.detection.ssdlite import _mobilenet_extractor
  12. from libs.vision_libs.models.resnet import resnet50, ResNet50_Weights, resnet18
  13. from libs.vision_libs.models.detection.backbone_utils import _resnet_fpn_extractor, _validate_trainable_layers
  14. from libs.vision_libs.ops import misc as misc_nn_ops, MultiScaleRoIAlign
  15. from torch import nn
  16. import torch
  17. from models.base.high_reso_swin import swin_v2_t
  18. def get_resnet50_fpn():
  19. is_trained = False
  20. trainable_backbone_layers = _validate_trainable_layers(is_trained, None, 5, 3)
  21. norm_layer = misc_nn_ops.FrozenBatchNorm2d if is_trained else nn.BatchNorm2d
  22. backbone = resnet50(weights=None, progress=True, norm_layer=norm_layer)
  23. backbone = _resnet_fpn_extractor(backbone, trainable_backbone_layers)
  24. return backbone
  25. def get_resnet18_fpn():
  26. is_trained = False
  27. trainable_backbone_layers = _validate_trainable_layers(is_trained, None, 5, 3)
  28. norm_layer = misc_nn_ops.FrozenBatchNorm2d if is_trained else nn.BatchNorm2d
  29. backbone = resnet18(weights=None, progress=True, norm_layer=norm_layer)
  30. backbone = _resnet_fpn_extractor(backbone, trainable_backbone_layers)
  31. return backbone
  32. def get_mobilenet_v3_large_fpn():
  33. is_trained = False
  34. trainable_backbone_layers = _validate_trainable_layers(is_trained, None, 6, 3)
  35. norm_layer = misc_nn_ops.FrozenBatchNorm2d if is_trained else nn.BatchNorm2d
  36. backbone = mobilenet_v3_large(weights=None, progress=True, norm_layer=norm_layer)
  37. backbone = _mobilenet_extractor(backbone, True, trainable_backbone_layers)
  38. return backbone
  39. def get_convnext_fpn():
  40. convnext = models.convnext_base(weights=ConvNeXt_Base_Weights.DEFAULT)
  41. # convnext = models.convnext_small(pretrained=True)
  42. # convnext = models.convnext_large(pretrained=True)
  43. in_channels_list = [128, 256, 512, 1024]
  44. backbone_with_fpn = BackboneWithFPN(
  45. convnext.features,
  46. return_layers={'1': '0', '3': '1', '5': '2', '7': '3'}, # 确保这些键对应到实际的层
  47. in_channels_list=in_channels_list,
  48. out_channels=256
  49. )
  50. return backbone_with_fpn
  51. def get_maxvit_fpn(input_size=(224*7,224*7)):
  52. maxvit = MaxVitBackbone(input_size=input_size)
  53. # print(maxvit.named_children())
  54. # for i,layer in enumerate(maxvit.named_children()):
  55. # print(f'layer:{i}:{layer}')
  56. test_input = torch.randn(1, 3, 224 * 7, 224 * 7)
  57. in_channels_list = [64, 64, 128, 256, 512]
  58. featmap_names = ['0', '1', '2', '3', '4', 'pool']
  59. # print(f'featmap_names:{featmap_names}')
  60. roi_pooler = MultiScaleRoIAlign(
  61. featmap_names=featmap_names,
  62. output_size=7,
  63. sampling_ratio=2
  64. )
  65. backbone_with_fpn = BackboneWithFPN(
  66. maxvit,
  67. return_layers={'stem': '0', 'block0': '1', 'block1': '2', 'block2': '3', 'block3': '4'}, # 确保这些键对应到实际的层
  68. in_channels_list=in_channels_list,
  69. out_channels=256
  70. )
  71. rpn_anchor_generator = get_anchor_generator(backbone_with_fpn, test_input=test_input),
  72. return backbone_with_fpn,rpn_anchor_generator,roi_pooler
  73. def get_efficientnetv2_fpn(name='efficientnet_v2_m', pretrained=True):
  74. # 加载EfficientNetV2模型
  75. if name == 'efficientnet_v2_s':
  76. weights = EfficientNet_V2_S_Weights.IMAGENET1K_V1 if pretrained else None
  77. backbone = efficientnet_v2_s(weights=weights).features
  78. if name == 'efficientnet_v2_m':
  79. weights = EfficientNet_V2_M_Weights.IMAGENET1K_V1 if pretrained else None
  80. backbone = efficientnet_v2_m(weights=weights).features
  81. if name == 'efficientnet_v2_l':
  82. weights = EfficientNet_V2_L_Weights.IMAGENET1K_V1 if pretrained else None
  83. backbone = efficientnet_v2_l(weights=weights).features
  84. # 定义返回的层索引和名称
  85. return_layers = {"1":"0", "2": "1", "3": "2", "4": "3", "6": "4"}
  86. input=torch.randn(1, 3, 512, 512)
  87. # out=backbone(input)
  88. # print(f'out:{out}')
  89. # 获取每个层输出通道数
  90. in_channels_list = []
  91. for layer_idx in [1,2, 3, 4, 6]:
  92. module = backbone[layer_idx]
  93. # print(f'efficientnet:{backbone}')
  94. if hasattr(module, 'out_channels'):
  95. in_channels_list.append(module.out_channels)
  96. elif hasattr(module[-1], 'out_channels'):
  97. # 如果module本身没有out_channels,检查最后一个子模块
  98. in_channels_list.append(module[-1].out_channels)
  99. else:
  100. raise ValueError(f"Cannot determine out_channels for layer {layer_idx}")
  101. # 使用BackboneWithFPN包装backbone
  102. print(f'in_channels_list: {in_channels_list}')
  103. backbone_with_fpn = BackboneWithFPN(
  104. backbone=backbone,
  105. return_layers=return_layers,
  106. in_channels_list=in_channels_list,
  107. out_channels=256
  108. )
  109. out=backbone_with_fpn(input)
  110. print(f'out0:{out['0'].shape}')
  111. print(f'out1:{out['1'].shape}')
  112. print(f'out2:{out['2'].shape}')
  113. print(f'out3:{out['3'].shape}')
  114. print(f'out4:{out['4'].shape}')
  115. return backbone_with_fpn
  116. # 加载 ConvNeXt 模型
  117. # convnext = models.convnext_base(pretrained=True)
  118. # convnext = models.convnext_tiny(pretrained=True)
  119. # convnext = models.convnext_small(pretrained=True)
  120. # print(convnext)
  121. # # 打印模型的所有命名层
  122. # for name, _ in convnext.features[5].named_children():
  123. # print(name)
  124. # 修改 ConvNeXt 以适应 Faster R-CNN
  125. # 修改 ConvNeXt 以适应 Faster R-CNN
  126. def get_anchor_generator(backbone, test_input):
  127. features = backbone(test_input) # 获取 backbone 输出的所有特征图
  128. featmap_names = list(features.keys())
  129. print(f'featmap_names:{featmap_names}')
  130. num_features = len(features) # 特征图数量
  131. print(f'num_features:{num_features}')
  132. # num_features=num_features-1
  133. # # 定义每层的 anchor 尺寸和比例
  134. # base_sizes = [32, 64, 128] # 支持最多 4 层
  135. # sizes = tuple((size,) for size in base_sizes[:num_features])
  136. anchor_sizes = tuple((int(16 * 2 ** i),) for i in range(num_features)) # 自动生成不同大小
  137. print(f'anchor_sizes:{anchor_sizes }')
  138. aspect_ratios = ((0.5, 1.0, 2.0),) * num_features
  139. print(f'aspect_ratios:{aspect_ratios}')
  140. return AnchorGenerator(sizes=anchor_sizes , aspect_ratios=aspect_ratios)
  141. class MaxVitBackbone(torch.nn.Module):
  142. def __init__(self,input_size=(224*7,224*7)):
  143. super(MaxVitBackbone, self).__init__()
  144. # 提取MaxVit的部分层作为特征提取器
  145. maxvit_model =maxvit_t(pretrained=False,input_size=input_size)
  146. self.stem = maxvit_model.stem # Stem层
  147. self.block0= maxvit_model.blocks[0]
  148. self.block1 = maxvit_model.blocks[1]
  149. self.block2 = maxvit_model.blocks[2]
  150. self.block3 = maxvit_model.blocks[3]
  151. def forward(self, x):
  152. print("Input size:", x.shape)
  153. x = self.stem(x)
  154. print("After stem size:", x.shape)
  155. x = self.block0(x)
  156. print("After block0 size:", x.shape)
  157. x = self.block1(x)
  158. print("After block1 size:", x.shape)
  159. x = self.block2(x)
  160. print("After block2 size:", x.shape)
  161. x = self.block3(x)
  162. print("After block3 size:", x.shape)
  163. return x
  164. from torchvision.models.feature_extraction import create_feature_extractor
  165. def get_swin_transformer_fpn(type='t'):
  166. class Trans(nn.Module):
  167. def __init__(self):
  168. super().__init__()
  169. def forward(self,x):
  170. x=x.permute(0, 3, 2, 1).contiguous()
  171. return x
  172. class SwinTransformer(nn.Module):
  173. def __init__(self,type='t'):
  174. super().__init__()
  175. swin = swin_v2_t(weights=None)
  176. if type=='t':
  177. # 加载 Swin Transformer v2 Tiny
  178. # swin = torchvision.models.swin_v2_t(weights=None)
  179. swin =swin_v2_t(weights=None)
  180. if type=='s':
  181. swin=torchvision.models.swin_v2_s(weights=None)
  182. if type=='b':
  183. swin=torchvision.models.swin_v2_b(weights=None)
  184. # for i,layer in enumerate(swin.named_children()):
  185. # print(f'layer{i}:,{layer}')
  186. # 保存需要提取的层
  187. self.layer0 = swin.features[0] # 第0层 patch embedding
  188. self.layer1 =nn.Sequential(swin.features[1],Trans()) # 第1层 stage1
  189. self.layer2 =nn.Sequential(Trans(),swin.features[2]) # 第2层 downsample
  190. self.layer3 =nn.Sequential(swin.features[3], Trans()) # 第3层 stage2
  191. self.layer4 =nn.Sequential( Trans(),swin.features[4]) # 第4层 downsample
  192. self.layer5 =nn.Sequential(swin.features[5], Trans()) # 第5层 stage3
  193. self.layer6 =nn.Sequential(Trans(),swin.features[6]) # 第6层 downsample
  194. self.layer7 =nn.Sequential(swin.features[7], Trans()) # 第7层 stage4
  195. def forward(self, x):
  196. x = self.layer0(x) # [B, C, H, W] -> [B, H_, W_, C]
  197. print(f'x0:{x.shape}')
  198. x = self.layer1(x)
  199. print(f'x1:{x.shape}')
  200. x = self.layer2(x)
  201. x = self.layer3(x)
  202. print(f'x2:{x.shape}')
  203. x = self.layer4(x)
  204. x = self.layer5(x)
  205. print(f'x3:{x.shape}')
  206. x = self.layer6(x)
  207. x = self.layer7(x)
  208. print(f'x4:{x.shape}')
  209. return x
  210. backbone = SwinTransformer(type=type)
  211. input=torch.randn(1,3,512,512)
  212. out=backbone(input)
  213. # print(f'out:{out.keys()}')
  214. # for i,layer in enumerate(swin.features.named_children()):
  215. # print(f'layer:{i}:{layer}')
  216. # out=swin(input)
  217. # print(f'out shape:{out.shape}')
  218. #
  219. channels_list = [96, 192, 384, 768]
  220. if type=='t':
  221. channels_list = [96, 192, 384, 768]
  222. if type=='s':
  223. channels_list = [96, 192, 384, 768]
  224. if type=='b':
  225. channels_list = [128, 256, 512, 1024]
  226. backbone_with_fpn = BackboneWithFPN(
  227. # swin.features,
  228. backbone,
  229. return_layers={'layer1': '0', 'layer3': '1', 'layer5': '2', 'layer7': '3'},
  230. in_channels_list=channels_list,
  231. out_channels=128
  232. )
  233. featmap_names = ['0', '1', '2', '3', 'pool']
  234. # print(f'featmap_names:{featmap_names}')
  235. roi_pooler = MultiScaleRoIAlign(
  236. featmap_names=featmap_names,
  237. output_size=7,
  238. sampling_ratio=2
  239. )
  240. # out=backbone_with_fpn(input)
  241. anchor_generator = get_anchor_generator(backbone_with_fpn, test_input=input)
  242. # print(f'out:{out}')
  243. return backbone_with_fpn,roi_pooler,anchor_generator
  244. if __name__ == '__main__':
  245. # backbone_with_fpn, roi_pooler, anchor_generator=get_swin_transformer_fpn(type='t')
  246. # model=FasterRCNN(backbone=backbone_with_fpn,num_classes=3,box_roi_pool=roi_pooler,rpn_anchor_generator=anchor_generator)
  247. # input=torch.randn(3,3,512,512,device='cuda')
  248. # model.eval()
  249. # model.to('cuda')
  250. # out=model(input)
  251. # out=backbone_with_fpn(input)
  252. # print(f'out:{out.shape}')
  253. backbone=get_efficientnetv2_fpn(name='efficientnet_v2_l')
  254. print(backbone)
  255. # # maxvit = models.maxvit_t(pretrained=True)
  256. # maxvit=MaxVitBackbone()
  257. # # print(maxvit.named_children())
  258. #
  259. # for i,layer in enumerate(maxvit.named_children()):
  260. # print(f'layer:{i}:{layer}')
  261. #
  262. # in_channels_list = [64,64,128, 256, 512]
  263. # backbone_with_fpn = BackboneWithFPN(
  264. # maxvit,
  265. # return_layers={'stem': '0','block0':'1','block1':'2','block2':'3','block3':'4'}, # 确保这些键对应到实际的层
  266. # in_channels_list=in_channels_list,
  267. # out_channels=256
  268. # )
  269. # model = FasterRCNN(
  270. # backbone=backbone_with_fpn,
  271. # num_classes=91, # COCO 数据集有 91 类
  272. # # rpn_anchor_generator=anchor_generator,
  273. # # box_roi_pool=roi_pooler
  274. # )
  275. #
  276. # test_input = torch.randn(1, 3, 896, 896)
  277. #
  278. # with torch.no_grad():
  279. # output = backbone_with_fpn(test_input)
  280. #
  281. # print("Output feature maps:")
  282. # for k, v in output.items():
  283. # print(f"{k}: {v.shape}")
  284. # model.eval()
  285. # output=model(test_input)