【目标检测】YOLOv7算法实现(一):模型搭建

news2024/11/30 10:39:54

  本系列文章记录本人硕士阶段YOLO系列目标检测算法自学及其代码实现的过程。其中算法具体实现借鉴于ultralytics YOLO源码Github,删减了源码中部分内容,满足个人科研需求。
  本篇文章在YOLOv5算法实现的基础上,进一步完成YOLOv7算法的实现。YOLOv7相比于YOLOv5,最主要的不同之处如下:

  • 模型结构:引进了更为高效的特征提取模块(ELAN)、下采样模块(MP),不同的空间池化层(SPPCSPC),重参数卷积(RepConv)
  • 损失计算:结合YOLOv5中和正样本匹配方法和YOLOX中的正样本筛选方法(SimOTA)

文章地址:
YOLOv7算法实现(一):模型搭建
YOLOv7算法实现(二):损失计算

本文目录

  • 1 模型结构
  • 2 模型模块实现(common.py)
    • 2.1 CBS模块
    • 2.2 ELAN模块
    • 2.3 MP模块
    • 2.4 SPPCSPC模块
    • 2.5 RepConv模块
      • 2.5.1 参数融合
      • 2.5.2 模块实现
    • 2.6 Detect模块
  • 3 模型配置文件构建(model.yaml)
  • 4 模型搭建(yolo.py)

1 模型结构

  YOLOv7的模型结构如图1所示,其包含以下几个模块:

  • CBS:卷积层、批标准化(BN)和SiLU激活函数
  • ELAN:多梯度融合特征提取模块,根据融合的梯度信息的不同分为ELAB-BELAB-H
  • MP:最大池化和CBS结合的下采样模块
  • SPPCSPC:跨阶段特征金字塔池化模块
  • RepConv:重参数化卷积
  • Detect:检测头(Anchor-based)
    在这里插入图片描述
图1 YOLOv7网络结构

2 模型模块实现(common.py)

2.1 CBS模块

Class Conv(nn.Module):
	'''
	卷积块:conv-BN-Activation
	'''
	default_act = nn.SiLU()  # 默认激活函数
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True, b=False):
       '''
       :param c1: 输入通道数
       :param c2: 输出通道数
       :param k: 卷积核大小
       :param s: 步长
       :param p: 填充 默认为None则表示填充至与输入分辨率相同
       :param g: 分组卷积,默认为1时为标准卷积
       :param d: 间隙卷积,默认为1时为标准卷积;不为1表示点之间有空隙的过滤器,对卷积核进行膨胀
       :param act: 是否使用激活函数
       :param b: 卷积偏置,默认使用无偏置卷积
       '''
       super(Conv, self).__init__()
       self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=b)
       self.bn = nn.BatchNorm2d(c2)
       # 若act为True:使用默认激活函数;若act为其他激活函数模块:则使用该激活函数;反之:使用nn.Identity,表示不对输入进行操作,直接输出输入
       self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()
    def forward(self, x):
    	# 前向传播
        return self.act(self.bn(self.conv(x)))

2.2 ELAN模块

ELAN_B

class ELAN_B(nn.Module):
    '''
    yolov7中特征提取模块(backbone部分)
    使用了密集的残差结构, 通过增加相当的深度来提高准确率; 内部的残差块使用跳跃连接,
    缓解了深度神经网络中增加深度带来的梯度消失问题。
    '''
    def __init__(self, c1, c2, e=0.5):
        super().__init__()

        c_ = int(c1 * e)
        self.cv1 = Conv(c1, c_, 1, 1)

        self.cv2 = Conv(c1, c_, 1, 1)

        self.cv3 = nn.Sequential(Conv(c_, c_, 3, 1),
                                 Conv(c_, c_, 3, 1))

        self.cv4 = nn.Sequential(Conv(c_, c_, 3, 1),
                                 Conv(c_, c_, 3, 1))

        self.cv5 = Conv(c_ * 4, c2, 1, 1)

    def forward(self, x):
        y1 = self.cv1(x)  # c1 // 2
        y2 = self.cv2(x)  # c1 // 2
        y3 = self.cv3(y2)  # c1
        y4 = self.cv4(y3)  # c1

        return self.cv5(torch.cat([y1, y2, y3, y4], dim=1))

