第二十八周学习周报

news2025/1/10 3:10:00

目录

    • 摘要
    • Abstract
    • 1 GFPGAN
      • 1.1 总体结构
      • 1.2 实验研究
      • 1.3 代码分析
    • 总结

摘要

本周主要的学习内容是GFPGAN模型。GFPGAN是一种基于生成对抗网络(GAN)的模型,其利用封装在预训练的人脸GAN中的丰富多样的先验进行人脸图像的修复。这种生成面部先验(GFP)通过空间特征变换层被整合到面部恢复过程中,使得GFPGAN能够实现真实性和保真度的良好平衡。 得益于强大的生成面部先验和精致的设计,GFPGAN只需一次前向传递即可共同还原面部细节并增强色彩。GFPGAN 的出现,解决了传统模型因输入质量低而无法提供准确的几何先验信息的问题。本周,作者将从总体结构、实验研究以及代码分析三部分对GFPGAN进行学习。

Abstract

The main content of this week’s study is the GFPGAN model. GFPGAN is a model based on Generative Adversarial Network (GAN)that leverages rich and diverse priors encapsu-lated in a pretrained face GAN for blind face restoration.This Generative Facial Prior (GFP) is incorporated intothe face restoration process via spatial feature transformlayers, which allow our method to achieve a good balanceof realness and fidelity. Thanks to the powerful genera-tive facial prior and delicate designs,GFP-GAN couldjointly restore facial details and enhance colors with just asingle forward pass. The emergence of GFPGAN has solved the problem of traditional models being degraded due to low input quality. This week, the author will study GFPGAN from three parts: overall structure, experimental research, and code analysis.

1 GFPGAN

GFPGAN是一种基于生成对抗网络(GAN)的模型,由腾讯应用研究中心开发的一种面向实际应用的人脸修复算法,利用预训练的人脸生成对抗网络中封装的丰富多样的先验知识进行盲人脸修复。近年来,GFPGAN在图像生成与修复领域备受瞩目。它凭借其强大的生成能力和高度逼真的修复效果,成为了众多研究者、开发者乃至普通用户关注的焦点。本次的学习基于一篇名为Towards Real-World Blind Face Restoration with Generative Facial Prior的论文。
在这里插入图片描述

在论文中作者提出了一种名为GFPGAN的模型,与最先进的面部修复方法在实际的低质量图像上的相比较,其中包括:HiFaceGAN 、DFDNet 、Wan和 PULSE 。以前的方法难以恢复正确的面部细节或保留面部特征,但论文提出的GFPGAN在真实性和保真度之间取得了良好的平衡,伪影要少得多。此外,强大的生成面部先验使其能够联合进行修复和色彩增强。

1.1 总体结构

GFPGAN作为GAN的一种变体模型,其结构主要也是生成器和判别器两部分。生成器负责将低分辨率图像转换为高分辨率图像,而判别器则用于判断生成的图像是否真实。生成器采用了残差块(Residual Block)作为基础模块,通过堆叠多个残差块来实现深度网络的构建。此外,为了进一步提高模型的性能,GFPGAN还引入了注意力机制,如通道注意力(Channel Attention)和空间注意力(Spatial Attention)。
在这里插入图片描述
生成器
生成器的结构如下图所示,其由包括一个降解去除模块(U-Net)和一个预先训练的面部GAN作为面部先验两部分组成。两部分由Flatent和Fspatial连接,MLP实际上就是由多个linear层所组成,而Fspatial则是包含U-Net中decoder部分的多个尺度的特征图。它们之间通过潜在的代码映射和若干通道分割空间特征变换进行连接(CS-SFT)层。
在这里插入图片描述
降级去除模块旨在显式地去除降级,并提取Flatent和Fspatial的“干净”特征,从而减轻后续模块的负担。而使用U-Net作为退化移除网络主要是为了增加大模糊消除的感受野以及生成多分辨率特征。
模型中会在U-Net的每个decoder层计算一个Restoration Loss,以此得到Flatent和Fspatial中的“干净”特征。Restoration Loss的定义如下所示:
在这里插入图片描述
在生成器中,输入图片首先经U-Net层得到瓶颈处的Flatent,Flatent在经MLP处理后得到中间潜在编码W,及16个512的latent code,w再经styleGAN处理得到FGAN,即中间卷积的特征。styleGAN每层生成的特征图(FGAN)的后半部分进行一个空间上的仿射变换,即平移和缩放操作。该操作是通过两个卷积层得到的。

