【人脸检测】Yolov5Face:优秀的one-stage人脸检测算法

news2024/11/17 3:23:46

论文题目:《YOLO5Face: Why Reinventing a Face Detector》
论文地址:https://arxiv.org/pdf/2105.12931.pdf
代码地址:https://github.com/deepcam-cn/yolov5-face

1.简介

       近年来,CNN在人脸检测方面已经得到广泛的应用。但是许多人脸检测器都是需要使用特别设计的人脸检测器来进行人脸的检测,而YOLOv5的作者则是把人脸检测作为一个一般的目标检测任务来看待的。YOLOv5Face在YOLOv5的基础上添加了一个 5-Point Landmark Regression Head(关键点回归),并对Landmark Regression Head使用了Wing loss进行约束。YOLOv5Face设计了不同模型尺寸的检测器,从大模型到超小模型,以实现在嵌入式或移动设备上的实时检测。

在这里插入图片描述

       在WiderFace数据集上的实验结果表明,YOLOv5Face在几乎所有的Easy、Medium和Hard子集上都能达到最先进的性能,超过了特定设计的人脸检测器。

为什么人脸检测=一般检测:

       在YOLOv5Face的方法中是把人脸检测作为一个一般的目标检测任务。与TinaFace想法类似把人脸作为一个目标。正如在TinaFace中所讨论的:
・从数据的角度来看,人脸所具有的诸如姿态、尺度、遮挡、光照以及模糊等也会出现在其他的一般检测任务之中;
・从面部的独特属来看性,如表情和化妆,也可以对应一般检测问题中的形状变化和颜色变化。
       Landmark相对来说是一个特殊的存在,但他们也并不是唯一的。它们只是一个物体的关键点。例如,在车牌检测中,也使用了Landmark。在目标预测模型的Head中添加Landmark回归相对来说是一键简单的事情。那么从人脸检测所面临的挑战来看,多尺度、小人脸、密集场景等在一般的目标检测中都存在。因此,人脸检测完全可以看作一个一般目标检测子任务。

设计目标

       YOLOv5Face针对人脸检测的对YOLOv5进行了再设计和修改,考虑到大人脸、小人脸、Landmark监督等不同的复杂性和应用。YOLOv5Face的目标是为不同的应用程序提供一个模型组合,从非常复杂的应用程序到非常简单的应用程序,以在嵌入式或移动设备上获得性能和速度的最佳权衡。

主要贡献

       1.重新设计了YOLOV5来作为一个人脸检测器,并称之为YOLOv5Face。对网络进行了关键的修改,以提高平均平均精度(mAP)和速度方面的性能;
       2.设计了一系列不同规模的模型,从大型模型到中型模型,再到超小模型,以满足不同应用中的需要。除了在YOLOv5中使用的Backbone外,还实现了一个基于ShuffleNetV2的Backbone,它为移动设备提供了最先进的性能和快速的速度;
       3.在WiderFace数据集上评估了YOLOv5Face模型。在VGA分辨率的图像上,几乎所有的模型都达到了SOTA性能和速度。这也证明了前面的结论,不需要重新设计一个人脸检测器,因为YOLO5就可以完成它。

2.Yolov5Face

2.1.网络结构

2.1.1.整体架构

       YOLOv5Face是以YOLOv5作为Baseline来进行改进和再设计以适应人脸检测。这里主要是检测小脸和大脸的修改。整体结构如下:
在这里插入图片描述
       YOLO5人脸检测器的网络架构如上图所示。它由Backbone、Neck和Head组成,描述了整体的网络体系结构。在YOLOv5中,使用了CSPNet Backbone。在Neck中使用了SPP和PAN来融合这些特征。在Head中也都使用了回归和分类。

2.1.2.CBS Block

在这里插入图片描述
       上图定义了一个CBS Block,它由Conv、BN和SiLU激活函数组成。CBS Block也被用于许多其他Block之中。

class Conv(nn.Module):
    # Standard convolution
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super(Conv, self).__init__()
        # 卷积层
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        # BN层
        self.bn = nn.BatchNorm2d(c2)
        # SiLU激活层
        self.act = nn.SiLU() 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)))

2.1.3.Head