ELAN-H

class ELAN_H(nn.Module):
    def __init__(self, c1, c2, e=0.5):
        '''Head部分'''
        super().__init__()
        c_ = int(c1 * e)
        c__ = c_ // 2
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c__, 3, 1)
        self.cv4 = Conv(c__, c__, 3, 1)
        self.cv5 = Conv(c__, c__, 3, 1)
        self.cv6 = Conv(c__, c__, 3, 1)
        self.cv7 = Conv(c_ * 2 + c__ * 4, c2, 1, 1)

    def forward(self, x):
        y1 = self.cv1(x)

        y2 = self.cv2(x)
        y3 = self.cv3(y2)
        y4 = self.cv4(y3)
        y5 = self.cv5(y4)
        y6 = self.cv6(y5)

        return self.cv7(torch.cat([y1, y2, y3, y4, y5, y6], dim=1))

2.3 MP模块

class MP(nn.Module):
    '''
    yolov7中下采样模块
    '''
    def __init__(self, c1, c2):
        super().__init__()
        # MP-1
        if c1 == c2:
            c_ = c1 // 2
        # MP-2
        else:
            c_ = c1
        # 第一个分支
        self.maxpool = MaxPool(k=2, s=2)
        self.cv1 = Conv(c1, c_, 1, 1)
        # 第二个分支
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c_, 3, 2)

    def forward(self, x):
        o1 = self.cv1(self.maxpool(x))
        o2 = self.cv3(self.cv2(x))
        return torch.cat([o1, o2], dim=1)

2.4 SPPCSPC模块

class SPPCSPC(nn.Module):
    def __init__(self, c1, c2, k=(5, 9, 13), e=0.5):
        super().__init__()
        c_ = int(2 * c2 * e)
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c_, 3, 1)
        self.cv4 = Conv(c_, c_, 1, 1)
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])
        self.cv5 = Conv(4 * c_, c_, 1, 1)
        self.cv6 = Conv(c_, c_, 3, 1)
        self.cv7 = Conv(2 * c_, c2, 1, 1)

    def forward(self, x):
        x1 = self.cv4(self.cv3(self.cv1(x)))
        y1 = self.cv6(self.cv5(torch.cat([x1] + [m(x1) for m in self.m], 1)))
        y2 = self.cv2(x)
        return self.cv7(torch.cat((y1, y2), dim=1))

2.5 RepConv模块

2.5.1 参数融合

  RepConv模块的具体结构如图1中所示,在推理阶段其将多个卷积模块融为一个卷积模块,提高模型计算的高效性。

卷积层+BN层 → 卷积层

  卷积层的计算公式为:
C o n v ( x ) = W ( x ) + b Conv(x){\rm{ }} = {\rm{ }}W(x) + b Conv(x)=W(x)+b
pytorch中,卷积层权重为conv.weight,偏置为conv.bias
  BN层的计算公式为:
B N ( x ) = γ x − m e a n v a r + β BN(x) = \gamma {{x - mean} \over {\sqrt {{\mathop{\rm var}} } }} + \beta BN(x)=γvar xmean+β
pytorch中,γ = bn.weightmean = bn.running_mean, var = bn.running_var, β = bn.bias
  卷积层和BN层融合公式为:

B N ( C o n v ( x ) ) = γ ( W ( x ) + b ) − m e a n v a r + β = n e w _ W ( x ) + n e w _ b BN(Conv(x)) = \gamma {{(W(x) + b) - mean} \over {\sqrt {{\mathop{\rm var}} } }} + \beta = new\_W(x) + new\_b BN(Conv(x))=γvar (W(x)+b)mean+β=new_W(x)+new_b
n e w _ W ( x ) = γ W ( x ) v a r , n e w _ b = γ ( b − m e a n ) v a r + β new\_W(x) = {{\gamma W(x)} \over {\sqrt {{\mathop{\rm var}} } }},new\_b = {{\gamma (b - mean)} \over {\sqrt {{\mathop{\rm var}} } }} + \beta new_W(x)=var γW(x),new_b=var γ(bmean)+β

