三、计算机视觉_05MTCNN人脸检测

0、人脸识别流程概述

人脸识别流程包括两个主要步骤:

  • Step1:人脸检测,确保我们处理的是正确的人脸区域

  • Step2:身份识别,确定该人脸的身份

0.1 人脸检测

人脸检测是从图像中定位人脸并抠出人脸区域的过程,这是人脸识别的第一步,用于确保后续的身份识别处理的是正确的人脸区域

因为人脸的类别少、形状比较固定、特征同样比较固定、周围环境也一般比较好,所以人脸检测其实是目标检测中最简单的任务

输入输出:

  • 输入:一张图像
  • 输出:所有人脸的坐标框

操作过程:

  • 抠图:用深度学习模型提取人脸图像中的特征,识别出人脸的位置,并将其抠出来
  • MTCNN:一种流行的人脸检测算法,通过三个阶段(P-Net、R-Net、O-Net)逐步精细化人脸检测结果

技术细节:(海选-->淘汰赛-->决赛)

  • P-Net:生成候选的人脸区域
  • R-Net:对P-Net的结果进行筛选和调整
  • O-Net:输出最终的人脸边界框和关键点位置

0.2 身份识别

身份识别是根据人脸图像判断其身份信息的过程,这一步骤通常涉及到人脸特征的提取和比较,所以比人脸检测稍复杂一点

操作过程

  • FaceNet:一种深度学习模型,用于从人脸图像中学习一个欧几里得空间中的嵌入表示,该表示可以用于直接比较人脸图像以确定身份
  • 人脸向量对比:将待识别的人脸图像通过FaceNet模型转换为向量,然后与数据库中存储的人脸向量进行比较,以确定身份

技术细节

  • 特征提取:使用FaceNet等深度学习模型提取人脸特征
  • 向量比较:使用余弦相似度等度量方法比较人脸向量的相似度
  • 阈值判断:设定一个阈值,当相似度超过这个阈值时,认为两个人脸是同一人

1、MTCNN简介

1.1 背景

MTCNN(Multi-task Cascaded Convolutional Networks)最初是在2016年由Kaipeng Zhang、Zhanpeng Zhang、Zhifeng Li 和 Yu Qiao 提出的,他们在论文《Joint Face Detection and Alignment Using Multitask Cascaded Convolutional Networks》中介绍了这一算法,用于解决在无约束环境中人脸检测和对齐的挑战性问题(包括不同姿势、照明和遮挡的影响等问题)

1.2 概述

MTCNN是一种多任务级联卷积神经网络,它将人脸检测和人脸关键点定位结合起来,通过三个阶段的级联网络实现从粗到细的人脸检测过程

MTCNN的主要创新点在于将人脸检测和人脸关键点对齐相结合以提升检测指标,并对在线难样本挖掘(Online Hard Sample Mining,OHSM)算法进行了改进

1.3 网络结构

MTCNN由三个级联的网络组成:P-Net、R-Net、O-Net