在这里插入图片描述
       在上图中,显示了Head的输出标签,其中包括边界框(bbox)、置信度(conf)、分类(cls)和5-Point Landmarks。这些Landmarks是对YOLOv5的改进点,使其成为一个具有Landmarks输出的人脸检测器。如果没有Landmarks,最后一个向量的长度应该是6而不是16。

请注意,P3中的输出尺寸80×80×16,P4中的40×40×16,P5中的20×20×16,可选P6中的10×10×16为每个Anchor。实际的尺寸应该乘以Anchor的数量。

2.1.4.stem结构

在这里插入图片描述

       上图为stem结构,它用于取代YOLOv5中原来的Focus层。在YOLOv5中引入Stem块用于人脸检测是YOLOv5Face的创新之一。用Stem模块替代网络中原有的Focus模块,提高了网络的泛化能力,降低了计算复杂度,同时性能也没有下降。Stem模块的图示中虽然都是用的CBS,但是看代码可以看出来第2个和第4个CBS是1×1卷积,第1个和第3个CBS是3×3,stride=2的卷积。配合yaml文件可以看到stem以后图像大小由640×640变成了160×160。

class StemBlock(nn.Module):
    def __init__(self, c1, c2, k=3, s=2, p=None, g=1, act=True):
        super(StemBlock, self).__init__()
        # 3×3卷积
        self.stem_1 = Conv(c1, c2, k, s, p, g, act)
        # 1×1卷积
        self.stem_2a = Conv(c2, c2 // 2, 1, 1, 0)
        # 3×3卷积
        self.stem_2b = Conv(c2 // 2, c2, 3, 2, 1)
        # 最大池化层
        self.stem_2p = nn.MaxPool2d(kernel_size=2, stride=2, ceil_mode=True)
        # 1×1卷积
        self.stem_3 = Conv(c2 * 2, c2, 1, 1, 0)

    def forward(self, x):
        stem_1_out = self.stem_1(x)
        stem_2a_out = self.stem_2a(stem_1_out)
        stem_2b_out = self.stem_2b(stem_2a_out)
        stem_2p_out = self.stem_2p(stem_1_out)
        out = self.stem_3(torch.cat((stem_2b_out, stem_2p_out), 1))
        return out

2.1.5.CSP Block(C3)

在这里插入图片描述
       上图显示了一个CSP Block(C3)。CSP Block的设计灵感来自于DenseNet。但是,不是在一些CNN层之后添加完整的输入和输出,输入被分成 2 部分。其中一半通过一个CBS Block,即一些Bottleneck Blocks,另一半是经过Conv层进行计算。

class C3(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(C3, self).__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)  # 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)), dim=1))

2.1.6. C3模块中的Bottleneck层

在这里插入图片描述

class Bottleneck(nn.Module):
    # Standard bottleneck
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
        super(Bottleneck, self).__init__()
        c_ = int(c2 * e)  # hidden channels
        #第1个CBS模块
        self.cv1 = Conv(c1, c_, 1, 1)
        #第2个CBS模块
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        #元素add操作
        self.add = shortcut and c1 == c2

    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

2.1.7.SPP Block

在这里插入图片描述

       上图是SPP Block。YOLOv5Face在这个Block中把YOLOv5中的13×13,9×9,5×5的kernel size修改为7×7,5×5,3×3,这个改进更适用于人脸检测并提高了人脸检测的精度

class SPP(nn.Module):
    # 这里主要是讲YOLOv5中的kernel=(5,7,13)修改为(3, 5, 7)
    def __init__(self, c1, c2, k=(3, 5, 7)):
        super(SPP, self).__init__()
        c_ = c1 // 2  # hidden channels
        # 对应第1个CBS Block
        self.conv1 = Conv(c1, c_, 1, 1)
        # 对应第2个 cat后的 CBS Block
        self.conv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
        # ModuleList=[3×3 MaxPool2d,5×5 MaxPool2d,7×7 MaxPool2d]
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])

    def forward(self, x):
        x = self.conv1(x)
        return self.conv2(torch.cat([x] + [m(x) for m in self.m], 1))

2.1.8.增加P6特征图

       同时,YOLOv5Face添加一个stride=64的P6输出块,P6可以提高对大人脸的检测性能。(之前的人脸检测模型大多关注提高小人脸的检测性能,这里作者关注了大人脸的检测效果,提高大人脸的检测性能来提升模型整体的检测性能)。P6的特征图大小为10x10。