BN层->卷积层:构造一个参数为0的卷积层(1×1),实现卷积层+BN层融合

卷积层(3×3)+卷积层(1×1) →卷积层(3×3):将卷积层(1×1)填充为3×3,再将卷积层权重和偏置相加实现融合

2.5.2 模块实现

class RepConv(nn.Module):
    def __init__(self, c1, c2, k=3, s=1, p=None, g=1, act=True, deploy=False):
        '''
        重参数卷积
        训练时:
            deploy = False
            rbr_dense(3x3卷积) + rbr_1x1(1x1卷积) + rbr_identity(c2==c1时)相加
            rbr_reparam = None
        推理时:
            deploy = True
            rbr_param = Conv2d
            rbr_dense, rbr_1x1, rbr_identity = None, None, None
        '''
        super().__init__()

        self.deploy = deploy
        self.groups = g
        self.in_channels = c1
        self.out_channels = c2

        assert k == 3
        assert autopad(k, p) == 1

        padding_11 = autopad(k, p) - k // 2

        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

        # 推理阶段, 仅有一个3x3卷积
        if self.deploy:
            self.rbr_reparam = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=True)
        else:
            # 输入输出通道数相同时, identity层(BN层)
            self.rbr_identity = (nn.BatchNorm2d(num_features=c1) if c2 == c1 and s == 1 else None)
            # 3×3卷积 + BN层
            self.rbr_dense = nn.Sequential(
                nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False),
                nn.BatchNorm2d(num_features=c2),
            )
            # 1×1卷积 + BN层
            self.rbr_1x1 = nn.Sequential(
                nn.Conv2d(c1, c2, 1, s, padding_11, groups=g, bias=False),
                nn.BatchNorm2d(num_features=c2),
            )

    def forward(self, x):
        # 推理阶段
        if hasattr(self, 'rbr_reparam'):
            return self.act(self.rbr_reparam(x))

        # 训练阶段
        if self.rbr_identity is None:
            id_out = 0
        else:
            id_out = self.rbr_identity(x)

        return self.act(self.rbr_dense(x) + self.rbr_1x1(x) + id_out)

    #融合卷积层和BN层: Conv2D+BN=Conv2D
    def fuse_conv_bn(self, conv, bn):
        std = (bn.running_var + bn.eps).sqrt()
        bias = bn.bias - bn.running_mean * bn.weight / std

        t = (bn.weight / std).reshape(-1, 1, 1, 1)
        weights = conv.weight * t

        bn = nn.Identity()
        conv = nn.Conv2d(in_channels=conv.in_channels,
                         out_channels=conv.out_channels,
                         kernel_size=conv.kernel_size,
                         stride=conv.stride,
                         padding=conv.padding,
                         dilation=conv.dilation,
                         groups=conv.groups,
                         bias=True,
                         padding_mode=conv.padding_mode)

        conv.weight = torch.nn.Parameter(weights)
        conv.bias = torch.nn.Parameter(bias)
        return conv
    # 重参数操作(在推理阶段执行)
    def fuse_repvgg_block(self):
        if self.deploy:
            return
        print(f"RepConv.fuse_repvgg_block")

        # 融合3x3的卷积层和BN层为一个3x3卷积(有偏置)
        self.rbr_dense = self.fuse_conv_bn(self.rbr_dense[0], self.rbr_dense[1])
        # 融合1x1的卷积层和BN层为一个1x1卷积(有偏置)
        self.rbr_1x1 = self.fuse_conv_bn(self.rbr_1x1[0], self.rbr_1x1[1])
        rbr_1x1_bias = self.rbr_1x1.bias
        # 填充卷积核大小与3x3卷积大小相同
        weight_1x1_expanded = torch.nn.functional.pad(self.rbr_1x1.weight, [1, 1, 1, 1])
        # 融合identity的BN层为一个1x1卷积(无偏置)
        if isinstance(self.rbr_identity, nn.BatchNorm2d) or isinstance(self.rbr_identity, nn.modules.batchnorm.SyncBatchNorm):
            identity_conv_1x1 = nn.Conv2d(
                    in_channels=self.in_channels,
                    out_channels=self.out_channels,
                    kernel_size=1,
                    stride=1,
                    padding=0,
                    groups=self.groups,
                    bias=False)
            identity_conv_1x1.weight.data = identity_conv_1x1.weight.data.to(self.rbr_1x1.weight.data.device)
            identity_conv_1x1.weight.data = identity_conv_1x1.weight.data.squeeze().squeeze()
            identity_conv_1x1.weight.data.fill_(0.0)
            identity_conv_1x1.weight.data.fill_diagonal_(1.0)
            identity_conv_1x1.weight.data = identity_conv_1x1.weight.data.unsqueeze(2).unsqueeze(3)
            # 融合该1x1卷积和Identity的BN层
            identity_conv_1x1 = self.fuse_conv_bn(identity_conv_1x1, self.rbr_identity)
            bias_identity_expanded = identity_conv_1x1.bias
            weight_identity_expanded = torch.nn.functional.pad(identity_conv_1x1.weight, [1, 1, 1, 1])
        else:
            bias_identity_expanded = torch.nn.Parameter(torch.zeros_like(rbr_1x1_bias))
            weight_identity_expanded = torch.nn.Parameter(torch.zeros_like(weight_1x1_expanded))

        # 融合3x3卷积和扩充的1x1卷积的权重和偏置
        self.rbr_dense.weight = torch.nn.Parameter(
            self.rbr_dense.weight + weight_1x1_expanded + weight_identity_expanded)
        self.rbr_dense.bias = torch.nn.Parameter(self.rbr_dense.bias + rbr_1x1_bias + bias_identity_expanded)

        self.rbr_reparam = self.rbr_dense
        self.deploy = True

        if self.rbr_identity is not None:
            del self.rbr_identity
            self.rbr_identity = None

        if self.rbr_1x1 is not None:
            del self.rbr_1x1
            self.rbr_1x1 = None

        if self.rbr_dense is not None:
            del self.rbr_dense
            self.rbr_dense = None

