YOLOv8改進 | 2023 | RCS-OSA替換C2f實現暴力漲點(減少通道的空間對象注意力機制)

一、本文介紹

?本文給大家帶來的改進機制是RCS-YOLO提出的RCS-OSA模塊,其全稱是"Reduced Channel Spatial Object Attention",意即"減少通道的空間對象注意力"。這個模塊的主要功能是通過減少特征圖的通道數量,同時關注空間維度上的重要特征,來提高模型的處理效率和檢測精度。親測在小目標檢測和大尺度目標檢測的數據集上都有大幅度的漲點效果(mAP直接漲了大概有0.6左右)同時本文對RCS-OSA模塊的框架原理進行了詳細的分析,不光讓大家會添加到自己的模型在寫論文的時候也能夠有一定的參照,最后本文會手把手教你添加RCS-OSA模塊到網絡結構中。

推薦指數:?????

漲點效果:?????

專欄回顧:YOLOv8改進系列專欄——本專欄持續復習各種頂會內容——科研必備????

訓練結果對比圖->??

這次試驗我用的數據集大概有七八百張照片訓練了150個epochs,雖然沒有完全擬合但是效果有很高的漲點幅度,所以大家可以進行嘗試畢竟不同的數據集上效果也可能差很多,同時我在后面給了多種yaml文件大家可以分別進行實驗來檢驗效果。

可以看到這個漲點幅度mAP直接漲了大概有0.6左右,這個漲幅還是很好的,所以非常建議大家進行嘗試這個機制的改進。

目錄

一、本文介紹

二、RCS-OSA模塊原理

2.1 RCS-OSA的基本原理

2.2?RCS

2.3?RCS模塊

2.4?OSA

2.5?特征級聯

三、RCS-OSA核心代碼

四、手把手教你添加RCS-OSA模塊

4.1?RCS-OSA添加步驟

4.1.1 步驟一

4.1.2 步驟二

4.1.3 步驟三

4.2 RCS-OSA的yaml文件和訓練截圖

4.2.1 RCS-OSA的yaml版本一(推薦)

4.2.2 RCS-OSA的yaml版本二

4.2.2 RCS-OSA的訓練過程截圖?

五、本文總結


二、RCS-OSA模塊原理

論文地址:官方論文地址

代碼地址:官方代碼地址


2.1 RCS-OSA的基本原理

RCSOSA(RCS-One-Shot Aggregation)RCS-YOLO中提出的一種結構,我們可以將主要原理概括如下:

1. RCS(Reparameterized Convolution based on channel Shuffle): 結合了通道混洗,通過重參數化卷積來增強網絡的特征提取能力。

2. RCS模塊: 在訓練階段,利用多分支結構學習豐富的特征表示;在推理階段,通過結構化重參數化簡化為單一分支,減少內存消耗。

3. OSA(One-Shot Aggregation): 一次性聚合多個特征級聯,減少網絡計算負擔,提高計算效率。

4. 特征級聯: RCS-OSA模塊通過堆疊RCS,確保特征的復用并加強不同層之間的信息流動。


2.2?RCS

RCS(基于通道Shuffle的重參數化卷積)是RCS-YOLO的核心組成部分,旨在訓練階段通過多分支結構學習豐富的特征信息,并在推理階段通過簡化為單分支結構來減少內存消耗,實現快速推理。此外,RCS利用通道分割和通道Shuffle操作來降低計算復雜性,同時保持通道間的信息交換,這樣在推理階段相比普通的3×3卷積可以減少一半的計算復雜度。通過結構重參數化,RCS能夠在訓練階段從輸入特征中學習深層表示,并在推理階段實現快速推理,同時減少內存消耗。


2.3?RCS模塊

RCS(基于通道Shuffle的重參數化卷積)模塊中,結構在訓練階段使用多個分支,包括1x1和3x3的卷積,以及一個直接的連接(Identity),用于學習豐富的特征表示。在推理階段,結構被重參數化成一個單一的3x3卷積,以減少計算復雜性和內存消耗,同時保持訓練階段學到的特征表達能力。這與RCS的設計理念緊密相連,即在不犧牲性能的情況下提高計算效率。

上圖為大家展示了RCS的結構,分為訓練階段(a部分)推理階段(b部分)。在訓練階段,輸入通過通道分割,一部分輸入經過RepVGG塊,另一部分保持不變。然后通過1x1卷積和3x3卷積處理RepVGG塊的輸出,與另一部分輸入進行通道Shuffle和連接。在推理階段,原來的多分支結構被簡化為一個單一的3x3 RepConv塊。這種設計允許在訓練時學習復雜特征,在推理時減少計算復雜度。黑色邊框的矩形代表特定的模塊操作,漸變色的矩形代表張量的特定特征,矩形的寬度代表張量的通道數。?