注意,这里只考虑VGA分辨率的输入图像。为了更精确地说,输入图像的较长的边缘被缩放到640,并且较短的边缘被相应地缩放。较短的边缘也被调整为SPP块最大步幅的倍数。例如,当不使用P6时,较短的边需要是32的倍数;当使用P6时,较短的边需要是64的倍数。

2.2.输入端改进

       YOLOv5Face作者发现一些目标检测的数据增广方法并不适合用在人脸检测中,包括上下翻转和Mosaic数据增广。删除上下翻转可以提高模型性能。对小人脸进行Mosaic数据增广反而会降低模型性能,但是对中尺度和大尺度人脸进行Mosaic可以提高性能。随机裁剪有助于提高性能。

这里主要还是COCO数据集和WiderFace数据集尺度有差异,WiderFace数据集小尺度数据相对较多。

2.3.Landmark回归

       Landmark是人脸的重要特征。它们可以用于人脸比对、人脸识别、面部表情分析、年龄分析等任务。传统Landmark由68个点组成。它们被简化为5点时,这5点Landmark就被广泛应用于面部识别。人脸标识的质量直接影响人脸对齐和人脸识别的质量。
       一般的物体检测器不包括Landmark。可以直接将其添加为回归Head。因此,作者将它添加到YOLO5Face中。Landmark输出将用于对齐人脸图像,然后将其发送到人脸识别网络。
在这里插入图片描述

       用于Landmark回归的一般损失函数为L2、L1或smooth-L1。MTCNN使用的就是L2损失函数。然而,作者发现这些损失函数对小的误差并不敏感。为了克服这个问题,提出了Wing loss:

在这里插入图片描述
在这里插入图片描述

landmark的获取:

#landmarks
lks = t[:,6:14]
lks_mask = torch.where(lks < 0, torch.full_like(lks, 0.), torch.full_like(lks, 1.0))
#应该是关键点的坐标除以anch的宽高才对,便于模型学习。使用gwh会导致不同关键点的编码不同,没有统一的参考标准
lks[:, [0, 1]] = (lks[:, [0, 1]] - gij)
lks[:, [2, 3]] = (lks[:, [2, 3]] - gij)
lks[:, [4, 5]] = (lks[:, [4, 5]] - gij)
lks[:, [6, 7]] = (lks[:, [6, 7]] - gij)

Wing Loss的计算如下:

#landmarks
lks = t[:,6:14]
lks_mask = torch.where(lks < 0, torch.full_like(lks, 0.), torch.full_like(lks, 1.0))
#应该是关键点的坐标除以anch的宽高才对,便于模型学习。使用gwh会导致不同关键点的编码不同,没有统一的参考标准
lks[:, [0, 1]] = (lks[:, [0, 1]] - gij)
lks[:, [2, 3]] = (lks[:, [2, 3]] - gij)
lks[:, [4, 5]] = (lks[:, [4, 5]] - gij)
lks[:, [6, 7]] = (lks[:, [6, 7]] - gij)
Wing Loss的计算如下:

class WingLoss(nn.Module):
    def __init__(self, w=10, e=2):
        super(WingLoss, self).__init__()
        # https://arxiv.org/pdf/1711.06753v4.pdf   Figure 5
        self.w = w
        self.e = e
        self.C = self.w - self.w * np.log(1 + self.w / self.e)
 
    def forward(self, x, t, sigma=1):  #这里的x,t分别对应之后的pret,truel
        weight = torch.ones_like(t) #返回一个大小为1的张量,大小与t相同
        weight[torch.where(t==-1)] = 0
        diff = weight * (x - t)
        abs_diff = diff.abs()
        flag = (abs_diff.data < self.w).float()
        y = flag * self.w * torch.log(1 + abs_diff / self.e) + (1 - flag) * (abs_diff - self.C) #全是0,1
        return y.sum()
 
