yolo_head.py 2.5 KB
Newer Older
1
import paddle.fluid as fluid
W
wangguanzhong 已提交
2
import paddle
W
wangxinxin08 已提交
3 4 5
import paddle.nn as nn
import paddle.nn.functional as F
from paddle import ParamAttr
6 7 8 9 10 11
from paddle.fluid.regularizer import L2Decay
from ppdet.core.workspace import register
from ..backbone.darknet import ConvBNLayer


@register
W
wangxinxin08 已提交
12
class YOLOv3Head(nn.Layer):
13 14
    __shared__ = ['num_classes']
    __inject__ = ['loss']
15

W
wangguanzhong 已提交
16
    def __init__(self,
17 18 19 20 21
                 anchors=[
                     10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90,
                     156, 198, 373, 326
                 ],
                 anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]],
W
wangguanzhong 已提交
22
                 num_classes=80,
23
                 loss='YOLOv3Loss'):
24
        super(YOLOv3Head, self).__init__()
25 26
        self.anchors = anchors
        self.anchor_masks = anchor_masks
27
        self.num_classes = num_classes
28 29 30 31 32 33 34 35
        self.loss = loss

        self.mask_anchors = self.parse_anchor(self.anchors, self.anchor_masks)
        self.num_outputs = len(self.mask_anchors)

        self.yolo_outputs = []
        for i in range(len(self.mask_anchors)):
            num_filters = self.num_outputs * (self.num_classes + 5)
W
wangguanzhong 已提交
36
            name = 'yolo_output.{}'.format(i)
37
            yolo_output = self.add_sublayer(
W
wangguanzhong 已提交
38
                name,
W
wangguanzhong 已提交
39
                nn.Conv2D(
W
wangxinxin08 已提交
40 41 42
                    in_channels=1024 // (2**i),
                    out_channels=num_filters,
                    kernel_size=1,
43 44
                    stride=1,
                    padding=0,
W
wangxinxin08 已提交
45
                    weight_attr=ParamAttr(name=name + '.conv.weights'),
46
                    bias_attr=ParamAttr(
W
wangguanzhong 已提交
47
                        name=name + '.conv.bias', regularizer=L2Decay(0.))))
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
            self.yolo_outputs.append(yolo_output)

    def parse_anchor(self, anchors, anchor_masks):
        anchor_num = len(self.anchors)
        mask_anchors = []
        for i in range(len(self.anchor_masks)):
            mask_anchor = []
            for m in self.anchor_masks[i]:
                assert m < anchor_num, "anchor mask index overflow"
                mask_anchor.extend(self.anchors[2 * m:2 * m + 2])
            mask_anchors.append(mask_anchor)

        return mask_anchors

    def forward(self, feats):
        assert len(feats) == len(self.mask_anchors)
        yolo_outputs = []
        for i, feat in enumerate(feats):
            yolo_output = self.yolo_outputs[i](feat)
            yolo_outputs.append(yolo_output)
        return yolo_outputs

    def loss(self, inputs, head_outputs):
        return self.loss(inputs, head_outputs, anchors, anchor_masks)