yolov5目标检测神经网络——损失函数计算原理

前面已经写了4篇关于yolov5的文章,链接如下:

1、基于libtorch的yolov5目标检测网络实现——COCO数据集json标签文件解析

2、基于libtorch的yolov5目标检测网络实现(2)——网络结构实现

3、基于libtorch的yolov5目标检测网络实现(3)——Kmeans聚类获取anchor框尺寸

4、C++实现Kmeans聚类算法获取COCO目标检测数据集的anchor框

其中:

  • 第一篇讲COCO数据集json标签的解析;

  • 第二篇讲yolov5神经网络正向传播的liborch实现;

  • 第三篇讲使用Opencv提供的Kmeans算法来获取anchor框尺寸;

  • 第四篇讲自己使用C++实现的Kmeans算法来获取anchor框尺寸,相对来说,本篇获取的anchor比第三篇获取的更精确。

本文我们主要讲yolov5网络的损失函数计算原理。


01

目标检测结果精确度的度量

目标检测任务有三个主要目的:

(1)检测出图像中目标的位置,同一张图像中可能存在多个检测目标;

(2)检测出目标的大小,通常为恰好包围目标的矩形框;

(3)对检测到的目标进行识别分类。

所以,判断检测结果精确不精确,主要基于以上三个目的来衡量:

(1)首先我们来定义理想情况:图像中实际存在目标的所有位置,都被检测出来。检测结果越接近这个理想状态,也即漏检/误检的目标越少,则认为结果越精确;

(2)同样定义理想情况:检测到的矩形框恰好能包围检测目标。检测结果越接近这个理想状态,那么认为结果越精确;

(3)对检测到的目标,进行识别与分类,分类结果与目标的实际分类越符合,说明结果越精确。

如下图所示,人、大巴为检测目标,既要检测出所有人和大巴的位置,也要检测出包围人和大巴的最小矩形框,同时还要识别出哪个矩形框内是人,哪个矩形框内是大巴。

5350f8df09baf91560df48bb39f12265.png


02

yolov5网络的损失函数构成

前文我们也讲过yolov5网络的基本思想:

把640*640的输入图像划分成N*N(通常为80*80、40*40、20*20)的网格,然后对网格的每个格子都预测三个指标:矩形框、置信度、分类概率

其中:
 

  • 矩形框表征目标的大小以及精确位置。

  • 置信度表征所预测矩形框(简称预测框)的可信程度,取值范围0~1,值越大说明该矩形框中越可能存在目标。

  • 分类概率表征目标的类别。

所以在实际检测时:

  • 首先判断每个预测框的预测置信度是否超过设定阈值,若超过则认为该预测框内存在目标,从而得到目标的大致位置。

  • 接着根据非极大值抑制算法对存在目标的预测框进行筛选,剔除对应同一目标的重复矩形框(非极大值抑制算法我们后续再详细讲)。

  • 最后根据筛选后预测框的分类概率,取最大概率对应的索引,即为目标的分类索引号,从而得到目标的类别。

a07b4f668e0ba1814efbe6a52a46d0c4.png

损失函数的作用为度量神经网络预测信息与期望信息(标签)的距离,预测信息越接近期望信息,损失函数值越小。由上述每个格子的预测信息可知,训练时主要包含三个方面的损失:矩形框损失(lossrect)置信度损失(lossobj)、分类损失(lossclc)。因此yolov5网络的损失函数定义为:
 

Loss=a*lossobj + b*lossrect + c*lossclc

也即总体损失为三个损失的加权和,通常置信度损失取最大权重,矩形框损失和分类损失的权重次之,比如:

a = 0.4

b = 0.3

c = 0.3

yolov5使用CIOU loss计算矩形框损失,置信度损失与分类损失都用BCE loss计算,下面我们会详细介绍各种损失函数的计算原理。


03

mask掩码矩阵

下面我们以80*80网格为例来说明mask掩码的定义、用途,以及如何获取。40*40网格与20*20网格也类似。

什么是mask掩码?

神经网络对一张图像分割成的80*80网格预测了3*80*80个预测框,那么每个预测框都存在检测目标吗?显然不是。所以在训练时首先需要根据标签作初步判断,哪些预测框里面很可能存在目标?mask掩码为这样的一个3*80*80的bool型矩阵:3*80*80个bool值与3*80*80个预测框一一对应,根据标签信息和一定规则判断每个预测框内是否存在目标,如果存在则将mask矩阵中对应位置的值设置为true,否则设置为false。

