YOLOv5改进系列(26)——添加RFAConv注意力卷积(感受野注意力卷积运算)

962f7cb1b48f44e29d9beb1d499d0530.gif【YOLOv5改进系列】前期回顾:

YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析

YOLOv5改进系列(1)——添加SE注意力机制

YOLOv5改进系列(2)——添加CBAM注意力机制

YOLOv5改进系列(3)——添加CA注意力机制

YOLOv5改进系列(4)——添加ECA注意力机制

YOLOv5改进系列(5)——替换主干网络之 MobileNetV3

YOLOv5改进系列(6)——替换主干网络之 ShuffleNetV2

YOLOv5改进系列(7)——添加SimAM注意力机制

YOLOv5改进系列(8)——添加SOCA注意力机制

YOLOv5改进系列(9)——替换主干网络之EfficientNetv2

​​​​​​YOLOv5改进系列(10)——替换主干网络之GhostNet

YOLOv5改进系列(11)——添加损失函数之EIoU、AlphaIoU、SIoU、WIoU

YOLOv5改进系列(12)——更换Neck之BiFPN

YOLOv5改进系列(13)——更换激活函数之SiLU,ReLU,ELU,Hardswish,Mish,Softplus,AconC系列等

YOLOv5改进系列(14)——更换NMS(非极大抑制)之 DIoU-NMS、CIoU-NMS、EIoU-NMS、GIoU-NMS 、SIoU-NMS、Soft-NMS

YOLOv5改进系列(15)——增加小目标检测层

YOLOv5改进系列(16)——添加EMA注意力机制(ICASSP2023|实测涨点)

YOLOv5改进系列(17)——更换IoU之MPDIoU(ELSEVIER 2023|超越WIoU、EIoU等|实测涨点)

YOLOv5改进系列(18)——更换Neck之AFPN(全新渐进特征金字塔|超越PAFPN|实测涨点)

YOLOv5改进系列(19)——替换主干网络之Swin TransformerV1(参数量更小的ViT模型)

YOLOv5改进系列(20)——添加BiFormer注意力机制(CVPR2023|小目标涨点神器)

YOLOv5改进系列(21)——替换主干网络之RepViT(清华 ICCV 2023|最新开源移动端ViT)

YOLOv5改进系列(22)——替换主干网络之MobileViTv1(一种轻量级的、通用的移动设备 ViT)

YOLOv5改进系列(23)——替换主干网络之MobileViTv2(移动视觉 Transformer 的高效可分离自注意力机制)

YOLOv5改进系列(24)——替换主干网络之MobileViTv3(移动端轻量化网络的进一步升级)

YOLOv5改进系列(25)——添加LSKNet注意力机制(大选择性卷积核的领域首次探索)

目录

🚀 一、RFAConv介绍 

1.1 RFAConv简介 

1.2 RFAConv网络结构 

(1)RFAConv

(2)RFCAConv

(3)RFCBAMConv

🚀二、RFAConv核心代码讲解

① class Bottleneck1

② class RFAConv

③ Bottleneck_RFAConv 

🚀三、具体添加方法 

3.1 添加顺序 

3.2 具体添加步骤  

第①步:在common.py中添加RFAConv模块  

第②步:在yolo.py文件里的parse_model函数加入类名

 第③步:创建自定义的yaml文件   

第④步:验证是否加入成功

🌟本人YOLOv5系列导航

🚀 一、RFAConv介绍 

  • 论文题目:《RFAConv: Innovating Spatial Attention and Standard Convolutional Operation》
  • 论文地址:https://arxiv.org/pdf/2304.03198.pdf
  • 代码实现:GitHub - Liuchen1997/RFAConv: RAFConv: Innovating Spatital Attention and Standard Convolutional Operation

1.1 RFAConv简介 

空间注意力机制的局限性

空间注意力机制就是寻找网络中最重要的部位进行处理。旨在提升关键区域的特征表达,本质上是将原始图片中的空间信息通过空间转换模块,变换到另一个空间中并保留关键信息,为每个位置生成权重掩膜(mask)并加权输出,从而增强感兴趣的特定目标区域同时弱化不相关的背景区域。

空间注意力机制从本质上解决了卷积核参数共享问题。然而,空间注意力生成的注意图所包含的信息对于大尺寸卷积核是不够的。

RFAConv的贡献

针对以上不足,作者提出了一种新的注意机制——感受野注意力(Receptive-Field Attention, RFA)现有的空间注意力,如卷积块注意力模块(CBAM)和协调注意力(CA),都存在着只关注空间特征,并没有完全解决卷积核参数共享的问题

