YOLOv10改进 | 主干篇 | 低照度增强网络PE-YOLO改进主干(改进暗光条件下的物体检测模型)

news2024/9/17 8:28:58

一、本文介绍

本文给大家带来的改进机制是低照度图像增强网络PE-YOLO中的PENet,PENet通过拉普拉斯金字塔将图像分解成多个分辨率的组件,增强图像细节和低频信息。它包括一个细节处理模块(DPM),用于通过上下文分支和边缘分支增强图像细节,以及一个低频增强滤波器(LEF),以捕获低频语义并减少高频噪声。同时该网络的发布版本并不完善,存在二次创新的机会,后期我会将其网络进行二次创新,增强低照度的检测性能。同时该网络发布版本存在Bug我也已经修复欢迎大家订阅本专栏,本专栏每周更新3-5篇最新机制,更有包含我所有改进的文件和交流群提供给大家。

欢迎大家订阅我的专栏一起学习YOLO!

 专栏回顾:YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备 


目录

一、本文介绍

二、PE-YOLO算法原理

2.1   PE-YOLO的基本原理

 2.2 金字塔增强网络

2.3 细节处理模块

 2.4 低频增强滤波器

三、PE-YOLO的核心代码 

四、PE-YOLO的添加方式 

4.1 修改一

4.2 修改二 

4.3 修改三 

关闭混合精度验证!

打印计算量的问题!

五、PE-YOLO的yaml文件和运行记录

5.1 PE-YOLO的yaml文件一

5.2 PE-YOLO的训练过程截图 

五、本文总结


二、PE-YOLO算法原理

论文地址: 官方论文地址

代码地址: 官方代码地址

 


2.1   PE-YOLO的基本原理

