飞道的博客

CV+Deep Learning——网络架构Pytorch复现系列——Detection(二:RtinaNet)更换backbones(DarkNet)

424人阅读  评论(0)

上一话

CV+Deep Learning——网络架构Pytorch复现系列——Detection(一:SSD:Single Shot MultiBox Detector 4.推理Detect)https://blog.csdn.net/XiaoyYidiaodiao/article/details/128683973?spm=1001.2014.3001.5501


复现Object Detection,会复现的网络架构有:

1.SSD: Single Shot MultiBox Detector(√)

2.RetinaNet(√)

3.Faster RCNN

4.YOLO系列

....

代码:

https://github.com/HanXiaoyiGitHub/Simple-CV-Pytorch-masterhttps://github.com/HanXiaoyiGitHub/Simple-CV-Pytorch-master


2.复现RetinaNet

之前已经讲过RetinaNet,链接如下:

目标检测——RetinaNet-Focal Loss 焦点损失函数的理解https://blog.csdn.net/XiaoyYidiaodiao/article/details/124553661?spm=1001.2014.3001.5502

也不想做过多的讲解了,就讲讲在RetinaNet中是如何更换Backbones(将以前的ResNet更换为DarkNet)

之前ResNet骨干网络的代码

我懒得写了直接调用Pytorch包的,但是值得注意的是输出的feature map的channels可能需要修改(这里我在RetinaNet.py中进行了修改),与之后Neck(FPN)网络中输入channles匹配。


  
  1. import torch
  2. from torch import nn
  3. from torchvision.models import resnet18, resnet34, resnet50, \
  4. resnet101, resnet152
  5. class ResNet(nn.Module):
  6. def __init__( self, resnet_type="resnet50", pretrained=False):
  7. super(ResNet, self).__init__()
  8. if resnet_type == "resnet18":
  9. self.model = resnet18(pretrained=pretrained)
  10. elif resnet_type == "resnet34":
  11. self.model = resnet34(pretrained=pretrained)
  12. elif resnet_type == "resnet50":
  13. self.model = resnet50(pretrained=pretrained)
  14. elif resnet_type == "resnet101":
  15. self.model = resnet101(pretrained=pretrained)
  16. elif resnet_type == "resnet152":
  17. self.model = resnet152(pretrained=pretrained)
  18. del self.model.fc
  19. del self.model.avgpool
  20. def forward( self, x):
  21. x = self.model.conv1(x)
  22. x = self.model.bn1(x)
  23. x = self.model.relu(x)
  24. x = self.model.maxpool(x)
  25. x = self.model.layer1(x)
  26. C3 = self.model.layer2(x)
  27. C4 = self.model.layer3(C3)
  28. C5 = self.model.layer4(C4)
  29. del x
  30. return [C3, C4, C5]
  31. if __name__ == "__main__":
  32. backbone = ResNet(resnet_type= 'resnet18', pretrained= True)
  33. x = torch.randn([ 16, 3, 512, 512])
  34. C3, C4, C5 = backbone(x)
  35. print(C3.shape) # torch.Size([16, 512, 64, 64])
  36. print(C4.shape) # torch.Size([16, 1024, 32, 32])
  37. print(C5.shape) # torch.Size([16, 2048, 16, 16])

DarkNet骨干网络的代码