2.4?OSA

OSA(One-Shot Aggregation)是一個關鍵的模塊,旨在提高網絡在處理密集連接時的效率。OSA模塊通過表示具有多個感受野的多樣化特征,并在最后的特征映射中僅聚合一次所有特征,從而克服了DenseNet中密集連接的低效率問題。

OSA模塊的使用有兩個主要目的:

1. 提高特征表示的多樣性:OSA通過聚合具有不同感受野的特征來增加網絡對于不同尺度的敏感性,這有助于提升模型對不同大小目標的檢測能力。

2. 提高效率:通過在網絡的最后一部分只進行一次特征聚合,OSA減少了重復的特征計算和存儲需求,從而提高了網絡的計算和能源效率。

在RCS-YOLO中,OSA模塊被進一步與RCS(基于通道Shuffle的重參數化卷積)相結合,形成RCS-OSA模塊。這種結合不僅保持了低成本的內存消耗,而且還實現了語義信息的有效提取,對于構建輕量級和大規模的對象檢測器尤為重要。

下面我將為大家展示RCS-OSA(One-Shot Aggregation of RCS)的結構。

在RCS-OSA模塊中,輸入被分為兩部分,一部分直接通過,另一部分通過堆疊的RCS模塊進行處理。處理后的特征和直接通過的特征在通道混洗(Channel Shuffle)后合并。這種結構設計用于增強模型的特征提取和利用效率,是RCS-YOLO架構中的一個關鍵組成部分旨在通過一次性聚合來提高模型處理特征的能力,同時保持計算效率。


2.5?特征級聯

特征級聯(feature cascade)是一種技術,通過在網絡的一次性聚合(one-shot aggregate)路徑上維持有限數量的特征級聯來實現的。在RCS-YOLO中,特別是在RCS-OSA(RCS-Based One-Shot Aggregation)模塊中,只保留了三個特征級聯。

特征級聯的目的是為了減輕網絡計算負擔并降低內存占用。這種方法可以有效地聚合不同層次的特征,提高模型的語義信息提取能力,同時避免了過度復雜化網絡結構所帶來的低效率和高資源消耗。

下面為大家提供的圖像展示的是RCS-YOLO的整體架構,其中包括RCS-OSA模塊。RCS-OSA在模型中用于堆疊RCS模塊,以確保特征的復用并加強不同層之間的信息流動。圖中顯示的多層RCS-OSA模塊的排列和組合反映了它們如何一起工作以優化特征傳遞和提高檢測性能。

總結:RCS-YOLO主要由RCS-OSA(藍色模塊)和RepVGG(橙色模塊)構成。這里的n代表堆疊RCS模塊的數量。n_cls代表檢測到的對象中的類別數量。圖中的IDetect是從YOLOv7中借鑒過來的,表示使用二維卷積神經網絡的檢測層。這個架構通過堆疊的RCS模塊和RepVGG模塊,以及兩種類型的檢測層,實現了對象檢測的任務。?


三、RCS-OSA核心代碼

在這里說一下這個原文是RCS-YOLO我們只是用其中的RCS-OSA模塊來替換我們YOLOv8中的C2f模塊,但是在RCS-YOLO中還有一個RepVGG模塊(大家在下面的代碼中可以看到),這個模塊可以替換Conv,但是如果都替換的話我覺得那就是RCS-YOLO了沒啥區別了,所以我下面的改進和這篇文章只用了RCS-OSA模塊來替換C2f,如果你對RCS-YOLO感興趣的話,我后面也會提高RCS-YOLO的yaml文件供大家參考。