(1)P-Net(Proposal Network):这是第一阶段,用于快速生成候选的人脸框(Bounding Boxes),特点:纯卷积网络,无全链接(精髓所在

P-Net接收输入图像,通过卷积层提取特征,然后利用几个简单的卷积层进行人脸分类和边框回归

P-Net会输出大量的候选框,这些候选框可能包含人脸,但也可能包含大量误检

(2)R-Net(Refine Network):这是第二阶段,用于对P-Net输出的候选框进行进一步筛选和调整

R-Net接收P-Net的候选框作为输入,通过更复杂的网络结构,对候选框进行更加细致的分类和边框回归

R-Net会去除大部分误检的候选框,并调整剩余候选框的位置和大小,使其更接近真实的人脸位置

(3)O-Net(Output Network):这是第三阶段,也是最复杂的网络

O-Net接收R-Net输出的候选框,通过更深层次的卷积神经网络处理人脸区域,优化人脸位置和姿态,并进行最终的人脸分类、边框回归以及人脸关键点的定位

O-Net的输出通常还可以用于后续的人脸识别、表情分析等任务

1.4 推理逻辑

MTCNN的推理逻辑如下:

Step1:输入一张图片(不限尺寸):MTCNN接受任意尺寸的输入图片

Step2:构建图像金字塔:为了检测不同尺度的人脸,MTCNN构建了一个图像金字塔,它会生成一系列不同尺寸的图像,以覆盖不同大小的人脸

Step3:遍历金字塔,取出每一个级别的图像:对于图像金字塔中的每个级别的图像,MTCNN执行以下步骤:

  • 把图像输入P-Net,得到P-Net的输出:P-Net是MTCNN的第一个阶段,它快速生成大量候选的人脸框,并给出人脸分类和边界框回归的初步预测

  • 把P-Net的输出,resize 24 × 24,输入R-Net,得到R-Net的输出:P-Net的输出经过筛选和调整大小后,输入到R-Net,这是一个更为精细的网络,用于进一步筛选和调整人脸框的位置和大小

  • 把R-Net的输出,resize 48 × 48,输入O-Net,得到O-Net的输出:R-Net的输出再次经过筛选和调整大小后,输入到O-Net,这是最终阶段的网络,用于精确地确定人脸框的位置和大小,并预测人脸关键点的位置

1.5 特点

  • 高效性:通过级联的网络结构,MTCNN能够在保证检测精度的同时,显著提高检测速度
  • 灵活性:MTCNN可以适应不同尺寸和分辨率的输入图像,具有较强的鲁棒性

2、MTCNN关键技术

MTCNN在人脸检测中使用了图像金字塔、IOU和NMS这几个关键技术,以下是相关介绍:

2.1 图像金字塔

MTCNN利用图像金字塔技术来检测不同尺寸的人脸

由于P-Net的建议框大小是固定的,只能检测12x12像素范围内的人脸,为了能够检测到更大尺寸的人脸,MTCNN回通过不断缩小图片以适应建议框的大小,形成图像金字塔,当下一次图像的最小边长小于12像素时,停止缩放,这样不仅可以在不同尺度的图像上进行人脸检测,还可以提高检测的准确性和鲁棒性

2.2 IOU(交并比)

IOU在MTCNN中用于计算两个边界框之间的重叠程度,MTCNN在O-Net阶段采用了两种方式计算IOU,以提高检测的准确性:

  • 方式一:交集比并集(也就是【交集】除以【并集】)

  • 方式二:交集比最小集(也就是【交集】除以【最小集】)

在处理大框套小框的情况时,第二种方式的IOU计算可以避免误检,因为这种方式更倾向于保留IOU值小的框(即:非重叠的框)

2.3 NMS(非极大值抑制)

NMS在MTCNN中用于去除预测结果中重复的边界框,保留最具代表性的边界框,以提高检测的准确性和效率

在P-Net、R-Net、O-Net的每个阶段后,都会应用NMS来筛选出最终的边界框,其工作原理如下:

  • Step1:根据每个边界框的置信度进行排序

  • Step2:选择置信度最高的边界框,计算它与其他所有边界框的IOU

  • Step3:如果IOU超过预设的阈值,则认为这两个框表示的是同一个目标

  • Step4:在确定两个边界框表示同一个目标后,NMS算法会保留置信度(即检测到目标的概率)较高的那个边界框,并“抑制”或删除置信度较低的那个边界框

  • Step5:重复上述过程,直到所有边界框都被处理,得到最终的边界框

MTCNN论文中提到了RNet和ONet的NMS阈值,默认分别为0.7,这些阈值可以根据实际需要进行调整,从而控制边界框的重叠程度

3、P-Net网络结构分析与实现

P-Net的具体网络结构如下:

  • 输入层:12x12像素的RGB三通道彩色图像

  • 第一层卷积:使用10个3x3的卷积核,步长为1,边缘填充数为0,输出10x10x10的特征图【(12 + 2*0 - 3) / 1 + 1 = 10】

  • 第一层池化:3x3的最大池化,步长为2,边缘填充数为1,输出10x5x5的特征图【(10 + 2*1 - 3) / 2 + 1 = 5】

  • 第二层卷积:使用16个3x3的卷积核,步长为1,边缘填充数为0,输出16x3x3的特征图【(5 + 2*0 - 3) / 1 + 1 = 3】

  • 第三层卷积:使用32个3x3的卷积核,步长为1,边缘填充数为0,输出32x1x1的特征图【(3 + 2*0 - 3) / 1 + 1 = 1】

  • 输出层:

    • face classification(人脸分类,卷积):使用2个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • bounding box regression(边界框回归,卷积):使用4个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • Facial landmark localization(面部标志点坐标):使用10个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

P-Net的网络结构实现:

# 引入pytorch和nn神经网络
import torch
import torch.nn as nnclass PNet(nn.Module):"""自定义一个PNet网络"""def __init__(self, in_channels=3, n_classes=32):super().__init__()self.feature_extractor = nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=10, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=10),nn.PReLU(),nn.MaxPool2d(kernel_size=3,stride=2, padding=1),nn.Conv2d(in_channels=10, out_channels=16, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=16),nn.PReLU(),nn.Conv2d(in_channels=16, out_channels=n_classes, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=n_classes),nn.PReLU())# 人脸概率输出self.cls_out = nn.Conv2d(in_channels=n_classes, out_channels=2, kernel_size=1, stride=1, padding=0)# 人脸框输出self.reg_out = nn.Conv2d(in_channels=n_classes, out_channels=4, kernel_size=1, stride=1, padding=0)# 人脸关键点坐标输出self.local_out = nn.Conv2d(in_channels=n_classes, out_channels=10, kernel_size=1, stride=1, padding=0)def forward(self, x):"""前向传播"""# 1. 先做特征抽取x = self.feature_extractor(x)# 2. 再做分类回归cls_out = self.cls_out(x)reg_out = self.reg_out(x)local_out = self.local_out(x)return cls_out, reg_out, local_out

