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

news2024/11/28 9:33:57

一、本文介绍

本文给大家带来的改进机制是FLAttention(聚焦线性注意力)是一种用于视觉Transformer模型的注意力机制(但是其也可以用在我们的YOLO系列当中从而提高检测精度),旨在提高效率和表现力。其解决了两个在传统线性注意力方法中存在的问题:聚焦能力和特征多样性。这种方法通过一个高效的映射函数和秩恢复模块来提高计算效率和性能,使其在处理视觉任务时更加高效和有效。简言之,FLAttention是对传统线性注意力方法的一种重要改进,提高了模型的聚焦能力和特征表达的多样性。通过本文你能够了解到:FLAttention的基本原理和框架,能够在你自己的网络结构中进行添加

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

目录

一、本文介绍

二、FLAttention的机制原理

2.1 Softmax和线性注意力机制的对比

2.2 FLAttention的提出

2.3 效果对比

三、实验效果对比

四、FLAttention代码

五、添加FLAttention到模型中

5.1 细节修改教程

5.1.1 修改一

​4.1.2 修改二

4.1.3 修改三 

4.1.4 修改四

5.2 FLAttention的yaml文件和训练截图

5.2.1 FLAttention的yaml文件一

5.2.2 FLAttention的yaml文件二 

5.2.2 FLAttention的训练过程截图 

六、全文总结 


二、FLAttention的机制原理

论文地址:官方论文地址

代码地址:官方代码地址


2.1 Softmax和线性注意力机制的对比

上面的图片是关于比较Softmax注意力和线性注意力的差异。在这张图中,Q、K、V 分别代表查询、键和值矩阵,它们的维度为 R N×d。这里提到的几个关键点包括:

1. Softmax注意力:它需要计算查询和键之间的成对相似度,导致计算复杂度为 O(N^2 d)。这种方法在计算上是昂贵的,特别是当处理大规模数据时。

2. 线性注意力:通过适当的近似手段,线性注意力可以解耦Softmax操作,并通过先计算K^{T}V来改变计算顺序,从而将复杂度降低到 O(Nd^{^{2}})。由于在现代视觉Transformer设计中通道维度 d 通常小于标记数 N(例如,在DeiT中d=64, N=196,在Swin Transformer中d=32, N=49),线性注意力模块实际上降低了总体计算成本。

此处提出了线性注意力机制的优势(为了后面提出论文提到的注意力机制在线性注意力机制上的优化):线性注意力模块因此能够在节省计算成本的同时,享受更大的接收域和更高的吞吐量的好处。

总结:这张图片可能是在说明线性注意力如何在保持注意力机制核心功能的同时,提高计算效率,尤其是在处理大规模数据集时的优势。这种方法对于改善视觉Transformer的性能和效率具有重要意义(我下面会出将其用在RT-DETR的模型上看看效果)


2.2 FLAttention的提出

线性注意力的限制和改进: 尽管线性注意力降低了复杂度,但现有的线性注意力方法仍存在性能下降的问题,并可能因映射函数带来额外的计算开销。为了解决这些问题,作者提出了一个新颖的聚焦线性注意力(Focused Linear Attention)模块。该模块通过简单的映射函数调整查询和键的特征方向,使注意力权重更加明显。此外,还通过深度卷积(DWC)应用于原始注意力矩阵的秩恢复模块来增加特征多样性。

Focused Linear Attention(聚焦线性注意力)是一种用于视觉Transformer模型的注意力机制(但是其也可以用在我们的YOLO系列当中从而提高检测精度),旨在提高效率和表现力。它解决了传统线性注意力方法的两个主要问题:

1. 聚焦能力: 以往的线性注意力缺乏足够的聚焦能力,导致模型难以有效地关注重要特征。Focused Linear Attention通过改进的机制增强了这种聚焦能力。

2. 特征多样性: 传统方法在特征表达上缺乏多样性,影响了模型的表现力。Focused Linear Attention通过特殊的设计来增加特征的多样性和丰富性。

这种方法通过一个高效的映射函数和秩恢复模块来提高计算效率和性能,使其在处理视觉任务时更加高效和有效。

总结:Focused Linear Attention是对传统线性注意力方法的一种重要改进,提高了模型的聚焦能力和特征表达的多样性。


2.3 效果对比

上面的图片显示了多个视觉Transformer模型的性能和计算复杂度的比较。图中分为四个部分:

1. PVT: 对比了不同版本的PVT(Pyramid Vision Transformer),DeiT(Data-efficient Image Transformer),以及T2T(Tokens-to-Token ViT)的Top-1准确率和计算量(FLOPs)。

2. PVT v2: 类似地,展示了PVT v2、ConvNext、DAT(Deformable Attention Transformer)的性能对比。