class LandmarksLoss(nn.Module):
    # BCEwithLogitLoss() with reduced missing label effects.
    def __init__(self, alpha=1.0):
        super(LandmarksLoss, self).__init__()
        self.loss_fcn = WingLoss()#nn.SmoothL1Loss(reduction='sum')
        self.alpha = alpha
 
    def forward(self, pred, truel, mask): #预测的,真实的 600(原来为62*10)(推测是去掉了那些没有标注的值)
        loss = self.loss_fcn(pred*mask, truel*mask)  #一个值(tensor)
        return loss / (torch.sum(mask) + 10e-14)

2.4.YOLOv5Face的后处理NMS

       其实本质上没有改变,这里仅仅给出对比的代码。

yolov5的NMS代码如下:

def non_max_suppression(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, labels=()):
    """Performs Non-Maximum Suppression (NMS) on inference results
    Returns:
         detections with shape: nx6 (x1, y1, x2, y2, conf, cls)
    """
 
    nc = prediction.shape[2] -5  # number of classes

yolov5face的NMS代码如下:

def non_max_suppression_face(prediction, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic=False, labels=()):
    """Performs Non-Maximum Suppression (NMS) on inference results
    Returns:
         detections with shape: nx6 (x1, y1, x2, y2, conf, cls)
    """
    # 不同之处
    nc = prediction.shape[2] - 15  # number of classes

综上,对比yolov5,yolov5face主要改进点简单总结如下:
1.增加了人脸landmark回归head,并提出和采用了更适用于landmark回归的wing loss。
2.替换Focus层为Stem层。增加了网络的通用性,同时减少了计算量,且模型表现没有下降。
3.将SPP的kernel尺寸改小。YOLOv5Face在这个Block中把YOLOv5中的13×13,9×9,5×5的kernel size修改为7×7,5×5,3×3,这个改进更适用于人脸检测并提高了人脸检测的精度。
4.增加了stride=64的P6特征图输出块。P6可以提高对大人脸的检测性能。(之前的人脸检测模型大多关注提高小人脸的检测性能,这里作者关注了大人脸的检测效果,提高大人脸的检测性能来提升模型整体的检测性能)。P6的特征图大小为10x10。

##################################################################################

分析比较L1,L2、Smooth L1损失函数和WingLoss

在这里插入图片描述

其中s是人脸关键点的ground-truth,函数f(x)就等价于:

在这里插入图片描述

损失函数对x的导数分别为:

在这里插入图片描述

       L2损失函数。当x增大时L2 loss对x的导数也增大,这就导致训练初期,预测值与ground-truth差异过大时,损失函数对预测值的梯度十分大,导致训练不稳定。
       L1损失函数。L1 loss的导数为常数,在训练后期,预测值与ground-truth差异很小时, 损失对预测值的导数的绝对值仍然为1,此时学习率(learning rate)如果不变,损失函数将在稳定值附近波动,难以继续收敛达到更高精度。
       Smooth L1损失函数。在x较小时,对x的梯度也会变小,而在x很大时,对x的梯度的绝对值达到上限 1,也不会太大以至于破坏网络参数。smooth L1完美地避开了L1和L2损失的缺陷。
       此外,根据fast rcnn的说法,“… L1 loss that is less sensitive to outliers than the L2 loss used in R-CNN and SPPnet.” 也就是smooth L1让loss对于离群点更加鲁棒,即相比于L2损失函数,其对离群点、异常值(outlier)不敏感,梯度变化相对更小,训练时不容易跑飞。
在这里插入图片描述

WingLoss的优势:

       上一部分中分析的所有损失函数在出现较大误差时表现良好。这说明神经网络的训练应更多地关注具有小或中误差的样本。为了实现此目标,提出了一种新的损失函数,即基于CNN的面部Landmark定位的Wing Loss。

在这里插入图片描述
       当NME在0.04的时候,测试数据比例已经接近1了,所以在0.04到0.05这一段,也就是所谓的large errros段,并没有分布更多的数据,说明各损失函数在large errors段都表现很好。模型表现不一致的地方就在于small errors和medium errors段,例如,在NME为0.02的地方画一根竖线,相差甚远的。因此作者提出训练过程中应该更多关注samll or medium range errros样本。

       可以使用ln x来增强小误差的影响,它的梯度是1/x,对于接近0的值就会越大,optimal step size为x的平方,这样gradient就由small errors“主导”,step size由large errors“主导”。这样可以恢复不同大小误差之间的平衡。
       但是,为了防止在可能的错误方向上进行较大的更新步骤,重要的是不要过度补偿较小的定位错误的影响。这可以通过选择具有正偏移量的对数函数来实现。
       但是这种类型的损失函数适用于处理相对较小的定位误差。在wild人脸关键点检测中,可能会处理极端姿势,这些姿势最初的定位误差可能非常大,在这种情况下,损失函数应促进从这些大错误中快速恢复。这表明损失函数的行为应更像L1或L2。由于L2对异常值敏感,因此选择了L1。
       所以,对于小误差,它应该表现为具有偏移量的对数函数,而对于大误差,则应表现为L1。因此复合损失函数Wing Loss就诞生了。

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

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