在这里插入图片描述
由于每一层的FGAN和Fspatial的大小和维度是相对应的,所以他们可以直接进行相乘或者相加的操作,

判别器
判别器结构如下图所示,它会对人脸的整体、局部(眼睛和嘴巴)以及身份保留信息三部分进行判别然后得到三个LOSS。
在这里插入图片描述
(1) Adversarial Loss:
在这里插入图片描述
(2) Facial Component Loss:
在这里插入图片描述
(3) Identity Preserving Loss:
在这里插入图片描述

1.2 实验研究

1.数据集
训练数据集:作者在FFHQ数据集上训练GFP-GAN,该数据集由70,000张高质量图像组成。在训练期间,作者将所有图像的大小调整为 512。 GFP-GAN 是在合成数据上训练的,这些合成数据近似于真实的低质量图像,并在推理过程中泛化到真实的图像。
测试数据集:
(1) CelebA-Test:CelebA-Test 是一个合成数据集,其中包含来自其测试分区的 3,000 张 CelebA-HQ 图像。生成方式与训练期间的生成方式相同。
(2)LFW: LFW 包含低质量野外图像。作者将验证分区中每个标识的所有第一个映像分组,形成 1711 个测试映像。
(3)CelebChild-Test:CelebChild-Test包含从互联网上收集的180张名人的童脸。它们质量低下,其中许多是黑白老照片。
(4)WebPhoto:这是作者在现实生活的互联网中抓取了 188 张低质量照片,提取 407 张人脸来构建 WebPhoto 测试数据集。这些照片具有多种多样且复杂的退化。 其中一些是老照片,在细节和颜色上都有非常严重的退化。
2. 实验评估
(1)广泛使用的非参考感知指标:FID 和NIQE。
(2)采用像素度量(PSNR和SSIM)和感知度量(LPIPS )进行CelebA-Test withGround-Truth (GT)。
(3)在ArcFace特征嵌入中用天使测量身份距离,其中较小的值表示与GT的同一性更近。

3.实验流程:
(1)作者采用预训练的StyleGAN2和512个输出作为生成面部的先验。StyleGAN2的通道倍增器设置为一,以缩小模型大小。用于降解去除的UNet由7个下采样和7个上采样组成,每个采样都有一个残差块。对于每个cS-SFT层,作者使用两个卷积层分别生成α和β的仿射参数。
(2)训练小批量大小设置为12。通过水平翻转和颜色抖动来增强训练数据。作者考虑三个组成部分:左眼、右眼、嘴巴对面部成分的损失,因为它们在感知上很重要。每个组件都按ROI裁剪对齐与面部对齐。
(3)使用Adam 优化器训练模型,总共进行了800k次迭代。学习率设置为2 ×10,然后在第
700k、750k次迭代中衰减了2倍。作者使用PyTorch框架实现模型,并使用四个NVIDIA Tesla P40 GPU对其进行训练。
(4)实验结果
论文中通过与其他先进的人类修复方法比较呈现GFP-GAN的实验成果。其中包括: HiFaceGAN、DFDNet、PSFRGAN、Super-FAN和Wan。用于面部恢复的GAN反转方法:PULSE 和mGANprior也用于比较。除此还将GFP-GAN与图像恢复方法进行了比较:RCAN、ESRGAN和DeblurGANv2,并在面部训练集上对它们进行了微调,以便进行公平的比较。
合成CelebA测试
测试是在两种设置下进行的:

  1. 盲人脸恢复,其输入和输出具有相同的分辨率,定量结果如下图所示。
    在这里插入图片描述

  2. 4倍人脸超分辨率。请注意,我们的方法可以接受上采样的图像作为人脸超分辨率的输入,定量结果如下图所示。
    在这里插入图片描述

