当前位置: 首页 > news >正文

【深度学习|目标检测】YOLO系列anchor-based原理详解

YOLO之anchor-based

  • 一、关于anchors的设置
  • 二、网络如何利用anchor来训练
    • 关于register_buffer
    • 训练阶段的anchor使用
    • 推理阶段的anchor使用
  • 三、训练时的正负样本匹配
    • anchor匹配
    • grid匹配

总结起来其实就是:基于anchor-based的yolo就是基于三个检测头的分支上的grids和anchors(通过正样本匹配选择出来的)来计算预测与gt的偏移量,同时考量该grid中是否含有物体,并且是什么样的物体,然后在满足这三者条件的最小loss下不断迭代模型的权重参数。那么会有人问,在推理的时候,模型怎么知道应该基于哪个grid下的anchor进行回归呢?这就可以交给objectness置信度了,根据模型权重最后得到的特征图在计算后的objectness低于阈值的话,我们根本就不会考虑这个位置的回归框。

一、关于anchors的设置

在yolov5的模型yaml文件中已经设置了一套默认的anchors的尺寸(针对640*640的输入):

# anchors
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

其中p3,p4,p5分别代表三个尺度的特征图,中括号内的数字两两一对,表示在640*640输入基准上的anchor尺寸。8,16,32分别代表各自的stride步长,即相对输入的降采样倍数,也代表了该特征图每一个grid的边长。
那么为什么降采样越多的检测头预设的anchor大小越大呢,因为降采样越多,grid的个数越少,因此每一个grid对于大目标的感知能力越强。降采样越少的,grid个数越多,对于小目标的感知能力越强,模型参数收敛的更快。因此我们会发先降采样越多的头,预设的anchor越大。即为了更快的收敛。

虽然给我们设置好了默认的anchors,但是我们可以不使用这个默认anchor,在训练的时候,打开autoanchor开关:

parser.add_argument("--noautoanchor", action="store_true", help="disable AutoAnchor")

然后会进入check_anchors函数中进行判断是否需要重新生成预设anchor:

check_anchors(dataset, model=model, thr=hyp["anchor_t"], imgsz=imgsz)  # run AutoAnchor

其中thr表示这一波数据集的标注中,宽高比的最大阈值,这个参数在hyp的yaml文件中有设置好,是4。核查的代码如下所示:

def metric(k):  # compute metric"""Computes ratio metric, anchors above threshold, and best possible recall for YOLOv5 anchor evaluation."""r = wh[:, None] / k[None]x = torch.min(r, 1 / r).min(2)[0]  # ratio metricbest = x.max(1)[0]  # best_xaat = (x > 1 / thr).float().sum(1).mean()  # anchors above thresholdbpr = (best > 1 / thr).float().mean()  # best possible recallreturn bpr, aat

返回的bpr参数就是用于来判断是否需要重新计算anchor的主要依据,当大于0.98时,我们则不需要为了这个数据集重新计算anchor。当小于0.98时,会自动重新计算。计算的方式就是使用kmeans聚类算法,根据我们这个数据集的标注情况来调整anchor的宽高和比例,计算完成后,还会再计算一次现在的bpr,然后和默认的bpr进行比较,如果小于默认的bpr则继续使用默认的anchor设置。


二、网络如何利用anchor来训练

在train.py中我们看到了train的函数中,建立网络整体架构的代码:

model = Model(cfg or ckpt["model"].yaml, ch=3, nc=nc, anchors=hyp.get("anchors")).to(device)  # create

我们进入Model类中,会进入到DetectionModel类中,这个类在初始化的过程中,会读取我们传入的模型结构yaml文件,然后通过parse_model方法来返回一个pytorch搭建的网络框架,包含了backbone+head。backbone就按照正常的流程构建,当搭建到head时,会进入Detect类中,初始化如下:

    def __init__(self, nc=80, anchors=(), ch=(), inplace=True):  # detection layersuper().__init__()self.nc = nc  # number of classes                     // 目标的类别个数self.no = nc + 5  # number of outputs per anchor      // 每一个grid的输出维度self.nl = len(anchors)  # number of detection layers  // 在几个尺度的特征层上进行设置anchorself.na = len(anchors[0]) // 2  # number of anchors   // 每一个grid上有的anchor的个数self.grid = [torch.zeros(1)] * self.nl  # init gridself.anchor_grid = [torch.zeros(1)] * self.nl  # init anchor gridself.register_buffer('anchors', torch.tensor(anchors).float().view(self.nl, -1, 2))  # shape(nl,na,2)self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch)  # output convself.inplace = inplace  # use in-place ops (e.g. slice assignment)

