PKaushik's picture
commit
b9ee486
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import math
import torch.nn as nn
from yolov6.layers.common import *
from yolov6.utils.torch_utils import initialize_weights
from yolov6.models.efficientrep import EfficientRep
from yolov6.models.reppan import RepPANNeck
from yolov6.models.effidehead import Detect, build_effidehead_layer
class Model(nn.Module):
'''YOLOv6 model with backbone, neck and head.
The default parts are EfficientRep Backbone, Rep-PAN and
Efficient Decoupled Head.
'''
def __init__(self, config, channels=3, num_classes=None, anchors=None): # model, input channels, number of classes
super().__init__()
# Build network
num_layers = config.model.head.num_layers
self.backbone, self.neck, self.detect = build_network(config, channels, num_classes, anchors, num_layers)
# Init Detect head
begin_indices = config.model.head.begin_indices
out_indices_head = config.model.head.out_indices
self.stride = self.detect.stride
self.detect.i = begin_indices
self.detect.f = out_indices_head
self.detect.initialize_biases()
# Init weights
initialize_weights(self)
def forward(self, x):
x = self.backbone(x)
x = self.neck(x)
x = self.detect(x)
return x
def _apply(self, fn):
self = super()._apply(fn)
self.detect.stride = fn(self.detect.stride)
self.detect.grid = list(map(fn, self.detect.grid))
return self
def make_divisible(x, divisor):
# Upward revision the value x to make it evenly divisible by the divisor.
return math.ceil(x / divisor) * divisor
def build_network(config, channels, num_classes, anchors, num_layers):
depth_mul = config.model.depth_multiple
width_mul = config.model.width_multiple
num_repeat_backbone = config.model.backbone.num_repeats
channels_list_backbone = config.model.backbone.out_channels
num_repeat_neck = config.model.neck.num_repeats
channels_list_neck = config.model.neck.out_channels
num_anchors = config.model.head.anchors
num_repeat = [(max(round(i * depth_mul), 1) if i > 1 else i) for i in (num_repeat_backbone + num_repeat_neck)]
channels_list = [make_divisible(i * width_mul, 8) for i in (channels_list_backbone + channels_list_neck)]
backbone = EfficientRep(
in_channels=channels,
channels_list=channels_list,
num_repeats=num_repeat
)
neck = RepPANNeck(
channels_list=channels_list,
num_repeats=num_repeat
)
head_layers = build_effidehead_layer(channels_list, num_anchors, num_classes)
head = Detect(num_classes, anchors, num_layers, head_layers=head_layers)
return backbone, neck, head
def build_model(cfg, num_classes, device):
model = Model(cfg, channels=3, num_classes=num_classes, anchors=cfg.model.head.anchors).to(device)
return model