import torch.nn as nn
import torch
import torch.nn.functional as F
import numpy as np
import math# build RepVGG block
# -----------------------------
def conv_bn(in_channels, out_channels, kernel_size, stride, padding, groups=1):result = nn.Sequential()result.add_module('conv', nn.Conv2d(in_channels=in_channels, out_channels=out_channels,kernel_size=kernel_size, stride=stride, padding=padding, groups=groups,bias=False))result.add_module('bn', nn.BatchNorm2d(num_features=out_channels))return resultclass SEBlock(nn.Module):def __init__(self, input_channels):super(SEBlock, self).__init__()internal_neurons = input_channels // 8self.down = nn.Conv2d(in_channels=input_channels, out_channels=internal_neurons, kernel_size=1, stride=1,bias=True)self.up = nn.Conv2d(in_channels=internal_neurons, out_channels=input_channels, kernel_size=1, stride=1,bias=True)self.input_channels = input_channelsdef forward(self, inputs):x = F.avg_pool2d(inputs, kernel_size=inputs.size(3))x = self.down(x)x = F.relu(x)x = self.up(x)x = torch.sigmoid(x)x = x.view(-1, self.input_channels, 1, 1)return inputs * xclass RepVGG(nn.Module):def __init__(self, in_channels, out_channels, kernel_size=3,stride=1, padding=1, dilation=1, groups=1, padding_mode='zeros', deploy=False, use_se=False):super(RepVGG, self).__init__()self.deploy = deployself.groups = groupsself.in_channels = in_channelspadding_11 = padding - kernel_size // 2self.nonlinearity = nn.SiLU()# self.nonlinearity = nn.ReLU()if use_se:self.se = SEBlock(out_channels, internal_neurons=out_channels // 16)else:self.se = nn.Identity()if deploy:self.rbr_reparam = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,stride=stride,padding=padding, dilation=dilation, groups=groups, bias=True,padding_mode=padding_mode)else:self.rbr_identity = nn.BatchNorm2d(num_features=in_channels) if out_channels == in_channels and stride == 1 else Noneself.rbr_dense = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size,stride=stride, padding=padding, groups=groups)self.rbr_1x1 = conv_bn(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=stride,padding=padding_11, groups=groups)# print('RepVGG Block, identity = ', self.rbr_identity)def get_equivalent_kernel_bias(self):kernel3x3, bias3x3 = self._fuse_bn_tensor(self.rbr_dense)kernel1x1, bias1x1 = self._fuse_bn_tensor(self.rbr_1x1)kernelid, biasid = self._fuse_bn_tensor(self.rbr_identity)return kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid, bias3x3 + bias1x1 + biasiddef _pad_1x1_to_3x3_tensor(self, kernel1x1):if kernel1x1 is None:return 0else:return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])def _fuse_bn_tensor(self, branch):if branch is None:return 0, 0if isinstance(branch, nn.Sequential):kernel = branch.conv.weightrunning_mean = branch.bn.running_meanrunning_var = branch.bn.running_vargamma = branch.bn.weightbeta = branch.bn.biaseps = branch.bn.epselse:assert isinstance(branch, nn.BatchNorm2d)if not hasattr(self, 'id_tensor'):input_dim = self.in_channels // self.groupskernel_value = np.zeros((self.in_channels, input_dim, 3, 3), dtype=np.float32)for i in range(self.in_channels):kernel_value[i, i % input_dim, 1, 1] = 1self.id_tensor = torch.from_numpy(kernel_value).to(branch.weight.device)kernel = self.id_tensorrunning_mean = branch.running_meanrunning_var = branch.running_vargamma = branch.weightbeta = branch.biaseps = branch.epsstd = (running_var + eps).sqrt()t = (gamma / std).reshape(-1, 1, 1, 1)return kernel * t, beta - running_mean * gamma / stddef forward(self, inputs):if hasattr(self, 'rbr_reparam'):return self.nonlinearity(self.se(self.rbr_reparam(inputs)))if self.rbr_identity is None:id_out = 0else:id_out = self.rbr_identity(inputs)return self.nonlinearity(self.se(self.rbr_dense(inputs) + self.rbr_1x1(inputs) + id_out))def fusevggforward(self, x):return self.nonlinearity(self.rbr_dense(x))# RepVGG block end
# -----------------------------class SR(nn.Module):# Shuffle RepVGGdef __init__(self, c1, c2):super().__init__()c1_ = int(c1 // 2)c2_ = int(c2 // 2)self.repconv = RepVGG(c1_, c2_)def forward(self, x):x1, x2 = x.chunk(2, dim=1)out = torch.cat((x1, self.repconv(x2)), dim=1)out = self.channel_shuffle(out, 2)return outdef channel_shuffle(self, x, groups):batchsize, num_channels, height, width = x.data.size()channels_per_group = num_channels // groupsx = x.view(batchsize, groups, channels_per_group, height, width)x = torch.transpose(x, 1, 2).contiguous()x = x.view(batchsize, -1, height, width)return xdef make_divisible(x, divisor):# Returns nearest x divisible by divisorif isinstance(divisor, torch.Tensor):divisor = int(divisor.max())  # to intreturn math.ceil(x / divisor) * divisorclass RCSOSA(nn.Module):# VoVNet with Res Shuffle RepVGGdef __init__(self, c1, c2, n=1, se=False, e=0.5, stackrep=True):super().__init__()n_ = n // 2c_ = make_divisible(int(c1 * e), 8)# self.conv1 = Conv(c1, c_)self.conv1 = RepVGG(c1, c_)self.conv3 = RepVGG(int(c_ * 3), c2)self.sr1 = nn.Sequential(*[SR(c_, c_) for _ in range(n_)])self.sr2 = nn.Sequential(*[SR(c_, c_) for _ in range(n_)])self.se = Noneif se:self.se = SEBlock(c2)def forward(self, x):x1 = self.conv1(x)x2 = self.sr1(x1)x3 = self.sr2(x2)x = torch.cat((x1, x2, x3), 1)return self.conv3(x) if self.se is None else self.se(self.conv3(x))if __name__ == '__main__':m = RCSOSA(256, 256)im = torch.randn(2, 256, 13, 13)y = m(im)print(y.shape)


