YOLOv5改进 | ODConv卷积助力极限涨点(附修改后的C2f、Bottleneck模块代码)

一、本文介绍

这篇文章给大家带来的是发表于2022年的ODConv(Omni-Dimensional Dynamic Convolution)中文名字全维度动态卷积,该卷积可以即插即用,可以直接替换网络结构中的任何一个卷积模块,在本文的末尾提供可以直接替换卷积模块的ODConv,添加ODConv模块的C3和Bottleneck(配合教程将代码复制粘贴到你自己的代码中即可运行)给大家,该卷积模块主要具有更小的计算量和更高的精度。下面的图片是精度的对比(因为训练成本我只是用了相同的数据集100张图片除了修改了ODConv以后其他配置都相同下面是效果对比图左面为修改版本,右面为基础版本)

适用场景:轻量化、所有检测目标时均可使用进行有效涨点

目录

一、本文介绍

二、基本原理介绍

2.1ODConv基本原理介绍 

2.2 论文总结

三、ODConv代码 

四、ODConv的官方代码报错解决

五、修改了ODConv的C2f和Bottleneck模块

六、在模型中调用ODConv模块

七、全文总结 


二、基本原理介绍

论文地址:论文地址点击即可跳转阅读

代码地址:文末提供复制粘贴的代码块

大家估计只是冲着代码来看,估计很少想要看其原理的,所以我们这里只做略微的介绍和简单的讲解,最起码知道其基本的原理。


2.1ODConv基本原理介绍 

ODConv的创新之处在于它采用了一种多维注意力机制这种机制通过并行策略来学习卷积核在核空间所有四个维度(即空间大小、输入通道数和每个卷积层的输出通道数)上的互补注意力。这种方法适用于任何卷积层,增强了网络的灵活性和适应性(这个四个维度的卷积可以在代码中清晰的体现出来)

ODConv卷积主要的改进机制就是在上面的地方体现出来的,这个变量名aggregate_weight就是文中提到的四个维度的卷积核,其中的通道数[16,16,3,3]的含义为其具有16个卷积核,每个卷积核有16个通道,卷积核的大小是3x3,所以这处就是体现其具体改动的地方,这处的代码可以在我文末提供的代码中可以找到如果想要了解可以自己debug看一下。

那么大家可能想问了,它是如何减少计算量的呢?因为他具有16个卷积核16个通道数所以他计算是通过并行的方式,因为这一机制导致它的计算量也变小了(是不是感觉一举两得)。

总结:其实ODConv就是提出了这么一种具有多维度的卷积核所以其减少了计算量同时提高了检测精度。

上面的总结是我个人的理解,下面的是文章中的总结-> 


2.2 论文总结

Omni-Dimensional Dynamic Convolution(ODConv)的基本原理是对传统的卷积神经网络(CNN)中卷积层的设计进行创新。在传统的CNN中,每个卷积层通常使用固定的、静态的卷积核来提取特征。相比之下,ODConv引入了一种动态的、多维的注意力机制,对卷积核的设计进行了全面的改进。下面详细介绍其原理:

  1. 多维动态注意力机制:ODConv的核心创新是其多维动态注意力机制。传统的动态卷积通常只在卷积核数量这一个维度上实现动态性,即通过对多个卷积核进行加权组合以适应不同的输入特征。ODConv则进一步扩展了这一概念,它不仅在卷积核数量上动态调整,还涉及到卷积核的其他三个维度:空间大小、输入通道数、输出通道数。这意味着ODConv能够更精细地适应输入数据的特征,从而提高特征提取的效果。

  2. 并行策略:ODConv采用并行策略来同时学习不同维度上的注意力。这种策略允许网络在处理每个维度的特征时更加高效,同时确保各维度之间的互补性和协同作用。

下面的图片左边的是传统的动态卷积右边是文章中提出的ODConv。 

ODConv的独特之处与DyConv和CondConv不同,ODConv采用了一种新颖的多维注意力机制。这种机制不是仅针对每个卷积核计算一个单一的注意力标量,而是沿着卷积核空间的所有四个维度计算四种类型的注意力:αsi​, αci​, αfi​, 和αwi​。这样的设计允许ODConv在空间大小、输入通道数、过滤器数量(输出通道数)和卷积核数量这四个维度上进行细粒度的动态调整。这一处在代码中也有清晰的体现如下图->

并行计算ODConv能够以并行的方式计算这四种类型的注意力,这提高了其效率,并允许它更全面地捕捉和利用输入数据的多维特征。

