第二十八周学习周报

目录

    • 摘要
    • 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还原的面部细节会因伪影而扭曲。这是因为合成降级和训练数据分布与实际不同造成的。解决方法是从真实数据中学习这些分布,而不是仅仅使用合成数据,这将是未来研究的一个突破口。

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

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

相关文章

MCP(Model Context Protocol)模型上下文协议 进阶篇3 - 传输

MCP 目前定义了两种标准的客户端-服务端通信传输机制&#xff1a; stdio&#xff08;标准输入输出通信&#xff09;HTTP with Server-Sent Events (SSE)&#xff08;HTTP 服务端发送事件&#xff09; 客户端应尽可能支持 stdio。此外&#xff0c;客户端和服务端也可以以插件方…

NVIDIA DLI课程《NVIDIA NIM入门》——学习笔记

先看老师给的资料&#xff1a; NVIDIA NIM是 NVIDIA AI Enterprise 的一部分&#xff0c;是一套易于使用的预构建容器工具&#xff0c;目的是帮助企业客户在云、数据中心和工作站上安全、可靠地部署高性能的 AI 模型推理。这些预构建的容器支持从开源社区模型到 NVIDIA AI 基础…

物联网云平台:构建物联网生态的核心

我们常说的物联网&#xff0c;简称是IoT&#xff0c; 全称 Internet of Things。 用通俗的语言理解物联网&#xff0c;其实就是万事万物的互联网络。物联网概念也已经传播很多年了&#xff0c; 目前正在各行各业发挥力量。 要构建一个物联网生态&#xff0c; 我们首先想到的是智…

VS2022引入sqlite数据库交互

法一&#xff1a;用官网编译好的动态库(推荐) 下载所需文件 sqlite官网地址&#xff1a;https://www.sqlite.org/howtocompile.html 下载以下的2个压缩包 第一个压缩包 sqlite-amalgamation-xxxx.zip&#xff0c;xxxx是版本号,保持一致即可&#xff0c;这里面有sqite3.h 第…

设计模式学习[15]---适配器模式

文章目录 前言1.引例2.适配器模式2.1 对象适配器2.2 类适配器 总结 前言 这个模式其实在日常生活中有点常见&#xff0c;比如我们的手机取消了 3.5 m m 3.5mm 3.5mm的接口&#xff0c;只留下了一个 T y p e − C Type-C Type−C的接口&#xff0c;但是我现在有一个 3.5 m m 3.…

Markdown如何导出Html文件Markdown文件

Markdown如何导出Html文件Markdown文件 前言语法详解小结其他文章快来试试吧☺️ Markdown 导出 HTML &#x1f448;点击这里也可查看 前言 Markdown的源文件以md为后缀。Markdown是HTML语法的简化版本&#xff0c;它本身不带有任何样式信息。我们所看到的Markdown网页(如&…

Python安装(新手详细版)

前言 第一次接触Python&#xff0c;可能是爬虫或者是信息AI开发的小朋友&#xff0c;都说Python 语言简单&#xff0c;那么多学一些总是有好处的&#xff0c;下面从一个完全不懂的Python 的小白来安装Python 等一系列工作的记录&#xff0c;并且遇到的问题也会写出&#xff0c…

JMeter + Grafana +InfluxDB性能监控 (二)

您可以通过JMeter、Grafana 和 InfluxDB来搭建一个炫酷的基于JMeter测试数据的性能测试监控平台。 下面&#xff0c;笔者详细介绍具体的搭建过程。 安装并配置InfluxDB 您可以从清华大学开源软件镜像站等获得InfluxDB的RPM包&#xff0c;这里笔者下载的是influxdb-1.8.0.x86_…

STL常用容器总结

1.Vector容器特性 vector 容器是一个长度动态改变的动态数组&#xff0c;既然也是数组&#xff0c;那么其内存是一段连续的内存&#xff0c;具有数组的随机存取的优点。 / 1.1.vector特性总结: 1.vector 是动态数组&#xff0c;连续内存空间&#xff0c;具有随机存取效率高的…