4、R-Net网络结构分析与实现

R-Net的具体网络结构如下:

  • 输入层:24x24像素的RGB三通道彩色图像

  • 第一层卷积:使用28个3x3的卷积核,步长为1,边缘填充数为0,输出28x22x22的特征图【(24 + 2*0 - 3) / 1 + 1 = 22】

  • 第一层池化:3x3的最大池化,步长为2,边缘填充数为1,输出28x11x11的特征图【(22 + 2*1 - 3) / 2 + 1 = 11】

  • 第二层卷积:使用48个3x3的卷积核,步长为1,边缘填充数为0,输出48x9x9的特征图【(11 + 2*0 - 3) / 1 + 1 = 9】

  • 第二层池化:3x3的最大池化,步长为2,边缘填充数为0,输出48x4x4的特征图【(9 + 2*0 - 3) / 2 + 1 = 4】

  • 第三层卷积:使用64个2x2的卷积核,步长为1,边缘填充数为0,输出64x3x3的特征图【(4 + 2*0 - 2) / 1 + 1 = 3】

  • 展平+全连接:将64x3x3的特征图展平,连接到128维向量

  • 输出层:

    • face classification(人脸分类,卷积):使用2个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • bounding box regression(边界框回归,卷积):使用4个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • Facial landmark localization(面部标志点坐标):使用10个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

R-Net的网络结构实现:

# 引入pytorch和nn神经网络
import torch
import torch.nn as nnclass RNet(nn.Module):"""自定义一个RNet网络"""def __init__(self, in_channels=3, n_classes=128):super().__init__()self.feature_extractor = nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=28, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=28),nn.PReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=False),nn.Conv2d(in_channels=28, out_channels=48, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=48),nn.PReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=False),nn.Conv2d(in_channels=48, out_channels=64, kernel_size=2, stride=1, padding=0),nn.BatchNorm2d(num_features=64),nn.PReLU(),nn.Flatten(),nn.Linear(in_features=3 * 3 * 64, out_features=n_classes))# 人脸概率输出self.cls_out = nn.Conv2d(in_channels=n_classes, out_channels=2, kernel_size=1, stride=1, padding=0)# 人脸框输出self.reg_out = nn.Conv2d(in_channels=n_classes, out_channels=4, kernel_size=1, stride=1, padding=0)# 人脸关键点坐标输出self.local_out = nn.Conv2d(in_channels=n_classes, out_channels=10, kernel_size=1, stride=1, padding=0)def forward(self, x):"""前向传播"""# 1. 先做特征抽取x = self.feature_extractor(x)# 2. 再做分类回归cls_out = self.cls_out(x)reg_out = self.reg_out(x)local_out = self.local_out(x)return cls_out, reg_out, local_out

5、O-Net网络结构分析与实现

O-Net的具体网络结构如下:

  • 输入层:48x48像素的RGB三通道彩色图像

  • 第一层卷积:使用32个3x3的卷积核,步长为1,边缘填充数为0,输出32x46x46的特征图【(48 + 2*0 - 3) / 1 + 1 = 46】

  • 第一层池化:3x3的最大池化,步长为2,边缘填充数为1,输出32x23x23的特征图【(46 + 2*1 - 3) / 2 + 1 = 23】

  • 第二层卷积:使用64个3x3的卷积核,步长为1,边缘填充数为0,输出64x21x21的特征图【(23 + 2*0 - 3) / 1 + 1 =21】

  • 第二层池化:3x3的最大池化,步长为2,边缘填充数为0,输出64x10x10的特征图【(21 + 2*0 - 3) / 2 + 1 = 10】

  • 第三层卷积:使用64个3x3的卷积核,步长为1,边缘填充数为0,输出64x8x8的特征图【(10 + 2*0 - 3) / 1 + 1 =8】

  • 第三层池化:2x2的最大池化,步长为2,边缘填充数为0,输出64x4x4的特征图【(8 + 2*0 - 2) / 2 + 1 = 4】

  • 第四层卷积:使用128个2x2的卷积核,步长为1,边缘填充数为0,输出128x3x3的特征图【(4 + 2*0 - 2) / 1 + 1 = 3】

  • 展平+全连接:将128x3x3的特征图展平,连接到256维向量

  • 输出层:

    • face classification(人脸分类,卷积):使用2个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • bounding box regression(边界框回归,卷积):使用4个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

    • Facial landmark localization(面部标志点坐标):使用10个1x1的卷积核,步长为1,边缘填充数为0,输出2x1x1的特征图【(1 + 2*0 - 1) / 1 + 1 = 3】