上面提到了每个通道分别计算其注意力机制,那么其是如何生效的呢?并且提高模型精度的呢? 

下面图片中分别具有a,b,c,d代表四个不同通道的注意力机制生效方式。 

如何在其四种不同类型的注意力机制中逐步应用到卷积核上的过程的呢,下面是对这一过程的解释:

  1. 位置维度的逐点乘法(Location-wise Multiplication):如上图(a)所示,这一步涉及到沿着卷积核的空间维度(即卷积核的高度和宽度)进行的乘法操作。在这里,ODConv计算的位置维度注意力(αsi​)被应用于卷积核的每个空间位置上,这允许网络动态调整卷积核在处理不同空间位置的信息时的重要性。

  2. 通道维度的逐通道乘法(Channel-wise Multiplication):如上图(b)所示,这一步是沿着输入通道维度进行的乘法操作。在这个阶段,通道维度的注意力(αci​)被应用于卷积核的每个输入通道上,使得网络能够针对不同的输入特征通道动态调整其处理方式。

  3. 输出通道维度的逐滤波器乘法(Filter-wise Multiplication):如上图(c)所示,这一步是沿着输出通道维度进行的乘法操作。在这里,输出通道维度的注意力(αfi​)影响卷积核的每个输出滤波器,从而使网络能够根据不同输出特征的重要性进行调整。

  4. 卷积核维度的逐核乘法(Kernel-wise Multiplication):如上图(d)所示,这一步是沿着卷积核维度进行的乘法操作。卷积核维度的注意力(αwi​)在这一阶段被应用,它允许网络动态调整不同卷积核的重要性。

通过这种分步骤的乘法操作,ODConv能够在卷积过程中综合考虑空间位置、输入通道、输出通道和卷积核数量等多个维度的信息,从而实现对卷积核的全方位动态调整。这种细致的调整方式使得ODConv能够更精准地提取特征,增强网络的学习和表达能力。论文的方法部分对这些操作的具体数学表达和实现细节(大家有兴趣可以看看论文,论文在开头我提供了地址)。


三、ODConv代码 

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.autograd


def autopad(k, p=None, d=1):  # kernel, padding, dilation
    # Pad to 'same' shape outputs
    if d > 1:
        k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-size
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
    return p


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

    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, 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):
        return self.act(self.bn(self.conv(x)))

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

class Attention(nn.Module):
    def __init__(self, in_planes, out_planes, kernel_size, groups=1, reduction=0.0625, kernel_num=4, min_channel=16):
        super(Attention, self).__init__()
        attention_channel = max(int(in_planes * reduction), min_channel)
        self.kernel_size = kernel_size
        self.kernel_num = kernel_num
        self.temperature = 1.0

        self.avgpool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Conv2d(in_planes, attention_channel, 1, bias=False)
        self.bn = nn.BatchNorm2d(attention_channel)
        self.relu = nn.ReLU(inplace=True)

        self.channel_fc = nn.Conv2d(attention_channel, in_planes, 1, bias=True)
        self.func_channel = self.get_channel_attention

        if in_planes == groups and in_planes == out_planes:  # depth-wise convolution
            self.func_filter = self.skip
        else:
            self.filter_fc = nn.Conv2d(attention_channel, out_planes, 1, bias=True)
            self.func_filter = self.get_filter_attention

        if kernel_size == 1:  # point-wise convolution
            self.func_spatial = self.skip
        else:
            self.spatial_fc = nn.Conv2d(attention_channel, kernel_size * kernel_size, 1, bias=True)
            self.func_spatial = self.get_spatial_attention

        if kernel_num == 1:
            self.func_kernel = self.skip
        else:
            self.kernel_fc = nn.Conv2d(attention_channel, kernel_num, 1, bias=True)
            self.func_kernel = self.get_kernel_attention

        self._initialize_weights()

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
                if m.bias is not None:
                    nn.init.constant_(m.bias, 0)
            if isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def update_temperature(self, temperature):
        self.temperature = temperature

    @staticmethod
    def skip(_):
        return 1.0

    def get_channel_attention(self, x):
        channel_attention = torch.sigmoid(self.channel_fc(x).view(x.size(0), -1, 1, 1) / self.temperature)
        return channel_attention

    def get_filter_attention(self, x):
        filter_attention = torch.sigmoid(self.filter_fc(x).view(x.size(0), -1, 1, 1) / self.temperature)
        return filter_attention

    def get_spatial_attention(self, x):
        spatial_attention = self.spatial_fc(x).view(x.size(0), 1, 1, 1, self.kernel_size, self.kernel_size)
        spatial_attention = torch.sigmoid(spatial_attention / self.temperature)
        return spatial_attention

    def get_kernel_attention(self, x):
        kernel_attention = self.kernel_fc(x).view(x.size(0), -1, 1, 1, 1, 1)
        kernel_attention = F.softmax(kernel_attention / self.temperature, dim=1)
        return kernel_attention

    def forward(self, x):
        x = self.avgpool(x)
        x = self.fc(x)
        # x = self.bn(x) # 在外面我提供了一个bn这里会报错
        x = self.relu(x)
        return self.func_channel(x), self.func_filter(x), self.func_spatial(x), self.func_kernel(x)