2.6 Detect模块

Detect模块的具体实现过程可见文章YOLOv5算法实现(二):模型搭建

3 模型配置文件构建(model.yaml)

基于图1所示的模型结构和模型模块所需的参数,构建模型配置文件。其中结构解析包含四个参数[from,number,module,args]:

  • from:当前层的输入来自于哪一层
  • number:当前层数量
  • module:当前层所有模块(在common.py中实现,需与类名对应)
  • args:第一个参数为当前层输出通道数,其余参数为模块特有参数;当前层的输入通道数由“from”参数指向的层决定,在结构解析时加入该参数。
# Parameters
nc: 80  # number of classes 类别数
depth_multiple: 1.0  # model depth multiple 模型深度(模块个数系数)
width_multiple: 1.0  # layer channel multiple 模型宽度(模块通道数系数)
anchors: 
  - [10,13, 16,30, 33,23]  # P3/8 (stride=8 feature_map所用Anchor,小目标检测)
  - [30,61, 62,45, 59,119]  # P4/16 (stride=16 feature_map所用Anchor)
  - [116,90, 156,198, 373,326]  # P5/32 (stride=32 feature_map所用Anchor,大目标检测)

backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [32, 3, 1]],  # 0
   [-1, 1, Conv, [64, 3, 2]],  # 1-P1/2
   [-1, 1, Conv, [64, 3, 1]],  # 2

   [-1, 1, Conv, [128, 3, 2]], # 3-P2/4
   [-1, 1, ELAN_B, [256]],       # 4

   [-1, 1, MP, [256]],         # 5-P3/8
   [-1, 1, ELAN_B, [512]],       # 6

   [ -1, 1, MP, [512]],        # 7-P4/16
   [ -1, 1, ELAN_B, [1024]],     # 8

   [ -1, 1, MP, [1024]],        # 9-P5/32
   [ -1, 1, ELAN_B, [1024, 0.25]],# 10
  ]