mask掩码有什么用?

神经网络对80*80网格的每个格子都预测三个矩形框,因此输出了3*80*80个预测框,每个预测框的预测信息包括矩形框信息、置信度、分类概率。实际上,并非所有预测框都需要计算所有类别的损失函数值,而是根据mask矩阵来决定:

  • 仅mask矩阵中对应位置为true的预测框,需要计算矩形框损失;

  • 仅mask矩阵中对应位置为true的预测框,需要计算分类损失;

  • 所有预测框都需要计算置信度损失,但是mask为true的预测框与mask为false的预测框的置信度标签值不一样。

对于80*80网格,其各类损失函数的计算表达式如下,其中a为mask为true时置信度损失的权重,通常取值0.5~1之间,使得网络在训练时更加专注于mask为true的情况

2774442302e32f5ff87aa54ec942ae5d.png

40*40网格和20*20网格的损失函数计算与80*80网格类似,最后把所有网格的损失函数值作加权和,即得到一张训练图像的最后的损失函数值:

2e672f76c2ac6f3c4ce70dd007bb06b6.png

6ed6eab6b0ac88f2a1d341941093c207.png

上式中α1、α2、α3为各网格损失函数值的权重系数。考虑到图像中往往小型目标比较多,中型目标次之,大型目标最少,因此通常把80*80网格的权重α1设置最大,40*40网格的权重α2次之,20*20网格的权重α3最小,使得训练时网络更加专注于数量多的目标,比如α1、α2、α3依次取0.5、0.3、0.2。

怎么得到mask掩码?

下面我们详细说明一下mask矩阵是怎么得到的。

首先将3*80*80的mask矩阵全部设置为false。对于COCO数据集json标签文件中标注的一张图像中的每个目标框,都按照以下步骤作判断,并根据判断结果将mask矩阵的对应位置设置为true:

(1)从json标签文件解析出单张图像中所有目标框的中心坐标和宽高,以及图像的宽高。假设解析得到一个目标框的中心坐标为(x, y),宽、高分别为w、h,图像的宽高分别为wi、hi。需要将(x, y)转换为640*640图像的坐标(x', y'),并将w、h转换为640*640图像中目标框的宽高wgt、hgt。

bcfb537c26081bbf2784ea692d21da61.png

(2)然后由(x', y')计算该目标框在80*80网格中的网格坐标(xg,yg),注意xg,、yg都是浮点数。

fc43f8f35ead7c3ddbc7631c156391b9.png

(3)接着对xg、yg向下取整,得到整型网格坐标(x0, y0)。同时为了加快训练的收敛速度,yolov5对网格(x0, y0)的左右、上下再各取一个邻近的网格:(x1, y0)和(x0, y1)。具体怎么取呢?如下图,红点为点(xg,yg):

1e5606449ea59ad6712ce41e714f29d4.png

  1. 如果点(xg,yg)在格子的左上角,则取左边、上方的两个格子;

  2. 如果点(xg,yg)在格子的右上角,则取右边、上方的两个格子;

  3. 如果点(xg,yg)在格子的左下角,则取左边、下方的两个格子;

  4. 如果点(xg,yg)在格子的右下角,则取右边、上下方的两个格子;

根据以上原则,x1和y1可按下式计算,其中round为四舍五入运算:

26b8f6b32f82cdbf774e9b0ac32b3e67.png

(4)经过第(3)步,得到三个互相邻近的格子(x0, y0)、(x1, y0)、(x0, y1),我们认为该目标框位于这三个格子的附近。

0b7f357607337a51b885a7b685b00b52.png

前文我们讲使用Kmeans聚类算法获取九个anchor框的时候,就讲过:

  • 宽、高最小的anchor0、anchor1anchor2分配给80*80网格的每个格子;

  • 宽、高次小的anchor3、anchor4anchor5分配给40*40网格的每个格子;

  • 宽、高最大的anchor6、anchor7anchor8分配给20*20网格的每个格子。

因此80*80网格中(x0, y0)、(x1, y0)、(x0, y1)这三个格子都对应anchor0、anchor1anchor2这三个anchor框。