class ODConv2d(nn.Module):
    def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, padding=1, dilation=1, groups=1,
                 reduction=0.0625, kernel_num=4):
        super(ODConv2d, self).__init__()
        in_planes = in_planes
        self.in_planes = in_planes
        self.out_planes = out_planes
        self.kernel_size = kernel_size
        self.stride = stride
        self.padding = padding
        self.dilation = dilation
        self.groups = groups
        self.kernel_num = kernel_num
        self.attention = Attention(in_planes, out_planes, kernel_size, groups=groups,
                                   reduction=reduction, kernel_num=kernel_num)
        self.weight = nn.Parameter(torch.randn(kernel_num, out_planes, in_planes//groups, kernel_size, kernel_size),
                                   requires_grad=True)
        self._initialize_weights()

        if self.kernel_size == 1 and self.kernel_num == 1:
            self._forward_impl = self._forward_impl_pw1x
        else:
            self._forward_impl = self._forward_impl_common

    def _initialize_weights(self):
        for i in range(self.kernel_num):
            nn.init.kaiming_normal_(self.weight[i], mode='fan_out', nonlinearity='relu')

    def update_temperature(self, temperature):
        self.attention.update_temperature(temperature)

    def _forward_impl_common(self, x):
        # Multiplying channel attention (or filter attention) to weights and feature maps are equivalent,
        # while we observe that when using the latter method the models will run faster with less gpu memory cost.
        channel_attention, filter_attention, spatial_attention, kernel_attention = self.attention(x)
        batch_size, in_planes, height, width = x.size()
        x = x * channel_attention
        x = x.reshape(1, -1, height, width)
        aggregate_weight = spatial_attention * kernel_attention * self.weight.unsqueeze(dim=0)
        aggregate_weight = torch.sum(aggregate_weight, dim=1).view(
            [-1, self.in_planes // self.groups, self.kernel_size, self.kernel_size])
        output = F.conv2d(x, weight=aggregate_weight, bias=None, stride=self.stride, padding=self.padding,
                          dilation=self.dilation, groups=self.groups * batch_size)
        output = output.view(batch_size, self.out_planes, output.size(-2), output.size(-1))
        output = output * filter_attention
        return output

    def _forward_impl_pw1x(self, x):
        channel_attention, filter_attention, spatial_attention, kernel_attention = self.attention(x)
        x = x * channel_attention
        output = F.conv2d(x, weight=self.weight.squeeze(dim=0), bias=None, stride=self.stride, padding=self.padding,
                          dilation=self.dilation, groups=self.groups)
        output = output * filter_attention
        return output

    def forward(self, x):
        return self._forward_impl(x)



class Bottleneck(nn.Module):
    """Standard bottleneck."""

    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
        """Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, and
        expansion.
        """
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = ODConv2d(c_, c2, k[1], 1)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        """'forward()' applies the YOLO FPN to input data."""
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))


class C3_ODConv(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)))

    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))


四、在模型中调用ODConv模块

4.1 细节修改教程

4.1.1 修改一

我们找到如下的目录'yolov5-master/models'在这个目录下创建一个文件目录(注意是目录,因为我这个专栏会出很多的更新,这里用一种一劳永逸的方法)文件目录起名modules,然后在下面新建一个文件,将我们的代码复制粘贴进去。


​4.1.2 修改二

然后新建一个__init__.py文件,然后我们在里面添加一行代码。注意标记一个'.'其作用是标记当前目录。


4.1.3 修改三 

然后我们找到如下文件''models/yolo.py''在开头的地方导入我们的模块按照如下修改->

(如果你看了我多个改进机制此处只需要添加一个即可,无需重复添加)

​​​​


4.1.4 修改四

然后我们找到parse_model方法,按照如下修改->

到此就修改完成了,复制下面的ymal文件即可运行。


