yolov7增加AFPN

news2024/11/19 7:49:26

论文学习:AFPN: Asymptotic Feature Pyramid Network for Object Detection-全新特征融合模块AFPN,完胜PAFPN_athrunsunny的博客-CSDN博客

        论文的作者是说在yolo上效果有提升,不过还没有测试,具体还不清楚,把代码撸出来先。yolov7的代码结构类似,可以参照tiny的yaml进行修改

先上配置文件yolov7-tiny-AFPN.yaml(hight-level做两次)

# parameters
nc: 80  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple

activation: nn.LeakyReLU(0.1)
# anchors
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# yolov7-tiny backbone
backbone:
  # [from, number, module, args] c2, k=1, s=1, p=None, g=1, act=True
  [[-1, 1, Conv, [32, 3, 2, None, 1]],  # 0-P1/2
  
   [-1, 1, Conv, [64, 3, 2, None, 1]],  # 1-P2/4
   
   [-1, 1, Conv, [32, 1, 1, None, 1]],
   [-2, 1, Conv, [32, 1, 1, None, 1]],
   [-1, 1, Conv, [32, 3, 1, None, 1]],
   [-1, 1, Conv, [32, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [64, 1, 1, None, 1]],  # 7
   
   [-1, 1, MP, []],  # 8-P3/8
   [-1, 1, Conv, [64, 1, 1, None, 1]],
   [-2, 1, Conv, [64, 1, 1, None, 1]],
   [-1, 1, Conv, [64, 3, 1, None, 1]],
   [-1, 1, Conv, [64, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [128, 1, 1, None, 1]],  # 14
   
   [-1, 1, MP, []],  # 15-P4/16
   [-1, 1, Conv, [128, 1, 1, None, 1]],
   [-2, 1, Conv, [128, 1, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1, None, 1]],  # 21
   
   [-1, 1, MP, []],  # 22-P5/32
   [-1, 1, Conv, [256, 1, 1, None, 1]],
   [-2, 1, Conv, [256, 1, 1, None, 1]],
   [-1, 1, Conv, [256, 3, 1, None, 1]],
   [-1, 1, Conv, [256, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [512, 1, 1, None, 1]],  # 28
  ]

# yolov7-tiny head
head:
  [[14, 1, Conv, [64, 1, 1, None, 1]],  # 29
   [21, 1, Conv, [128, 1, 1, None, 1]],  # 30
   [28, 1, Conv, [256, 1, 1, None, 1]], # 31

   [ 29, 1, Conv, [ 64, 1, 1, None, 1 ] ], # 32
   [ 30, 1, Conv, [ 128, 1, 1, None, 1 ] ], # 33
   [ 31, 1, Conv, [ 256, 1, 1, None, 1 ] ], # 34

   [ [ 33, 34 ], 1, ASFF_2, [ 128, 0 ] ], # 35
   [ [ 33, 34 ], 1, ASFF_2, [ 256, 1 ] ], # 36

   [35, 1, Conv, [64, 1, 1, None, 1]],
   [35, 1, Conv, [64, 1, 1, None, 1]],
   [-1, 1, Conv, [64, 3, 1, None, 1]],
   [-1, 1, Conv, [64, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [128, 1, 1, None, 1]],  # 42

   [ 36, 1, Conv, [ 128, 1, 1, None, 1 ] ],
   [ 36, 1, Conv, [ 128, 1, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 128, 3, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 128, 3, 1, None, 1 ] ],
   [ [ -1, -2, -3, -4 ], 1, Concat, [ 1 ] ],
   [ -1, 1, Conv, [ 256, 1, 1, None, 1 ] ],  # 48

   [[32, 42, 48], 1, ASFF_3, [64, 0]], # 49
   [[32, 42, 48], 1, ASFF_3, [128, 1]], # 50
   [[32, 42, 48], 1, ASFF_3, [256, 2]], # 51

   [ 49, 1, Conv, [ 32, 1, 1, None, 1 ] ],
   [ 49, 1, Conv, [ 32, 1, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 32, 3, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 32, 3, 1, None, 1 ] ],
   [ [ -1, -2, -3, -4 ], 1, Concat, [ 1 ] ],
   [ -1, 1, Conv, [ 64, 1, 1, None, 1 ] ],  # 57

   [ 50, 1, Conv, [ 64, 1, 1, None, 1 ] ],
   [ 50, 1, Conv, [ 64, 1, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 64, 3, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 64, 3, 1, None, 1 ] ],
   [ [ -1, -2, -3, -4 ], 1, Concat, [ 1 ] ],
   [ -1, 1, Conv, [ 128, 1, 1, None, 1 ] ],  # 63

   [51, 1, Conv, [128, 1, 1, None, 1]],
   [51, 1, Conv, [128, 1, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1, None, 1]],  # 69

   [57, 1, Conv, [64, 3, 1, None, 1]],
   [63, 1, Conv, [128, 3, 1, None, 1]],
   [69, 1, Conv, [256, 3, 1, None, 1]],

   [[70,71,72], 1, Detect, [nc, anchors]],   # Detect(P3, P4, P5)
  ]

yolov7-tiny-AFPN.yaml(low-level做两次,论文的方法)

# parameters
nc: 80  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple

activation: nn.LeakyReLU(0.1)
# anchors
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# yolov7-tiny backbone
backbone:
  # [from, number, module, args] c2, k=1, s=1, p=None, g=1, act=True
  [[-1, 1, Conv, [32, 3, 2, None, 1]],  # 0-P1/2

   [-1, 1, Conv, [64, 3, 2, None, 1]],  # 1-P2/4

   [-1, 1, Conv, [32, 1, 1, None, 1]],
   [-2, 1, Conv, [32, 1, 1, None, 1]],
   [-1, 1, Conv, [32, 3, 1, None, 1]],
   [-1, 1, Conv, [32, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [64, 1, 1, None, 1]],  # 7

   [-1, 1, MP, []],  # 8-P3/8
   [-1, 1, Conv, [64, 1, 1, None, 1]],
   [-2, 1, Conv, [64, 1, 1, None, 1]],
   [-1, 1, Conv, [64, 3, 1, None, 1]],
   [-1, 1, Conv, [64, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [128, 1, 1, None, 1]],  # 14

   [-1, 1, MP, []],  # 15-P4/16
   [-1, 1, Conv, [128, 1, 1, None, 1]],
   [-2, 1, Conv, [128, 1, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1, None, 1]],  # 21

   [-1, 1, MP, []],  # 22-P5/32
   [-1, 1, Conv, [256, 1, 1, None, 1]],
   [-2, 1, Conv, [256, 1, 1, None, 1]],
   [-1, 1, Conv, [256, 3, 1, None, 1]],
   [-1, 1, Conv, [256, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [512, 1, 1, None, 1]],  # 28
  ]

# yolov7-tiny head
head:
  [[14, 1, Conv, [64, 1, 1, None, 1]],  # 29
   [21, 1, Conv, [128, 1, 1, None, 1]],  # 30
   [28, 1, Conv, [256, 1, 1, None, 1]], # 31

   [ 29, 1, Conv, [ 64, 1, 1, None, 1 ] ], # 32
   [ 30, 1, Conv, [ 128, 1, 1, None, 1 ] ], # 33
   [ 31, 1, Conv, [ 256, 1, 1, None, 1 ] ], # 34

   [ [ 32, 33 ], 1, ASFF_2, [ 64, 0 ] ], # 35
   [ [ 32, 33 ], 1, ASFF_2, [ 128, 1 ] ], # 36

   [35, 1, Conv, [32, 1, 1, None, 1]],
   [35, 1, Conv, [32, 1, 1, None, 1]],
   [-1, 1, Conv, [32, 3, 1, None, 1]],
   [-1, 1, Conv, [32, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [64, 1, 1, None, 1]],  # 42

   [ 36, 1, Conv, [ 64, 1, 1, None, 1 ] ],
   [ 36, 1, Conv, [ 64, 1, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 64, 3, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 64, 3, 1, None, 1 ] ],
   [ [ -1, -2, -3, -4 ], 1, Concat, [ 1 ] ],
   [ -1, 1, Conv, [ 128, 1, 1, None, 1 ] ],  # 48

   [[42, 48, 34], 1, ASFF_3, [64, 0]], # 49
   [[42, 48, 34], 1, ASFF_3, [128, 1]], # 50
   [[42, 48, 34], 1, ASFF_3, [256, 2]], # 51

   [ 49, 1, Conv, [ 32, 1, 1, None, 1 ] ],
   [ 49, 1, Conv, [ 32, 1, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 32, 3, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 32, 3, 1, None, 1 ] ],
   [ [ -1, -2, -3, -4 ], 1, Concat, [ 1 ] ],
   [ -1, 1, Conv, [ 64, 1, 1, None, 1 ] ],  # 57

   [ 50, 1, Conv, [ 64, 1, 1, None, 1 ] ],
   [ 50, 1, Conv, [ 64, 1, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 64, 3, 1, None, 1 ] ],
   [ -1, 1, Conv, [ 64, 3, 1, None, 1 ] ],
   [ [ -1, -2, -3, -4 ], 1, Concat, [ 1 ] ],
   [ -1, 1, Conv, [ 128, 1, 1, None, 1 ] ],  # 63

   [51, 1, Conv, [128, 1, 1, None, 1]],
   [51, 1, Conv, [128, 1, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [-1, 1, Conv, [128, 3, 1, None, 1]],
   [[-1, -2, -3, -4], 1, Concat, [1]],
   [-1, 1, Conv, [256, 1, 1, None, 1]],  # 69

   [57, 1, Conv, [64, 3, 1, None, 1]],
   [63, 1, Conv, [128, 3, 1, None, 1]],
   [69, 1, Conv, [256, 3, 1, None, 1]],

   [[70,71,72], 1, Detect, [nc, anchors]],   # Detect(P3, P4, P5)
  ]

        两个配置文件的区别在于一个是将backbone中最后一层的输出做两次ASFF,另一个是将倒数第三层的输出做两次ASFF,也就是论文的做法,不过论文的做法参数会量少一点,总共5.9M多一点

在models/common.py中修改,确保可以从yaml中传入参数

class Conv(nn.Module):
    # Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, activation)
    default_act = nn.SiLU()  # default activation

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()

    def forward(self, x):
        x = self.act(self.bn(self.conv(x)))
        return x

    def forward_fuse(self, x):
        return self.act(self.conv(x))

在models/common.py增加

class Upsample(nn.Module):
    def __init__(self, in_channels, out_channels, scale_factor=2):
        super(Upsample, self).__init__()

        self.upsample = nn.Sequential(
            Conv(in_channels, out_channels, 1),
            nn.Upsample(scale_factor=scale_factor, mode='bilinear')
        )

        # carafe
        # from mmcv.ops import CARAFEPack
        # self.upsample = nn.Sequential(
        #     BasicConv(in_channels, out_channels, 1),
        #     CARAFEPack(out_channels, scale_factor=scale_factor)
        # )

    def forward(self, x):
        x = self.upsample(x)

        return x


class Downsample(nn.Module):
    def __init__(self, in_channels, out_channels, scale_factor=2):
        super(Downsample, self).__init__()

        self.downsample = nn.Sequential(
            Conv(in_channels, out_channels, scale_factor, scale_factor, 0)
        )

    def forward(self, x):
        x = self.downsample(x)

        return x


class ASFF_2(nn.Module):
    def __init__(self, inter_dim=512, level=0, channel=[64, 128]):
        super(ASFF_2, self).__init__()

        self.inter_dim = inter_dim
        compress_c = 8

        self.weight_level_1 = Conv(self.inter_dim, compress_c, 1, 1)
        self.weight_level_2 = Conv(self.inter_dim, compress_c, 1, 1)

        self.weight_levels = nn.Conv2d(compress_c * 2, 2, kernel_size=1, stride=1, padding=0)

        self.conv = Conv(self.inter_dim, self.inter_dim, 3, 1)
        self.upsample = Upsample(channel[1], channel[0])
        self.downsample = Downsample(channel[0], channel[1])
        self.level = level

    def forward(self, x):
        input1, input2 = x
        if self.level == 0:
            input2 = self.upsample(input2)
        elif self.level == 1:
            input1 = self.downsample(input1)

        level_1_weight_v = self.weight_level_1(input1)
        level_2_weight_v = self.weight_level_2(input2)

        levels_weight_v = torch.cat((level_1_weight_v, level_2_weight_v), 1)
        levels_weight = self.weight_levels(levels_weight_v)
        levels_weight = F.softmax(levels_weight, dim=1)

        fused_out_reduced = input1 * levels_weight[:, 0:1, :, :] + \
                            input2 * levels_weight[:, 1:2, :, :]

        out = self.conv(fused_out_reduced)

        return out


class ASFF_3(nn.Module):
    def __init__(self, inter_dim=512, level=0, channel=[64, 128, 256]):
        super(ASFF_3, self).__init__()

        self.inter_dim = inter_dim
        compress_c = 8

        self.weight_level_1 = Conv(self.inter_dim, compress_c, 1, 1)
        self.weight_level_2 = Conv(self.inter_dim, compress_c, 1, 1)
        self.weight_level_3 = Conv(self.inter_dim, compress_c, 1, 1)

        self.weight_levels = nn.Conv2d(compress_c * 3, 3, kernel_size=1, stride=1, padding=0)

        self.conv = Conv(self.inter_dim, self.inter_dim, 3, 1)

        self.level = level
        if self.level == 0:
            self.upsample4x = Upsample(channel[2], channel[0], scale_factor=4)
            self.upsample2x = Upsample(channel[1], channel[0], scale_factor=2)
        elif self.level == 1:
            self.upsample2x1 = Upsample(channel[2], channel[1], scale_factor=2)
            self.downsample2x1 = Downsample(channel[0], channel[1], scale_factor=2)
        elif self.level == 2:
            self.downsample2x = Downsample(channel[1], channel[2], scale_factor=2)
            self.downsample4x = Downsample(channel[0], channel[2], scale_factor=4)

    def forward(self, x):
        input1, input2, input3 = x
        if self.level == 0:
            input2 = self.upsample2x(input2)
            input3 = self.upsample4x(input3)
        elif self.level == 1:
            input3 = self.upsample2x1(input3)
            input1 = self.downsample2x1(input1)
        elif self.level == 2:
            input1 = self.downsample4x(input1)
            input2 = self.downsample2x(input2)
        level_1_weight_v = self.weight_level_1(input1)
        level_2_weight_v = self.weight_level_2(input2)
        level_3_weight_v = self.weight_level_3(input3)

        levels_weight_v = torch.cat((level_1_weight_v, level_2_weight_v, level_3_weight_v), 1)
        levels_weight = self.weight_levels(levels_weight_v)
        levels_weight = F.softmax(levels_weight, dim=1)

        fused_out_reduced = input1 * levels_weight[:, 0:1, :, :] + \
                            input2 * levels_weight[:, 1:2, :, :] + \
                            input3 * levels_weight[:, 2:, :, :]

        out = self.conv(fused_out_reduced)

        return out

在models/yolo.py中修改:

def parse_model(d, ch):  # model_dict, input_channels(3)
    logger.info('\n%3s%18s%3s%10s  %-40s%-30s' % ('', 'from', 'n', 'params', 'module', 'arguments'))
    # anchors, nc, gd, gw = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple']
    anchors, nc, gd, gw, act = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple'], d.get('activation')
    if act:
        Conv.default_act = eval(act)  # redefine default activation, i.e. Conv.default_act = nn.SiLU()

    na = (len(anchors[0]) // 2) if isinstance(anchors, list) else anchors  # number of anchors
    no = na * (nc + 5)  # number of outputs = anchors * (classes + 5)

    layers, save, c2 = [], [], ch[-1]  # layers, savelist, ch out
    for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']):  # from, number, module, args
        m = eval(m) if isinstance(m, str) else m  # eval strings
        for j, a in enumerate(args):
            try:
                args[j] = eval(a) if isinstance(a, str) else a  # eval strings
            except:
                pass

        n = max(round(n * gd), 1) if n > 1 else n  # depth gain
        if m in [nn.Conv2d, Conv, RobustConv, RobustConv2, DWConv, GhostConv, RepConv, RepConv_OREPA, DownC, 
                 SPP, SPPF, SPPCSPC, GhostSPPCSPC, MixConv2d, Focus, Stem, GhostStem, CrossConv, 
                 Bottleneck, BottleneckCSPA, BottleneckCSPB, BottleneckCSPC, 
                 RepBottleneck, RepBottleneckCSPA, RepBottleneckCSPB, RepBottleneckCSPC,  
                 Res, ResCSPA, ResCSPB, ResCSPC, 
                 RepRes, RepResCSPA, RepResCSPB, RepResCSPC, 
                 ResX, ResXCSPA, ResXCSPB, ResXCSPC, 
                 RepResX, RepResXCSPA, RepResXCSPB, RepResXCSPC, 
                 Ghost, GhostCSPA, GhostCSPB, GhostCSPC,
                 SwinTransformerBlock, STCSPA, STCSPB, STCSPC,
                 SwinTransformer2Block, ST2CSPA, ST2CSPB, ST2CSPC]:
            c1, c2 = ch[f], args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)

            args = [c1, c2, *args[1:]]
            if m in [DownC, SPPCSPC, GhostSPPCSPC, 
                     BottleneckCSPA, BottleneckCSPB, BottleneckCSPC, 
                     RepBottleneckCSPA, RepBottleneckCSPB, RepBottleneckCSPC, 
                     ResCSPA, ResCSPB, ResCSPC, 
                     RepResCSPA, RepResCSPB, RepResCSPC, 
                     ResXCSPA, ResXCSPB, ResXCSPC, 
                     RepResXCSPA, RepResXCSPB, RepResXCSPC,
                     GhostCSPA, GhostCSPB, GhostCSPC,
                     STCSPA, STCSPB, STCSPC,
                     ST2CSPA, ST2CSPB, ST2CSPC]:
                args.insert(2, n)  # number of repeats
                n = 1
        elif m is nn.BatchNorm2d:
            args = [ch[f]]
        elif m is Concat:
            c2 = sum([ch[x] for x in f])
        elif m is Chuncat:
            c2 = sum([ch[x] for x in f])
        elif m is Shortcut:
            c2 = ch[f[0]]
        elif m is Foldcut:
            c2 = ch[f] // 2
        elif m in [Detect, IDetect, IAuxDetect, IBin, IKeypoint]:
            args.append([ch[x] for x in f])
            if isinstance(args[1], int):  # number of anchors
                args[1] = [list(range(args[1] * 2))] * len(f)
        elif m is ReOrg:
            c2 = ch[f] * 4
        elif m is Contract:
            c2 = ch[f] * args[0] ** 2
        elif m is Expand:
            c2 = ch[f] // args[0] ** 2
        elif m in {ASFF_2, ASFF_3}:
            c2 = args[0]
            if c2 != no:  # if not output
                c2 = make_divisible(c2 * gw, 8)
            args[0] = c2
            args.append([ch[x] for x in f])
        else:
            c2 = ch[f]

        m_ = nn.Sequential(*[m(*args) for _ in range(n)]) if n > 1 else m(*args)  # module
        t = str(m)[8:-2].replace('__main__.', '')  # module type
        np = sum([x.numel() for x in m_.parameters()])  # number params
        m_.i, m_.f, m_.type, m_.np = i, f, t, np  # attach index, 'from' index, type, number params
        logger.info('%3s%18s%3s%10.0f  %-40s%-30s' % (i, f, n, np, t, args))  # print
        save.extend(x % i for x in ([f] if isinstance(f, int) else f) if x != -1)  # append to savelist
        layers.append(m_)
        if i == 0:
            ch = []
        ch.append(c2)
    return nn.Sequential(*layers), sorted(save)

 在yolo.py中配置--cfg为yolov7-tiny-AFPN.yaml,点击运行,可见下图:

PS:不过这个14.5GFLOPs是在yolov5代码框架上的结果,在v7上竟然算出来是315.8GFLOPs,有点离谱,看了一圈也没发现问题在哪。。。评论区有说是正常的,那应该是我的v7有问题了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/726636.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源网安受邀参加2023全球数字经济大会,分享软件安全落地实践经验

近日,2023全球数字经济大会数字安全生态建设专题论坛在京隆重举行。作为2023全球数字经济大会的重要组成部分,本次论坛围绕“数字安全生态建设”这一主题,邀请政府主管部门、行业专家学者、关键信息基础设施运营主体、数字安全企业、数据要素…

第八章 实现商品详情数据异构及静态化

lua操作 设计图详解 1、 普通模式,用户获得redis数据需要经过nginx,php-fpm,php框架,再到redis 2 、直接模式,对于部分高并发请求, 为了提高吞吐率, 有必要砍掉一些环节和应用来实现快速响应,如上图,这里我们将普通模式中的php-fpm和php框架砍掉了。nginx直接从r…

arvr虚拟现实服务商为文旅行业提供全新的交互式营销体验

在AR领域,很多企业都会遇到场景化展示需求的问题,比如需要制作一个宣传片视频、远程协作软件或者产品营销等等,对于这样的场景制作需求,一般都是找像深圳华锐视点这样的第三方AR开发技术公司进行AR场景定制。 AR是将计算机生成的虚…

在萌诺母婴综合体旗下萌诺尊享(新华店)坐月子可以享受哪些服务?

第一次怀孕生孩子内心比较恐惧,尤其担心月子坐不好身体和身材难以恢复。在怀孕期间刷微博看到郑恺苗苗在萌诺尊享(新华店)坐月子的vlog,感觉这里的环境和服务都还不错,主要是看到苗苗在月子期间身材恢复的很快,于是和老公亲自去门…

深入理解计算机系统(一)

信息就是位上下文 #include<stdio.h>int main() {printf("hello,world\n");return 0; } 上面是一个hello程序。它的生命周期是从一个源程序开始的&#xff0c;就是程序员通过编辑器创建并保存的文本文件&#xff0c;文件名是hello.c。&#xff08;源程序实际…

QT 之蓝牙BLE编程

简介 使用PC蓝牙和蓝牙透传模块通讯。 准备 QT core gui bluetoothQT蓝牙库相关头文件 #include <QtBluetooth/qbluetoothglobal.h> #include <QtBluetooth/qbluetoothlocaldevice.h> #include <qbluetoothaddress.h> #include <qbluetoothdev…

造船码头行车/电动葫芦控制系统的无线技改

一、应用背景 近年来&#xff0c;我国造船业在高技术船舶研发和建造方面持续取得新突破&#xff0c;据统计截止到2022年&#xff0c;我国造船业完工量、新接订单量、手持订单量三大指标国际市场份额均保持世界前列。连续13年位居全球居首。随着船舶制造的综合能力不断提高&…

微信小程序制作 购物商城首页 【内包含源码】

1、实现效果 手机效果预览,这里的首页使用到了轮播图。页面图片数据可以替换成自己的数据。 2、开发者工具效果图 3、项目的目录结构 4、首页核心代码 4.1 index.js 这里用来存放数据,页面的数据。目前是假数据,也可以调用接口接收真实数据 // index.jsimport {request }…

spring-依赖注入的方式

setter注入-可选依赖注入 简单类型&#xff1a; 1.配置类 2.set方法 引用类型&#xff1a; 构造器注入-强制依赖注入 简单类型&#xff1a; 引用类型&#xff1a; 通过有参构造&#xff0c;获得需要注入的对象 <construct-arg />标签中name属性中填写的时构造方…

数据结构--二叉树的层遍历

数据结构–二叉树的层遍历 算法思想: ①初始化一个辅助 队列 \color{red}队列 队列 ②根结点入队 ③若队列非空&#xff0c;则队头结点出队&#xff0c;访问该结点&#xff0c;并将其左、右孩子插入队尾&#xff08;如果有的话) ④重复③直至队列为空 代码实现 typedef struc…

pycharm的环境配置运行

刚开始用pycharm打开一个项目文件时&#xff0c;由于没有配置文件&#xff0c; 程序是不能运行的 运行的按钮为灰色 此时在项目浏览器中右键点击项目主程序&#xff0c;在下拉菜单中选择运行&#xff0c; 快捷键为ctrlshiftF10在配置中会自动添加以主程序为名称的配置 这时可…

vue3实现折叠面板

总是忘记vue怎么实现折叠面板&#xff0c;记录一下&#xff0c;没有动画样式。 <div class"item-content padding15" style"font-size: 0.875rem;" click"changeCollapse(index)" v-for"(item, index) in collData.dataList" :key&…

mtk log、kernel log、adb log的详细使用

目录 mtk logkernel logadb log 打印MTK log&#xff0c;里面就包含了kernel层的log&#xff0c;像我们adb log打印的是上层应用的log&#xff0c;mtk log打印的则是更底层的log。 那么什么时候需要用到mtk log 呢&#xff1f; 就比如你想抓一些从关机到开机的log&#xff0c;…

基于 SpringBoot + Vue 的前后端分离的高校招生管理系统

【程序员徐师兄】&#xff1a;hello你好我是程序员徐师兄&#xff0c;6年大厂经验。很高兴你能来阅读&#xff0c;希望我们能不断精进&#xff0c;向着优秀程序员前行&#xff01; 博客来源于项目以及编程中遇到的问题总结&#xff0c;偶尔会有读书分享&#xff0c;我会陆续更新…

AICG - Stable Diffusion 的扩展插件 (Extensions) 的配置与使用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131576762 Prompt: (masterpiece, top quality, best quality, ((standing in centre)), ((1girl, black hair)), ((upper body, symmetrical com…

leetcode 141.环形链表 I - 142.环形链表 II 代码及指针相遇证明问题

⭐️ 环形链表 I 题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 如果链表中存在环 &#xff0c;则返回 true 。 否则&#xff0c;返回 false 。 思…

Vue项目在IE浏览器页面白屏且报错SCRIPT1010:缺少标识符

背景 &#xff1a;Vue2 项目在谷歌浏览器运行好好的&#xff0c;在 IE 浏览器打开就会出现各种的问题。。 控制台报错 &#xff1a;SCRIPT1010: 缺少标识符 文件&#xff1a;app.403ea2d4.js&#xff0c;行&#xff1a;1&#xff0c;列&#xff1a;180 问题 &#xff1a; 同伴 …

Linux 中查找 IP 地址的方法

概要 在 Linux 系统中&#xff0c;经常需要查找 IP 地址以进行网络配置、故障排除或安全管理。无论是查找本地主机的 IP 地址还是查找其他设备的 IP 地址&#xff0c;本文将介绍三种简单的方法&#xff0c;帮助你在 Linux 中轻松找到所需的 IP 地址。 方法一&#xff1a;使用 i…

Greenplum数据库优化器——Join类型

join 类型语法支持 from语句允许JOIN表达式和表名列表&#xff0c;将joined_table从table_ref中分离出来&#xff0c;It may seem silly to separate joined_table from table_ref, but there is method in SQL’s madness: if you don’t do it this way you get reduce-redu…

【网络结构】——TinyViT 一种transformer的蒸馏方案

来自 Microsoft 摘要 TinyViT是一种新型的小型transformer&#xff0c;它们高效且可以在大规模数据集上进行预训练。TinyViT通过在预训练期间应用蒸馏来传输知识&#xff0c;将大型预训练模型的知识转移到小型模型中&#xff0c;同时使小型模型能够获得大量预训练数据的红利。…