相关文章

【C++的OpenCV】第一课-opencv的间接和安装(Linux环境下)

第一课-目录一、基本介绍1.1 官网1.2 git源码1.3 介绍二、OpenCV的相关部署工作2.1 Linux平台下部署OpenCV一、基本介绍 1.1 官网 opencv官网 注意&#xff1a;官网为英文版本&#xff0c;可以使用浏览器自带的翻译插件进行翻译&#xff0c;真心不推荐大家去看别人翻译的&am…

过滤器和监听器

1、过滤器Filter 作用是防止SQL注入、参数过滤、防止页面攻击、空参数矫正、Token校验、Session验证、点击率统计等等&#xff1b; 使用Filter的步骤 新建类&#xff0c;实现Filter抽象类&#xff1b;重写init、doFilter、destroy方法&#xff1b;在SpringBoot入口中添加注解…

演示Ansible中的角色使用方法(ansible roles)

文章目录一、ansible 角色简介二、roles目录结构三、role存放的路径&#xff1a;配置文件ansible.cfg中定义四、创建目录结构五、playbook中使用rolesplaybook变量会覆盖roles中的定义变量六、控制任务执行顺序七、ansible—galaxy命令工具八、安装选择的角色1.从网上下载&…

使用vue3,vite,less,flask,python从零开始学习硅谷外卖(41-82集)

第41集&#xff1a;这里遇到个大坑&#xff0c;因为这种项目有很多页面&#xff0c;有时候有的页面忘了保存就会出错&#xff0c;还很难排查&#xff0c;浪费了我快半天的时间。可以把vscode的代码自动保存打开&#xff0c;以后就不会踩坑了。 第42集&#xff1a;没啥好说的。 …

判断字符串中的字符的类型isdecimal();isalpha();isdigit();isalnum()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 判断字符串中的字符的类型 isdecimal()&#xff1b;isalpha()&#xff1b;isdigit()&#xff1b;isalnum() [太阳]选择题 对于代码中isdecimal()和isalnum()输出的结果是? s "ABc123&…

亿级高并发电商项目-- 实战篇 --万达商城项目 十一(编写商品搜索功能、操作商品同步到ES、安装RabbitMQ与Erlang,配置监听队列与消息队列)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

Sandboxie-沙箱软件-Plus版本(Qt)-主框架程序-SandMan.exe-创建语言文件-tr-Qt-语言国际化

文章目录1.功能介绍2.Qt语言国际化3.设置软件的语言版本4.作者答疑1.功能介绍 沙箱软件的增强版本采用Qt架构开发&#xff0c;核心模块与经典版本相同&#xff0c;本文主要介绍SandMan.exe这个主程序代码。在main.cpp这个入口函数里&#xff0c;有主窗口入口&#xff0c;如下所…

2.5|iot冯|方元-嵌入式linux系统开发入门|2.13+2.18

一、 Linux 指令操作题&#xff08;共5题&#xff08;共 20 分&#xff0c;每小题 4分&#xff09;与系统工作、系统状态、工作目录、文件、目录、打包压缩与搜索等主题相关。1.文件1.1文件属性1.2文件类型属性字段的第1个字符表示文件类型&#xff0c;后9个字符中&#xff0c;…

【物联网】智慧农业病虫害精准辨识竞赛思路及代码分享

来源&#xff1a;投稿 作者&#xff1a;LSC 编辑&#xff1a;学姐 比赛官网: https://www.dataglobal.cn/cmpt/signUpInfo200.html 任务描述 请参赛者设计智慧农业病虫害检测系统&#xff0c;给出一体化问题解决方案&#xff0c;鼓励参赛选手结合某一果园/农作物实际情况建立…