相反,RFA不仅关注感受野空间特征,而且为大尺寸卷积核提供了有效的注意力权重。

由RFA开发的感受野注意卷积运算(RFAConv)代表了一种取代标准卷积运算的新方法。它可以显著提高网络性能,但是几乎可以忽略不计的计算成本和参数增量。RFAConv的核心思想是将空间注意力机制与卷积操作相结合,与感受野特征信息交互以学习注意力图,从而提高卷积神经网络(CNN)的性能。


1.2 RFAConv网络结构 

(1)RFAConv

具有3×3大小卷积核的RFAConv的总体结构如下图所示:

我们先看上半部分: 

  • 首先,通过使用AvgPool池化每个感受野特征的全局信息。
  • 然后,通过1×1的组卷积运算与信息交互。
  • 最后,softmax用于强调感受野特征中每个特征的重要性。

目的:为了减少额外的的计算开销和参数数量。

计算公式:

g表示分组卷积,k表示卷积核的大小,Norm代表规范化,X表示输入特征图,F是通过将注意力图A_{rf}与变换的感受野空间特征F_{rf}相乘而获得的。 

下半部分:

通过快速分组卷积提取感受野特征,替换了原来比较慢的提取感受野特征的方法。


(2)RFCAConv

与RFA类似,使用stride为k的k×k的最终卷积运算来提取特征信息。


(3)RFCBAMConv

为了比原始的CBAM减少计算开销,可以使用SE注意力来代替RFCBAM中的CAM。


🚀二、RFAConv核心代码讲解

 源码太长读不下去,找了核心代码读一读吧~

from einops import rearrangeclass Bottleneck1(nn.Module):"""Standard bottleneck."""# __init__ 方法:初始化函数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, andexpansion."""super().__init__()# 计算隐藏通道数c_ = int(c2 * e)  # hidden channels# 两个卷积层,分别是输入通道数到隐藏通道数和隐藏通道数到输出通道数的卷积。self.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = Conv(c_, c2, k[1], 1, g=g)# 判断是否使用快捷连接,条件是启用快捷连接并且输入通道数等于输出通道数。self.add = shortcut and c1 == c2def 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 RFAConv(nn.Module):def __init__(self, in_channel, out_channel, kernel_size, stride=1):super().__init__()# 存储卷积核的尺寸self.kernel_size = kernel_size# 生成权重self.get_weight = nn.Sequential(nn.AvgPool2d(kernel_size=kernel_size, padding=kernel_size // 2, stride=stride),nn.Conv2d(in_channel, in_channel * (kernel_size ** 2), kernel_size=1,groups=in_channel, bias=False))# 生成特征self.generate_feature = nn.Sequential(nn.Conv2d(in_channel, in_channel * (kernel_size ** 2), kernel_size=kernel_size, padding=kernel_size // 2,stride=stride, groups=in_channel, bias=False),nn.BatchNorm2d(in_channel * (kernel_size ** 2)),nn.ReLU())self.conv = Conv(in_channel, out_channel, k=kernel_size, s=kernel_size, p=0)def forward(self, x):b, c = x.shape[0:2]weight = self.get_weight(x)h, w = weight.shape[2:]weighted = weight.view(b, c, self.kernel_size ** 2, h, w).softmax(2)  # b c*kernel**2,h,w ->  b c k**2 h wfeature = self.generate_feature(x).view(b, c, self.kernel_size ** 2, h,w)  # b c*kernel**2,h,w ->  b c k**2 h wweighted_data = feature * weightedconv_data = rearrange(weighted_data, 'b c (n1 n2) h w -> b c (h n1) (w n2)', n1=self.kernel_size,# b c k**2 h w ->  b c h*k w*kn2=self.kernel_size)return self.conv(conv_data)# Bottleneck1的子类
class Bottleneck_RFAConv(Bottleneck1):"""Standard bottleneck with RFAConv."""def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):  # ch_in, ch_out, shortcut, groups, kernels, expandsuper().__init__(c1, c2, shortcut, g, k, e)c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = RFAConv(c_, c2, k[1])# C3的子类
class C3_RFAConv(C3):def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):super().__init__(c1, c2, n, shortcut, g, e)c_ = int(c2 * e)  # hidden channelsself.m = nn.Sequential(*(Bottleneck_RFAConv(c_, c_, shortcut, g, k=(1, 3), e=1.0) for _ in range(n)))

① class Bottleneck1

这是一个标准的残差块,在以前代码讲解中我们讲过很多次。

首先,通过__init__ 方法初始化函数,然后计算隐藏通道数 c_,即第一个卷积层的输出通道数。