四、手把手教你添加RCS-OSA模塊

4.1?RCS-OSA添加步驟

4.1.1 步驟一

首先我們找到如下的目錄'ultralytics/nn/modules',然后在這個目錄下創建一個py文件,名字為RCSOSA即可,然后將RCS-OSA的核心代碼復制進去。

4.1.2 步驟二

之后我們找到'ultralytics/nn/tasks.py'文件,在其中注冊我們的RCS-OSA模塊。

首先我們需要在文件的開頭導入我們的RCS-OSA模塊,如下圖所示->

4.1.3 步驟三

我們找到parse_model這個方法,可以用搜索也可以自己手動找,大概在六百多行吧。?我們找到如下的地方,然后將RCS-OSA添加進去即可

到此我們就注冊成功了,可以修改yaml文件中輸入RCSOSA使用這個模塊了。


4.2 RCS-OSA的yaml文件和訓練截圖

下面推薦幾個版本的yaml文件給大家,大家可以復制進行訓練,但是組合用很多具體那種最有效果都不一定,針對不同的數據集效果也不一樣,我不可每一種都做實驗,所以我下面推薦了幾種我自己認為可能有效果的配合方式,你也可以自己進行組合。


4.2.1 RCS-OSA的yaml版本一(推薦)

下面的配置文件為我修改的RCS-OSA的位置(我的對比實驗是用這個版本跑出來的)。

?此版本的GFLOPs大概漲到了24.4GFOPs,參數量為407120 parameters。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'# [depth, width, max_channels]n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPss: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPsm: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPsl: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPsx: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs# YOLOv8.0n backbone
backbone:# [from, repeats, module, args]- [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2- [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4- [-1, 3, RCSOSA, [128, True]]- [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8- [-1, 6, RCSOSA, [256, True]]- [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16- [-1, 6, RCSOSA, [512, True]]- [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32- [-1, 3, RCSOSA, [1024, True]]- [-1, 1, SPPF, [1024, 5]]  # 9# YOLOv8.0n head
head:- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 6], 1, Concat, [1]]  # cat backbone P4- [-1, 3, RCSOSA, [512]]  # 12- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 4], 1, Concat, [1]]  # cat backbone P3- [-1, 3, RCSOSA, [256]]  # 15 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 12], 1, Concat, [1]]  # cat head P4- [-1, 3, RCSOSA, [512]]  # 18 (P4/16-medium)- [-1, 1, Conv, [512, 3, 2]]- [[-1, 9], 1, Concat, [1]]  # cat head P5- [-1, 3, RCSOSA, [1024]]  # 21 (P5/32-large)- [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)


4.2.2 RCS-OSA的yaml版本二

添加的版本二具體那種適合你需要大家自己多做實驗來嘗試。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'# [depth, width, max_channels]n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPss: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPsm: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPsl: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPsx: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs# YOLOv8.0n backbone
backbone:# [from, repeats, module, args]- [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2- [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4- [-1, 3, RCSOSA, [128, True]]- [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8- [-1, 6, RCSOSA, [256, True]]- [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16- [-1, 6, RCSOSA, [512, True]]- [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32- [-1, 3, RCSOSA, [1024, True]]- [-1, 1, SPPF, [1024, 5]]  # 9# YOLOv8.0n head
head:- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 6], 1, Concat, [1]]  # cat backbone P4- [-1, 3, C2f, [512]]  # 12- [-1, 1, nn.Upsample, [None, 2, 'nearest']]- [[-1, 4], 1, Concat, [1]]  # cat backbone P3- [-1, 3, C2f, [256]]  # 15 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 12], 1, Concat, [1]]  # cat head P4- [-1, 3, C2f, [512]]  # 18 (P4/16-medium)- [-1, 1, Conv, [512, 3, 2]]- [[-1, 9], 1, Concat, [1]]  # cat head P5- [-1, 3, C2f, [1024]]  # 21 (P5/32-large)- [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)