其中register_buffer即将anchor注册到网络结构中的一步,在下面会详细讲解这个函数的作用。
head的最后输出会经过一层头部的卷积层(p3,p4,p5分别对应一个),这个卷积层的输入维度以yolov5s为例子的话,分别是(128,256,512),输出维度是(xywh + objectness + nc)* 3,其中3是每个grid上的锚框个数。以640* 640的输入为例,我们将三个锚框的维度移动到grid个数上,那么最后三个检测头的输出维度分别是:(bs, 80* 80 * 3, xywh + objectness + nc) ,(bs, 40* 40 * 3, xywh + objectness + nc),(bs, 20* 20 * 3, xywh + objectness + nc),将这三个头合起来之后就是网络的输出结果,即(bs,25200,xywh + objectness + nc)。


关于register_buffer

nn.Module.register_buffer 是 PyTorch 提供的方法,用于向模型中注册一个缓冲区(buffer)。这些缓冲区是与模型相关的固定数据,在模型训练和保存时非常有用,但它们不会参与梯度计算,也不会被优化器更新。
使用场景:
● 存储模型所需的固定参数(例如锚点、均值、方差等)。
● 在保存和加载模型时,确保这些数据一并存储和恢复。
● 用于在模型中共享某些不可训练的参数。

import torch
import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()# 注册一个缓冲区self.register_buffer("my_buffer", torch.tensor([1.0, 2.0, 3.0]))def forward(self, x):# 使用缓冲区中的数据return x + self.my_buffer# 创建模型实例
model = MyModel()
print("缓冲区内容:", model.my_buffer)# 保存模型
torch.save(model.state_dict(), "model.pth")# 加载模型
new_model = MyModel()
new_model.load_state_dict(torch.load("model.pth"))
print("加载后的缓冲区内容:", new_model.my_buffer)

示例说明:

  1. register_buffer 的作用:
    ○ self.register_buffer(name, tensor) 会将 tensor 注册为缓冲区,名称为 name。
    ○ 例如,代码中的 my_buffer 是模型的一部分,但它不会参与梯度计算。
  2. 访问缓冲区:
    ○ 缓冲区可以通过模型属性直接访问,例如 model.my_buffer。
  3. 保存与加载:
    ○ 缓冲区会被存储在模型的 state_dict 中,使用 torch.save 和 torch.load 保存/加载。

训练阶段的anchor使用

在训练阶段中,并没有在检测头中直接使用anchor,而是在其他两个地方使用anchor的信息,一个是正负样本匹配的过程中,一个是损失函数计算的过程中。
那么我们看一下,训练的时候,DetectionModel类到底做了什么吧:
parse_model之后便是拿到模型的最后一层,记为m,然后做个判断,是否是检测头或者分割头,是的话进入代码段中,然后以256 * 256的尺寸为例,输入_forward_once中进行一次模型的输出,得到了最后三个检测头的输出,遍历这三个输出,分别取特征图的尺寸,用输入除以特征图的尺寸得到stride张量,说实话个人感觉这一步有点脱裤子放屁的意思。然后就是检查anchor和stride的对应关系,以及将每一个检测头的anchor尺寸缩放到该特征图尺度上的对应大小。然后就是初始化偏置和初始化权重了:

# Build strides, anchors
m = self.model[-1]  # Detect()
if isinstance(m, (Detect, Segment)):def _forward(x):"""Passes the input 'x' through the model and returns the processed output."""return self.forward(x)[0] if isinstance(m, Segment) else self.forward(x)s = 256  # 2x min stridem.inplace = self.inplacem.stride = torch.tensor([s / x.shape[-2] for x in _forward(torch.zeros(1, ch, s, s))])  # forwardcheck_anchor_order(m)m.anchors /= m.stride.view(-1, 1, 1)self.stride = m.strideself._initialize_biases()  # only run once# Init weights, biasesinitialize_weights(self)
self.info()
LOGGER.info("")