head:
  [[-1, 1, SPPCSPC, [512]],     # 11

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [8, 1, Conv, [256, 1, 1]],  # route backbone P4
   [[-1, -2], 1, Concat, [1]],

   [-1, 1, ELAN_H, [256]],  # 16

   [-1, 1, Conv, [128, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [6, 1, Conv, [128, 1, 1]], # route backbone P3
   [[-1, -2], 1, Concat, [1]],

   [-1, 1, ELAN_H, [128]],  # 21 (P3/8-samll)

   [-1, 1, MP, [256]],
   [[-1, 16], 1, Concat, [1]],

   [-1, 1, ELAN_H, [256]],  # 24 (P4/16-medium)

   [-1, 1, MP, [512]],
   [[-1, 11], 1, Concat, [1]],

   [-1, 1, ELAN_H, [512]],  # 27 (P5/32-large)

   [21, 1, RepConv, [256, 3, 1]], # 28
   [24, 1, RepConv, [512, 3, 1]], # 29
   [27, 1, RepConv, [1024, 3, 1]], # 30

   [[28, 29, 30], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

4 模型搭建(yolo.py)

模型搭建的具体实现方法可见文章YOLOv5算法实现(二):模型搭建,在YOLOv7中,在模型类中额外添加一个如下函数实现RepConv模块的融合即可。

    def fuse(self):
        print('Fusing layers...')
        for m in self.model.modules():
            if isinstance(m, RepConv):
                m.fuse_repvgg_block()
        return self

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

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

相关文章

yum仓库以及NFS共享

yum实现过程 1.光驱里自带yum 2.网络下载到本地 3.直接通过网络 如何实现安装服务 yum客户端找到yum服务端,找到yum的仓库位置,下载元信息,因为里面有软件的位置,因此可以找到软件包的位置,然后下载到本地 仓库的类…

Matlab 求解非刚性微分方程(ode45)

语法 1、[t,y] ode45(odefun,tspan,y0) 2、[t,y] ode45(odefun,tspan,y0,options) 3、[t,y,te,ye,ie] ode45(odefun,tspan,y0,options) 4、sol ode45(___)描述 [t,y] ode45(odefun,tspan,y0) 其中,tspan [t0 tf] 为微分方程 odefun 的积分区间,y…

mobi文件怎么转换成pdf?

mobi文件怎么转换成pdf?在数字化时代,电子书籍成为了越来越受欢迎的阅读方式。我们可以通过多种格式的电子书来获取知识和娱乐,其中一种常见的格式就是Mobi文件。Mobi文件是亚马逊公司开发的一种电子书格式,它主要用于Kindle设备和…

Maven 依赖传递和冲突、继承和聚合

一、依赖传递和冲突 1.1 Maven 依赖传递特性 1.1.1 概念 假如有三个 Maven 项目 A、B 和 C,其中项目 A 依赖 B,项目 B 依赖 C。那么我们可以说 A 依赖 C。也就是说,依赖的关系为:A—>B—>C, 那么我们执行项目 …

从零开发短视频电商 PaddleOCR Java推理 (三)优化文本检测模型输入和输出

背景 PaddleOCR提供了一系列测试图片,你可以通过点击这里来下载。 值得注意的是,PaddleOCR的模型更新速度远远快于DJL,这导致了一些DJL的优化滞后问题。因此,我们需要采取一些策略来跟上PaddleOCR的最新进展。 针对文本检测模型…

Postgresql 12.2 + PostGIS 3.0.1 安装部署

参考文档: 按照该文档安装即可,如果遇到报错,可以参考下文: https://blog.csdn.net/weixin_41166785/article/details/127674169 所需的安装包 在资源里面(我看下怎么可以不用积分下载) 1、no acceptable…

项目01——《3D滚球跑酷》

布局通常2 by 3 接下来我们布置场景,我们的预期结果(功能分析)是: 游戏中中的小球会以恒定速度向前移动,而玩家控制着小球左右移动来躲避跑道中的红色障碍物,如果玩家能控制小球在跑到上移动一定距离则视为…

从CISC到RISC-V:揭开指令集的面纱

对于大多数同学来说,计算机或智能手机的运行似乎就像魔法一样神奇。你可能知道它们内部都是一些复杂的电子组件,比如CPU、内存等等,但这些组件是如何协同工作,让我们可以在电脑上打字,或者在手机上看视频呢&#xff1f…

基于SSM的在线宠物商城设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue、HTML 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是…

Tide Quencher 7.1WS azide,TQ7.1WS N3,适用于多种荧光物质的分析

您好,欢迎来到新研之家 文章关键词:Tide Quencher 7.1WS 叠氮,TQ7.1WS 叠氮,Tide Quencher 7.1WS azide,TQ7.1WS N3,TQ7.1WS azide,Tide Quencher 7.1WS N3 一、基本信息 产品简介&#xff1…

java SECS管理系统 将逐步推出 SECS 客户端(Passive) 管理系统 SECS快速开发平台 springboot secs开发平台

SECS管理系统 这是一套SECS客户端(Passive),可以直接连接PLC设备,支持Modbus、三菱MC、欧姆龙Fine、OPC-UA、西门子S7设备等通信。 企业已经有了EAP软件,但是设备没有SECS通信功能,这时候可以使用这套框架,直接连接设备&#xff…

springboot集成shiro+前端vue,前后端分离项目遇到跨域以及sessionid拿不到等问题

近期在写前后端分离的项目,由于前后端分离导致原来使用的shiro配置无法满足现有系统要求。同时在前后端分离项目中存在的一些问题。例如,一些用户信息需要存储在后端方便进行安全性判断,但这些存储在后端的session前端却获取不到(…

专业140+总410+哈尔滨工业大学803信号与系统和数字逻辑电路考研经验哈工大电子信息(信息与通信工程-信通)

一年的努力付出终于有了收获,今年专业课140,总分410顺利上岸哈工大803电子信息(信息与通信-信通),回顾总结了自己这一年的复习,有得有失,希望对大家复习有所帮助。 数学 时间安排:…

C++力扣题目40--组合总和II

力扣题目链接(opens new window) 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 说明: 所有数字(包括目标数)都是…

linux pxe高效批量网络装机

系统装机的三种方式 U盘(pe) 光驱 网络启动(pxe) pxe PXE 的全称是 preboot execute environment它其实是Intel在很久以前提出来的一项用于通过网络来引导系统的标准。允许客户机通过网络从远程服务器上下载引导镜像&#…

252:vue+openlayers 绘制锥形渐变填充色的圆形

第252个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayer中绘制带有锥形渐变填充色的圆形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共131行)相关API参考专栏目标示例效果 </

【论文阅读】Speech Driven Video Editing via an Audio-Conditioned Diffusion Model

DiffusionVideoEditing&#xff1a;基于音频条件扩散模型的语音驱动视频编辑 code&#xff1a;GitHub - DanBigioi/DiffusionVideoEditing: Official project repo for paper "Speech Driven Video Editing via an Audio-Conditioned Diffusion Model" paper&#…

IOS-高德地图SDK接入-Swift

申请key 这个要前往高德开发平台注册成为个人开发者然后在控制台创建一个应用&#xff1a; 高德开发平台 注册步骤就不写了&#xff0c;写一下创建应用的步骤&#xff1a; 1、点击应用管理——>我的应用 2、点击右上角的创建新应用 3、输入内容&#xff1a; 4、点击添加ke…

计算机视觉丨基于OpenCV的人脸识别打卡系统

文章目录 写在前面项目分析需求分析1.数据模型2.打卡功能3.数据维护4.考勤报表 系统设计项目设计1.文件系统2.数据模块3.工具模块4.服务模块5.人脸识别6.主函数 运行结果写在后面 写在前面 本期内容&#xff1a;基于OpenCV的WANT公司人脸识别打卡系统。 项目需求&#xff1a;…

Flink(十三)【Flink SQL(上)】

前言 最近在假期实训&#xff0c;但是实在水的不行&#xff0c;三天要学完SSM&#xff0c;实在一言难尽&#xff0c;浪费那时间干什么呢。SSM 之前学了一半&#xff0c;等后面忙完了&#xff0c;再去好好重学一遍&#xff0c;毕竟这玩意真是面试必会的东西。 今天开始学习 Flin…