daf78f5dc4554c371c58984725412650.png

(5)假设anchor0、anchor1、anchor2这三个anchor框的宽高分别为(w0, h0)、(w1, h1)、(w2, h2),从json标签文件解析得到该目标框的宽高为(wgt, hgt),然后分别计算(wgt, hgt)与(w0, h0)、(w1, h1)、(w2, h2)的比例,再根据比例剔除不满足要求的anchor框:

88a3f2b96ddb191493d9dfa31f030cd6.png

将保留的anchor框标记为true,剔除的anchor框标记为false,那么anchor0、anchor1、anchor2对应的标记为(m0, m1, m2):

a61e1306f7c117bacba51ff445a897ef.png

(6)根据80*80网格中(x0, y0)、(x1, y0)、(x0, y1)这三个坐标位置,我们分别对mask矩阵赋值:

d8c6468496a1d759c4d27f5d7fa0c558.png

对一张图像中的所有目标框,都作以上判断并对mask矩阵赋值,即可得到该图像的mask矩阵。


04

矩形框损失计算原理

这里为什么先讲矩形框损失呢?因为后面讲的置信度损失原理会使用到矩形框损失。

我们前文讲过,yolov5对每个格子预测3个不同位置和大小的矩形框,其中每个矩形框的信息为矩形中心的x坐标、y坐标,以及矩形宽、高。假设对某个格子预测的矩形框为(xp, yp, wp, hp),该格子对应的目标矩形框为(xl, yl, wl, hl),下面依次讲解几种最常见的矩形框损失函数的计算原理。

  • L1、L2、smooth L1损失函数

首先是L1损失函数:

 其次是L2损失函数:

接着是smooth L1损失函数:

以上式子中,记d=x1-x2,分别画出fL1(d)、fL2(d)、fsL1(d)的曲线如下图:

57db5ae7927c0e67c61855e9f56be36d.png

由以上计算公式和曲线可以看出:

(1)fL1(d)函数的左右两侧曲线对于d的导数(斜率)是恒定不变的,但是在d=0处该函数不可导,然而随着训练的进行,d=x1-x2会逐渐接近0,这就导致在训练后期损失函数的值在某个值附近波动,很难收敛。

(2)fL2(d)函数在d=0出处是可导的,不存在fL1(d)函数的问题,但是在前期训练阶段d很大的时候,fL2(d)函数对于d的导数也会很大,这很可能会导致梯度爆炸问题,从而训练没能朝着最优化的方向进行。

(3)fsL1(d)函数为分段函数,它将fL1(d)函数、fL2(d)函数的优点结合起来,同时完美规避了fL1(d)函数、fL2(d)函数的缺点。

  • IOU系列损失函数

上述计算矩形框的L1、L2、smooth L1损失时有一个共同点,都是分别计算矩形框中心点x坐标、中心点y坐标、宽、高的损失,最后再将四个损失值相加得到该矩形框的最终损失值。这种计算方法的前提假设是中心点x坐标、中心点y坐标、宽、高这四个值是相互独立的,实际上它们具有相关性,所以该计算方法存在问题

于是,IOU系列损失函数(IOU、GIOU、DIOU、CIOU)又被陆续提了出来。计算IOU系列损失函数需要使用矩形框左上角、右下角的坐标,假设预测矩形框的左上角、右下角坐标分别为(xp1, yp1)、(xp2, yp2),标签矩形框的左上角、右下角坐标分别为(xl1, yl1)、(xl2, yl2),如下图所示:

df3a19ee910e7881f1470305e2537990.png

矩形框的中心坐标、宽、高可根据下式转换到左上角、右下角坐标:

99cfb88b4a6a6f92fbbbd52baa3ea569.png

下面分别介绍IOU、GIOU、DIOU、CIOU损失函数的计算原理。

(1)IOU loss

IOU为两个方框相交区域面积与相并部分面积的比值,所以也称为交并比。

首先求相交部分面积:
 

fa6ad9332e91c2fcd4109fc94c5b10e2.png

789b21fc016134ea266e2be65a6bdb52.png

然后求相并部面积:

3a7f6ba18d35355599731e88c88e1653.png

从而得到交并比IOU:

c76bf910e1eac97d4abefe5959d3801c.png