推理阶段的anchor使用

由于在我们的train.py中,我们首先是创建网络,此时还没有到model.train()的状态,因此在训练调试代码时,会先进入检测头的not self.training中,这里我们就可以看到在推理阶段是如何使用anchor来进行预测的。首先我们会使用_make_grid方法来对我们的三个尺度的特征图进行grid的和anchor的搭建,即预设好grid的左上角的框的坐标以及对应的anchor的大小。然后我们将这个预设好的grid点的左上角坐标和每个grid上的anchor给到模型最后的output,从output的最后一个维度拆分,拿到xy,wh,conf =(objectness,nc)一共三组结果,其中conf的结果是可以直接使用的,但是xy,wh还需要和我们预设好的grids和anchors,以及每个检测头的stride来得到最后的精确检测结果。最后将每个检测头上设置的anchor的个数乘到grid上,即代表了我们的结果一共有na * (80 * 80 + 40 * 40 + 20 * 20)个,然后输出的结果维度便是(1,25200,6)。

         if not self.training:  # inferenceif self.dynamic or self.grid[i].shape[2:4] != x[i].shape[2:4]:self.grid[i], self.anchor_grid[i] = self._make_grid(nx, ny, i)if isinstance(self, Segment):  # (boxes + masks)xy, wh, conf, mask = x[i].split((2, 2, self.nc + 1, self.no - self.nc - 5), 4)xy = (xy.sigmoid() * 2 + self.grid[i]) * self.stride[i]  # xywh = (wh.sigmoid() * 2) ** 2 * self.anchor_grid[i]  # why = torch.cat((xy, wh, conf.sigmoid(), mask), 4)else:  # Detect (boxes only)xy, wh, conf = x[i].sigmoid().split((2, 2, self.nc + 1), 4)xy = (xy * 2 + self.grid[i]) * self.stride[i]  # xywh = (wh * 2) ** 2 * self.anchor_grid[i]  # why = torch.cat((xy, wh, conf), 4)z.append(y.view(bs, self.na * nx * ny, self.no))

三、训练时的正负样本匹配

首先,什么是正负样本匹配。正样本匹配即通过计算gt与被选中的grid和anchor来计算偏移量来调整网络的权重参数。正样本的匹配然后loss计算是为了让模型朝着更小的损失去迭代更新这样的权重,负样本的作用则是让模型的权重往更远离能检测出错误目标的权重方向迭代。

yolov5在正负样本匹配在v3, 和v4的基础上作出了改进,yolov5通过跨分支(检测头)和跨grid和跨anchor来匹配多个grid和多个anchor,目的就是增加正样本的数量。yolov5的正样本匹配过程分为两步,一个是匹配grid点,一个是匹配anchor。
首先来看匹配anchor。

anchor匹配

在YoloV5网络中,一共设计了9个不同大小的先验框。每个输出的特征层对应3个先验框。
对于任何一个真实框gt,YoloV5不再使用iou进行正样本的匹配,而是直接采用高宽比进行匹配,即使用真实框和9个不同大小的先验框计算宽高比。
如果真实框与某个先验框的宽高比例大于设定阈值,则说明该真实框和该先验框匹配度不够,将该先验框认为是负样本。
比如此时有一个真实框,它的宽高为[200, 200],是一个正方形。YoloV5默认设置的9个先验框为[10,13], [16,30], [33,23], [30,61], [62,45], [59,119], [116,90], [156,198], [373,326]。设定阈值门限为4。
此时我们需要计算该真实框和9个先验框的宽高比例。比较宽高时存在两个情况,一个是真实框的宽高比先验框大,一个是先验框的宽高比真实框大。因此我们需要同时计算:真实框的宽高/先验框的宽高;先验框的宽高/真实框的宽高。然后在这其中选取最大值。
下个列表就是比较结果,这是一个shape为[9, 4]的矩阵,9代表9个先验框,4代表真实框的宽高/先验框的宽高;先验框的宽高/真实框的宽高。