再定义两个卷积层 cv1 cv2分别将输入通道数映射到隐藏通道数,接着从隐藏通道数映射到输出通道数。

最后通过self.add判断是否使用shortcut

② class RFAConv

这个类就是实现了具有区域注意力机制的卷积操作通过生成权重并将其应用到输入特征上,以获得加权的特征表示。最终,通过卷积操作将这些加权的特征映射到输出通道数

其中,self.get_weight包含两个子模块的顺序模块,用于生成权重。

  • 第一个子模块是一个平均池化层,用于降低空间分辨率。
  • 第二个子模块是一个 1x1 的卷积层,用于生成权重,并通过设置 groups=in_channel 实现通道间的独立

③ Bottleneck_RFAConv 

这个类是①的子类,参数也和①一样,就不细讲了~

目的是残差块结构中引入区域注意力机制,从而提高模型对输入数据的关注度。

④class C3_RFAConv

它是 C3 类的子类,通过引入 Bottleneck_RFAConv 模块实现了区域注意力机制。

目的是C3 模块结构中引入区域注意力机制,通过使用 Bottleneck_RFAConv 模块替代标准的瓶颈模块。这样可以在模块内引入区域注意力,从而在整个 C3 模块内提高模型对输入数据的关注度。 


🚀三、具体添加方法 

3.1 添加顺序 

(1)models/common.py    -->  加入新增的网络结构

(2)     models/yolo.py       -->  设定网络结构的传参细节,将RFAConv系列类名加入其中。(当新的自定义模块中存在输入输出维度时,要使用qw调整输出维度)
(3) models/yolov5*.yaml  -->  新建一个文件夹,如yolov5s_RFAConv.yaml,修改现有模型结构配置文件。(当引入新的层时,要修改后续的结构中的from参数)
(4)         train.py                -->  修改‘--cfg’默认参数,训练时指定模型结构配置文件


3.2 具体添加步骤  

第①步:在common.py中添加RFAConv模块  

将下面的RFAConv代码复制粘贴到common.py文件的末尾  