IOU的取值范围为0~1,当两个矩形框完全没有交集时,IOU为0,当它们完全重合时IOU为1,也即重合度越小IOU越接近0,重合度越大IOU越接近1。

最后得到IOU loss的计算公式如下,两个矩形框重合度越高IOU loss越接近0:

ac72bd658581ce8e87efd3dbb9ab48de.png

(2)GIOU loss

当两个矩形框完全没有重叠区域时,无论它们距离多远,它们的IOU都为0。这种情况下梯度也为0,导致无法优化。为了解决这个问题,GIOU又被提了出来。

ce8710a2176f662eb964e0a799d7693a.png

如上图所示,GIOU在IOU的基础上,把包围矩形框A和矩形框B的最小矩形框(图中的虚线框)的面积也加入到计算中。

GIOU可按下式计算,其中S1为A、B相交部分的面积(红色区域)。其中S3为包围A、B的最小矩形框的面积,S2为A、B相并区域的面积(蓝色+红色+灰色区域)。

7be727e9529667a75533cd4d725a5a1b.png

由上式可知GIOU相比IOU,新增了(S3-S2)/S3这一项。新增项表示什么意义呢?由上述可知S3-S2为虚线框中白色区域的面积,也即虚线框中不属于A也不属于B的空白区域,那么(S3-S2)/S3就是空白区域面积占虚线框面积的比例,这个比例越大说明A、B距离越远、重叠度越小,反之则A、B距离越近、重叠度越大。

GIOU的取值范围是-1~1,当A、B完全没有重叠区域时IOU为0,那么GIOU取负值,极端情况,当A、B无重叠区域且距离无限远时,此时(S3-S2)/S3等于1,那么GIOU取-1;另一个极端情况,当A、B完全重叠时(S3-S2)/S3等于0,IOU为1,那么GIOU取1。

因此,GIOU解决了当A、B完全没有重叠区域时IOU恒为0的问题。

最后得到GIOU loss的计算公式:

a79eadcd6cc1ef6df7d554e81c21308b.png

(3)DIOU loss

GIOU虽然把IOU的问题解决了,但它还是基于面积的度量,并没有把两个矩形框A、B的距离考虑进去。为了使训练更稳定、收敛更快,DIOU随之被提了出来,DIOU把矩形框A、B的中心点距离ρ、外接矩形框(虚线框)的对角线长度c都直接考虑进去,如下图所示:

c9d3cd89359c07ded867205fb4280e70.png

DIOU可按下式计算:

f55e03e6737dad9cf8deabe867e16395.png

由上式可知DIOU的取值范围也为-1~1,当两个框A、B完全重合时DIOU取1,当A、B距离无限远时,DIOU取-1。

从而得到DIOU loss的计算公式:

92a503693869e80c9a3c6254dd4c92d1.png

(4)CIOU loss

yolov5使用CIOU loss来衡量矩形框的损失。

DIOU把两个矩形框A、B的重叠面积、中心点距离都考虑了进去,但并未考虑A、B的宽高比。为了进一步提升训练的稳定性和收敛速度,在DIOU的基础上CIOU又被提了出来,它将重叠面积、中心点距离、宽高比同时加入了计算。

CIOU可按下式计算:

1cb8d8139fd418e7de6f694eb10c239a.png

上式中,ρ为框A和框B的中心点距离,c为框A和框B的最小包围矩形的对角线长度,v为框A、框B的宽高比相似度,α为v的影响因子。

反正切arctan函数的取值范围是0~Π/2,那么v的取值范围为0~1,当框A、框B的的宽高比相等时v取0,当框A、框B的的宽高比相差无限大时v取1。

当框A、框B的距离无限远,且宽高比差别无限大时DIOU取-1,v取1,alpha取0.5,此时CIOU取-1-0.5=-1.5;当框A、框B完全重叠时,DIOU取1,v取0,α取0,则CIOU取1。因此CIOU取值范围是-1.5~1

IOU越大也即A、B的重叠区域越大,则α越大,从而v的影响越大;反之IOU越小也即A、B的重叠区域越小,则α越小,从而v的影响越小。因此在优化过程中:

  • 如果A、B的重叠区域较小,则宽高比v在损失函数中影响较小,此时着重优化A、B的距离;

  • 如果A、B的重叠区域较大,则宽高比v在损失函数中影响也较大,此时着重优化A、B的宽高比。

