YOLOX-FPN

# YOLOFPN 全称是 YOLOv5 Feature Pyramid Network
# 该模块是 YOLOv5 的 backbone,用于提取特征图,用于后续的检测,分割等任务
class YOLOFPN(nn.Module):
    """
    YOLOFPN module. Darknet 53 is the default backbone of this model.
    """

    def __init__(
        self,
        depth=53,
        in_features=["dark3", "dark4", "dark5"],
    ):
        super().__init__()

        self.backbone = Darknet(depth)  # backbone,Darknet53,用于提取特征图
        self.in_features = in_features  # in_features,用于提取特征图的层级

        # out 1
        self.out1_cbl = self._make_cbl(512, 256, 1) # cbl全称是conv-bn-leakyrelu
                                                    # 该层是将输入的通道数从512变为256
                                                    # 该层的作用是将输入的特征图进行下采样
        self.out1 = self._make_embedding([256, 512], 512 + 256)
        # embedding,嵌入层,用于将输入的特征图进行下采样,同时将输入的特征图与下采样后的特征图进行融合
        # 其中[256, 512]是嵌入层的卷积核的个数,512+256是输入的通道数
        # 512+256是因为下采样后的特征图的通道数是256,输入的特征图的通道数是512,所以需要将两者进行融合
        # 融合的方式是将两者的特征图进行拼接,然后再进行卷积操作,最终输出的通道数是512

        # out 2
        self.out2_cbl = self._make_cbl(256, 128, 1)
        # 该层是将输入的通道数从256变为128
        self.out2 = self._make_embedding([128, 256], 256 + 128)
        # embedding,嵌入层,用于将输入的特征图进行下采样,同时将输入的特征图与下采样后的特征图进行融合
        # 其中[128, 256]是嵌入层的卷积核的个数,256+128是输入的通道数
        # 256+128是因为下采样后的特征图的通道数是128,输入的特征图的通道数是256,所以需要将两者进行融合
        # 融合的方式是将两者的特征图进行拼接,然后再进行卷积操作,最终输出的通道数是256

        # upsample
        self.upsample = nn.Upsample(scale_factor=2, mode="nearest")
        # 上采样层,用于将输入的特征图进行上采样,上采样的方式是将输入的特征图进行放大,放大的倍数是2倍
        # scale_factor=2,表示放大的倍数是2倍
        # mode="nearest",表示放大的方式是最近邻插值

    def _make_cbl(self, _in, _out, ks):
        return BaseConv(_in, _out, ks, stride=1, act="lrelu")

    def _make_embedding(self, filters_list, in_filters):
        m = nn.Sequential(
            *[
                self._make_cbl(in_filters, filters_list[0], 1),
                self._make_cbl(filters_list[0], filters_list[1], 3),
                self._make_cbl(filters_list[1], filters_list[0], 1),
                self._make_cbl(filters_list[0], filters_list[1], 3),
                self._make_cbl(filters_list[1], filters_list[0], 1),
            ]
        )
        return m

    def load_pretrained_model(self, filename="./weights/darknet53.mix.pth"):
        # load pretrained model的作用是加载预训练模型
        # 其中mix是指将darknet53的预训练模型与yolov5的预训练模型进行融合
        with open(filename, "rb") as f:
            state_dict = torch.load(f, map_location="cpu")
            # map_location="cpu",表示将模型加载到cpu上
        print("loading pretrained weights...")
        self.backbone.load_state_dict(state_dict)
        # backbone是Darknet53,用于提取特征图,load_state_dict是用于加载预训练模型的函数

    def forward(self, inputs):
        """
        Args:
            inputs (Tensor): input image.

        Returns:
            Tuple[Tensor]: FPN output features..
        """
        #  backbone
        out_features = self.backbone(inputs)
        x2, x1, x0 = [out_features[f] for f in self.in_features]
        # 将dark3, dark4, dark5三个层级的特征图进行提取,对应的是yolo的三个分支

        #  yolo branch 1
        x1_in = self.out1_cbl(x0)
        # 将输入的特征图进行下采样,下采样的方式是将输入的特征图进行卷积操作,卷积核的个数是256
        x1_in = self.upsample(x1_in)
        # 将下采样后的特征图进行上采样,上采样的方式是将输入的特征图进行放大,放大的倍数是2倍
        x1_in = torch.cat([x1_in, x1], 1)
        # 将下采样后的特征图与输入的特征图进行融合,融合的方式是将两者的特征图进行拼接
        out_dark4 = self.out1(x1_in)
        # 将融合后的特征图进行卷积操作,卷积核的个数是[256, 512],最终输出的通道数是512

        #  yolo branch 2
        x2_in = self.out2_cbl(out_dark4)
        # 将输入的特征图进行下采样,下采样的方式是将输入的特征图进行卷积操作,卷积核的个数是128
        x2_in = self.upsample(x2_in)
        # 将下采样后的特征图进行上采样,上采样的方式是将输入的特征图进行放大,放大的倍数是2倍
        x2_in = torch.cat([x2_in, x2], 1)
        # 将下采样后的特征图与输入的特征图进行融合,融合的方式是将两者的特征图进行拼接
        out_dark3 = self.out2(x2_in)
        # 将融合后的特征图进行卷积操作,卷积核的个数是[128, 256],最终输出的通道数是256

        outputs = (out_dark3, out_dark4, x0)
        # 将dark3, dark4, dark5三个层级的特征图进行融合,对应的是yolo的三个分支
        return outputs
# YOLOFPN的数据流程图
# W*H*3 -> backbone -> dark3, dark4, dark5 -> out1_cbl -> out1 -> out2_cbl -> out2 -> upsample -> out_dark4 -> upsample -> out_dark3
# 该模型的输入是W*H*3的图片,经过backbone提取特征图,然后将dark3, dark4, dark5三个层级的特征图进行提取,对应的是yolo的三个分支
# 然后将dark3, dark4, dark5三个层级的特征图进行融合,对应的是yolo的三个分支

已发布

分类

来自

标签:

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注