|
|
@@ -36,7 +36,7 @@ def DWConv(c1, c2, k=1, s=1, act=True): |
|
|
|
class Conv(nn.Module): |
|
|
|
# Standard convolution |
|
|
|
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups |
|
|
|
super(Conv, self).__init__() |
|
|
|
super().__init__() |
|
|
|
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False) |
|
|
|
self.bn = nn.BatchNorm2d(c2) |
|
|
|
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) |
|
|
@@ -87,7 +87,7 @@ class TransformerBlock(nn.Module): |
|
|
|
class Bottleneck(nn.Module): |
|
|
|
# Standard bottleneck |
|
|
|
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5): # ch_in, ch_out, shortcut, groups, expansion |
|
|
|
super(Bottleneck, self).__init__() |
|
|
|
super().__init__() |
|
|
|
c_ = int(c2 * e) # hidden channels |
|
|
|
self.cv1 = Conv(c1, c_, 1, 1) |
|
|
|
self.cv2 = Conv(c_, c2, 3, 1, g=g) |
|
|
@@ -100,7 +100,7 @@ class Bottleneck(nn.Module): |
|
|
|
class BottleneckCSP(nn.Module): |
|
|
|
# CSP Bottleneck https://github.com/WongKinYiu/CrossStagePartialNetworks |
|
|
|
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion |
|
|
|
super(BottleneckCSP, self).__init__() |
|
|
|
super().__init__() |
|
|
|
c_ = int(c2 * e) # hidden channels |
|
|
|
self.cv1 = Conv(c1, c_, 1, 1) |
|
|
|
self.cv2 = nn.Conv2d(c1, c_, 1, 1, bias=False) |
|
|
@@ -119,7 +119,7 @@ class BottleneckCSP(nn.Module): |
|
|
|
class C3(nn.Module): |
|
|
|
# CSP Bottleneck with 3 convolutions |
|
|
|
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansion |
|
|
|
super(C3, self).__init__() |
|
|
|
super().__init__() |
|
|
|
c_ = int(c2 * e) # hidden channels |
|
|
|
self.cv1 = Conv(c1, c_, 1, 1) |
|
|
|
self.cv2 = Conv(c1, c_, 1, 1) |
|
|
@@ -139,10 +139,18 @@ class C3TR(C3): |
|
|
|
self.m = TransformerBlock(c_, c_, 4, n) |
|
|
|
|
|
|
|
|
|
|
|
class C3SPP(C3): |
|
|
|
# C3 module with SPP() |
|
|
|
def __init__(self, c1, c2, k=(5, 9, 13), n=1, shortcut=True, g=1, e=0.5): |
|
|
|
super().__init__(c1, c2, n, shortcut, g, e) |
|
|
|
c_ = int(c2 * e) |
|
|
|
self.m = SPP(c_, c_, k) |
|
|
|
|
|
|
|
|
|
|
|
class SPP(nn.Module): |
|
|
|
# Spatial pyramid pooling layer used in YOLOv3-SPP |
|
|
|
def __init__(self, c1, c2, k=(5, 9, 13)): |
|
|
|
super(SPP, self).__init__() |
|
|
|
super().__init__() |
|
|
|
c_ = c1 // 2 # hidden channels |
|
|
|
self.cv1 = Conv(c1, c_, 1, 1) |
|
|
|
self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1) |
|
|
@@ -156,7 +164,7 @@ class SPP(nn.Module): |
|
|
|
class Focus(nn.Module): |
|
|
|
# Focus wh information into c-space |
|
|
|
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups |
|
|
|
super(Focus, self).__init__() |
|
|
|
super().__init__() |
|
|
|
self.conv = Conv(c1 * 4, c2, k, s, p, g, act) |
|
|
|
# self.contract = Contract(gain=2) |
|
|
|
|
|
|
@@ -196,27 +204,13 @@ class Expand(nn.Module): |
|
|
|
class Concat(nn.Module): |
|
|
|
# Concatenate a list of tensors along dimension |
|
|
|
def __init__(self, dimension=1): |
|
|
|
super(Concat, self).__init__() |
|
|
|
super().__init__() |
|
|
|
self.d = dimension |
|
|
|
|
|
|
|
def forward(self, x): |
|
|
|
return torch.cat(x, self.d) |
|
|
|
|
|
|
|
|
|
|
|
class NMS(nn.Module): |
|
|
|
# Non-Maximum Suppression (NMS) module |
|
|
|
conf = 0.25 # confidence threshold |
|
|
|
iou = 0.45 # IoU threshold |
|
|
|
classes = None # (optional list) filter by class |
|
|
|
max_det = 1000 # maximum number of detections per image |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
super(NMS, self).__init__() |
|
|
|
|
|
|
|
def forward(self, x): |
|
|
|
return non_max_suppression(x[0], self.conf, iou_thres=self.iou, classes=self.classes, max_det=self.max_det) |
|
|
|
|
|
|
|
|
|
|
|
class AutoShape(nn.Module): |
|
|
|
# YOLOv5 input-robust model wrapper for passing cv2/np/PIL/torch inputs. Includes preprocessing, inference and NMS |
|
|
|
conf = 0.25 # NMS confidence threshold |
|
|
@@ -225,7 +219,7 @@ class AutoShape(nn.Module): |
|
|
|
max_det = 1000 # maximum number of detections per image |
|
|
|
|
|
|
|
def __init__(self, model): |
|
|
|
super(AutoShape, self).__init__() |
|
|
|
super().__init__() |
|
|
|
self.model = model.eval() |
|
|
|
|
|
|
|
def autoshape(self): |
|
|
@@ -292,7 +286,7 @@ class AutoShape(nn.Module): |
|
|
|
class Detections: |
|
|
|
# YOLOv5 detections class for inference results |
|
|
|
def __init__(self, imgs, pred, files, times=None, names=None, shape=None): |
|
|
|
super(Detections, self).__init__() |
|
|
|
super().__init__() |
|
|
|
d = pred[0].device # device |
|
|
|
gn = [torch.tensor([*[im.shape[i] for i in [1, 0, 1, 0]], 1., 1.], device=d) for im in imgs] # normalizations |
|
|
|
self.imgs = imgs # list of images as numpy arrays |
|
|
@@ -383,7 +377,7 @@ class Detections: |
|
|
|
class Classify(nn.Module): |
|
|
|
# Classification head, i.e. x(b,c1,20,20) to x(b,c2) |
|
|
|
def __init__(self, c1, c2, k=1, s=1, p=None, g=1): # ch_in, ch_out, kernel, stride, padding, groups |
|
|
|
super(Classify, self).__init__() |
|
|
|
super().__init__() |
|
|
|
self.aap = nn.AdaptiveAvgPool2d(1) # to x(b,c1,1,1) |
|
|
|
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g) # to x(b,c2,1,1) |
|
|
|
self.flat = nn.Flatten() |