在这两种设置下,GFP-GAN都实现了最低的LPIPS,这表明GFPGAN的结果在感知上接近真实值。GFP-GAN还获得了最低的FID和NIQE,表明输出分别与真实人脸分布和自然图像分布具有近距离。除了感知性能外,GFP-GAN还保留了更好的身份,由面部特征嵌入的最小程度表示。
但需注意以下两点:
1)GFP-GAN的FID和NIQE低于GT并不意味着其性能优于GT,因为这些“感知”指标在粗尺度上与人类意见分数密切相关,但在更精细的尺度上并不总是密切相关;
2)像素指标PSNR和SSIM与人类观察者的主观评价[2,41]相关性不佳,GFP-GAN在这两个指标上并不擅长。
在这里插入图片描述
在这里插入图片描述

结果如上图所示,主要的发现有以下几点:
1)得益于强大的生成式面部先验,GFPGAN可以恢复眼睛(瞳孔和睫毛)、牙齿等的忠实细节。
2)GFPGAN在修复中将面部视为整体,也可以生成逼真的头发,而以前依赖组件字典(DFDNet)或解析映射(PSFRGAN)的方法无法产生忠实的头发纹理。
3)GFP-GAN能够保持保真度,例如,它产生自然的闭口没有像PSFRGAN那样强制添加齿。除此,GFP-GAN还可以恢复合理的眼睛注视方向。
LFW、CelebChild和WedPhoto测试
为了测试模型的泛化能力,作者在三个不同的真实数据集上评估了GFP-GAN。定量结果如下图所示。
在这里插入图片描述
GFP-GAN在这三个数据集上都取得了优越的性能,显示出其显著的泛化能力。尽管PULSE也能获得较高的感知质量(较低的FID分数),但它无法保留面部身份。如下图所示,GFP-GAN能够联合进行人脸恢复和色彩增强,利用强大的生成先验来处理真实生活中的照片。作者的方法能够在复杂的现实世界退化条件下生成合理且逼真的面部,而其他方法则无法恢复忠实的面部细节或会产生伪影(特别是在图5中的WebPhoto-Test)。
在这里插入图片描述
除了眼睛和牙齿等常见面部组件外,GFP-GAN在头发和耳朵方面也表现得更好,因为GFP先验考虑的是整个面部,而不是单独的部分。通过SC-SFT层,GFP-GAN能够实现高保真度。大多数先前的方法无法恢复闭着的眼睛,而GFP-GAN能够成功地恢复它们,并且产生的伪影更少。

1.3 代码分析

GFPGAN的项目代码是开源的,代码地址为:https://github.com/TencentARC/GFPGAN
接下来我将以我自身学习的实际情况对项目的一部分代码进行简单分析。
(1)Input处理
Dataset的代码如下:

def __getitem__(self, index):
	......
	#直接看return内容
	if self.crop_components:
            return_dict = {
                'lq': img_lq,
                'gt': img_gt,
                'gt_path': gt_path,
                'loc_left_eye': loc_left_eye,
                'loc_right_eye': loc_right_eye,
                'loc_mouth': loc_mouth
            }
            return return_dict
        else:
            return {'lq': img_lq, 'gt': img_gt, 'gt_path': gt_path}

这里返回的主要有三项:img_lq,img_gt, gt_path,分别是LR输入、真值,和gt的路径。loc_left_eye、loc_right_eye、loc_mouth是使用眼睛和嘴巴位置信息时,作为可选输出。
其中img_lq是由img_gt变换得到的LR图像,img_gt是高分辨图像
再来看一下img_lq的生成过程