PE-YOLO是一种改进的暗光条件下的物体检测模型。它结合了金字塔增强网络(PENet)和YOLOv3。PENet通过拉普拉斯金字塔将图像分解成多个分辨率的组件,增强图像细节和低频信息。它包括一个细节处理模块(DPM,用于通过上下文分支和边缘分支增强图像细节,以及一个低频增强滤波器(LEF),以捕获低频语义并减少高频噪声。PE-YOLO采用端到端的训练方法,简化训练过程。

PE-YOLO的基本原理可以分为几个关键点:

1. 金字塔增强网络(PENet): 使用拉普拉斯金字塔将图像分解为不同分辨率的组件,以提升细节和低频信息。
2. 细节处理模块(DPM): 包含上下文分支和边缘分支,专门用于增强图像的细节。
3. 低频增强滤波器(LEF): 用于捕获低频语义信息,同时减少高频噪声。

下面为大家展示了PE-YOLO系统的总览

它说明了如何通过拉普拉斯金字塔将输入图像分解为不同层级(L0到L3),并通过PENet进行处理,最终提升图像质量以便进行物体检测。图中的细节处理模块(DPM)和低频增强滤波器(LEF)协同工作以增强图像。


 2.2 金字塔增强网络

金字塔增强网络(Pyramid Enhancement Network)是PE-YOLO的关键组成部分,用于增强模型对不同尺度的目标的检测能力。

金字塔增强网络主要包括以下几个关键要点:

1. 多尺度特征金字塔:金字塔增强网络使用多个不同尺度的特征金字塔,这些金字塔包含了来自不同层级的特征图。这允许PE-YOLO同时检测不同大小的目标,从小尺寸物体到大尺寸物体都可以有效地检测。

2. 特征融合:金字塔增强网络通过特征融合的方式将来自不同尺度的特征图进行组合。这有助于提高模型对目标的定位和检测准确性,因为不同尺度的信息被有效地整合在一起。

3. 上采样和下采样:金字塔增强网络还包括上采样和下采样操作,以进一步调整特征金字塔的尺度。上采样用于增加分辨率,以更好地捕捉小目标的细节信息,而下采样则用于减小分辨率,以更好地捕捉大目标的全局信息。

4. 注意力机制:金字塔增强网络还引入了注意力机制,以使模型能够集中注意力在最重要的特征上,从而进一步提高检测性能。这有助于减少误检和漏检的情况。

总之,金字塔增强网络是PE-YOLO的关键创新之一,通过多尺度特征金字塔、特征融合、上采样、下采样和注意力机制等技术,提高了PE-YOLO模型在目标检测任务中的性能,使其能够更好地应对不同大小和尺度的目标。


2.3 细节处理模块

细节处理模块(Detail Processing Module,简称DPM)是PE-YOLO目标检测算法的一个关键组件,旨在增强模型对目标的细节信息的感知和处理能力。DPM的主要任务是通过上下文分支和边缘分支来对目标进行更详细的处理。

我为大家总结了PE-YOLO中细节处理模块(DPM)的主要特点和功能:

1. 上下文分支(Context Branch):上下文分支负责获取上下文信息,通过捕捉远程依赖关系来理解目标周围的环境。这有助于模型更好地理解目标与其周围环境的关系,从而提高目标检测的准确性。上下文信息的引入可以使模型更好地分辨目标和背景之间的区别。

2. 边缘分支(Edge Branch):边缘分支使用两个Sobel算子(Sobel operators)在不同方向上计算图像的梯度,从而获得目标的边缘信息。这有助于模型更好地识别目标的轮廓和边缘特征,并增强目标组件的纹理信息。边缘信息对于目标的细节识别和检测非常重要。

3. 组件增强:DPM的综合作用是增强目标的各个组件,包括上下文信息的增强和边缘信息的增强。这使得模型更能够准确地捕捉目标的细节特征,从而提高目标检测性能。

下图展示的是DPM的结构包括上下文分支(CB)和边缘分支(EB)

上下文分支通过捕捉远程依赖关系来获取上下文信息,并全局增强组件。

边缘分支使用两个不同方向的Sobel运算符来计算图像梯度,以获取边缘并增强组件的纹理。 


 2.4 低频增强滤波器

低频增强滤波器(Low-Frequency Enhancement Filter,简称LEF)用于捕捉和增强图像中的低频信息,这些低频信息通常包含了图像的大部分语义和关键信息,对于检测器的预测非常重要。

PE-YOLO中低频增强滤波器(LEF)的主要特点和功能总结如下:

1. 自适应平均池化:LEF使用不同尺寸的自适应平均池化操作来截取低频分量。这意味着LEF可以动态地适应不同尺度和语义的低频信息,以确保最大程度地捕捉图像中的关键细节。

2. 低频信息捕捉:LEF的主要任务是捕捉和增强图像中的低频信息,这些信息包含了图像的主要语义和关键细节。通过使用低通滤波器来过滤特征,LEF只允许低于截止频率的信息通过,从而增强了低频成分。

3. 多尺度处理:考虑到Inception的多尺度结构,LEF在不同的尺寸上应用自适应平均池化,以适应不同语义和尺度的低频信息。这有助于提高模型对图像细节的理解和捕捉。

4. 通道分离:LEF将特征f分为四个部分,即{f1, f2, f3, f4},通过通道分离的方式,每个部分都可以独立处理,以进一步增强低频信息。

下图展示了低频增强滤波器(LEF)的详细信息。LEF由不同大小的自适应平均池化组成,用于截取低频分量。 

考虑到Inception的多尺度结构,我们使用了大小分别为1×1、2×2、3×3、6×6的自适应平均池化,并在每个尺度的末尾使用上采样来恢复特征的原始大小。不同核大小的平均池化形成了一个低通滤波器。我们通过通道分离将f分成四个部分,即{f1, f2, f3, f4}。每个部分都使用不同尺寸的池化进行处理,描述如下:

其中f_{i}是分割在通道上的f的一部分,Up是双线性插值采样,\beta _{s}是不同尺寸s × s的自适应平均池化。最后,在张量拼接每个{f_{i}, i = 1, 2, 3, 4}之后,我们将它们还原为f ∈ R^{h×w×3}


三、PE-YOLO的核心代码 

这个代码的使用方式比较特殊,大家需要注意看后面的使用教程!

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


class Lap_Pyramid_Conv(nn.Module):
    def __init__(self, num_high=3, kernel_size=5, channels=3):
        super().__init__()

        self.num_high = num_high
        self.kernel = self.gauss_kernel(kernel_size, channels)

    def gauss_kernel(self, kernel_size, channels):
        kernel = cv2.getGaussianKernel(kernel_size, 0).dot(
            cv2.getGaussianKernel(kernel_size, 0).T)
        kernel = torch.FloatTensor(kernel).unsqueeze(0).repeat(
            channels, 1, 1, 1)
        kernel = torch.nn.Parameter(data=kernel, requires_grad=False)
        return kernel

    def conv_gauss(self, x, kernel):
        n_channels, _, kw, kh = kernel.shape
        x = torch.nn.functional.pad(x, (kw // 2, kh // 2, kw // 2, kh // 2),
                                    mode='reflect')  # replicate    # reflect
        x = torch.nn.functional.conv2d(x, kernel, groups=n_channels)
        return x

    def downsample(self, x):
        return x[:, :, ::2, ::2]

    def pyramid_down(self, x):
        return self.downsample(self.conv_gauss(x, self.kernel))

    def upsample(self, x):
        up = torch.zeros((x.size(0), x.size(1), x.size(2) * 2, x.size(3) * 2),
                         device=x.device)
        up[:, :, ::2, ::2] = x * 4

        return self.conv_gauss(up, self.kernel)

    def pyramid_decom(self, img):
        self.kernel = self.kernel.to(img.device)
        current = img
        pyr = []
        for _ in range(self.num_high):
            down = self.pyramid_down(current)
            up = self.upsample(down)
            diff = current - up
            pyr.append(diff)
            current = down
        pyr.append(current)
        return pyr

    def pyramid_recons(self, pyr):
        image = pyr[0]
        for level in pyr[1:]:
            up = self.upsample(image)
            image = up + level
        return image


class ResidualBlock(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.conv_x = nn.Conv2d(in_features, out_features, 3, padding=1)

        self.block = nn.Sequential(
            nn.Conv2d(in_features, in_features, 3, padding=1),
            nn.LeakyReLU(True),
            nn.Conv2d(in_features, in_features, 3, padding=1),
        )

    def forward(self, x):
        return self.conv_x(x + self.block(x))


class PENet(nn.Module):

    def __init__(self,
                 num_high=3,
                 gauss_kernel=5):
        super().__init__()
        self.num_high = num_high
        self.lap_pyramid = Lap_Pyramid_Conv(num_high, gauss_kernel)

        for i in range(0, self.num_high + 1):
            self.__setattr__('AE_{}'.format(i), AE(3))

    def forward(self, x):
        pyrs = self.lap_pyramid.pyramid_decom(img=x)

        trans_pyrs = []

        for i in range(self.num_high + 1):
            trans_pyr = self.__getattr__('AE_{}'.format(i))(
                pyrs[-1 - i])
            trans_pyrs.append(trans_pyr)
        out = self.lap_pyramid.pyramid_recons(trans_pyrs)

        return out


class DPM(nn.Module):
    def __init__(self, inplanes, planes, act=nn.LeakyReLU(negative_slope=0.2, inplace=True), bias=False):
        super(DPM, self).__init__()

        self.conv_mask = nn.Conv2d(inplanes, 1, kernel_size=1, bias=bias)
        self.softmax = nn.Softmax(dim=2)
        self.sigmoid = nn.Sigmoid()

        self.channel_add_conv = nn.Sequential(
            nn.Conv2d(inplanes, planes, kernel_size=1, bias=bias),
            act,
            nn.Conv2d(planes, inplanes, kernel_size=1, bias=bias)
        )

    def spatial_pool(self, x):
        batch, channel, height, width = x.size()
        input_x = x
        # [N, C, H * W]
        input_x = input_x.view(batch, channel, height * width)
        # [N, 1, C, H * W]
        input_x = input_x.unsqueeze(1)
        # [N, 1, H, W]
        context_mask = self.conv_mask(x)
        # [N, 1, H * W]
        context_mask = context_mask.view(batch, 1, height * width)
        # [N, 1, H * W]
        context_mask = self.softmax(context_mask)
        # [N, 1, H * W, 1]
        context_mask = context_mask.unsqueeze(3)
        # [N, 1, C, 1]
        context = torch.matmul(input_x, context_mask)
        # [N, C, 1, 1]
        context = context.view(batch, channel, 1, 1)

        return context

    def forward(self, x):
        # [N, C, 1, 1]
        context = self.spatial_pool(x)

        # [N, C, 1, 1]
        channel_add_term = self.channel_add_conv(context)
        x = x + channel_add_term
        return x


import cv2
from torchvision import transforms


def sobel(img):
    device = img.device
    add_x_total = torch.zeros(img.shape)

    for i in range(img.shape[0]):
        x = img[i, :, :, :].squeeze(0).cpu().detach().numpy().transpose(1, 2, 0)
        x = x * 255
        x_x = cv2.Sobel(x, cv2.CV_64F, 1, 0)
        x_y = cv2.Sobel(x, cv2.CV_64F, 0, 1)
        add_x = cv2.addWeighted(x_x, 0.5, x_y, 0.5, 0)
        add_x = transforms.ToTensor()(add_x).unsqueeze(0)
        add_x_total[i, :, :, :] = add_x
    add_x_total = add_x_total.to(device)
    return add_x_total


class AE(nn.Module):
    def __init__(self, n_feat, reduction=8, bias=False, act=nn.LeakyReLU(negative_slope=0.2, inplace=True), groups=1):
        super(AE, self).__init__()

        self.n_feat = n_feat
        self.groups = groups
        self.reduction = reduction
        self.agg = nn.Conv2d(6,
                             3,
                             1,
                             stride=1,
                             padding=0,
                             bias=False)
        self.conv_edge = nn.Conv2d(3, 3, kernel_size=1, bias=bias)

        self.res1 = ResidualBlock(3, 32)
        self.res2 = ResidualBlock(32, 3)
        self.dpm = nn.Sequential(DPM(32, 32))

        self.conv1 = nn.Conv2d(3, 32, kernel_size=1)
        self.conv2 = nn.Conv2d(32, 3, kernel_size=1)
        self.lpm = LowPassModule(32)
        self.fusion = nn.Conv2d(6, 3, kernel_size=1)

    def forward(self, x):
        s_x = sobel(x)
        s_x = self.conv_edge(s_x)

        res = self.res1(x)
        res = self.dpm(res)
        res = self.res2(res)
        out = torch.cat([res, s_x + x], dim=1)
        out = self.agg(out)

        low_fea = self.conv1(x)
        low_fea = self.lpm(low_fea)
        low_fea = self.conv2(low_fea)

        out = torch.cat([out, low_fea], dim=1)
        out = self.fusion(out)

        return out


class LowPassModule(nn.Module):
    def __init__(self, in_channel, sizes=(1, 2, 3, 6)):
        super().__init__()
        self.stages = []
        self.stages = nn.ModuleList([self._make_stage(size) for size in sizes])
        self.relu = nn.ReLU()
        ch = in_channel // 4
        self.channel_splits = [ch, ch, ch, ch]

    def _make_stage(self, size):
        prior = nn.AdaptiveAvgPool2d(output_size=(size, size))
        return nn.Sequential(prior)

    def forward(self, feats):
        h, w = feats.size(2), feats.size(3)
        feats = torch.split(feats, self.channel_splits, dim=1)
        priors = [F.upsample(input=self.stages[i](feats[i]), size=(h, w), mode='bilinear') for i in range(4)]
        bottle = torch.cat(priors, 1)
        return self.relu(bottle)


if __name__ == "__main__":
    # Generating Sample image
    image_size = (1, 3, 224, 224)
    image = torch.rand(*image_size)

    # Model
    mobilenet_v1 = PENet()

    out = mobilenet_v1(image)
    print(out.size())

四、PE-YOLO的添加方式 

 这个添加方式和之前的变了一下,以后的添加方法都按照这个来了,是为了和群内的文件适配。


4.1 修改一

第一还是建立文件,我们找到如下ultralytics/nn/modules文件夹下建立一个目录名字呢就是'Addmodules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。


4.2 修改二 

第二步我们在该目录下创建一个新的py文件名字为'__init__.py'(用群内的文件的话已经有了无需新建),然后在其内部导入我们的检测头如下图所示。


4.3 修改三 

第三步我门中到如下文件'ultralytics/nn/tasks.py'进行导入和注册我们的模块(用群内的文件的话已经有了无需重新导入直接开始第四步即可)

从今天开始以后的教程就都统一成这个样子了,因为我默认大家用了我群内的文件来进行修改!!

到此就完事了注册的工作,该模型无需添加任何参数是一种无参的机制,所以导入进来即可,该网络本身存在一个设备定义的错误,我解决以后需要关闭混合精度验证这是必须的否则会报错,其次该网络修改完打印不出来参数,都可以通过下面的步骤来解决。大家注意看!!


关闭混合精度验证!

找到'ultralytics/engine/validator.py'文件找到 'class BaseValidator:' 然后在其'__call__'中 self.args.half = self.device.type != 'cpu' # force FP16 val during training的一行代码下面加上self.args.half = False

打印计算量的问题!

计算的GFLOPs计算异常不打印,所以需要额外修改一处, 我们找到如下文件'ultralytics/utils/torch_utils.py'文件内有如下的代码按照如下的图片进行修改,有一个get_flops的函数我们直接用我给的代码全部替换!

def get_flops(model, imgsz=640):
    """Return a YOLO model's FLOPs."""
    if not thop:
        return 0.0  # if not installed return 0.0 GFLOPs

    try:
        model = de_parallel(model)
        p = next(model.parameters())
        if not isinstance(imgsz, list):
            imgsz = [imgsz, imgsz]  # expand if int/float
        try:
            # Use stride size for input tensor
            stride = 640
            im = torch.empty((1, 3, stride, stride), device=p.device)  # input image in BCHW format
            flops = thop.profile(deepcopy(model), inputs=[im], verbose=False)[0] / 1e9 * 2  # stride GFLOPs
            return flops * imgsz[0] / stride * imgsz[1] / stride  # imgsz GFLOPs
        except Exception:
            # Use actual image size for input tensor (i.e. required for RTDETR models)
            im = torch.empty((1, p.shape[1], *imgsz), device=p.device)  # input image in BCHW format
            return thop.profile(deepcopy(model), inputs=[im], verbose=False)[0] / 1e9 * 2  # imgsz GFLOPs
    except Exception:
        return 0.0


五、PE-YOLO的yaml文件和运行记录

5.1 PE-YOLO的yaml文件

训练信息:YOLOv10n-PEYOLO summary: 536 layers, 2807993 parameters, 2807902 gradients, 30.9 GFLOPs

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv10 object detection model. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov10n.yaml' will call yolov10.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]

backbone:
  # [from, repeats, module, args]
  - [-1, 1, PENet, []] # 0-P1/2
  - [-1, 1, Conv, [64, 3, 2]] # 1-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 2-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]] # 4-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, SCDown, [512, 3, 2]] # 6-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, SCDown, [1024, 3, 2]] # 8-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]] # 10
  - [-1, 1, PSA, [1024]] # 11

# YOLOv10.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 7], 1, Concat, [1]] # cat backbone P4
  - [-1, 3, C2f, [512]] # 14

  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 5], 1, Concat, [1]] # cat backbone P3
  - [-1, 3, C2f, [256]] # 17 (P3/8-small)

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

  - [-1, 1, SCDown, [512, 3, 2]]
  - [[-1, 11], 1, Concat, [1]] # cat head P5
  - [-1, 3, C2fCIB, [1024, True, True]] # 23 (P5/32-large)

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

5.2 PE-YOLO的训练过程截图 


五、本文总结

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

 专栏回顾:YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备 

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

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

相关文章

数据链路层(超详细)

引言 数据链路层是计算机网络协议栈中的第二层,位于物理层之上,负责在相邻节点之间的可靠数据传输。数据链路层使用的信道主要有两种类型:点对点信道和广播信道。点对点信道是指一对一的通信方式,而广播信道则是一对多的通信方式…

办公必备——ONLYOFFICE8.1版本桌面编辑器

一、介绍ONLYOFFICE ONLYOFFICE是一款免费的开源办公软件,它可以让你创建、编辑和分享文档、表格和演示文稿。就像微软的Office一样,但它是完全免费的,而且可以在多种设备上使用,包括电脑和手机。它还支持多人同时在线编辑文档&am…

Golang | Leetcode Golang题解之第223题矩形面积

题目: 题解: func computeArea(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2 int) int {area1 : (ax2 - ax1) * (ay2 - ay1)area2 : (bx2 - bx1) * (by2 - by1)overlapWidth : min(ax2, bx2) - max(ax1, bx1)overlapHeight : min(ay2, by2) - max(ay1, by1)…

独立开发者系列(22)——API调试工具apifox的使用

接口的逻辑已经实现,需要对外发布接口,而发布接口的时候,我们需要能自己简单调试接口。当然,其实自己也可以写简单的代码调试自己的接口,因为其实就是简单的request请求或者curl库读取,调整请求方式get或者…

第11章 规划过程组(二)(11.10制订进度计划)

第11章 规划过程组(二)11.10制订进度计划,在第三版教材第395~397页;文字图片音频方式 第一个知识点:定义及作用 分析活动顺序、持续时间、资源需求和进度制约因素,创建项目进度模型,从而落实项目…

基于单片机的太阳能热水器控制系统设计

随着我国经济水平的不断提高,民众对生活质量的追求也在不断进步,对于现代家庭而言,热水器成为了必备的生活电器。目前市面上的电器主要是电热水器、燃气热水器以及太阳能热水器。就能源节约性能而言,太阳能热水器占据了绝对优势&a…

01day C++初入学习

这里写目录标题 1.C区别于C的输入输出2.什么是命名空间3. namespace的定义namespace的使用(1)namespace嵌套使用(2)多⽂件中可以定义同名namespace(3) 4.命名空间的使用5.C输⼊&输出6.缺省参数7.函数重载8.引用8.1引用的特性8.3引用的使用 1.C区别于C的输入输出 #include&…

接口调用的三种方式

例子: curl --location http://110.0.0.1:1024 \ --header Content-Type: application/json \ --data {"task_id": 1 }方式一:postman可视化图形调用 方式二:Vscode中powershell发送请求 #powershell (psh) Invoke-WebRequest -U…

探展2024世界人工智能大会之令人惊艳的扫描黑科技~

文章目录 ⭐️ 前言⭐️ AIGC古籍修复文化遗产焕新⭐️ 高效的文档图像处理解决方案⭐️ AIGC扫描黑科技一键全搞定⭐️ 行业级的知识库大模型加速器⭐️ 结语 ⭐️ 前言 大家好,我是 哈哥(哈哥撩编程),这次非常荣幸受邀作为专业…

科研绘图系列:R语言分组柱状图一(Grouped Bar Chart)

介绍 分组柱状图(Grouped Bar Chart)是一种数据可视化图表,用于比较不同类别(分组)内各子类别(子组)的数值。在分组柱状图中,每个分组有一组并列的柱子,每个柱子代表一个子组的数值,不同的分组用不同的列来表示。 特点: 并列柱子:每个分组内的柱子是并列的,便于…

python-24-零基础自学python while循环+交互+数据的存储

学习内容:《python编程:从入门到实践》第二版 知识点: 文件处理 with open()while 练习内容:10章练习题10-3、10-4、10-5 练习10-3:访客 编写一个程序,提示用户输入名字。用户做…

Redis基础教程(十五):Redis GEO地理信息查询与管理

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 💝&#x1f49…

jQuery 笔记

一、什么是jQuery 框架:半成品软件 Jquery就是封装好的js 本质上还是js jQuery是一个快速、简洁的JavaScript**框架**,是继Prototype之后又一个优秀的**JavaScript代码库**(*或JavaScript框架*)。 JQuery:封装好的代码库。有一…

树莓派_Pytorch学习笔记20:初步认识深度学习框架

今日继续学习树莓派4B 4G:(Raspberry Pi,简称RPi或RasPi) 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: ​ Python 版本3.7.3: ​ 本文很水,就介绍一下我以后的学习使用P…

全志A527 T527 android13支持usb摄像头

1.前言 我们发现usb摄像头在A527 android13上面并不能正常使用,需要支持相关的摄像头。 2.系统节点查看 我们查看系统是否有相关的节点生成,发现/dev/video相关的节点已经生成了。并没有问题,拔插正常。 3.这里我们需要查看系统层是否支持相关的相机, 我们使用命令进行…

前端传到后端的data数组中有些属性值为空

将前端输入框中的值全部放入data中传入后端,但是在后端查看发现后端接收到的数据有些属性值为空。 第一种情况:只有第一个属性为空,其余属性接收正常 可能原因:后端用来接收的 比如前端发送数据: 实际上前端发送的数…

Java | Leetcode Java题解之第224题基本计算器

题目&#xff1a; 题解&#xff1a; class Solution {public int calculate(String s) {Deque<Integer> ops new LinkedList<Integer>();ops.push(1);int sign 1;int ret 0;int n s.length();int i 0;while (i < n) {if (s.charAt(i) ) {i;} else if (s…

政安晨:【Keras机器学习示例演绎】(五十三)—— 使用 TensorFlow 决策森林进行分类

目录 简介 设置 准备数据 定义数据集元数据 配置超参数 实施培训和评估程序 实验 1&#xff1a;使用原始特征的决策森林 检查模型 实验 2&#xff1a;目标编码决策森林 创建模型输入 使用目标编码实现特征编码 使用预处理器创建梯度提升树模型 训练和评估模型 实验…

FastReport 指定sql,修改数据源 ( 非DataSet修改 )

FastReport 指定sql&#xff0c;修改数据源&#xff0c;非DataSet修改 介绍报告文件&#xff1a; codetest.frx 文件核心代码&#xff1a;&#xff08;扩展&#xff09;小结一下&#xff1a; 介绍 在FastReport中&#xff0c;经常会遇到需要给 sql 加条件的情况。 &#xff0…

k8s 部署 metribeat 实现 kibana 可视化 es 多集群监控指标

文章目录 [toc]环境介绍老(来)板(把)真(展)帅(示)helm 包准备配置监控集群获取集群 uuid生成 api_key配置 values.yaml 配置 es 集群获取集群 uuid 和 api_key配置 values.yaml 查看监控 缺少角色的报错 开始之前&#xff0c;需要准备好以下场景 一套 k8s 环境 k8s 内有两套不同…