4.2 ODConv的yaml文件

4.2.1 ODConv的yaml文件一

下面的配置文件为我修改的ODConv的位置,参数的位置里面什么都不用添加空着就行,大家复制粘贴我的就可以运行,同时我提供多个版本给大家,根据我的经验可能涨点的位置。

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
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

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]


# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3_ODConv, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3_ODConv, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3_ODConv, [1024, False]],  # 23 (P5/32-large)


   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]


4.2.2 ODConv的yaml文件二

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
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

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]


# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3_ODConv, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3_ODConv, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3_ODConv, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3_ODConv, [1024, False]],  # 23 (P5/32-large)


   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]


4.2.3 ODConv的yaml文件三

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
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

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, ODConv2d, [128, 3, 2]],  # 1-P2/4
   [-1, 3, C3, [128]],
   [-1, 1, ODConv2d, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3, [256]],
   [-1, 1, ODConv2d, [512, 3, 2]],  # 5-P4/16
   [-1, 9, C3, [512]],
   [-1, 1, ODConv2d, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]


# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, C3, [256, False]],  # 17 (P3/8-small)

   [-1, 1, ODConv2d, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, ODConv2d, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 23 (P5/32-large)


   [[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

4.3 ODConv运行成功截图

附上我的运行记录确保我的教程是可用的。 

4.4 推荐ODConv可添加的位置 

ODConv是一种即插即用的卷积模块(注意是2d的),其可以添加的位置有很多,添加的位置不同效果也不同,所以我下面推荐几个添加的位,置大家可以进行参考,当然不一定要按照我推荐的地方添加。

  1. 残差连接中:在残差网络的残差连接中加入ODConv

  2. Neck部分:YOLOv5的Neck部分负责特征融合,这里添加修改后的C3_ODConv可以帮助模型更有效地融合不同层次的特征。

  3. 检测头:可以再检测头前面添加。

  4. 检测头中:可以再检测头的内部添加该机制(未提供因为需要修改检测头比较麻烦,后期专栏收费后大家购买专栏之后大家会得到一个包含上百个机制的v5文件里面包含所有的改进机制)


五、本文总结 

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv5改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~),如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

 专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HLS 2017.4 导出 RTL 报错:ERROR: [IMPL 213-28] Failed to generate IP.

软件版本:HLS 2017.4 在使用 HLS 导出 RTL 的过程中产生如下错误: 参考 Xilinx 解决方案:https://support.xilinx.com/s/article/76960?languageen_US 问题描述 DESCRIPTION As of January 1st 2022, the export_ip command used by Vivad…

SpingBoot的项目实战--模拟电商【2.登录】

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于SpringBoot电商项目的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.功能需求 二.代码编写 …

【STM32】程序在SRAM中运行

程序在RAM中运行 1、配置内存分配。 2、修改跳转文件 FUNC void Setup(void) { SP _RDWORD(0x20000000); PC _RDWORD(0x20000004); } LOAD RAM\Obj\Project.axf INCREMENTAL Setup(); 3、修改下载ROM地址和RAM地址; 中断向量表映射 中断向量表映射到SRA…

AI大模型引领未来智慧科研暨丨ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮,可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

某后台管理系统加密参数逆向分析

前言 在我们日常的渗透中经常会遇到开局一个登录框的情况,弱口令爆破当然是我们的首选。但是有的网站会对账号密码等登录信息进行加密处理,这一步不由得阻碍了很多人的脚步。前端的加解密是比较常见的,无论是 web 后台还是小程序&#xff0c…

ThinkPHP6.0任意文件上传 PHPSESSION 已亲自复现

ThinkPHP6.0任意文件上传 PHPSESSION 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建安装thinkphp6漏洞信息配置 漏洞利用 修复建议 漏洞名称 漏洞描述 2020年1月10日,ThinkPHP团队发布一个补丁更新,修复了一处由不安全的SessionId导致的任意文…

【MySQL】数据库并发控制:悲观锁与乐观锁的深入解析

🍎个人博客:个人主页 🏆个人专栏: 数 据 库 ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 悲观锁(Pessimistic Locking): 乐观锁(Optimistic Locking): 总结&#x…

10. UVM Environment

环境为agents, scoreboards和其他验证组件(包括有助于在 SoC 级别重用块级环境组件的其他环境类)提供良好的层次结构和容器。用户定义的 env 类必须从 uvm_env 类扩展。 10.1 uvm_env class hierarchy 类声明: virtual class uvm_env extend…

2023.12.27 关于 Redis 数据类型 List 常用命令

目录 List 类型基本概念 List 类型特点 List 操作命令 LPUSH LPUSHX RPUSH RPUSHX LRANGE LPOP RPOP LINDEX LINSERT LREM LTRIM LSET 阻塞版本的命令 阻塞版本 和 非阻塞版本的区别 BLPOP & BRPOP List 类型基本概念 Redis 中的列表(list&am…

水果软件2024FL Studio21.3mac苹果中文版

FL STUDIO21发布,提供您一直在等待的出色工作流程功能。通过新效果、多个播放列表曲目选择和无所畏惧的撤消一切编辑,将您的音乐带入2024年。FL Studio21中文完整版是一个功能齐全、开放式架构的PC音乐创作和制作环境。它具有基于音乐音序器的图形用户界…

flutter学习-day21-使用permission_handler进行系统权限的申请和操作

文章目录 1. 介绍2. 环境准备2-1. Android2-2. iOS 3. 使用 1. 介绍 在大多数操作系统上,权限不是在安装时才授予应用程序的。相反,开发人员必须在应用程序运行时请求用户的许可。在 flutter 开发中,则需要一个跨平台(iOS, Android)的 API 来…

Angular进阶之六:Progressive rendering

简介 Progressive Rendering 是一种提高 Web 应用性能的方法,允许页面在加载过程中逐步呈现,以提高用户体验。在本文中,我们将探讨如何在 Angular 中通过自定义指令实现 Progressive Rendering,特别是处理从服务器获取大量数据的…

flutter 安卓使用高德插件黑屏

地址 https://lbs.amap.com/api/android-sdk/guide/create-project/android-studio-create-project 下面介绍的方式是Native配置 sdk,也就是需要手动下载到本地在引入的方式 1、添加 jar 文件: 将下载的地图 SDK 的 jar包复制到工程(此处截…

V-rep(CoppeliaSim)添加相机,与python联合仿真,并使用python读取V-rep中的RGB图与深度图

目录 前言在V-rep中构建场景建立python与V-rep通信 前言 本文主要介绍了如何使用python与V-rep联合仿真,并用OpenCV可视化V-rep中视觉传感器所能看到的 RGB图和深度图,效果图如下。 在V-rep中构建场景 本文使用的V-rep版本是3.5: 打开V-…

YOLOv5改进 | 2023注意力篇 | FocusedLinearAttention聚焦线性注意力

一、本文介绍 本文给大家带来的改进机制是FLAttention(聚焦线性注意力)是一种用于视觉Transformer模型的注意力机制(但是其也可以用在我们的YOLO系列当中从而提高检测精度),旨在提高效率和表现力。其解决了两个在传统线性注意力方法中存在的…

【2023 CCF 大数据与计算智能大赛】基于TPU平台实现超分辨率重建模型部署 基于FSRCNN的TPU平台超分辨率模型部署方案

2023 CCF 大数据与计算智能大赛 基于TPU平台实现超分辨率重建模型部署 基于FSRCNN的TPU平台超分辨率模型部署方案 WELL 刘渝 人工智能 研一 西安交通大学 中国-西安 1461003622qq.com 史政立 网络空间安全 研一 西安交通大学 中国-西安 1170774291qq.com 崔琳、张…

Hive中支持毫秒级别的时间精度

实际上,Hive 在较新的版本中已经支持毫秒级别的时间精度。你可以通过设置 hive.exec.default.serialization.format 和 mapred.output.value.format 属性为 1,启用 Hive 的时间精度为毫秒级。可以使用以下命令进行设置: set hive.exec.defau…

idea中终端Terminal页面输入命令git log后如何退出

1、idea中Terminal输入命令git log后如何退出? 2、解决 输入q键会自动退出git log命令

【Redis前奏曲】初识Redis

文章目录 一.Redis的一些特性(优点)1. 在内存中存储数据2. 可编程的3. 可扩展的4.持久化5. 聚集(集群)6. 高可用Redis快的原因 二. 使用案例1.数据库2. 缓存3. 消息队列 一.Redis的一些特性(优点) 我们在上一篇博客中说到,Redis是一个在内存中存储数据的中间件.用作数据库,数据…

C++面向对象(OOP)编程-C++11新特性详解

C11作为一个重要的版本,引入了很多新的特性,解决了C语言本身很多遗留的内存泄露问题,并且提供了很多比较灵活的用法。引入的auto,智能指针、线程机制都使得C语言的灵活性、安全性、并发性有了很大的提升。 本文会比较详细的介绍C1…