3. Swin: 对比了Swin Transformer、CvT(Convolutional vision Transformer),以及CoTNet(Contextual Transformer Network)的模型。

4. CSwin: 展示了CSwin Transformer、MViTv2、CoAtNet的性能对比。

在每个图中,还包括了作者提出的FLatten版本的Transformer模型(标记为“Ours”),其在每个分类中都显示了相对较高的准确率或者在相似的FLOPs计算量下具有竞争力的准确率。

右侧的表格详细列出了不同模型的分辨率(Reso)、参数数量(#Params)、计算量(Flops)和Top-1准确率。表中突出了FLatten版本的Transformer模型在Top-1准确率上相对于原始模型的提升(括号中的百分点)。

个人总结:这张图片展示了通过改进的线性注意力模块,即FLatten模型,在保持或稍微增加计算量的前提下,提高了Transformer架构的图像识别准确率。


三、实验效果对比


四、FLAttention代码

在场的FocusedLinearAttention代码是用于Transformer的想要将其用于YOLO上是需要进行很大改动的,所以我这里进行了挺多的改动的,创作不易而且免费给大家看,所以如果能够帮助到大家希望大家能给点个赞和关注支持一下。

import torch.nn as nn
import torch
from einops import rearrange

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 FocusedLinearAttention(nn.Module):
    def __init__(self, dim, num_patches=64, num_heads=8, qkv_bias=True, qk_scale=None, attn_drop=0.0, proj_drop=0.0, sr_ratio=1,
                 focusing_factor=3.0, kernel_size=5):
        super().__init__()
        assert dim % num_heads == 0, f"dim {dim} should be divided by num_heads {num_heads}."
        self.dim = dim
        self.num_heads = num_heads
        head_dim = dim // num_heads

        self.q = nn.Linear(dim, dim, bias=qkv_bias)
        self.kv = nn.Linear(dim, dim * 2, bias=qkv_bias)
        self.attn_drop = nn.Dropout(attn_drop)
        self.proj = nn.Linear(dim, dim)
        self.proj_drop = nn.Dropout(proj_drop)

        self.sr_ratio = sr_ratio
        if sr_ratio > 1:
            self.sr = nn.Conv2d(dim, dim, kernel_size=sr_ratio, stride=sr_ratio)
            self.norm = nn.LayerNorm(dim)

        self.focusing_factor = focusing_factor
        self.dwc = nn.Conv2d(in_channels=head_dim, out_channels=head_dim, kernel_size=kernel_size,
                             groups=head_dim, padding=kernel_size // 2)
        self.scale = nn.Parameter(torch.zeros(size=(1, 1, dim)))
        # self.positional_encoding = nn.Parameter(torch.zeros(size=(1, num_patches // (sr_ratio * sr_ratio), dim)))


    def forward(self, x):
        B, C, H, W = x.shape  # 输入为四维:[批次大小, 通道数, 高度, 宽度]
        dtype, device = x.dtype, x.device
        # 调整输入以匹配原始模块的预期格式
        x = rearrange(x, 'b c h w -> b (h w) c')
        q = self.q(x)
        if self.sr_ratio > 1:
            x_ = x.permute(0, 2, 1).reshape(B, C, H, W)
            x_ = self.sr(x_).reshape(B, C, -1).permute(0, 2, 1)
            x_ = self.norm(x_)
            kv = self.kv(x_).reshape(B, -1, 2, C).permute(2, 0, 1, 3)
        else:
            kv = self.kv(x).reshape(B, -1, 2, C).permute(2, 0, 1, 3)
        k, v = kv[0], kv[1]
        N = H * W  # 序列长度
        # 重新生成位置编码
        positional_encoding = nn.Parameter(torch.zeros(size=(1, N, self.dim), device=device))
        k = k + positional_encoding
        focusing_factor = self.focusing_factor
        kernel_function = nn.ReLU()
        scale = nn.Softplus()(self.scale)
        q = kernel_function(q) + 1e-6
        k = kernel_function(k) + 1e-6
        q = q / scale
        k = k / scale
        q_norm = q.norm(dim=-1, keepdim=True)
        k_norm = k.norm(dim=-1, keepdim=True)
        q = q ** focusing_factor
        k = k ** focusing_factor
        q = (q / q.norm(dim=-1, keepdim=True)) * q_norm
        k = (k / k.norm(dim=-1, keepdim=True)) * k_norm
        bool = False
        if dtype == torch.float16:
            q = q.float()
            k = k.float()
            v = v.float()
            bool = True
        q, k, v = (rearrange(x, "b n (h c) -> (b h) n c", h=self.num_heads) for x in [q, k, v])
        i, j, c, d = q.shape[-2], k.shape[-2], k.shape[-1], v.shape[-1]
        z = 1 / (torch.einsum("b i c, b c -> b i", q, k.sum(dim=1)) + 1e-6)
        if i * j * (c + d) > c * d * (i + j):
            kv = torch.einsum("b j c, b j d -> b c d", k, v)
            x = torch.einsum("b i c, b c d, b i -> b i d", q, kv, z)
        else:
            qk = torch.einsum("b i c, b j c -> b i j", q, k)
            x = torch.einsum("b i j, b j d, b i -> b i d", qk, v, z)
        if self.sr_ratio > 1:
            v = nn.functional.interpolate(v.permute(0, 2, 1), size=x.shape[1], mode='linear').permute(0, 2, 1)
        if bool:
            v = v.to(torch.float16)
            x = x.to(torch.float16)

        num = int(v.shape[1] ** 0.5)
        feature_map = rearrange(v, "b (w h) c -> b c w h", w=num, h=num)
        feature_map = rearrange(self.dwc(feature_map), "b c w h -> b (w h) c")
        x = x + feature_map
        x = rearrange(x, "(b h) n c -> b n (h c)", h=self.num_heads)

        x = self.proj(x)
        x = self.proj_drop(x)
        x = rearrange(x, 'b (h w) c -> b c h w', h=H, w=W)
        return 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 = Conv(c_, c2, k[1], 1, g=g)
        self.Attention = FocusedLinearAttention(c2)
        self.add = shortcut and c1 == c2

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


class C3_FLAttention(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))


五、添加FLAttention到模型中

5.1 细节修改教程

5.1.1 修改一

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


​4.1.2 修改二

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


4.1.3 修改三 

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

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

​​​​


4.1.4 修改四

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

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

5.2 FLAttention的yaml文件和训练截图

5.2.1 FLAttention的yaml文件一

同时我发现这个FLAttention在训练的适合不稳定,有的数据集可以用有的不可以用,我一开始用一个数据集跑不通换了一个就可以了。

# 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_FLAttention, [256, False]],  # 17 (P3/8-small)

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

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

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

5.2.2 FLAttention的yaml文件二 

下面的是放在Neck部分的截图,参数我以及设定好了,无需进行传入会根据模型输入自动计算,帮助大家省了一些事。

# 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, [256, False]],  # 17 (P3/8-small)
   [-1, 1, FocusedLinearAttention, []],  # 18

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, C3, [512, False]],  # 21 (P4/16-medium)
   [-1, 1, FocusedLinearAttention, []], #22

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, C3, [1024, False]],  # 25 (P5/32-large)
   [-1, 1, FocusedLinearAttention, []], #26

   [[18, 22, 26], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

5.2.2 FLAttention的训练过程截图 

下面的是将FLAttention机制我添加到了C3和Bottleneck的训练截图。

下面的是我将FLAttention放在Neck中的截图。 


六、全文总结 

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

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

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

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

相关文章

网络攻防中应该掌握的进阶工具udp2raw,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS

网络攻防中应该掌握的进阶工具udp2raw,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS。 udp2raw tunnel,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS,或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的…

企业级依赖管理: 深入解读 Maven BOM

一、背景 当开发者在一个大型项目中使用 Maven 进行依赖管理时,项目往往会包含多个模块或子项目,并且这些模块会共享相同的依赖项。但是,不同模块可能会独立地指定各自的依赖版本,这可能导致以下问题: 依赖版本不一致…

Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0

文/朱季谦 以前在工作当中做过不少与工作流Activiti有关的工作,当时都是spring集成activiti5.22的项目,现在回过头去看,其实版本已经稍微老了,因此,基于先前的工作经验,决定用较新版本的技术来重新梳理下以…

字符串转成时间的SQL,一个多种数据库通用的函数

select date 2010-10-06 from dual; date 函数,此函数适用于: 1.MySQL数据库 2.Oracle数据库 3.达梦数据库 4.人大金仓数据库

NFC物联网构建移动智能仓储系统解决方案

仓储管理作为企业研发生产活动的重要环节,正朝着标准化、信息化方向发展。高新作为典型的资产密集 技术密集型企业,原料样品为代表的资产数量巨大品种繁杂,对仓库管理的实时性及准确性要求较高。传统的人工作业模式和管理方法逐渐难以满足仓储管理对高效…

【 YOLOv5】目标检测 YOLOv5 开源代码项目调试与讲解实战(4)-自制数据集及训练(使用makesense标注数据集)

如何制作和训练自己的数据集 看yolov5官网创建数据集1.搜索需要的图片2.创建标签标注数据集地址:放入图片后选择目标检测创建文档,每个标签写在单独的一行上传结果此处可以编辑类别把车框选选择类别即可导出数据 3.新建一个目录放数据写yaml文件 4. 测试…

软件测试/测试开发丨学习笔记之Python控制流-分支、循环

分支判断 什么是分支判断 一条一条语句顺序执行叫做顺序结构分支结构就是在某个判断条件后,选择一条分支去执行 1. IF if condition_1:statement_block_1 elif condition_2:statement_block_2 else:statement_block_32. if 嵌套 在嵌套 if 语句中,可…

【北亚服务器数据恢复】ZFS文件系统服务器ZPOOL下线的数据恢复案例

服务器数据恢复环境: 服务器中有32块硬盘,组建了3组RAIDZ,部分磁盘作为热备盘。zfs文件系统。 服务器故障: 服务器运行中突然崩溃,排除断电、进水、异常操作等外部因素。工作人员将服务器重启后发现无法进入操作系统。…

【CISSP学习笔记】6. 安全开发

该知识领域涉及如下考点,具体内容分布于如下各个子章节: 理解安全并将其融入软件开发生命周期 (SDLC) 中在软件开发环境中识别和应用安全控制评估软件安全的有效性评估获得软件对安全的影响定义并应用安全编码准则和标准 6.1. 系统开发控制 6.1.1. 软…

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

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

Grafana Loki 配置解析

Grafana Loki 配置文件是一个YML文件,在Grafana Loki 快速尝鲜的示例中是loki-config.yaml,该文件包含关于Loki 服务和各个组件的配置信息。由于配置数量实在太多,没法全部翻译,只能后期有需要了再补充。 如下是Grafana Loki 快速…

JVM篇:JVM内存结构

程序计数器 程序计数器英文名叫:Program Counter Register 作用:用来记录下一条jvm指令的地址行号。 先来查看一段jvm指令,这些指令对应的java代码就是输出1-5 操作系统运行该Java程序时具体流程如下 语言解释:源文件通过编译转…

设计模式-对象池模式

设计模式专栏 模式介绍模式特点应用场景对象池模式和工厂模式的区别代码示例Java实现对象池模式Python实现对象池模式 对象池模式在spring中的应用 模式介绍 对象池模式是一种创建型设计模式,它将对象预先创建并初始化后放入一个池中,以供其他对象使用。…

python如何读取被压缩的图像

读取压缩的图像数据: PackBits 压缩介绍: CCITT T.3 压缩介绍: 读取压缩的图像数据: 在做图像处理的时候,平时都是使用 函数io.imread() 或者是 函数cv2.imread( ) 函数来读取图像数据,很少用PIL.Image…

数据结构——红黑树 and B-树

红黑树 根据平衡条件第4、5两点 最短路径,都是黑色 最长路径,红黑相间 最长是最短的两倍 B-树

Android集成OpenSSL实现加解密-集成

导入so 将编译生成的 OpenSSL 动态库文件(.so 文件)复制到你的 Android 项目的 libs 目录中 导入头文件 将编译生成的include文件夹导入到项目中 build.gradle添加配置 defaultConfig {……testInstrumentationRunner "androidx.test.runner…

大厂前端面试题总结(百度、字节跳动、腾讯、小米.....),附上热乎面试经验!

先简单介绍下自己,我“平平无奇小天才”一枚,毕业于南方普通985普通学生,有幸去百度、字节面试,感觉大公司就是不一样,印象最深的是字节,所以有必要总结一下面试经验,以及面试中遇到的一些问题&…

SuperMap iServer发布的ArcGIS REST 地图服务如何通过ArcGIS API进行要素查询

作者:yx 前言 前面我们介绍了SuperMap iServer发布的ArcGIS REST 地图服务如何通过ArcGIS API加载,这里呢我们再来看看如何进行要素查询呢? 一、服务发布 SuperMap iServer发布的ArcGIS REST 地图服务如何通过ArcGIS API加载已经介绍如何发…

gem5学习(7):内存系统中创建 SimObjects--Creating SimObjects in the memory system

目录 一、gem5 master and slave ports 二、Packets 三、Port interface 1、主设备发送请求时从设备忙 2、从设备发送响应时主设备忙 四、Simple memory object example 1、Declare the SimObject 2、Define the SimpleMemobj class 3、Define the SimpleMemobj class…

docker compose 部署 grafana + loki + vector 监控kafka消息

Centos7 随笔记录记录 docker compose 统一管理 granfana loki vector 监控kafka 信息。 当然如果仅仅是想通过 Grafana 监控kafka,推荐使用 Grafana Prometheus 通过JMX监控kafka 目录 1. 目录结构 2. 前提已安装Docker-Compose 3. docker-compose 自定义服…