[[20.         15.38461538  0.05        0.065     ][12.5         6.66666667  0.08        0.15      ][ 6.06060606  8.69565217  0.165       0.115     ][ 6.66666667  3.27868852  0.15        0.305     ][ 3.22580645  4.44444444  0.31        0.225     ][ 3.38983051  1.68067227  0.295       0.595     ][ 1.72413793  2.22222222  0.58        0.45      ][ 1.28205128  1.01010101  0.78        0.99      ][ 0.53619303  0.61349693  1.865       1.63      ]]

我们自然可以看出[59,119], [116,90], [156,198], [373,326]是满足条件的anchor。

grid匹配

确定了满足条件的anchor之后,我们就该找具体是哪里的grid了。
在过去的Yolo系列中,grid的选择是看gt框的中心点所处的网格的坐上角(即当前grid)。对于yolov5而言,对于被选中的特征层,首先计算gt落在哪个网格内,此时该网格左上角特征点便是一个负责预测的特征点。同时利用四舍五入规则,找出最近的两个网格,将这三个网格都认为是负责预测该真实框的。如下图所示:
在这里插入图片描述
红色点表示该真实框的中心,除了当前所处的网格外,其2个最近的邻域网格也被选中。从这里就可以发现预测框的XY轴偏移部分的取值范围不再是0-1,而是0.5-1.5。
找到对应特征点后,对应特征点的刚才anchor匹配中被选中的anchor负责该真实框的预测。

相关文章:

【深度学习|目标检测】YOLO系列anchor-based原理详解

YOLO之anchor-based 一、关于anchors的设置二、网络如何利用anchor来训练关于register_buffer训练阶段的anchor使用推理阶段的anchor使用 三、训练时的正负样本匹配anchor匹配grid匹配 总结起来其实就是:基于anchor-based的yolo就是基于三个检测头的分支上的grids和…...

vue3+Ts+elementPlus二次封装Table分页表格,表格内展示图片、switch开关、支持

目录 一.项目文件结构 二.实现代码 1.子组件(表格组件) 2.父组件(使用表格) 一.项目文件结构 1.表格组件(子组件)位置 2.使用表格组件的页面文件(父组件)位置 3.演示图片位置 ele…...

【C/C++】文件句柄

什么是文件句柄? 文件句柄(File Handle)是操作系统中的一种抽象概念,它用来表示一个打开的文件或输入/输出设备。 文件句柄是程序与文件之间的桥梁,程序通过文件句柄来访问和操作文件的内容。 1. 文件句柄——作用 文…...

Matlab 基于专家pid控制的时滞系统

1、内容简介 Matlab 185-基于专家pid控制的时滞系统 可以交流、咨询、答疑 2、内容说明 略 在处理时滞系统(Time Delay Systems)时,使用传统的PID控制可能会面临挑战,因为时滞会导致系统的不稳定或性能下降。专家PID控制通过结…...

【高项】信息系统项目管理师(六)项目进度管理【3分】

项目进度管理是为了保证项目按时完成。对项目所需的各个过程进行管理,包括规划进度、定义活动、排列活动顺序、估算活动持续时间、制订项目进度计划和控制进度。小型项目中,定义活动、排列活动顺序、估算活动持续时间以及制订进度模型形成进度计划等过程的联系非常紧密,可以…...

通过MATLAB和Carsim进行联合仿真,利用强化学习实现自动驾驶人机控制权策略的详细步骤和示例代码

以下是一个通过MATLAB和Carsim进行联合仿真,利用强化学习实现自动驾驶人机控制权策略的详细步骤和示例代码: 步骤概述 Carsim配置:对Carsim进行必要的设置,包括车辆模型、道路场景等,并生成S - function接口。MATLAB环境搭建:在MATLAB中配置Carsim的S - function,并创建…...

iOS 模块化架构设计:主流方案与实现详解

随着 iOS 工程规模的扩大,模块化设计成为提升代码可维护性、团队协作效率和开发灵活性的关键。本文将探讨为什么需要模块化,介绍四种主流的模块化架构方案(协议抽象、依赖注入、路由机制和事件总线),并通过代码示例和对…...

PostreSQL指南-内幕探索-学习笔记-01-数据库集簇的逻辑与物理结构

