本文主要是介绍torch学习 (40):图像转换与增广 (Transforming and Augmenting Images),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 引入
- 1 库引入
- 2 测试函数
- 3 测试图像
- 4 转换器
- 4.1 PIL和tensor均可
- 4.1.1 中心裁剪CenterCrop
- 4.1.2 颜色改变ColorJitter
- 4.1.3 五分裁剪FiveCrop
- 4.1.4 灰度转换Grayscale
- 4.1.5 填充Pad
- 4.1.6 中心不变随机仿射变换RandomAffine
- 4.1.7 随机转换RandomApply
- 4.1.8 随机裁剪RandomCrop
- 4.1.9 概率灰度图转换RandomGrayscale
- 4.1.10 概率水平翻转RandomHorizontalFlip
- 4.1.11 概率透视变换RandomPerspective
- 4.1.12 随机裁剪并改变大小RandomResizedCrop
- 4.1.13 随机旋转RandomRotation
- 4.1.14 概率竖直翻转RandomVerticalFlip
- 4.1.15 改变大小Resize
- 4.1.16 四角加中心裁剪加翻转TenCrop
- 4.1.17 高斯滤波GaussianBlur
- 4.1.18 概率反向RandomInvert
- 4.1.19 概率色彩分离RandomPosterize
- 4.1.20 概率阈值反向RandomSolarize
- 4.1.21 概率锐度调整RandomAdjustSharpness
- 4.1.22 概率对比度调整RandomAutocontrast
- 4.1.23 概率直方图均衡RandomEqualize
- 4.2 仅PIL
- 4.2.1 随机选择变换RandomChoice
- 4.2.2 变换乱序RandomOrder
- 4.3 仅tensor
- 4.3.1 PIL和numpy转tensor
- 4.3.2 tensor转PIL
- 4.3.3 线性变换LinearTransformation
- 4.3.4 标准化Normalize
- 4.3.5 概率擦除RandomErasing
- 4.3.6 图像数据类型转换ConvertImageDtype
- 4.4 自定义变换Lambda
- 4.5 变换组合
- 4.6 自动增强变换Automatic Augmentation Transforms
- 4.6.1 自动增强AutoAugment
- 4.6.2 自动搜索空间缩减增强RandAugment
- 4.6.3 无需调整的图像增强TrivialAugmentWide
- 4.7 函数式变换
- 4.7.1 自定义函数
- 4.7.2 自定义类
- 4.7.3 亮度调整adjust_brightness
- 4.7.4 调整对比度adjust_contrast
- 4.7.5 调整gamma
- 4.7.6 调整色调adjust_hue
- 4.7.7 调整饱和度adjust_saturation
- 4.7.8 调整锐度adjust_sharpness
- 4.7.9 仿射变换affine
- 4.7.10 自动对比度autocontrast
- 4.7.11 中心裁剪center_crop
- 4.7.12 转换图像类型convert_image_dtype
- 4.7.13 指定位置裁剪crop
- 4.7.14 直方图均衡equalize
- 4.7.15 指定区域消除erase
- 4.7.16 四角与中心裁剪five_crop
- 4.7.17 高斯滤波gaussian_blur
- 4.7.18 获取图像通道数get_image_num_channels
- 4.7.19 获取图像大小
- 4.7.20 翻转hflip&vflip
- 4.7.21 反向invert
- 4.7.22 标准化normalize
- 4.7.23 填充pad
- 4.7.24 透视变换perspective
- 4.7.25 PIL图像转tensor
- 4.7.26 减少图像通道位数posterize
- 4.7.27 改变图像大小resize
- 4.7.28 裁剪并改变大小
- 4.7.29 RGB转灰度图rgb_to_grayscale
- 4.7.30 旋转rotate
- 4.7.31 反向高于阈值的像素
- 4.7.32 十次裁剪ten_crop
- 4.7.33 PIL转换为灰度图to_grayscale
- 4.7.34 tensor或numpy转PIL:to_pil_image
- 4.7.35 PIL或numpy转tensor:to_tensor
引入
图像增广的前期研究可以参照https://blog.csdn.net/weixin_44575152/article/details/118056405。
本节依据torch官网展示的图像转换与增广进行相应说明,希望自己在测试的同时可以学习一些新知识。
首先对torch的转换器进行以后总体说明:
1) 大多数转换器均可接受PIL或者tensor图像,少部分则只能处理其中的一种。torch则包含用于转换这两种输入的函数。
2) torch转换器既可接收多通道的图像,格式为 (C, H, W),分别对应通道数、图像高、图像宽;亦可接收多批次多通道图像,格式为 (B, C, H, W),B表示批次数;
3) tensor图像的取值范围是明确定义了的:
∙ \bull ∙ float类型,范围为[0, 1)
∙ \bull ∙ integer类型,范围为[0, MAX_TYPE],其中MAX_TYPE为当前转换器的限定参数;
4)尽管随机转换器可以批量处理,但是对应于单张图像,处理结果其实是随机的。
1 库引入
所以的库如下:
import torch
import torchvision
import matplotlib.pyplot as plt
from PIL import Image
2 测试函数
以下是简单的测试函数,使用matplotlib绘图,aug则表示转换器,将结合主函数使用:
def test(img=Image.open("miao.png")):plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img)plt.show()
3 测试图像
4 转换器
4.1 PIL和tensor均可
4.1.1 中心裁剪CenterCrop
函数:CenterCrop(size)
参数:
∙ \bull ∙ size: 从图像中心开始的裁剪大小,如果提供单个整数,则执行正方形裁剪;提供一个二元列表 (元组也行,之后都不做区别),则按指定裁剪:
if __name__ == '__main__':aug = torchvision.transforms.CenterCrop([500, 400])test()
4.1.2 颜色改变ColorJitter
函数:ColorJitter( brightness, contrast, saturation, hue)
功用:随机改变图像的亮度、对比度、饱和度和色调。
参数:依次对应以上被改变值。
if __name__ == '__main__':aug = torchvision.transforms.ColorJitter(0.5, 0.5, 0.5, 0.5)test()
4.1.3 五分裁剪FiveCrop
函数:FiveCrop (size)
功用:裁剪四个角和中心,因此返回值是五个子图,这里我们只展示其中一个。
参数:与中心裁剪一致。
def test(img=Image.open("miao.png")):plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img[0])plt.show()if __name__ == '__main__':aug = torchvision.transforms.FiveCrop(500)test()
4.1.4 灰度转换Grayscale
函数:Grayscale(num_output_channels)
功用:转换图像为灰度图
参数:
∙ \bull ∙ num_out_channels:输出通道,可选1或者3
def test(img=Image.open("miao.png")):plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img)plt.show()if __name__ == '__main__':aug = torchvision.transforms.Grayscale(3)test()
4.1.5 填充Pad
函数:Pad(padding, fill=0, padding_mode=“constant”)
功用:填充图像边缘
参数:
∙ \bull ∙ padding:填充区域,指定单个数字,则填充上下左右该值;指定二值列表,则填充左右/上下;指定四值列表,则依次填充左上右下;
∙ \bull ∙ fill:填充值,可以填充代表RGB的三值列表;
∙ \bull ∙ padding_mode:填充模式
注:参数只说明大致用法,详细的看torch中函数注释就可以了
if __name__ == '__main__':aug = torchvision.transforms.Pad([100, 200, 150, 400])test()
4.1.6 中心不变随机仿射变换RandomAffine
函数:RandomAffine(degrees…)
参数:
∙ \bull ∙ degrees:等级的可供选择范围,设置为0停用旋转;设置单个数则范围为[-degrees, +degrees];设置二值列表则为所指定的范围。
if __name__ == '__main__':aug = torchvision.transforms.RandomAffine(10)test()
4.1.7 随机转换RandomApply
函数:RandomApply(transforms, p=0.5)
功用:指定一组变换器,从而在指定概率下运行。
参数:
∙ \bull ∙ transforms:转换器列表
∙ \bull ∙ p:概率
if __name__ == '__main__':aug = torchvision.transforms.RandomApply([torchvision.transforms.RandomAffine(10), torchvision.transforms.Pad(100)], 0.3)test()
4.1.8 随机裁剪RandomCrop
函数:RandomCrop(size…)
参数:
∙ \bull ∙ size:裁剪图像的大小
if __name__ == '__main__':aug = torchvision.transforms.RandomCrop(500)test()
4.1.9 概率灰度图转换RandomGrayscale
函数:RandomGrayscale§
4.1.10 概率水平翻转RandomHorizontalFlip
函数:RandomHorizontalFlip§
4.1.11 概率透视变换RandomPerspective
函数:RandomPerspective(p…)
4.1.12 随机裁剪并改变大小RandomResizedCrop
函数:RandomResizedCrop(size, scale, ratio…)
参数:
∙ \bull ∙ size:裁剪区域大小
∙ \bull ∙ scale:指定裁剪区域的上下限
∙ \bull ∙ ratio:随机纵横比的下限和上限
if __name__ == '__main__':aug = torchvision.transforms.RandomResizedCrop(500)test()
4.1.13 随机旋转RandomRotation
函数:RandomRotation(degrees…)
参数:
∙ \bull ∙ degrees
if __name__ == '__main__':aug = torchvision.transforms.RandomRotation(10)test()
4.1.14 概率竖直翻转RandomVerticalFlip
函数:RandomVerticalFlip§
4.1.15 改变大小Resize
函数:Resize(size…)
参数:
∙ \bull ∙ 改变后的大小
if __name__ == '__main__':aug = torchvision.transforms.Resize([500, 505])test()
4.1.16 四角加中心裁剪加翻转TenCrop
函数:TenCrop(size)
功能:裁剪图像的四个角加中心,反而这些结果及其翻转版本
4.1.17 高斯滤波GaussianBlur
函数:GaussianBlur(kernel_size)
4.1.18 概率反向RandomInvert
函数:RandomInvert§
功能:给定概率下图像反向
if __name__ == '__main__':aug = torchvision.transforms.RandomInvert(0.9)test()
4.1.19 概率色彩分离RandomPosterize
函数:RandomPosterize(bits, p)
参数:
∙ \bull ∙ bits:每个通道要保留的位数
∙ \bull ∙ p:概率
if __name__ == '__main__':aug = torchvision.transforms.RandomPosterize(2, 0.9)test()
4.1.20 概率阈值反向RandomSolarize
函数:RandomSolarize(threshold, p)
功能:对于大于阈值的像素点,以一定的概率反向
if __name__ == '__main__':aug = torchvision.transforms.RandomSolarize(125, 0.9)test()
4.1.21 概率锐度调整RandomAdjustSharpness
函数:RandomAdjustSharpness(sharpness_factor, p)
4.1.22 概率对比度调整RandomAutocontrast
函数:RandomAutocontrast§
4.1.23 概率直方图均衡RandomEqualize
函数:RandomEqualize§
if __name__ == '__main__':aug = torchvision.transforms.RandomEqualize(0.9)test()
4.2 仅PIL
4.2.1 随机选择变换RandomChoice
函数:RandomChoice(transforms)
功能:从给定变换列表中随机选择一个使用
参数:
∙ \bull ∙ transforms:变换的集合
if __name__ == '__main__':aug = torchvision.transforms.RandomChoice([torchvision.transforms.RandomHorizontalFlip(),torchvision.transforms.RandomVerticalFlip()])test()
4.2.2 变换乱序RandomOrder
函数:RandomOrder(transforms)
功能:对于给定的一组变换,乱序后使用。
4.3 仅tensor
为了方便的使用各种变换,可以灵活地对PIL与tensor进行转换。
4.3.1 PIL和numpy转tensor
PIL转tensor还可以用PILToTensor()
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)# .T.transpose(1, 0)是为了使得显示图像和原来已一样plt.imshow(img.T.transpose(1, 0))plt.show()if __name__ == '__main__':test()
4.3.2 tensor转PIL
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)img = torchvision.transforms.ToPILImage()(img)plt.imshow(img)plt.show()if __name__ == '__main__':test()
4.3.3 线性变换LinearTransformation
函数:LinearTransformation(transformation_matrix, mean_vector)
def test(img=Image.open("miao.png")):# 图像太大了因为img = torchvision.transforms.Resize((40, 60))(img)img = torchvision.transforms.ToTensor()(img)# 计算必备参数import numpy as npD = np.prod(img.shape)transformation_matrix = torch.randn(D, D)mean_vector = torch.randn(D)aug = torchvision.transforms.LinearTransformation(transformation_matrix, mean_vector)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img.T.transpose(1, 0))plt.show()if __name__ == '__main__':test()
4.3.4 标准化Normalize
函数:Normalize(mean, std)
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)aug = torchvision.transforms.Normalize((0.1307,), (0.3081,))plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img.T.transpose(1, 0))plt.show()if __name__ == '__main__':test()
4.3.5 概率擦除RandomErasing
函数:RandomErasing(p…)
功能:以一定概率消除图像中的某一部分,默认黑色填充
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)aug = torchvision.transforms.RandomErasing(p=0.99)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img.T.transpose(1, 0))plt.show()
4.3.6 图像数据类型转换ConvertImageDtype
函数:ConvertImageDtype(dtype)
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)aug = torchvision.transforms.ConvertImageDtype(torch.uint8)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img.T.transpose(1, 0))plt.show()
4.4 自定义变换Lambda
函数:Lambda(…)
4.5 变换组合
transforms = torch.nn.Compose(transforms.CenterCrop(10),transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
)
4.6 自动增强变换Automatic Augmentation Transforms
自动增强图像,以提升分类性能。
4.6.1 自动增强AutoAugment
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)# IMAGENET, CIFAR10 and SVHNaug = torchvision.transforms.AutoAugment(torchvision.transforms.AutoAugmentPolicy.CIFAR10)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img.T.transpose(1, 0))plt.show()
4.6.2 自动搜索空间缩减增强RandAugment
def test(img=Image.open("miao.png")):aug = torchvision.transforms.RandAugment()plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img)plt.show()
4.6.3 无需调整的图像增强TrivialAugmentWide
def test(img=Image.open("miao.png")):aug = torchvision.transforms.TrivialAugmentWide()plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = aug(img)plt.imshow(img)plt.show()
4.7 函数式变换
4.7.1 自定义函数
def my_transforms(img):import torchvision.transforms.functional as TFimg = TF.rotate(img, 45)return imgdef test(img=Image.open("miao.png")):plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = my_transforms(img)plt.imshow(img)plt.show()
4.7.2 自定义类
import torchvision.transforms.functional as TFclass MyTransform:def __init__(self):""""""def __call__(self, x):return TF.rotate(x, 66)def test(img=Image.open("miao.png")):plt.subplot(1, 2, 1)plt.imshow(img)plt.subplot(1, 2, 2)img = MyTransform()(img)plt.imshow(img)plt.show()
4.7.3 亮度调整adjust_brightness
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.adjust_brightness(img, 2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.4 调整对比度adjust_contrast
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.adjust_contrast(img, 2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.5 调整gamma
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.adjust_gamma(img, 2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.6 调整色调adjust_hue
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.adjust_hue(img, 0.2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.7 调整饱和度adjust_saturation
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.adjust_saturation(img, 0.2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.8 调整锐度adjust_sharpness
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.adjust_sharpness(img, 2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.9 仿射变换affine
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.affine(img, 45, [0.2, 1], 6, [6])plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.10 自动对比度autocontrast
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.autocontrast(img)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.11 中心裁剪center_crop
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.center_crop(img, [500, 500])plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.12 转换图像类型convert_image_dtype
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.convert_image_dtype(img, torch.uint8)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.13 指定位置裁剪crop
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.crop(img, 100, 1000, 100, 800)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.14 直方图均衡equalize
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.convert_image_dtype(img, torch.uint8)img = TF.equalize(img)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.15 指定区域消除erase
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.erase(img, 100, 100, 500, 300, torch.tensor([255]))plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.16 四角与中心裁剪five_crop
函数:five_crop
4.7.17 高斯滤波gaussian_blur
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.gaussian_blur(img, [5, 5])plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.18 获取图像通道数get_image_num_channels
函数:get_image_num_channels()
4.7.19 获取图像大小
函数:get_image_size()
4.7.20 翻转hflip&vflip
函数:hflip()&vflip()
4.7.21 反向invert
函数:invert()
4.7.22 标准化normalize
函数:normalize()
4.7.23 填充pad
函数:pad()
4.7.24 透视变换perspective
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.perspective(img, [[100, 100], [100, 500], [500, 100], [500, 500]],[[100, 100], [100, 500], [500, 100], [500, 500]])plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.25 PIL图像转tensor
函数:pil_to_tensor()
4.7.26 减少图像通道位数posterize
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.posterize(TF.convert_image_dtype(img, torch.uint8), 2)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.27 改变图像大小resize
函数:resize()
4.7.28 裁剪并改变大小
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.resized_crop(img, 100, 1000, 100, 500, [200, 200])plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.29 RGB转灰度图rgb_to_grayscale
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.rgb_to_grayscale(img)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.30 旋转rotate
函数:rotate()
4.7.31 反向高于阈值的像素
def test(img=Image.open("miao.png")):img = torchvision.transforms.ToTensor()(img)plt.subplot(1, 2, 1)plt.imshow(img.T.transpose(1, 0))plt.subplot(1, 2, 2)img = TF.solarize(img, 0.5)plt.imshow(img.T.transpose(1, 0))plt.show()
4.7.32 十次裁剪ten_crop
函数:ten_crop()
4.7.33 PIL转换为灰度图to_grayscale
函数:to_grayscale()
4.7.34 tensor或numpy转PIL:to_pil_image
函数:to_pil_image()
4.7.35 PIL或numpy转tensor:to_tensor
函数:to_tensor()
这篇关于torch学习 (40):图像转换与增广 (Transforming and Augmenting Images)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!