from einops import rearrangeclass Bottleneck1(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, andexpansion."""super().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = Conv(c_, c2, k[1], 1, g=g)self.add = shortcut and c1 == c2def 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 RFAConv(nn.Module):def __init__(self, in_channel, out_channel, kernel_size, stride=1):super().__init__()self.kernel_size = kernel_sizeself.get_weight = nn.Sequential(nn.AvgPool2d(kernel_size=kernel_size, padding=kernel_size // 2, stride=stride),nn.Conv2d(in_channel, in_channel * (kernel_size ** 2), kernel_size=1,groups=in_channel, bias=False))self.generate_feature = nn.Sequential(nn.Conv2d(in_channel, in_channel * (kernel_size ** 2), kernel_size=kernel_size, padding=kernel_size // 2,stride=stride, groups=in_channel, bias=False),nn.BatchNorm2d(in_channel * (kernel_size ** 2)),nn.ReLU())self.conv = Conv(in_channel, out_channel, k=kernel_size, s=kernel_size, p=0)def forward(self, x):b, c = x.shape[0:2]weight = self.get_weight(x)h, w = weight.shape[2:]weighted = weight.view(b, c, self.kernel_size ** 2, h, w).softmax(2)  # b c*kernel**2,h,w ->  b c k**2 h wfeature = self.generate_feature(x).view(b, c, self.kernel_size ** 2, h,w)  # b c*kernel**2,h,w ->  b c k**2 h wweighted_data = feature * weightedconv_data = rearrange(weighted_data, 'b c (n1 n2) h w -> b c (h n1) (w n2)', n1=self.kernel_size,# b c k**2 h w ->  b c h*k w*kn2=self.kernel_size)return self.conv(conv_data)class Bottleneck_RFAConv(Bottleneck1):"""Standard bottleneck with RFAConv."""def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):  # ch_in, ch_out, shortcut, groups, kernels, expandsuper().__init__(c1, c2, shortcut, g, k, e)c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = RFAConv(c_, c2, k[1])class C3_RFAConv(C3):def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):super().__init__(c1, c2, n, shortcut, g, e)c_ = int(c2 * e)  # hidden channelsself.m = nn.Sequential(*(Bottleneck_RFAConv(c_, c_, shortcut, g, k=(1, 3), e=1.0) for _ in range(n)))

第②步:在yolo.py文件里的parse_model函数加入类名

首先找到yolo.py里面parse_model函数的这一行

加入 RFAConvC3_RFAConv 这两个模块


 第③步:创建自定义的yaml文件   

 第1种,更改Conv模块

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # 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, RFAConv, [128, 3, 2]],  # 1-P2/4[-1, 3, C3, [128]],[-1, 1, RFAConv, [256, 3, 2]],  # 3-P3/8[-1, 6, C3, [256]],[-1, 1, RFAConv, [512, 3, 2]],  # 5-P4/16[-1, 9, C3, [512]],[-1, 1, RFAConv, [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, RFAConv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]],  # cat head P4[-1, 3, C3, [512, False]],  # 20 (P4/16-medium)[-1, 1, RFAConv, [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)]

 第2种,更改C3模块

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # 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_RFAConv, [128]],[-1, 1, Conv, [256, 3, 2]],  # 3-P3/8[-1, 6, C3_RFAConv, [256]],[-1, 1, Conv, [512, 3, 2]],  # 5-P4/16[-1, 9, C3_RFAConv, [512]],[-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32[-1, 3, C3_RFAConv, [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_RFAConv, [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_RFAConv, [256, False]],  # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]],  # cat head P4[-1, 3, C3_RFAConv, [512, False]],  # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]],  # cat head P5[-1, 3, C3_RFAConv, [1024, False]],  # 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)]

第④步:验证是否加入成功

运行yolo.py   

第1种

第2种 

这样就OK啦!

代码参考:

优化改进YOLOv5算法之感受野注意力卷积运算(RFAConv),效果秒杀CBAM和CA等-CSDN博客


🌟本人YOLOv5系列导航

962f7cb1b48f44e29d9beb1d499d0530.gif​​   🍀YOLOv5源码详解系列:  

YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析

​​​​​​YOLOv5源码逐行超详细注释与解读(2)——推理部分detect.py

YOLOv5源码逐行超详细注释与解读(3)——训练部分train.py

YOLOv5源码逐行超详细注释与解读(4)——验证部分val(test).py

YOLOv5源码逐行超详细注释与解读(5)——配置文件yolov5s.yaml

YOLOv5源码逐行超详细注释与解读(6)——网络结构(1)yolo.py

YOLOv5源码逐行超详细注释与解读(7)——网络结构(2)common.py


962f7cb1b48f44e29d9beb1d499d0530.gif​​​   🍀YOLOv5入门实践系列:  

YOLOv5入门实践(1)——手把手带你环境配置搭建

YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集

YOLOv5入门实践(3)——手把手教你划分自己的数据集

YOLOv5入门实践(4)——手把手教你训练自己的数据集

YOLOv5入门实践(5)——从零开始,手把手教你训练自己的目标检测模型(包含pyqt5界面)

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

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

相关文章

VM安装群晖系统 挂载整个硬盘给群晖系统

前言 在我们日常业务需求中,经常需要把整个磁盘的空间分配给群晖使用,那么如何通过vm分配整个磁盘空间给群晖系统。 操作 需要用管理员运行VM虚拟机 然后添加硬盘 就可以有权限全部添加了。这样会清除要挂载的磁盘的全部的数据。

十五、CSS3DObject和CSS2DObject的区别

在3d场景中我们会遇到很多标签,主要分为三种,css3dobject、css2dobject、css3dsprite三种,今天主要说说css3dobject和css2dobject的相似点和区别。 Threejs版本:0.138.3 下面看实现的效果: 相似点 使用方法都是差不多的,下面讲解下css2dobject的使用方法在index.html增…

[ACM学习] 动态规划基础之一二三维dp

课内学习的动态规划 有记忆的迭代 优化解的结构:原始问题的一部分解是子问题的解 三要素:1.子问题 2.状态的定义 3.状态转移方程 定义 线性dp的一道例题 dp[i]表示以位置 i 结尾的方案总数,dp[4]2,因为:首先只放一…

【驱动】TI AM437x(内核调试-06):网卡(PHY和MAC)、七层OSI

1、网络基础知识 1.1 七层OSI 第一层:物理层。 1)需求: 两个电脑之间如何进行通信? 具体就是一台发比特流,另一台能够收到。于是就有了物理层:主要是定义设备标准,如网线的额接口类型、管线的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流,就是从1/0…

【GitHub项目推荐--一行命令下载全网视频】【转载】

项目地址:https://github.com/soimort/you-get 首先声明,请不要使用该项目从事违法活动哦~仅供学习使用! 解决痛点 如果你上网的时候看了一些东西不错,想下载下来,或者在线观看喜欢的视频,但是没有找到网…

xilinxi mulitboot 启动

xilinix在线更新有两种方式,一种是使用ICAP原语,另一中是在xdc中约束,根据应用的场景不同,选用不同的启动方式,第二种更为简单。 可参考官方提供的手册和实例 XAPP1247 链接: XAPP1247 golden和updata.b…

【零基础入门Python数据分析】Anaconda3 JupyterNotebookseaborn版

目录 一、安装环境 python介绍 anaconda介绍 jupyter notebook介绍 anaconda3 环境安装 解决JuPyter500:Internal Server Error问题-CSDN博客 Jupyter notebook快捷键操作大全 二、Python基础入门 数据类型与变量 数据类型 变量及赋值 布尔类型与逻辑运算…

基于时域有限差分法的FDTD的计算电磁学算法-YEE网格下的更新公式推导

基于时域有限差分法的FDTD的计算电磁学算法(含Matlab代码)-YEE网格下的更新公式推导 参考书籍:The finite-difference time-domain method for electromagnetics with MATLAB simulations(国内翻译版本:MATLAB模拟的电…

【MATLAB】 SSA奇异谱分析信号分解算法

有意向获取代码,请转文末观看代码获取方式~ 1 基本定义 SSA奇异谱分析(Singular Spectrum Analysis)是一种处理非线性时间序列数据的方法,可以对时间序列进行分析和预测。 它基于构造在时间序列上的特定矩阵的奇异值分解&#…

C#,入门教程(66)——枚举Enum的高等用法

前言:国内码农与国外优秀程序员的最大区别是,我们的专家、教授喜欢唾沫横飞地,夸夸其谈语言特性、框架、性能,唯一目的是带私货(书籍或教程),很少能写出真有用的程序。差距在哪呢?基…

线性代数——行列式相关性质

目录 一、行列式与它的转置列行列式相等 二、对换行列式的两行(列),行列式变号 三、行列式某行(列)有公因子k,则k可以提到行列式外 四、行列式中若两行成比例,则行列式为0 五、行列式的某一行…

Python | 三、函数

函数的形参和实参(对应卡码网11题句子缩写) 除非实参是可变对象,如列表、字典和集合,则此时形参会复制实参的地址,即此时二者指向同一个地址,因此在函数内对形参的操作会影响到实参除这种情况外&#xff0…

【江科大STM32合集】day2按键控制LED光敏传感器控制峰鸣器

【STM32合集】day2按键控制LED&光敏传感器控制峰鸣器 电路基础c语言基础main.ckey.c结果 实现一个键开关灯实验结果避坑 电路基础 运算放大器-在江科大51单片机b站视频(AD/DA)复习 原理:两个极端 同相输入端电压 》反相输入端 电压输出最…

如何利用小程序介绍公司品牌形象?

企业小程序的建设对于现代企业来说已经成为了一项必不可少的工作。随着移动互联网的快速发展,越来越多的职场人士和创业老板希望通过小程序来提升企业形象,增强与用户的互动,实现更好的商业效果。在这个过程中,使用第三方制作平台…

Java零基础教学文档第五篇:jQuery

今日新篇章 【jQuery】 【主要内容】 jQuery简介 jQuery安装 jQuery语法 jQuery选择器 jQuery事件处理 jQueryDOM操作 jQuery元素遍历 jQuery过滤 jQuery其它方法 【学习目标】 1.jQuery简介 1.1 jQuery简介 jQuery 库可以通过一行简单的标记被添加到网页中。 1.…

国内镜像:极速下载编译WebRTC源码(For Android/Linux/IOS)(二十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

Vue学习笔记5-- nextTick | Vue封装的过渡与动画

一、nextTick(tick-工作,起作用;下次起作用) 语法: this.$nextTick(回调函数)作用:在下一次DOM更新结束后执行其指定的回调。什么时候用:当改变数据后,要基于更新后的新DOM进行某些…

面试百问:Redis常见的故障以及发生场景

作为一个测试同学,被测系统架构中有使用到redis吗?对redis常见的故障有了解吗?又是如何进行测试的呢? 针对常见的redis面试问题,怎样才算一个高质量的回答呢,回答思路一般包括 问题的类型是什么&#xff…

快速入门Java NIO(Not I/O)的网络通信框架--Netty

Netty 入门 了解netty前需要对nio有一定认识,该笔记基础来自bilinbili黑马,在此基础上自己学习的笔记,添加了一些自己的理解 了解java 非阻塞io编程 1. 概述 1.1 Netty 是什么? Netty is an asynchronous event-driven network application framework for rapid …

Flink启动Yarn Session报错:Couldn‘t deploy Yarn session cluster

Flink版本:1.1.3 启动Yarn Session的语句:bin/yarn-session.sh -nm test -d 报错截图如下: 仅通过ERROR信息只能知道是yarn session集群未能正常启动,因此继续向下查找: 找到报错信息的Caused by部分: 报…