目录 一、环境信息 二、参考内容 三、逻辑结构概念 四、物理结构概念 五、逻辑映射关系 1、数据库与oid映射关系 2、堆表对象与oid映射关系 五、物理映射关系 1、数据库与oid映射关系 2、堆表对象与oid映射关系 六、数据库文件布局 1、表格 2、postmaster.pid文件解…...

java使用(Preference、Properties、XML、JSON)实现处理(读写)配置信息或者用户首选项的方式的代码示例和表格对比

在Java应用程序中,处理应用首选项(preferences)有多种方法,包括使用java.util.prefs.Preferences类、属性文件(如.properties文件)、XML文件和JSON文件。下面是每种方法的详细说明和代码示例,最…...

spring动态代理是在生命周期的哪个阶段实现的

Spring AOP(面向切面编程)的动态代理是在 Bean 生命周期的 初始化后阶段 实现的,具体来说是在 BeanPostProcessor 的 postProcessAfterInitialization() 方法中完成的。下面我们来详细分析 Spring AOP 动态代理的实现位置及其工作原理。 1. S…...

Oracle静默安装方法

Web服务器上面的Linux一般是不会有图形界面的,所有通过图形界面来安装Linux的方式在没有图形界面的Linux上面是行不通的,我们要使用的安装方式叫做Linux的静默安装。即在没有图形界面的Linux上面安装。 1. 下载地址 http://www.oracle.com/technetwork…...

本地部署deepseek-r1建立向量知识库和知识库检索实践【代码】

目录 一、本地部署DS 二、建立本地知识库 1.安装python和必要的库 2.设置主目录工作区 3.编写文档解析脚本 4.构建向量数据库 三、基于DS,使用本地知识库检索 本地部署DS,其实非常简单,我写了一篇操作记录,我终于本地部署了DeepSeek-R1(图文全过程)-CSDN博客 安装…...

单词翻转(信息学奥赛一本通-1144)

【题目描述】 输入一个句子(一行),将句子中的每一个单词翻转后输出。 【输入】 只有一行,为一个字符串,不超过500个字符。单词之间以空格隔开。 【输出】 翻转每一个单词后的字符串,单词之间的空格需与原文一致。 【输入样例】 he…...

Python基础入门掌握(十三)