BBP飞控板中的坐标系变换

一般飞控板中至少存在以下坐标系&#xff1a; 陀螺Gyro坐标系加速度计Acc坐标系磁强计Mag坐标系飞控板坐标系 在BBP飞控板采用的IMU为同时包含了陀螺&#xff08;Gyro&#xff09;及加速度计&#xff08;Acc&#xff09;的6轴传感器&#xff0c;故Gyro及Acc为同一坐标系。同时…

【OAuth2系列】如何使用OAuth 2.0实现安全授权?详解四种授权方式

作者&#xff1a;后端小肥肠 &#x1f347; 我写过的文章中的相关代码放到了gitee&#xff0c;地址&#xff1a;xfc-fdw-cloud: 公共解决方案 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 【OAuth2系列】集成微…

鸿蒙MPChart图表自定义(六)在图表中绘制游标

在鸿蒙开发中&#xff0c;MPChart 是一个非常强大的图表库&#xff0c;它可以帮助我们创建各种精美的图表。今天&#xff0c;我们将继续探索鸿蒙MPChart的自定义功能&#xff0c;重点介绍如何在图表中绘制游标。 OpenHarmony三方库中心仓 一、效果演示 以下是效果演示图&…

《新概念模拟电路》-电流源电路

电流源电路 本系列文章主要学习《新概念模拟电路》中的知识点。在工作过程中&#xff0c;碰到一些问题&#xff0c;于是又翻阅了模电这本书。我翻阅的是ADI出版的&#xff0c;西安交通大学电工中心杨建国老师编写的模电书。 本文主要是基于前文《新概念模拟电路》-三极管的基础…

Java实现下载excel模板,并实现自定义下拉框

GetMapping("excel/download")ApiOperation(value "模板下载")public void getUserRecordTemplate(HttpServletResponse response, HttpServletRequest request) throws IOException {OutputStream outputStream response.getOutputStream();InputStream…

C 实现植物大战僵尸(四)

C 实现植物大战僵尸&#xff08;四&#xff09; 音频稍卡顿问题&#xff0c;用了 SFML 三方库已优化解决 安装 SFML 资源下载 https://www.sfml-dev.org/download/sfml/2.6.2/ C 实现植物大战僵尸&#xff0c;完结撒花&#xff08;还有个音频稍卡顿的性能问题&#xff0c;待…

回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiLSTM-Attention多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 一、方法概述 CNN-BiLSTM-Attention多输入单输出回归预测方法旨在通过融合CNN的局…

Ansible之批量管理服务器

文章目录 背景第一步、安装第二步、配置免密登录2.1 生成密钥2.2 分发公钥2.3 测试无密连接 背景 Ansible是Python强大的服务器批量管理 第一步、安装 首先要拉取epel数据源&#xff0c;执行以下命令 yum -y install epel-release安装完毕如下所示。 使用 yum 命令安装 an…

让css设置的更具有合理性

目录 一、合理性设置宽高 二、避免重叠情况&#xff0c;不要只设置最大宽 三、优先使用弹性布局特性 四、单词、数字换行处理 五、其他编码建议 平常写css时&#xff0c;除了遵循一些 顺序、简化、命名上的规范&#xff0c;让css具有合理性也是重要的一环。 最近的需求场…

【微服务】1、引入;注册中心;OpenFeign

微服务技术学习引入 - 微服务自2016年起搜索指数持续增长&#xff0c;已成为企业开发大型项目的必备技术&#xff0c;中高级java工程师招聘多要求熟悉微服务相关技术。微服务架构介绍 概念&#xff1a;微服务是一种软件架构风格&#xff0c;以专注于单一职责的多个响应项目为基…

设计模式 结构型 组合模式(Composite Pattern)与 常见技术框架应用 解析

组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。通过这种模式&#xff0c;客户端可以一致地处理单个对象和对象组合。 在软件开发中&#xff0c;我们经常会遇到处理对象的层…