def __getitem__(self, index):
	...#数据读入部分
	        # ------------------------ generate lq image ------------------------ #
        # blur
        kernel = degradations.random_mixed_kernels(...)
        img_lq = cv2.filter2D(img_gt, -1, kernel)
        # downsample
        scale = np.random.uniform(self.downsample_range[0], self.downsample_range[1])
        img_lq = cv2.resize(img_lq, (int(w // scale), int(h // scale)), interpolation=cv2.INTER_LINEAR)
        # noise
        if self.noise_range is not None:
            img_lq = degradations.random_add_gaussian_noise(img_lq, self.noise_range)
        # jpeg compression
        if self.jpeg_range is not None:
            img_lq = degradations.random_add_jpg_compression(img_lq, self.jpeg_range)

        # resize to original size
        img_lq = cv2.resize(img_lq, (w, h), interpolation=cv2.INTER_LINEAR)

        # random color jitter (only for lq)
        if self.color_jitter_prob is not None and (np.random.uniform() < self.color_jitter_prob):
            img_lq = self.color_jitter(img_lq, self.color_jitter_shift)
        # random to gray (only for lq)
        if self.gray_prob and np.random.uniform() < self.gray_prob:
            img_lq = cv2.cvtColor(img_lq, cv2.COLOR_BGR2GRAY)
            img_lq = np.tile(img_lq[:, :, None], [1, 1, 3])
            if self.opt.get('gt_gray'):  # whether convert GT to gray images
                img_gt = cv2.cvtColor(img_gt, cv2.COLOR_BGR2GRAY)
                img_gt = np.tile(img_gt[:, :, None], [1, 1, 3])  # repeat the color channels

        # BGR to RGB, HWC to CHW, numpy to tensor
        img_gt, img_lq = img2tensor([img_gt, img_lq], bgr2rgb=True, float32=True)

        # random color jitter (pytorch version) (only for lq)
        if self.color_jitter_pt_prob is not None and (np.random.uniform() < self.color_jitter_pt_prob):
            brightness = self.opt.get('brightness', (0.5, 1.5))
            contrast = self.opt.get('contrast', (0.5, 1.5))
            saturation = self.opt.get('saturation', (0, 1.5))
            hue = self.opt.get('hue', (-0.1, 0.1))
            img_lq = self.color_jitter_pt(img_lq, brightness, contrast, saturation, hue)
       ...#像素值范围映射unit8,正则化
       ...#return

主要就是模糊、加噪、随机像素值抖动、随机灰度化、随机色彩变化等过程生成LR图像

(2)GFPGANv1
这块算是整个结构中内容最多的一部分了,该部分是对输入图像的通道进行降维,产生latent code,通过MLP送到生成器中。首先经过一个3通道到512通道的变换,然后再做通道和空间都进行下采样的6个相同操作,这部分是BasicSR里面的ResBlock函数完成的,可以自行查一下相关实现,最终输出latent code和需要进行空间特征约束的condition。

其中一部分作用是将img_lr 变成 latent code

  	def __init__(self, ...)
		first_out_size = 2**(int(math.log(out_size, 2)))
		#ConvLayer
        self.conv_body_first = ConvLayer(3, channels[f'{first_out_size}'], 1, bias=True, activate=True)
        # downsample
        in_channels = channels[f'{first_out_size}']
        self.conv_body_down = nn.ModuleList()
        for i in range(self.log_size, 2, -1):
            out_channels = channels[f'{2**(i - 1)}']
            self.conv_body_down.append(ResBlock(in_channels, out_channels, resample_kernel))
            in_channels = out_channels
        	self.final_linear = EqualLinear(channels['4'] * 4 * 4, linear_out_channel, bias=True, bias_init_val=0, lr_mul=1, activation=None)
        ...
   	def forward(self, ...)
   		# encoder
        feat = self.conv_body_first(x)
        for i in range(self.log_size - 2):
            feat = self.conv_body_down[i](feat)
            unet_skips.insert(0, feat)

        feat = self.final_conv(feat)
        style_code = self.final_linear(feat.view(feat.size(0), -1))
        ...	

另外一部分产生Fspatial再通过卷积操作得到两个系数作为condition约束,送到下面的代码中处理

	def __init__():
		 # for SFT modulations (scale and shift)
        self.condition_scale = nn.ModuleList()
        self.condition_shift = nn.ModuleList()
        for i in range(3, self.log_size + 1):
            out_channels = channels[f'{2**i}']
            if sft_half:
                sft_out_channels = out_channels
            else:
                sft_out_channels = out_channels * 2
            self.condition_scale.append(
                nn.Sequential(
                    EqualConv2d(out_channels, out_channels, 3, stride=1, padding=1, bias=True, bias_init_val=0),
                    ScaledLeakyReLU(0.2),
                    EqualConv2d(out_channels, sft_out_channels, 3, stride=1, padding=1, bias=True, bias_init_val=1)))
            self.condition_shift.append(
                nn.Sequential(
                    EqualConv2d(out_channels, out_channels, 3, stride=1, padding=1, bias=True, bias_init_val=0),
                    ScaledLeakyReLU(0.2),
                    EqualConv2d(out_channels, sft_out_channels, 3, stride=1, padding=1, bias=True, bias_init_val=0)))

然后将上面的两部分送到StyleGAN2Generator中处理,在逐层进行卷积运算时,将前面产生的conditions约束也加入运算。

总结

在实际应用中,GFPGAN模型已经成为人脸修复和增强的重要工具之一,为增强现实、AI主播制作等领域带来了更加自然、逼真和智能的交互体验。随着技术的不断发展和完善,GFPGAN模型将会在未来发挥更加重要的作用。通过本周的学习,我对wav2lip有了初步的认识和了解,尽管GFPGAN相较于过去的技术有显著提升,但其也是存在不足。作者提出,当真实图像退化严重时,GFPGAN还原的面部细节会因伪影而扭曲。这是因为合成降级和训练数据分布与实际不同造成的。解决方法是从真实数据中学习这些分布,而不是仅仅使用合成数据,这将是未来研究的一个突破口。

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

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

相关文章

成为LabVIEW自由开发者

成为LabVIEW自由开发者的体验可以非常丰富且具有挑战性&#xff0c;同时也充满了自我成长和多样化项目的机会。 ​ 1. 高度的灵活性与自由度 工作时间与地点&#xff1a;作为自由开发者&#xff0c;你可以自由选择工作时间和地点。你可以在家工作&#xff0c;也可以选择在咖啡…

Electron快速入门——跨平台桌面端应用开发框架

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

SpringBoot之核心配置

学习目标&#xff1a; 1.熟悉Spring Boot全局配置文件的使用 2.掌握Spring Boot配置文件属性值注入 3.熟悉Spring Boot自定义配置 4.掌握Profile多环境配置 5.了解随机值设置以及参数间引用 1.全局配置文件 Spring Boot使用 application.properties 或者application.yaml 的文…

openai swarm agent框架源码详解及应用案例实战

文章目录 简介数据类型Agent类Response类Result类Swarm类run_demo_loop交互式会话 基础应用agent-handsofffunction-callingcontext_variablestriage_agent 高阶应用通用客服机器人(support bot)构建航班服务agent 参考资料 openai 在24年10月份开源了一个教育性质的多agents协…

JVM vs JDK vs JRE

JVM是Java虚拟机的缩写&#xff0c; 用于实现Java的一次编译&#xff0c;处处运行。 Java代码写成.class后&#xff0c;由本地的虚拟机运行。 JDK&#xff08;Java Development Kit&#xff09;是一个功能齐全的 Java 开发工具包&#xff0c;供开发者使用。 JDK包含了JRE。…

【网页自动化】篡改猴入门教程

安装篡改猴 打开浏览器扩展商店&#xff08;Edge、Chrome、Firefox 等&#xff09;。搜索 Tampermonkey 并安装。 如图安装后&#xff0c;浏览器右上角会显示一个带有猴子图标的按钮。 创建用户脚本 已进入篡改猴管理面板点击创建 脚本注释说明 name&#xff1a;脚本名称。…

微信小程序用的SSL证书有什么要求吗?

微信小程序主要建立在手机端使用&#xff0c;然而手机又涉及到各种系统及版本&#xff0c;所以对SSL证书也有要求&#xff0c;如果要小程序可以安全有效的访问需要满足以下要求&#xff1a; 1、原厂SSL证书&#xff08;原厂封&#xff09;。 2、DV单域名或者DV通配符。 3、兼…

【电子通识】PWM驱动让有刷直流电机恒流工作

电机的典型驱动方法包括电压驱动、电流驱动以及PWM驱动。本文将介绍采用PWM驱动方式的恒流工作。 首先介绍的是什么是PWM驱动的电机恒流工作&#xff0c;其次是PWM驱动电机恒流工作时电路的工作原理。 PWM驱动 当以恒定的电流驱动电机时&#xff0c;电机会怎样工作呢&#xff1…

Unity学习之UGUI进阶

一、事件监听接口 1、作用 用于实现类型长按、双击、拖拽等基础控件无法实现的功能 所有控件都能够添加更多的事件监听来处理对应的逻辑 2、事件监听接口类型 &#xff08;1&#xff09;常用事件接口 &#xff08;2&#xff09;不常用事件接口 3、使用事件监听接口 &#…

电脑硬盘系统迁移及问题处理

一、系统迁移准备 1、确认你的电脑主板是否支持安装两块硬盘,如电脑主板有多个M2硬盘接口,我们将新硬盘安装到主板上,原来的老硬盘安装在第二个接口上,主板只有一个M2接口的话可以使用移动硬盘盒。 2、新硬盘安装好后,我们进入原来的系统,在 此电脑–右键–管理–磁盘管…

【NLP高频面题 - Transformer篇】Transformer的输入中为什么要添加位置编码?

Transformer的输入中为什么要添加位置编码&#xff1f; 重要性&#xff1a;★★★ Transformer 将句子中的所有词并行地输入到神经网络中。并行输入有助于缩短训练时间&#xff0c;同时有利于学习长期依赖。不过&#xff0c;并行地将词送入 Transformer&#xff0c;却不保留词…

http range 下载大文件分片

摘自&#xff1a;https://www.jianshu.com/p/32c16103715a 上传分片下载也能分 HTTP 协议范围请求允许服务器只发送 HTTP 消息的一部分到客户端。范围请求在传送大的媒体文件&#xff0c;或者与文件下载的断点续传功能搭配使用时非常有用。 检测服务器端是否支持范围请求 假…

Improving Language Understanding by Generative Pre-Training GPT-1详细讲解

Improving Language Understanding by Generative Pre-Training 2018.06 GPT-1 0.有监督、半监督、无监督 CV&#xff1a;ImageNet pre-trained model NLP&#xff1a;pre-trained model? 在计算机视觉中任务包含分类、检测、分割&#xff0c;任务类别数少&#xff0c;对应…

onLoad 生命周期函数是否执行取决于跳转的方式和小程序的页面栈管理机制

文章目录 1. 页面跳转方式2. 你的场景分析3. 页面生命周期4. 总结5. 建议 在微信小程序中&#xff0c;页面跳转时&#xff0c; onLoad 生命周期函数是否执行取决于跳转的方式和小程序的页面栈管理机制。以下是详细说明&#xff1a; 1. 页面跳转方式 微信小程序提供了多种页面…

后台管理系统引导功能的实现

引导是软件中经常见到的一个功能&#xff0c;无论是在后台项目还是前台或者是移动端项目中。 那么对于引导页而言&#xff0c;它是如何实现的呢&#xff1f;通常情况下引导页是通过 聚焦 的方式&#xff0c;高亮一块视图&#xff0c;然后通过文字解释的形式来告知用户该功能的作…

vue js实现时钟以及刻度效果

2025.01.08今天我学习如何用js实现时钟样式&#xff0c;效果如下&#xff1a; 一、html代码如下&#xff1a; <template><!--圆圈--><div class"notice_border"><div class"notice_position notice_name_class" v-for"item in …

CSS Grid 布局全攻略:从基础到进阶

文章目录 一.Grid 是什么二.示例代码1. 基础使用 - 固定宽高2.百分百宽高3.重复设置-repeat4.单位-fr5.自适应6.间距定义其他 一.Grid 是什么 CSS 中 Grid 是一种强大的布局方式&#xff0c;它可以同时处理行和列 Grid 和Flex有一些类似&#xff0c;都是由父元素包裹子元素使用…

【adb】5分钟入门adb操作安卓设备

ADB&#xff08;Android Debug Bridge&#xff09; 是一个多功能的命令行工具&#xff0c;用于与 Android 设备进行交互、调试和管理。它提供了对设备的直接控制&#xff0c;能够帮助开发者进行调试、安装应用、传输文件等。 目录 将设备和电脑连接 adb shell 文件的基本操…

Jenkins-持续集成、交付、构建、部署、测试

Jenkins-持续集成、交付、构建、部署、测试 一: Jenkins 介绍1> Jenkins 概念2> Jenkins 目的3> Jenkins 特性4> Jenkins 作用 二&#xff1a;Jenkins 版本三&#xff1a;DevOps流程简述1> 持续集成&#xff08;Continuous Integration&#xff0c;CI&#xff0…

Golang笔记:使用net包进行TCP监听回环测试

文章目录 前言TCP监听回环代码演示 附&#xff1a;UDP监听回环 前言 TCP是比较基础常用的网络通讯方式&#xff0c;这篇文章将使用Go语言实现TCP监听回环测试。 本文中使用 Packet Sender 工具进行测试&#xff0c;其官网地址如下&#xff1a; https://packetsender.com/ TC…