从基础到进阶,轻松掌握文件读写 目录 文件操作的基本概念 文件的打开与关闭 读取文件内容 写入文件内容 文件操作的高级技巧 总结与建议‍ 文件操作的基本概念 在Python中,文件操作主要涉及以下几个步骤: 打开文件(open…...

【再读】R1-Onevision通过跨模态形式化为复杂多模态推理任务提供了系统性解决方案

R1-Onevision:跨模态形式化驱动的多模态推理技术突破,R1-Onevision通过跨模态形式化、双阶段训练和教育级基准测试,为多模态推理树立了新标杆。其技术创新不仅提升了模型在复杂任务中的表现,更重要的是为行业提供了一种可解释、可迁移的多模态处理范式。随着形式化方法的不断…...

【AWS入门】2025 AWS亚马逊云科技账户注册指南

【AWS入门】2025 AWS亚马逊云科技账户注册指南 A Guide To Register a New account on AWS By JacksonML 0. AWS亚马逊云科技简介 Amazon Web Service(AWS) 即亚马逊云科技,其在全球Cloud Computing(云计算)市场占有最为重要的地位。 AWS连续13年被Gartner评为…...

重生之我在学Vue--第18天 Vue 3 项目功能扩展

重生之我在学Vue–第18天 Vue 3 项目功能扩展 文章目录 重生之我在学Vue--第18天 Vue 3 项目功能扩展前言一、权限管理系统1.1 用户角色体系设计1.2 路由权限控制1.3 组件级权限控制 二、分页与搜索系统2.1 分页类型对比2.2 分页组件实现2.3 搜索功能实现 三、文件上传系统3.1 …...

基于SpringBoot的房地产销售管理系统【附源码】

基于SpringBoot的房地产销售管理系统(源码L文说明文档) 目录 4 系统设计 4.1用户登录功能的详细实现 4.2管理员权限的功能实现 4.2.1客户信息管理功能的详细实现 4.2.2房产管理功能的详细实现 4.2.3预约看房功能的详细实现 4.2.4论…...

数组题型-二分查找-JS

二分查找伪代码 1.定义 target 是在⼀个在左闭右闭的区间⾥&#xff0c;也就是[left, right] let left0;let rightnums.length-1;// 定义target在左闭右闭的区间⾥&#xff0c;[left, right]while(left<right){// 当leftright&#xff0c;区间[left, right]依然有效&#x…...

STL——vector

目录 1 vector介绍 2 vector使用 2.1 vector的定义 2.1.1 无参构造 2.1.2 构造并初始化N个Val 2.1.3 拷贝构造 2.1.4 使用迭代器初始化构造 2.1.5 使用大括号初始化构造 2.2 vector的迭代器 2.2.1 const 迭代器 2.3 vector的空间增长 2.4 vector的增删改查 2.5 ve…...

国内首款载重1吨级无人运输机TP1000首飞成功 2026年投入应急救援

大湾区经济网珠海快讯&#xff0c;据央视新闻报道&#xff0c;3月15日上午&#xff0c;国内首款载重1吨级大型无人运输机TP1000在山东成功首飞。该机由中国民航适航标准完全自主研发&#xff0c;起飞重量3.3吨&#xff0c;满载航程达1000公里&#xff0c;具备智能空投功能&…...

python-leetcode 54.全排列

题目&#xff1a; 给定不含重复数字的数组nums,返回其所有可能的全排列&#xff0c;可以按任意顺序返回答案 回溯法 一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解&#xff08;或者至少不是最后一个解&#xff09;&#xff0c;回溯算法会通…...

人工智能实现电脑任务自动化的开源软件

人工智能实现电脑任务自动化的开源软件 hallo大家好&#xff0c;我是星哥&#xff0c;今天给大家介绍一个开源软件&#xff0c;融合了人工智能与机器人流程自动化&#xff08;AIRPA&#xff09;的开源软件autoMate! autoMate是什么 autoMate 是一款由开源开发的本地自动化工…...

串口烧录出现频繁回复乱码 频繁回复一个数字且烧录失败 字节混乱

这是因为你的芯片没有处于系统存储区启动一直未进入bootloader 解决办法是检查boot引脚接正确没&#xff0c;要在系统存储器启动...

ens33没有分配到IPV4问题

方法一&#xff1a;手动为 ens33 接口分配 IP 地址 你能够借助 ip 命令手动给 ens33 接口分配 IP 地址。不过这种方式在系统重启之后就会失效。 步骤 查看网络信息 先查看一下当前网络的子网信息&#xff0c;例如网关地址和子网掩码等&#xff0c;你可以通过路由器管理界面或…...

搭建主从服务器

任务需求 客户端通过访问 www.nihao.com 后&#xff0c;能够通过 dns 域名解析&#xff0c;访问到 nginx 服务中由 nfs 共享的首页文件&#xff0c;内容为&#xff1a;Very good, you have successfully set up the system. 各个主机能够实现时间同步&#xff0c;并且都开启防…...

【实测闭坑】LazyGraphRAG利用本地ollama提供Embedding model服务和火山引擎的deepseek API构建本地知识库

LazyGraphRAG 2024年4月&#xff0c;为解决传统RAG在全局性的查询总结任务上表现不佳&#xff0c;微软多部门联合提出Project GraphRAG&#xff08;大模型驱动的KG&#xff09;&#xff1b;2024年7月&#xff0c;微软正式开源GraphRAG项目&#xff0c;引起极大关注&#xff0c…...

[Lc14_priority_queue] 最后一块石头重量 | 数据流中的第 K 大元素 | 前K个高频单词 | 数据流的中位数

目录 1.最后一块石头的重量 题解 2.数据流中的第 K 大元素 题解 3.前K个高频单词 题解 代码 ⭕4.数据流的中位数 题解 在C中&#xff0c;使用标准库中的priority_queue&#xff0c;默认情况下它是一个最大堆&#xff08;即大堆排序&#xff09;&#xff0c;这意味着最…...

Electron使用WebAssembly实现CRC-16 MAXIM校验

Electron使用WebAssembly实现CRC-16 MAXIM校验 将C/C语言代码&#xff0c;经由WebAssembly编译为库函数&#xff0c;可以在JS语言环境进行调用。这里介绍在Electron工具环境使用WebAssembly调用CRC-16 MAXIM格式校验的方式。 CRC-16 MAXIM校验函数WebAssembly源文件 C语言实…...

案例5_1:单位数码管显示0

文章目录 文章介绍效果图仿真图5_1放置单位数码管 代码5_1.c 文章介绍 效果图 仿真图5_1 复制案例1_2的仿真图&#xff0c;在此基础上修改 注意&#xff1a;栅格大小需要缩小 放置单位数码管 代码5_1.c #include <reg52.h>#define uchar unsigned char #define uint un…...

OpenCV计算摄影学(20)非真实感渲染之增强图像的细节函数detailEnhance()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 此滤波器增强特定图像的细节。 cv::detailEnhance用于增强图像的细节&#xff0c;通过结合空间域和频率域的处理&#xff0c;提升图像中特定细节…...

linux按照nginx

第一步先按照依赖gcc 一键安装上面四个依赖 Nginx的编译安装需要一些依赖库&#xff0c;如gcc、make、zlib、openssl等。可以使用yum命令安装这些依赖&#xff1a; yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 创建目录 mkdir /usr/nginx 切换…...

SpringMVC(八)Knife4j 接口文档

目录 一 基础使用 1 配置pom.xml相关依赖 2 项目配置 3 输入指定路径&#xff08;http://localhost:8080/doc.html&#xff09; 二 一些使用方法 1 Tag 2 Operation 3 Schema 4 Parameter 5 可以根据需求来设置 补充&#xff1a;日期的格式化 Knife4j 是基于 Swag…...

Java集成MQTT和Kafka实现稳定、可靠、高性能的物联网消息处理系统

Java集成MQTT和Kafka实现高可用方案 1. 概述 在物联网(IoT)和分布式系统中,消息传递的可靠性和高可用性至关重要。本文将详细介绍如何使用Java集成MQTT和Kafka来构建一个高可用的消息处理系统。 MQTT(消息队列遥测传输)是一种轻量级的发布/订阅协议,适用于资源受限的设备和…...

【操作系统安全】任务6:Linux 系统文件与文件系统安全 学习指南

目录 一、文件系统基础概念 二、查看文件系统信息 2.1 磁盘空间查看 2.2 分区与挂载管理 2.3 文件系统类型操作 三、文件系统权限配置 3.1 基础权限管理 3.2 所有权管理 3.3 特殊权限设置 四、文件操作基础 4.1 文件创建 4.2 文件删除 4.3 文件复制与移动 4.4 文件…...

华为中小型企业项目案例

实验目的(1) 熟悉华为交换机和路由器的应用场景 (2) 掌握华为交换机和路由器的配置方法 实验拓扑实验拓扑如图所示。 华为中小型企业项目案例拓扑图 实验配置市场部和技术部的配置创建VLANLSW1的配置 [LSW1]vlan batch 10 20 [LSW1]q…...

Zabbix安装(保姆级教程)

Zabbix 是一款开源的企业级监控解决方案,能够监控网络的多个参数以及服务器、虚拟机、应用程序、服务、数据库、网站和云的健康状况和完整性。它提供了灵活的通知机制,允许用户为几乎任何事件配置基于电子邮件的告警,从而能够快速响应服务器问题。Zabbix 基于存储的数据提供…...

JDBC数据库连接池技术详解——从传统连接方式到高效连接管理

1. 引言 在开发数据库应用时&#xff0c;我们通常需要与数据库建立连接并执行SQL语句。传统的JDBC连接方式虽然简单直接&#xff0c;但在高并发场景下容易带来性能问题&#xff0c;甚至导致系统崩溃。因此&#xff0c;引入数据库连接池&#xff08;Connection Pool&#xff09…...

微服务存在的问题及解决方案

微服务存在的问题及解决方案 1. 存在问题 1.1 接口拖慢 因为一个接口在并发时&#xff0c;正好执行时长又比较长&#xff0c;那么当前这个接口占用过多的 Tomcat 连接&#xff0c;导致其他接口无法即时获取到 Tomcat 连接来完成请求&#xff0c;导致接口拖慢&#xff0c;甚至…...

C语言中的结构体数组

一、什么是结构体数组? 在C语言中,**结构体(struct)**是一种自定义数据类型,它可以将不同类型的数据组合成一个单一的数据结构。结构体数组则是多个结构体元素按顺序存储在内存中的集合。通过结构体数组,可以存储多个相同类型的结构体,每个结构体都拥有自己独立的成员变…...

[GESP 202412 一级 T1] 温度转换

描述 小杨最近学习了开尔文温度、摄氏温度和华氏温度的转换。令符号 KK 表示开尔文温度&#xff0c;符号 CC 表示摄氏温度&#xff0c;符号 FF 表示华氏温度&#xff0c;这三者的转换公式如下&#xff1a; C K - 273.15 F C*1.8 32 现在小杨想编写一个程序计算某一开尔文…...

虚幻基础:GAS

文章目录 Gameplay Tag&#xff1a;项目类&#xff1a;可直接按标签管理游戏中的各种对象。其他&#xff1a;数据表格&#xff1a;gameplaytag primary data asset&#xff1a;项目类&#xff1a;存储游戏中的数据&#xff1a;通常用于配置表蓝图&#xff1a;primary data asse…...

案例:图书管理

掌握图书管理案例的实现&#xff0c;能够使用Spring Boot整合Thymeleaf完成图书管理案例。 1.任务需求 &#xff08;1&#xff09;项目使用Spring Boot整合Thymeleaf&#xff0c;项目展示的页面效果全部通过Thymeleaf的模板文件实现。 &#xff08;2&#xff09;查询所有图书。…...

Pycharm 社区版安装教程

找到安装包双击安装文件---点击下一步 一般路径是&#xff1a;C:\Rambo\Software\Development 选择完成后就是如下地址&#xff1a; C:\Rambo\Software\Development\PyCharm Community Edition 2024.3.3 点击上述3个位置就可以了----下一步 等待安装就可以了---完成后点击完成…...

RabbitMQ 全面详解(附面试重点)

RabbitMQ 全面详解&#xff08;附面试重点&#xff09; 一、RabbitMQ 与其他消息队列对比 特性RabbitMQKafkaRocketMQActiveMQ设计定位企业级消息中间件&#xff08;传统业务场景&#xff09;高吞吐分布式流处理平台&#xff08;日志、大数据&#xff09;金融级高可靠消息中间…...

浏览器好用的去广告插件和暗黑模式护眼插件

提升浏览体验&#xff1a;Edge浏览器的Adblock和Dark Mode扩展 Adblock&#xff1a;告别广告干扰 功能&#xff1a;高效拦截弹窗、横幅和视频广告&#xff0c;提升网页整洁度&#xff0c;加快加载速度&#xff0c;节省流量。安装链接&#xff1a;安装Adblock Dark Mode for E…...

VBA第二十七期 数据录入中验证格式有效性

Excel的数据有效性验证是一个有用的工具&#xff0c;但会需要我们向使用数据单元格提前设定有效性验证规则。这样一来使数据的有效性验证功能不能使用在VBA编程中。下面介绍如何在工作表中使用Change事件来创建数据有效性验证过程。监视单元格区域验证数据输入的有效性&#xf…...

基于 Verilog 的时序设计:从理论到实践的深度探索

在数字电路设计领域,时序设计是一个至关重要的环节,它涉及到组合逻辑电路与时序逻辑电路的设计差异、时钟信号的运用以及触发器的工作原理等多个方面。本文将围绕基于 Verilog 的时序设计实验展开,详细阐述实验过程、代码实现以及结果分析,帮助读者深入理解时序设计的核心概…...

[JAVASE] 反射

一. 反射概念 反射&#xff08;Reflection&#xff09;允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态操作类的能力。 二. Java反射的基本使用和应用 java.lang.reflect 是 Java 反射机制的核心包 &#xff0c;提供了操作类及其成员&…...

C++11智能指针简述

一、实现原理 在智能指针对象中有一个裸指针&#xff0c;此指针存储的是动态创建对象的地址&#xff0c;用于生存期控制&#xff0c;能够确保智能指针对象离开所在作用域时&#xff0c;自动正确地销毁动态创建的对象&#xff0c;防止内存泄漏。 使用裸指针存在的问题&#xff…...