4.2.2 RCS-OSA的訓練過程截圖?

下面是添加了RCS-OSA的訓練截圖。

大家可以看下面的運行結果和添加的位置所以不存在我發的代碼不全或者運行不了的問題大家有問題也可以在評論區評論我看到都會為大家解答(我知道的)。

??????


五、本文總結

到此本文的正式分享內容就結束了,在這里給大家推薦我的YOLOv8改進有效漲點專欄,本專欄目前為新開的平均質量分98分,后期我會根據各種最新的前沿頂會進行論文復現,也會對一些老的改進機制進行補充,目前本專欄免費閱讀(暫時,大家盡早關注不迷路~),如果大家覺得本文幫助到你了,訂閱本專欄,關注后續更多的更新~

專欄回顧:YOLOv8改進系列專欄——本專欄持續復習各種頂會內容——科研必備

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/209449.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/209449.shtml
英文地址,請注明出處:http://en.pswp.cn/news/209449.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android Studio APK打包指定包名

在最近寫的一個案列中嘗試用最新版的Android studio對項目進行打包測試,想要指定打包的包名這樣便于區分的時候發現以前的許多方法都過時了,查了很多資料才弄明白each被拋棄了。本教程建議先看第三步。 目錄 一、配置根目錄下gradle.build 二、通過bui…

Billu_b0x

信息收集 #正常進行信息收集就好Starting Nmap 7.94 ( https://nmap.org ) at 2023-11-18 22:07 CST Nmap scan report for 192.168.182.142 (192.168.182.142) Host is up (0.00073s latency).PORT STATE SERVICE 22/tcp open ssh 80/tcp open http | http-cookie-flags:…

VSC改造MD編輯器及圖床方案分享

VSC改造MD編輯器及圖床方案分享 用了那么多md編輯器,到頭來還是覺得VSC最好用。這次就來分享一下我的blog文件編輯流吧。 這篇文章包括:VSC下md功能擴展插件推薦、圖床方案、blog文章管理方案 VSC插件 Markdown All in One Markdown Image - 粘粘圖片…

【電子通識】為什么電阻都是2.2、3.3、4.7、5.1這樣的小數,而不是整數?

剛開始接觸電路設計可能會對市面上已經有的電阻值如:2.2Ω、4.7Ω、5.1Ω、22Ω、47Ω、51Ω,通常都不是整數覺得非常困惑,所以查閱了一些資料,總結如下: 電阻是使用指數分布來設計生產的,即遵循國際電工委…

【CSP】202303-2_墾田計劃Python實現

文章目錄 [toc]試題編號試題名稱時間限制內存限制問題描述輸入格式輸出格式樣例輸入1樣例輸出1樣例解釋樣例輸入2樣例輸出2樣例解釋子任務Python實現 試題編號 202303-2 試題名稱 墾田計劃 時間限制 1.0s 內存限制 512.0MB 問題描述 頓頓總共選中了 n n n塊區域準備開墾田地&a…

基于STM32 + DMA介紹,應用和步驟詳解(ADC多通道)

前言 本篇博客主要學習了解DMA的工作原理和部分寄存器解析,針對ADC多通道來對代碼部分,應用部分作詳細講解,掌握代碼編程原理。本篇博客大部分是自己收集和整理,如有侵權請聯系我刪除。 本次博客開發板使用的是正點原子精英版&am…

23種策略模式之策略模式

文章目錄 前言優缺點使用場景角色定義UML模擬示例小結 前言 在軟件開發中,設計模式是為了解決常見問題而提供的一套可重用的解決方案。策略模式(Strategy Pattern)是其中一種常見的設計模式,它屬于行為型模式。該模式的核心思想是…

Java程序設計實驗6 | 集合類