用一句话来说,就是越缺什么,就越着重弥补什么,从而达到加速优化训练的收敛速度和稳定性的目的。

由以上可得CIOU loss的计算公式为:

1542e78fd5e0e45dadc5039ea5440066.png


05

置信度损失计算原理

下面以80*80网格为例,详细讲置信度损失的计算原理,40*40和20*20网格的置信度损失计算原理与80*80网格一样,可依此类推。

  • 神经网络预测的置信度

对于一张图像分割成的80*80的网格,神经网络对其中每个格子都预测个位于该格子附近的矩形框(简称预测框),每个预测框的预测信息包括中心坐标、宽、高、置信度、分类概率,因此神经网络总共输出3*80*80个0~1的预测置信度,与3*80*80个预测框一 一对应。每个预测框的置信度表征这个预测框的靠谱程度,值越大表示该预测框越可信靠谱,也即越接近目标的真实最小包围框。

比如下图中,红点A、B、C、D表示检测目标,那么每个红点所在格子的三个预测置信度应该比较大甚至接近1,而其它格子的预测置信度应该较小甚至接近0。

2fc5b42e48aa451ddabbbc2a317bcba5.png

  • 置信度的标签

标签的维度应该与神经网络的输出维度保持一致,因此置信度的标签也是维度为3*80*80的矩阵

这里就用到了上文我们讲的mask掩码矩阵:以维度同样为3*80*80的mask矩阵为标记,对置信度标签矩阵进行赋值。yolo之前版本直接对mask矩阵为true的地方赋值1,mask矩阵为false的地方赋值0,认为只要mask为true就表示对应预测框完美包围了目标。这样做就太绝对了,因为mask为true只是表示该预测框在目标附近而已,并不一定完美包围了目标。所以yolov5改变了做法:对mask为true的位置不直接赋1,而是计算对应预测框与目标框的CIOU,使用CIOU作为该预测框的置信度标签,当然对mask为false的位置还是直接赋0

这样一来,标签值的大小与预测框、目标框的重合度有关,两框重合度越高则标签值越大。当然,上文我们讲CIOU的取值范围是-1.5~1,而置信度标签的取值范围是0~1,所以需要对CIOU做一个截断处理:当CIOU小于0时直接取0值作为标签

  • BCE loss损失函数

假设置信度标签为矩阵L,预测置信度为矩阵P,那么矩阵中每个数值的BCE loss的计算公式如下:

2ee681dd5839ba7522b7540f0873b86d.png

注意BCE loss要求输入数据的取值范围必须在0~1之间。

从得到80*80网格的置信度损失值:

1201425153e9b3b5834d3f79609548c6.png

此外,我们称对应mask位true的预测框为正样本,对应mask为false的预测框为负样本,负样本肯定是远远多于正样本的,为了使训练更专注于正样本,后来Focal loss又被提了出来,我们在此暂时不细说,下篇文章再详细介绍吧。


06

分类损失计算原理

下面也以80*80网格为例,详细讲分类损失的计算原理,40*40和20*20网格的分类损失计算原理与80*80网格一样,可依此类推。

神经网络对80*80网格的每个格子都预测三个预测框,每个预测框的预测信息都包含了N个分类概率。其中N为总类别数,比如COCO数据集有80个类别,那么N取80。所以对于COCO数据集,每个预测框有80个0~1的分类概率,那么神经网络总共预测3*80*80*80个分类概率,组成预测概率矩阵。

80*80网格的标签概率矩阵与预测概率矩阵的维度一样,也是3*80*80*80。每个预测框的标签,由解析json标签文件得到,是一个0~79的数值,需要将0~79的数值转换成80个数的独热码:

dcbd473e8594b400a31781acadaea165.png

然而,为了减少过拟合,且增加训练的稳定性,通常对独热码标签做一个平滑操作。如下式,label为独热码中的所有数值,α为平滑系数,取值范围0~1,通常取0.1。

9511bcfe207d86ffef28e0f074d2058c.png

同样假设置标签概率为矩阵Lsmooth,预测概率为矩阵P,那么矩阵中每个数值的BCE loss的计算公式如下:

2579d603d160a6d6c42563a2dca339ff.png

于是得到80*80网格的分类损失函数值的计算公式:

0e2dfbc81735aaeecc8871fdfaa9d9d4.png


07

结语

好了,本文我们就讲到这里。说点题外话,隔了两三个月没有更新文章了,感觉很对不起粉丝们。因为本人在年底不仅换了工作,工作城市也换了,免不了一番奔波与适应,所以更新就被耽搁了。不过呢,我还是会在业余抽时间来学习、更新,不辜负粉丝们对我的期望~祝朋友们新年快乐,事事顺心(迟来的祝福^^)!

欢迎关注"萌萌哒程序猴"微信公众号,接下来会不定时更新更加精彩的内容,敬请期待~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AcWing 861. 二分图的最大匹配—匈牙利算法

题目链接:AcWing 861. 二分图的最大匹配 问题描述 分析 该题是一道典型的二分图匹配模板题,求解最大匹配数,可以用匈牙利算法来解决,下面举一个例子来说明匈牙利算法是如何运行的 以该图为例,其中 1可以匹配a,c 2可以匹配a,b 3…

面试算法90:环形房屋偷盗

题目 一条环形街道上有若干房屋。输入一个数组表示该条街道上的房屋内财产的数量。如果这条街道上相邻的两幢房屋被盗就会自动触发报警系统。请计算小偷在这条街道上最多能偷取的财产的数量。例如,街道上5家的财产用数组[2,3,4,5…

亚马逊店铺遇到账号申诉模版分享

1.表达诚意,先认错再说:我知道,最近我们在Amazon.com上作为卖家的表现已经低于亚马逊和我们自己的质量标准。 2.清楚分明的格式:我们库存管理的混乱导致了延迟发货,更糟糕的是,物品无法使用。当延迟发货和…

T527 Android 13 编译步骤

步骤1: cd longan./build.sh config (0 2 1) 选择 Android 平台: 步骤2:选择IC为t527: 步骤3:板子类型选为demo_car: 步骤4:选择 flash,默认选择 default 则可: 步骤5&…

性能优化-OpenMP基础教程(四)-Android上运行OpenMP

本文主要介绍如何在一个常规的Android手机上调试OpenMP程序,包括Android NDK的环境配置和使用JNI编写一个OpenMP程序运行在Android手机中。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能&#…

stable diffusion 人物高级提示词(三)动作、表情、眼神

一、动作 中文英文站立Standing走路Walking身体前倾Leaning Forward鞠躬Bowing战斗姿势Fighting Stance单腿站立Standing on One Leg坐在椅子上Sitting on a Chair手叉腰Hand on Hip手插兜Hand in Pocket双臂交叉Crossed Arms翘二郎腿Crossed Legs跪地Kneeling双手举起来Hands…

C# .Net学习笔记—— 异步和多线程(异常处理)

一、异常处理 1、下面for循环20个线程&#xff0c;到11&#xff0c;12号的时候执行失败&#xff0c;这里我也用了try catch来捕获异常。 private void button11_Click(object sender, EventArgs e){TaskFactory taskFactory new TaskFactory();List<Task> taskList ne…

湖仓架构的演进

1.数据仓库架构的历史演进 起初&#xff0c;业界数据处理首选方式是数仓架构。通常数据处理的流程是把一些业务数据库&#xff0c;通过ETL的方式加载到Data Warehouse中&#xff0c;再在前端接入一些报表或者BI的工具去展示。 数据仓库概念是 Inmon 于 1990 年提出并给出了完…

文献综述方法论|全文翻译

最常见的错误是文献综述往往未能为该领域提供真正有价值的贡献。无论综述文章多么优秀和严谨&#xff0c;如果它没有提供足够的新内容&#xff0c;就不会被发表。太常见的情况是&#xff0c;文献综述只是对特定年份之间进行的研究进行描述性总结&#xff0c;描述了诸如发表的文…

聚会小游戏+摇色子+愤怒的大叔+真心话太冒险微信小程序源码系统:活跃气氛神器 带完整的安装包以及搭建教程

在现代社交活动中&#xff0c;如何快速破冰并调动气氛一直是人们关注的焦点。微信小程序以其便捷性、互动性和多样性成为了解决这一问题的理想工具。今天&#xff0c;小编将为大家介绍一款集聚会小游戏、摇色子、真心话大冒险等功能于一身的微信小程序源码系统——“活跃气氛神…

Leetcode13-解密消息(2325)

1、题目 给你字符串 key 和 message &#xff0c;分别表示一个加密密钥和一段加密消息。解密 message 的步骤如下&#xff1a; 使用 key 中 26 个英文小写字母第一次出现的顺序作为替换表中的字母 顺序 。 将替换表与普通英文字母表对齐&#xff0c;形成对照表。 按照对照表 …

[C#]使用OpenCvSharp实现区域文字提取

【官方框架地址】 github.com/shimat/opencvsharp 【算法介绍】 采用opencv算法实现文字区域提取&#xff0c;步骤如下&#xff1a; &#xff08;1&#xff09;形态学操作 &#xff08;2&#xff09;查找轮廓 &#xff08;3&#xff09;筛选那些面积小的 &#xff08;4&#…

Element ui 改变el-transfer 穿梭框的大小

修改el-transfer 左右两个穿梭框的高度和宽度&#xff0c;具体效果如下正常大小的穿梭框修改之后的&#xff0c;主要在style中加上如下样式即可 /deep/ .el-transfer-panel{ width: 470px; /* 左右两个穿梭框的高度和宽度 */ height: 450px; } /deep/ .el-transfer-panel__li…

【Bootstrap5学习 day10】

Flex布局 弹性盒子是CSS3的一种新的布局模式&#xff0c;更适合响应式的设计 创建一个弹性盒子容器 使用d-flex类&#xff0c;创建flexbox容器并将直接子项转换为flex项 <div class"d-flex p-3 bg-info text-white"><div class"p-2 bg-secondary"…

03Spring实现IoC:依赖注入/构造注入

● 控制反转&#xff0c;反转的是什么&#xff1f; ○ 将对象的创建权利交出去&#xff0c;交给第三方容器负责。 ○ 将对象和对象之间关系的维护权交出去&#xff0c;交给第三方容器负责。 ● 控制反转这种思想如何实现呢&#xff1f; ○ DI&#xff08;Dependency Injection&…

G1为什么更适合亿级流量系统以及YGC优化策略screenflow

大白话&#xff1a; 1.ParNew执行回收的时候&#xff0c;STW会比较长&#xff0c;CMS存在碎片化的问题&#xff0c;当物理机的内存变大&#xff0c;这套组合存在的问题会更大&#xff0c;加大物理内存&#xff0c;反而让垃圾回收更慢。 大白话&#xff1a; 之前讲过&#xff0c…

vue-打包

打包的作用 说明&#xff1a;vue脚手架只是开发过程中&#xff0c;协助开发的工具&#xff0c;当真正开发完了>脚手架不参与上线 打包的作用&#xff1a; 1&#xff09;将多个文件压缩合并成一个文件 2&#xff09;语法降级 3&#xff09;less sass ts语法解析 打包后…

羊大师解读,羊奶的口味更适合哪些人群?

羊大师解读&#xff0c;羊奶的口味更适合哪些人群&#xff1f; 羊奶作为一种营养丰富的乳制品&#xff0c;拥有许多独特的品质和口味&#xff0c;备受消费者的青睐。它不仅含有丰富的蛋白质、维生素和矿物质&#xff0c;还具有更易消化的特点&#xff0c;适合许多人群的饮用。…

CSS新增文本描边-text-stroke属性

-webkit-text-stroke属性 概念&#xff1a;-webkit-text-stroke属性为文本添加描边效果。所谓的描边效果&#xff0c;指的是给文字添加边框 语法&#xff1a; -webkit-text-stroke:width color;Chrome和Firefox这两个浏览器都只能识别带有-webkit前缀的text-stroke属性 -web…

【HarmonyOS开发】ArkUI-X 跨平台框架(使用ArkTs开发AndroidIOS)

ArkUI-X 跨平台框架进一步将 ArkUI 开发框架扩展到了多个OS平台&#xff0c;目前支持OpenHarmony、HarmonyOS、Android、 iOS&#xff0c;后续会逐步增加更多平台支持。开发者基于一套主代码&#xff0c;就可以构建支持多平台的精美、高性能应用。 一、跨平台框架有哪些? 1、…