O-Net的网络结构实现:

# 引入pytorch和nn神经网络
import torch
import torch.nn as nnclass ONet(nn.Module):"""自定义一个ONet网络"""def __init__(self, in_channels=3, n_classes=256):super().__init__()self.feature_extractor = nn.Sequential(nn.Conv2d(in_channels=in_channels, out_channels=32, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=32),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=False),nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=False),nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, padding=0),nn.BatchNorm2d(num_features=64),nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2, padding=0, ceil_mode=False),nn.Conv2d(in_channels=64, out_channels=128, kernel_size=2, stride=1, padding=0),nn.BatchNorm2d(num_features=128),nn.ReLU(),nn.Flatten(),nn.Linear(in_features=3 * 3 * 128, out_features=n_classes))# 人脸概率输出self.cls_out = nn.Conv2d(in_channels=n_classes, out_channels=2, kernel_size=1, stride=1, padding=0)# 人脸框输出self.reg_out = nn.Conv2d(in_channels=n_classes, out_channels=4, kernel_size=1, stride=1, padding=0)# 人脸关键点坐标输出self.local_out = nn.Conv2d(in_channels=n_classes, out_channels=10, kernel_size=1, stride=1, padding=0)def forward(self, x):"""前向传播"""# 1. 先做特征抽取x = self.feature_extractor(x)# 2. 再做分类回归cls_out = self.cls_out(x)reg_out = self.reg_out(x)local_out = self.local_out(x)return cls_out, reg_out, local_out

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

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

相关文章

「Chromeg谷歌浏览器/Edge浏览器」篡改猴Tempermongkey插件的安装与使用