这里更换的backbones是DarkNetTiny,DarkNet19和DarkNet53,DarkNet系列是出自YOLO系列,其中DarkNet19是来自于YOLO9000(也就是我们通常意义上的YOLOv2[1],DarkNet53是来自于最经典的YOLOv3[2],而DarkNetTiny是来自YOLOv3-Tiny[2]。


  
  1. import torch
  2. import torch.nn as nn
  3. __all__ = [
  4. 'darknettiny',
  5. 'darknet19',
  6. 'darknet53',
  7. ]
  8. class DarkNet(nn.Module):
  9. def __init__( self, darknet_type='darknet19'):
  10. super(DarkNet, self).__init__()
  11. self.darknet_type = darknet_type
  12. if darknet_type == 'darknettiny':
  13. self.model = darknettiny()
  14. elif darknet_type == 'darknet19':
  15. self.model = darknet19()
  16. elif darknet_type == 'darknet53':
  17. self.model = darknet53()
  18. def forward( self, x):
  19. out = self.model(x)
  20. return out
  21. class ActBlock(nn.Module):
  22. def __init__( self, act_type='leakyrelu', inplace=True):
  23. super(ActBlock, self).__init__()
  24. assert act_type in [ 'silu', 'relu', 'leakyrelu'], \
  25. "Unsupported activation function!"
  26. if act_type == 'silu':
  27. self.act = nn.SiLU(inplace=inplace)
  28. elif act_type == 'relu':
  29. self.act = nn.ReLU(inplace=inplace)
  30. elif act_type == 'leakyrelu':
  31. self.act = nn.LeakyReLU( 0.1, inplace=inplace)
  32. def forward( self, x):
  33. x = self.act(x)
  34. return x
  35. class ConvBlock(nn.Module):
  36. def __init__( self, inplanes, planes, kernel_size, stride, padding, groups=1, has_bn=True, has_act=True,
  37. act_type='leakyrelu'):
  38. super(ConvBlock, self).__init__()
  39. bias = False if has_bn else True
  40. self.layer = nn.Sequential(
  41. nn.Conv2d(in_channels=inplanes, out_channels=planes, kernel_size=kernel_size, stride=stride,
  42. padding=padding, groups=groups, bias=bias),
  43. nn.BatchNorm2d(planes) if has_bn else nn.Sequential(),
  44. ActBlock(act_type=act_type, inplace= True) if has_act else nn.Sequential()
  45. )
  46. def forward( self, x):
  47. x = self.layer(x)
  48. return x
  49. class DarkNetTiny(nn.Module):
  50. def __init__( self, act_type='leakyrelu'):
  51. super(DarkNetTiny, self).__init__()
  52. self.conv1 = ConvBlock(inplanes= 3, planes= 16, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  53. has_act= True, act_type=act_type)
  54. self.conv2 = ConvBlock(inplanes= 16, planes= 32, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  55. has_act= True, act_type=act_type)
  56. self.conv3 = ConvBlock(inplanes= 32, planes= 64, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  57. has_act= True, act_type=act_type)
  58. self.conv4 = ConvBlock(inplanes= 64, planes= 128, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  59. has_act= True, act_type=act_type)
  60. self.conv5 = ConvBlock(inplanes= 128, planes= 256, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  61. has_act= True, act_type=act_type)
  62. self.conv6 = ConvBlock(inplanes= 256, planes= 512, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  63. has_act= True, act_type=act_type)
  64. self.maxpool = nn.MaxPool2d(kernel_size= 2, stride= 2)
  65. self.zeropad = nn.ZeroPad2d(( 0, 1, 0, 1))
  66. self.last_maxpool = nn.MaxPool2d(kernel_size= 2, stride= 1)
  67. self.out_channels = [ 64, 128, 256]
  68. for m in self.modules():
  69. if isinstance(m, nn.Conv2d):
  70. nn.init.kaiming_normal_(m.weight, mode= 'fan_out', nonlinearity= 'relu')
  71. elif isinstance(m, nn.BatchNorm2d):
  72. nn.init.constant_(m.weight, 1)
  73. nn.init.constant_(m.bias, 0)
  74. def forward( self, x):
  75. x = self.conv1(x)
  76. x = self.maxpool(x)
  77. x = self.conv2(x)
  78. x = self.maxpool(x)
  79. C3 = self.conv3(x)
  80. C3 = self.maxpool(C3)
  81. C4 = self.conv4(C3)
  82. C4 = self.maxpool(C4) # 128
  83. C5 = self.conv5(C4)
  84. C5 = self.maxpool(C5) # 256
  85. del x
  86. return [C3, C4, C5]
  87. class D19Block(nn.Module):
  88. def __init__( self, inplanes, planes, layer_num, use_maxpool=False, act_type='leakyrelu'):
  89. super(D19Block, self).__init__()
  90. self.use_maxpool = use_maxpool
  91. layers = []
  92. for i in range( 0, layer_num):
  93. if i % 2 == 0:
  94. layers.append(
  95. ConvBlock(inplanes=inplanes, planes=planes, kernel_size= 3, stride= 1, padding= 1, groups= 1,
  96. has_bn= True, has_act= True, act_type=act_type))
  97. else:
  98. layers.append(
  99. ConvBlock(inplanes=planes, planes=inplanes, kernel_size= 1, stride= 1, padding= 0, groups= 1,
  100. has_bn= True, has_act= True, act_type=act_type))
  101. self.D19Block = nn.Sequential(*layers)
  102. if self.use_maxpool:
  103. self.maxpool = nn.MaxPool2d(kernel_size= 2, stride= 2)
  104. def forward( self, x):
  105. x = self.D19Block(x)
  106. if self.use_maxpool:
  107. x = self.maxpool(x)
  108. return x
  109. class DarkNet19(nn.Module):
  110. def __init__( self, act_type='leakyrelu'):
  111. super(DarkNet19, self).__init__()
  112. self.layer1 = ConvBlock(inplanes= 3, planes= 32, kernel_size= 3, stride= 1, padding= 1, groups= 1, has_bn= True,
  113. has_act= True, act_type=act_type)
  114. self.layer2 = D19Block(inplanes= 32, planes= 64, layer_num= 1, use_maxpool= True, act_type=act_type)
  115. self.layer3 = D19Block(inplanes= 64, planes= 128, layer_num= 3, use_maxpool= True, act_type=act_type)
  116. self.layer4 = D19Block(inplanes= 128, planes= 256, layer_num= 3, use_maxpool= True, act_type=act_type)
  117. self.layer5 = D19Block(inplanes= 256, planes= 512, layer_num= 5, use_maxpool= True, act_type=act_type)
  118. self.layer6 = D19Block(inplanes= 512, planes= 1024, layer_num= 5, use_maxpool= False, act_type=act_type)
  119. self.maxpool = nn.MaxPool2d(kernel_size= 2, stride= 2)
  120. self.out_channels = [ 128, 256, 512]
  121. for m in self.modules():
  122. if isinstance(m, nn.Conv2d):
  123. nn.init.kaiming_normal_(m.weight, mode= 'fan_out', nonlinearity= 'relu')
  124. elif isinstance(m, nn.BatchNorm2d):
  125. nn.init.constant_(m.weight, 1)
  126. nn.init.constant_(m.bias, 0)
  127. def forward( self, x):
  128. x = self.layer1(x)
  129. x = self.maxpool(x)
  130. x = self.layer2(x)
  131. C3 = self.layer3(x)
  132. C4 = self.layer4(C3)
  133. C5 = self.layer5(C4)
  134. del x
  135. return [C3, C4, C5]
  136. # conv*2+residual
  137. class BasicBlock(nn.Module):
  138. def __init__( self, inplanes, planes):
  139. super(BasicBlock, self).__init__()
  140. self.conv1 = ConvBlock(inplanes=inplanes, planes=planes, kernel_size= 1, stride= 1, padding= 0)
  141. self.conv2 = ConvBlock(inplanes=planes, planes=planes * 2, kernel_size= 3, stride= 1, padding= 1)
  142. def forward( self, x):
  143. out = self.conv1(x)
  144. out = self.conv2(out)
  145. out += x
  146. del x
  147. return out
  148. class DarkNet53(nn.Module):
  149. def __init__( self):
  150. super(DarkNet53, self).__init__()
  151. self.conv1 = ConvBlock(inplanes= 3, planes= 32, kernel_size= 3, stride= 1, padding= 1)
  152. self.conv2 = ConvBlock(inplanes= 32, planes= 64, kernel_size= 3, stride= 2, padding= 1)
  153. self.block1 = nn.Sequential(
  154. BasicBlock(inplanes= 64, planes= 32),
  155. ConvBlock(inplanes= 64, planes= 128, kernel_size= 3, stride= 2, padding= 1)
  156. ) # 128
  157. self.block2 = nn.Sequential(
  158. BasicBlock(inplanes= 128, planes= 64),
  159. BasicBlock(inplanes= 128, planes= 64),
  160. ConvBlock(inplanes= 128, planes= 256, kernel_size= 3, stride= 2, padding= 1)
  161. ) # 256
  162. self.block3 = nn.Sequential(
  163. BasicBlock(inplanes= 256, planes= 128),
  164. BasicBlock(inplanes= 256, planes= 128),
  165. BasicBlock(inplanes= 256, planes= 128),
  166. BasicBlock(inplanes= 256, planes= 128),
  167. BasicBlock(inplanes= 256, planes= 128),
  168. BasicBlock(inplanes= 256, planes= 128),
  169. BasicBlock(inplanes= 256, planes= 128),
  170. BasicBlock(inplanes= 256, planes= 128),
  171. ConvBlock(inplanes= 256, planes= 512, kernel_size= 3, stride= 2, padding= 1)
  172. ) # 512
  173. self.block4 = nn.Sequential(
  174. BasicBlock(inplanes= 512, planes= 256),
  175. BasicBlock(inplanes= 512, planes= 256),
  176. BasicBlock(inplanes= 512, planes= 256),
  177. BasicBlock(inplanes= 512, planes= 256),
  178. BasicBlock(inplanes= 512, planes= 256),
  179. BasicBlock(inplanes= 512, planes= 256),
  180. BasicBlock(inplanes= 512, planes= 256),
  181. BasicBlock(inplanes= 512, planes= 256),
  182. ConvBlock(inplanes= 512, planes= 1024, kernel_size= 3, stride= 2, padding= 1)
  183. ) # 1024
  184. self.block5 = nn.Sequential(
  185. BasicBlock(inplanes= 1024, planes= 512),
  186. BasicBlock(inplanes= 1024, planes= 512),
  187. BasicBlock(inplanes= 1024, planes= 512),
  188. BasicBlock(inplanes= 1024, planes= 512)
  189. )
  190. self.out_channels = [ 256, 512, 1024]
  191. for m in self.modules():
  192. if isinstance(m, nn.Conv2d):
  193. nn.init.kaiming_normal_(m.weight, mode= 'fan_out', nonlinearity= 'relu')
  194. elif isinstance(m, nn.BatchNorm2d):
  195. nn.init.constant_(m.weight, 1)
  196. nn.init.constant_(m.bias, 0)
  197. def forward( self, x):
  198. x = self.conv1(x)
  199. x = self.conv2(x)
  200. x = self.block1(x)
  201. C3 = self.block2(x)
  202. C4 = self.block3(C3)
  203. C5 = self.block4(C4)
  204. del x
  205. return [C3, C4, C5]
  206. def darknettiny( **kwargs):
  207. model = DarkNetTiny(**kwargs)
  208. return model
  209. def darknet19( **kwargs):
  210. model = DarkNet19(**kwargs)
  211. return model
  212. def darknet53( **kwargs):
  213. model = DarkNet53(**kwargs)
  214. return model
  215. if __name__ == '__main__':
  216. x = torch.randn([ 8, 3, 512, 512])
  217. darknet = DarkNet(darknet_type= 'darknet53')
  218. [C3, C4, C5] = darknet(x)
  219. print( "C3.shape:{}". format(C3.shape))
  220. print( "C4.shape:{}". format(C4.shape))
  221. print( "C5.shape:{}". format(C5.shape))
  222. # DarkNet53
  223. # C3.shape: torch.Size([8, 256, 64, 64])
  224. # C4.shape: torch.Size([8, 512, 32, 32])
  225. # C5.shape: torch.Size([8, 1024, 16, 16])
  226. # DarkNet19
  227. # C3.shape: torch.Size([8, 128, 64, 64])
  228. # C4.shape: torch.Size([8, 256, 32, 32])
  229. # C5.shape: torch.Size([8, 512, 16, 16])
  230. # DarkNetTiny
  231. # C3.shape: torch.Size([8, 64, 64, 64])
  232. # C4.shape: torch.Size([8, 128, 32, 32])
  233. # C5.shape: torch.Size([8, 256, 16, 16])

如何在RetinaNet网络中使用呢?我设置了个Backbones_type,修改这个就行。

RetinaNet.py代码


  
  1. import os
  2. import sys
  3. BASE_DIR = os.path.dirname(
  4. os.path.dirname(
  5. os.path.abspath(__file__)))
  6. sys.path.append(BASE_DIR)
  7. import torch
  8. import torch.nn as nn
  9. from torchvision.ops import nms
  10. from models.detection.RetinaNet.neck import FPN
  11. from models.detection.RetinaNet.loss import FocalLoss
  12. from models.detection.RetinaNet.anchor import Anchors
  13. from models.detection.RetinaNet.head import clsHead, regHead
  14. from models.detection.RetinaNet.backbones.ResNet import ResNet
  15. from models.detection.RetinaNet.utils.ClipBoxes import ClipBoxes
  16. from models.detection.RetinaNet.backbones.DarkNet import DarkNet
  17. from models.detection.RetinaNet.utils.BBoxTransform import BBoxTransform
  18. # assert input annotations are [x_min, y_min, x_max, y_max]
  19. class RetinaNet(nn.Module):
  20. def __init__( self,
  21. backbones_type="resnet50",
  22. num_classes=80,
  23. planes=256,
  24. pretrained=False,
  25. training=False):
  26. super(RetinaNet, self).__init__()
  27. self.backbones_type = backbones_type
  28. # coco 80, voc 20
  29. self.num_classes = num_classes
  30. self.planes = planes
  31. self.training = training
  32. if backbones_type[: 6] == 'resnet':
  33. self.backbone = ResNet(resnet_type=self.backbones_type,
  34. pretrained=pretrained)
  35. elif backbones_type[: 7] == 'darknet':
  36. self.backbone = DarkNet(darknet_type=self.backbones_type)
  37. expand_ratio = {
  38. "resnet18": 1,
  39. "resnet34": 1,
  40. "resnet50": 4,
  41. "resnet101": 4,
  42. "resnet152": 4,
  43. "darknettiny": 0.5,
  44. "darknet19": 1,
  45. "darknet53": 2
  46. }
  47. C3_inplanes, C4_inplanes, C5_inplanes = \
  48. int( 128 * expand_ratio[self.backbones_type]), \
  49. int( 256 * expand_ratio[self.backbones_type]), \
  50. int( 512 * expand_ratio[self.backbones_type])
  51. self.fpn = FPN(C3_inplanes=C3_inplanes,
  52. C4_inplanes=C4_inplanes,
  53. C5_inplanes=C5_inplanes,
  54. planes=self.planes)
  55. self.cls_head = clsHead(inplanes=self.planes,
  56. num_classes=self.num_classes)
  57. self.reg_head = regHead(inplanes=self.planes)
  58. self.anchors = Anchors()
  59. self.regressBoxes = BBoxTransform()
  60. self.clipBoxes = ClipBoxes()
  61. self.loss = FocalLoss()
  62. self.freeze_bn()
  63. def freeze_bn( self):
  64. '''Freeze BatchNorm layers.'''
  65. for layer in self.modules():
  66. if isinstance(layer, nn.BatchNorm2d):
  67. layer. eval()
  68. def forward( self, inputs):
  69. if self.training:
  70. img_batch, annots = inputs
  71. # inference
  72. else:
  73. img_batch = inputs
  74. [C3, C4, C5] = self.backbone(img_batch)
  75. del inputs
  76. features = self.fpn([C3, C4, C5])
  77. del C3, C4, C5
  78. # (batch_size, total_anchors_nums, num_classes)
  79. cls_heads = torch.cat([self.cls_head(feature) for feature in features], dim= 1)
  80. # (batch_size, total_anchors_nums, 4)
  81. reg_heads = torch.cat([self.reg_head(feature) for feature in features], dim= 1)
  82. del features
  83. anchors = self.anchors(img_batch)
  84. if self.training:
  85. return self.loss(cls_heads, reg_heads, anchors, annots)
  86. # inference
  87. else:
  88. transformed_anchors = self.regressBoxes(anchors, reg_heads)
  89. transformed_anchors = self.clipBoxes(transformed_anchors, img_batch)
  90. # scores
  91. finalScores = torch.Tensor([])
  92. # anchor id:0~79
  93. finalAnchorBoxesIndexes = torch.Tensor([]).long()
  94. # coordinates size:[...,4]
  95. finalAnchorBoxesCoordinates = torch.Tensor([])
  96. if torch.cuda.is_available():
  97. finalScores = finalScores.cuda()
  98. finalAnchorBoxesIndexes = finalAnchorBoxesIndexes.cuda()
  99. finalAnchorBoxesCoordinates = finalAnchorBoxesCoordinates.cuda()
  100. # num_classes
  101. for i in range(cls_heads.shape[ 2]):
  102. scores = torch.squeeze(cls_heads[:, :, i])
  103. scores_over_thresh = (scores > 0.05)
  104. if scores_over_thresh. sum() == 0:
  105. # no boxes to NMS, just continue
  106. continue
  107. scores = scores[scores_over_thresh]
  108. anchorBoxes = torch.squeeze(transformed_anchors)
  109. anchorBoxes = anchorBoxes[scores_over_thresh]
  110. anchors_nms_idx = nms(anchorBoxes, scores, 0.5)
  111. # use idx to find the scores of anchor
  112. finalScores = torch.cat((finalScores, scores[anchors_nms_idx]))
  113. # [0,0,0,...,1,1,1,...,79,79]
  114. finalAnchorBoxesIndexesValue = torch.tensor([i] * anchors_nms_idx.shape[ 0])
  115. if torch.cuda.is_available():
  116. finalAnchorBoxesIndexesValue = finalAnchorBoxesIndexesValue.cuda()
  117. finalAnchorBoxesIndexes = torch.cat((finalAnchorBoxesIndexes, finalAnchorBoxesIndexesValue))
  118. # [...,4]
  119. finalAnchorBoxesCoordinates = torch.cat((finalAnchorBoxesCoordinates, anchorBoxes[anchors_nms_idx]))
  120. return finalScores, finalAnchorBoxesIndexes, finalAnchorBoxesCoordinates
  121. if __name__ == "__main__":
  122. C = torch.randn([ 8, 3, 512, 512])
  123. annot = torch.randn([ 8, 15, 5])
  124. model = RetinaNet(backbones_type= "darknet19", num_classes= 80, pretrained= True, training= True)
  125. model = model.cuda()
  126. C = C.cuda()
  127. annot = annot.cuda()
  128. model = torch.nn.DataParallel(model).cuda()
  129. model.training = True
  130. out = model([C, annot])
  131. # if model.training == True out==loss
  132. # out = model([C, annot])
  133. # if model.training == False out== scores
  134. # out = model(C)
  135. for i in range( len(out)):
  136. print(out[i])
  137. # Scores: torch.Size([486449])
  138. # tensor([4.1057, 4.0902, 4.0597, ..., 0.0509, 0.0507, 0.0507], device='cuda:0')
  139. # Id: torch.Size([486449])
  140. # tensor([ 0, 0, 0, ..., 79, 79, 79], device='cuda:0')
  141. # loc: torch.Size([486449, 4])
  142. # tensor([[ 45.1607, 249.4807, 170.5788, 322.8085],
  143. # [ 85.9825, 324.4150, 122.9968, 382.6297],
  144. # [148.1854, 274.0474, 179.0922, 343.4529],
  145. # ...,
  146. # [222.5421, 0.0000, 256.3059, 15.5591],
  147. # [143.3349, 204.4784, 170.2395, 228.6654],
  148. # [208.4509, 140.1983, 288.0962, 165.8708]], device='cuda:0')

使用此模型的评估结果(并非以上的DarkNet骨干网络,而是自带的ResNet),未精细调节参数以及精度

模型评估VOC结果


  
  1. Network: RetinaNet
  2. backbone: ResNet50
  3. neck: FPN
  4. loss: Focal Loss
  5. dataset: voc
  6. batch_size: 4
  7. optim: Adam
  8. lr: 0.0001
  9. scheduler: WarmupCosineSchedule
  10. epoch: 80

epochs AP(%) Download Baidu yun Key
80 70.1 https://pan.baidu.com/s/1Bv9IodSnNszbpsxGdzJn0g dww8

模型voc可视化结果

 


模型评估COCO结果


  
  1. Network: RetinaNet
  2. backbone: ResNet50
  3. neck: FPN
  4. loss: Focal Loss
  5. dataset: coco
  6. batch_size: 4
  7. optim: Adam
  8. lr: 0.0001
  9. scheduler: ReduceLROnPlateau
  10. patience: 3
  11. epoch: 30
  12. pretrained: True

epochs AP(%) Download Baidu yun Key
30 29.3 https://pan.baidu.com/s/1eosb5gi9HowC5B-fFncT2g 5vak

模型COCO可视化结果

 


若想知道更多代码详情,请翻看我的gitHub!!

未完...


参考文献

[1] Redmon J, Farhadi A. YOLO9000: better, faster, stronger[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 7263-7271.

[2] Redmon J, Farhadi A. Yolov3: An incremental improvement[J]. arXiv preprint arXiv:1804.02767, 2018.

[3] Lin T Y, Goyal P, Girshick R, et al. Focal loss for dense object detection[C]//Proceedings of the IEEE international conference on computer vision. 2017: 2980-2988.


转载:https://blog.csdn.net/XiaoyYidiaodiao/article/details/128689730
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场