*本文是博主對Java各種實驗的再整理與詳解,除了代碼部分和解析部分,一些題目還增加了拓展部分(?)。拓展部分不是實驗報告中原有的內容,而是博主本人自己的補充,以方便大家額外學習、參考。 (解…

基于ssm的大型商場會員管理系統論文

摘 要 進入信息時代以來,很多數據都需要配套軟件協助處理,這樣可以解決傳統方式帶來的管理困擾。比如耗時長,成本高,維護數據困難,數據易丟失等缺點。本次使用數據庫工具MySQL和編程框架SSM開發的大型商場會員管理系統…

【漏洞復現】FLIR AX8紅外線熱成像儀命令執行漏洞

漏洞描述 eledyne FLIR 設計、開發、制造以及強大的傳感和意識技術。自透射熱圖像、可見光圖像、可見頻率分析、來自測量和診斷的先進威脅測量系統以及日常生活的創新解決方案。 Teledyne FLIR 提供多種產品用于政府、國防、工業和商業市場。我們的產品,緊急救援人員,軍事人…

插入排序與希爾排序(C語言實現)

1.插入排序 由上面的動圖可以知道插入排序的邏輯就是從第一個元素開始往后遍歷,如果找到比前一個元素小的(或者大的)就往前排,所以插入排序的每一次遍歷都會保證前面的數據是有序的,接下類用代碼進行講解。 我們這里傳…

bash中通過變量中的內容獲取對應的關聯數組

bash中通過變量中的內容獲取對應的關聯數組 Bash declare 手冊: https://phoenixnap.com/kb/bash-declare 實際問題: 在 bash 中創建了多個關聯數組,需要根據輸入的值,獲取不同的關聯數組。 可以使用 if 進行多次判斷&#xff…

智能優化算法應用:基于浣熊算法無線傳感器網絡(WSN)覆蓋優化 - 附代碼

智能優化算法應用:基于浣熊算法無線傳感器網絡(WSN)覆蓋優化 - 附代碼 文章目錄 智能優化算法應用:基于浣熊算法無線傳感器網絡(WSN)覆蓋優化 - 附代碼1.無線傳感網絡節點模型2.覆蓋數學模型及分析3.浣熊算法4.實驗參數設定5.算法結果6.參考文獻7.MATLAB…

解決HTTP錯誤500.19 - internal server error -內部服務器錯誤的終極指南

在開發和維護網絡應用程序時,難免會遇到各種HTTP錯誤代碼。其中,HTTP錯誤500.19 - 內部服務器錯誤可謂是最令人頭痛的問題之一。當你的應用程序遇到這個錯誤時,它似乎就像一道墻壁,擋住了你前進的道路。但別擔心,本篇技…

Git全局設置命令---設置提交人姓名

介紹 使用git命令設置提交人姓名 命令 git config --global user.name "超音速"

react-photo-view 的介紹、安裝、使用。

目錄 基本介紹 安裝 使用 基本介紹 react-photo-view 是一個基于 React 的圖片查看器組件,用于在網頁上展示和瀏覽圖片。該組件提供了用戶友好的界面和交互,可以輕松地在應用程序中集成并使用。 支持觸摸手勢,拖動/平移/物理效果滑動…

修改移遠提供的GobiNet、quectel-CM源碼,使其支持有方N720 4G模塊

最近在研究imx6ull linux下4G模塊驅動的移植,參考的移遠ec20的移植方法,添加了GobiNet驅動,編譯了quectel-CM工具,并且可以正常撥號,分配到ip,如下: ping外網也沒有壓力,如下…

軟件工程 考試重點

結構化分析 考慮數據和處理的需求分析方法,稱為結構分析方法(SA) 結構化分析基于 分解、抽象 的基本思想 分解:對于復雜的系統,為將復雜度降低到可以掌握的程度,可以把大問題分解為若干個小問題&#xf…

【go-zero】go-zero使用ent框架 如何使用源生sql完成查詢

背景 本篇教程我們采用的是go-zero的快速腳手架工具 simple-admin 框架的開發 github地址:https://github.com/suyuan32/simple-admin-core 因為框架推薦使用Ent 這篇教程我們則對Ent的基本使用的幾種形式進行一個總結 一、開啟ent的源生sql 1、simple-admin生成rpc 【go-…

QT 中 線程池 (備查)

QRunnable類 API 1)在Qt中使用線程池需要先創建任務,添加到線程池中的每一個任務都需要是一個 QRunnable 類型,因此在程序中需要創建子類繼承 QRunnable 這個類。 2)然后重寫 run() 方法,在這個函數中編寫要在線程池中…