1. 谷歌浏览器安装及使用流程 1.1 准备篡改猴扩展程序包。 因为谷歌浏览器的扩展商城打不开,所以需要准备一个篡改猴压缩包。 其他浏览器只需打开扩展商城搜索篡改猴即可。 没有压缩包的可以进我主页下载。 也可直接点击下载:Chrome浏览器篡改猴(油猴…

STM32F103C8T6实时时钟RTC

目录 前言 一、RTC基本硬件结构 二、Unix时间戳 2.1 unix时间戳定义 2.2 时间戳与日历日期时间的转换 2.3 指针函数使用注意事项 ​三、RTC和BKP硬件结构 四、驱动代码解析 前言 STM32F103C8T6外部低速时钟LSE(一般为32.768KHz)用的引脚是PC14和PC…

【JavaEE初阶】多线程初阶下部

文章目录 前言一、volatile关键字volatile 能保证内存可见性 二、wait 和 notify2.1 wait()方法2.2 notify()方法2.3 notifyAll()方法2.4 wait 和 sleep 的对比(面试题) 三、多线程案例单例模式 四、总结-保证线程安全的思路五、对比线程和进程总结 前言…

【人工智能】Python在机器学习与人工智能中的应用

Python因其简洁易用、丰富的库支持以及强大的社区,被广泛应用于机器学习与人工智能(AI)领域。本教程通过实用的代码示例和讲解,带你从零开始掌握Python在机器学习与人工智能中的基本用法。 1. 机器学习与AI的Python生态系统 Pyth…

“iOS profile文件与私钥证书文件不匹配”总结打ipa包出现的问题

目录 文件和证书未加载或特殊字符问题 证书过期或Profile文件错误 确认开发者证书和私钥是否匹配 创建证书选择错误问题 申请苹果 AppId时勾选服务不全问题 ​总结 在上线ios平台的时候,在Hbuilder中打包遇见了问题,生成ipa文件时候,一…

element-ui 中el-calendar 日历插件获取显示的第一天和最后一天【原创】

需要获取el-calendar 日历组件上的第1天和最后一天。可以通过document.querySelector()方法进行获取dom元素中的值,这样避免计算问题。 获取的过程中主要有两个难点,第1个是处理上1月和下1月的数据,第2个是跨年的数据。 直接贴代码&#xff…

JavaScript的基础数据类型

一、JavaScript中的数组 定义 数组是一种特殊的对象,用于存储多个值。在JavaScript中,数组可以包含不同的数据类型,如数字、字符串、对象、甚至其他数组。数组的创建有两种常见方式: 字面量表示法:let fruits [apple…

5.5 W5500 TCP服务端与客户端

文章目录 1、TCP介绍2、W5500简介2.1 关键函数socketlistensendgetSn_RX_RSRrecv自动心跳包检测getSn_SR 1、TCP介绍 TCP 服务端: 创建套接字[socket]:服务器首先创建一个套接字,这是网络通信的端点。绑定套接字[bind]:服务器将…

Android 15 版本更新及功能介绍

Android 15版本时间戳 Android 15,代号Vanilla Ice Cream(香草冰淇淋),是当下 Android 移动操作系统的最新主要版本。 开发者预览阶段:2024年2月,谷歌发布了Android 15的第一个开发者预览版本(DP1),这标志着新系统开发的正式启动。随后,在3月和4月,谷歌又相继推出了D…

第02章_MySQL环境搭建(基础)

1. MySQL 的卸载 1.1 步骤1:停止 MySQL 服务 在卸载之前,先停止 MySQL8.0 的服务。按键盘上的 “Ctrl Alt Delete” 组合键,打开“任务管理器”对话 框,可以在“服务”列表找到“MySQL8.0” 的服务,如果现在“正在…

红队笔记--W1R3S、JARBAS、SickOS、Prime打靶练习记录

W1R3S(思路为主) 信息收集 首先使用nmap探测主机,得到192.168.190.147 接下来扫描端口,可以看到ports文件保存了三种格式 其中.nmap和屏幕输出的一样;xml这种的适合机器 nmap -sT --min-rate 10000 -p- 192.168.190.147 -oA nmapscan/ports…

学习笔记|MaxKB对接本地大模型时,选择Ollma还是vLLM?

在使用MaxKB开源知识库问答系统的过程中,除了对接在线大模型,一些用户出于资源配置、长期使用成本、安全性等多方面考虑,还在积极尝试通过Ollama、vLLM等模型推理框架对接本地离线大模型。而在用户实践的过程中,经常会对候选的模型…

计算机网络八股整理(一)

计算机网络八股文整理 一:网络模型 1:网络osi模型和tcp/ip模型分别介绍一下 osi模型是国际标准的网络模型,它由七层组成,从上到下分别是:应用层,表示层,会话层,传输层,…

Spring Boot教程之五:在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序

在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序 IntelliJ IDEA 是一个用 Java 编写的集成开发环境 (IDE)。它用于开发计算机软件。此 IDE 由 Jetbrains 开发,提供 Apache 2 许可社区版和商业版。它是一种智能的上下文感知 IDE,可用于在各种应用程序…

单片机学习笔记 9. 8×8LED点阵屏

更多单片机学习笔记:单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

vue 预览pdf 【@sunsetglow/vue-pdf-viewer】开箱即用,无需开发

sunsetglow/vue-pdf-viewer 开箱即用的pdf插件sunsetglow/vue-pdf-viewer, vue3 版本 无需多余开发,操作简单,支持大文件 pdf 滚动加载,缩放,左侧导航,下载,页码,打印,文本复制&…

Css—实现3D导航栏

一、背景 最近在其他的网页中看到了一个很有趣的3d效果,这个效果就是使用css3中的3D转换实现的,所以今天的内容就是3D的导航栏效果。那么话不多说,直接开始主要内容的讲解。 二、效果展示 三、思路解析 1、首先我们需要将这个导航使用一个大…

重新定义社媒引流:AI社媒引流王如何为品牌赋能?

在社交媒体高度竞争的时代,引流已经不再是单纯追求流量的数字游戏,而是要找到“对的用户”,并与他们建立真实的连接。AI社媒引流王通过技术创新和智能策略,重新定义了社媒引流的方式,帮助品牌在精准触达和高效互动中脱…

Docker1:认识docker、在Linux中安装docker

欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…

Centos 8, add repo

Centos repo前言 Centos 8更换在线阿里云创建一键更换repo 自动化脚本 华为Centos 源 , 阿里云Centos 源 华为epel 源 , 阿里云epel 源vim /centos8_repo.sh #!/bin/bash # -*- coding: utf-8 -*- # Author: make.han