使用 URLSearchParams 解析和管理URL query参数

介绍 首先 URLSearchParams是一个构造函数&#xff0c;会生成一个URLSearchParams对象&#xff0c;参数类型&#xff1a; 不传 &#xff5c; string &#xff5c; object &#xff5c; URLSearchParams&#xff0c; 并且遇到特殊字符它会自动帮我们encode 和 decode const ur…

Java模块化概述

3 模块化 3.1 模块化概述 Java语言随着这些年的发展已经成为了一]影响深远的编程语言&#xff0c;无数平台,系统都采用Java语言编写。但是&#xff0c;伴随着发展&#xff0c;Java也越来越庞大&#xff0c;逐渐发展成为-门“臃肿” 的语言。而且&#xff0c;无论是运行个大型的…

Vulnhub 渗透练习(五)—— lazysysadmin1

环境搭建 下载链接 vmware 打开靶机&#xff0c;nat 网络适配&#xff0c;攻击机同样。 信息收集 一个一个的看过去&#xff0c;这边就不贴图了。 漏洞挖掘 用 kail 的 wpscan 扫一下 wordpress&#xff0c;没发现漏洞。 ┌──(geng㉿geng)-[~] └─$ wpscan --url http…

【Linux06-基础IO】4.5万字的基础IO讲解

前言 本期分享基础IO的知识&#xff0c;主要有&#xff1a; 复习C语言文件操作文件相关的系统调用文件描述符fd理解Linux下一切皆文件缓冲区文件系统软硬链接动静态库的理解和制作动静态编译 博主水平有限&#xff0c;不足之处望请斧正&#xff01; C语言文件操作 #再谈文件…

SQLSERVER2019安装步骤过程

第一步官网下载SQLSERVER软件包 目前官网只能下载最新版本2022版本。 通过迅雷下载网址 SQL Server 2019 Enterprise (x64) - DVD (Chinese-Simplified)企业版 ed2k://|file|cn_sql_server_2019_enterprise_x64_dvd_2bfe815a.iso|1632086016|58C258FF0F1D006DD3C1F5F17AF3E…

ELK_Elasticsearch环境搭建

目录 一、Windows安装elasticsearch 1、安装JDK 2、下载和解压 3、配置文件 4、启动 5、检查ES是否启动成功 6、浏览器访问 二、 Windows安装Kibana 一、Windows安装elasticsearch 1、安装JDK 安装JDK&#xff0c;至少1.8.0_73以上版本&#xff0c;验证&#xff1a;j…

dbForge Source Control for SQL Server 2.5.X Crack

SQL Server功能概述 的 dbForge 源代码管理 dbForge Source Control for SQL Server 是一个可视化的 SSMS 插件&#xff0c;具有简单易用的界面&#xff0c;可帮助您轻松跟踪 SQL Server 数据库对象中的更改内容、更改时间和原因。该工具使您能够将数据库连接到多个版本控制系统…

【Python学习笔记】40.Python3 SMTP发送邮件

前言 SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则&#xff0c;由它来控制信件的中转方式。 Python3 SMTP发送邮件 python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了…

CSS基础选择器,你认识多少?

前言在上一文初识CSS中&#xff0c;我们了解到了其格式&#xff1a;选择器{ }在初步尝试使用时&#xff0c;我们笼统的直接输入了p { }以选择p标签来对其操作&#xff0c;而这一章节里&#xff0c;我们再进一步探索有关基础选择器的相关内容&#xff0c;理解选择器的作用。选择…

2019蓝桥杯真题平方序列(填空题) C语言/C++

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 小明想找到两个正整数 X 和 Y&#xff0c;满足2019<X<Y;2019^2, X^2, Y^2组成等差数列。 请你求出在所有可能的解中&#xff0c;XY 的最小值是多少&#xff1f…

QT(17)- QNetworkAccessManager

QT&#xff08;17&#xff09;- QNetworkAccessManager1 简介2 公有类型3 函数3.1 addStrictTransportSecurityHosts3.2 autoDeleteReplies3.3 cache3.4 clearAccessCache3.5 clearConnectionCache3.6 connectToHost3.7 connectToHostEncrypted3.8 cookieJar3.9 deleteResource…