目的就是扩充数据集,opencv和torchvision中的transform只是提供一种手段,防止重复造轮子
知道内核后,再去理解图像增强,才能具体情况具体对应
对于简单的图像旋转、拼接等处理可以直接用torchvision.transform
下面介绍的标题上的torchvision功能都是在torchvision.transforms以及torchvision.transforms.functional.下,opencv实现方式会在标题后面
部分opencv的方式需要获取转移矩阵,再通过cv2.warpXXXX等方式转换,下面不再叙述
torchvision
import cv2
import numpy as np
import matplotlib.pyplot as plt
from torchvision import transforms
import torch
#这里特意说一下 PIL读入 和CV 读入不一样
img = cv2.imread('data\monet_800600.jpg')
# cv2载入的是BGR模式 如果plt显示图像要用下面代码转成RGB
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
plt.imshow(img)
原图像
再具体介绍各种操作前,先掌握一下compose标准写法:
#Compose处理 可以把多个transform合并顺序处理
trans = transforms.Compose(
#如果opencv载入图片的话,先要转成tensor
[transforms.ToTensor(),
#中间省略 会按照顺序进行transform处理
transforms.CenterCrop(500),
]
)
如果你想随机选取的话可以用下面这个RandomApply
# 用torch.nn.ModuleList套上你想要的处理,用P指定概率
transforms = transforms.RandomApply(torch.nn.ModuleList([
transforms.某个处理(),
]), p=0.3)
scripted_transforms = torch.jit.script(transforms)
transforms.CenterCrop([400,500]) 就是从中间为基准切割出图片
transforms.RandomCrop([400,800],padding=100)
以随机点为基准切割,可以加padding在外圈补0
transforms.RandomHorizontalFlip(p=0.5)
根据p的概率随机水平翻转
这个参数比较多,首先是截取一个随机图片(占原图比率上下限是scale,比如上面这个是0.08-1倍大小) 然后长宽比是ratio, 最后resize到[400,500]的大小,最后的interpolation表示插值方式(默认BILINEAR双线性插值,其他还有NEAREST最近插值和BICUBIC双三次插值)
这个挺简单的 就是按size剪裁4个角+中心,注意返回的是5个值,相要翻转的话还有个TenCrop
参数其实差不多 主要是degrees指定度数区间,插值interpolation都看上面,expand表示是否扩展边界(如果是True的话边界会扩展),fill就是背景图像填充
opencv中的旋转是cv2.getRotationMatrix2D((cols , rows), 旋转角度=45, 旋转因子=0.6)
仿射变化可以通过一系列上面的操作,如平移、翻转(Flip)、旋转和剪切实现,目的就是让图像可以任意倾斜,并且在倾斜的方向上伸缩变换
具体可以参考仿射变换
参数可以参考上面的,其余的:translate 变换值,比如设定(1, 2) 他在水平方向就是【-长,长】,垂直方向就是【-2高,2高】shear:剪切,可以理解成按着某个模式剪切,输入一个值就是沿着(-v,v)方向,两个值就是(v1,v2)方向,4个值就是再加一个y轴(v3,v4)
这个方式在opencv中是cv2.getAffineTransform(pst1,pst2) 其中pst1,pst2是起始、终止位置的三个点坐标
透视变换是将图片投影到一个新的视平面,也称作投影映射
具体可以参考透视变换
参数除了interpolation和fill上面有介绍外,startpoints和endpoints对应起始,终止位置4个点坐标:
同样还有RandomPerspective(distortion_scale=0.6, p=1.0)指定随机透视变换,这里distortion_scale是指失真率,也就是偏转度
透视变换在opencv中是cv2.getPerspectiveTransform(pts1,pts2) 其中pst1,pst2是起始、终止位置四个点坐标
通过变换锐度调整图像的清晰度,sharpness_factor是锐度系数,如果是2,就是原图像的2倍锐度
可以使用RandomAdjustSharpness(sharpness_factor,p=0.5)随机调整锐度
同上,通过调整contrast_factor,saturation_factor,hue_factor(-0.5到0.5) 调整系数
反转图像颜色,可以设定RandomInvert(p=0.5)来设定随机颜色反转
这个抖动包含亮度,饱和度,对比度和色调
这几个参数确定是取值范围,可以输入一个数,范围就是[1-v,1+v] 或者输入[min,max]直接确定范围
顺带一提这个数是比率 取值范围是[0,1] 比如你输入0.5 就是在原图像的百分之50-150%内随机变换
色调分离是指一幅图像原本是由紧紧相邻的渐变色阶构成,被数种突然的颜色转变所代替。
pytorch中是通过减少每个颜色通道的比特数随机分离图像色阶,bits取值范围,就是1到8个色阶
同理还有RandomPosterize来随机
指定像素阈值后,超过阈值的都会被反转,达到曝光效果
同样的也有随机曝光RandomSolarize(threshold=192.0)
2D卷积我直接把opencv和torch写法放在下面了 自己对照一下
#torch写法:
kernel = np.ones([5,5])*(1/25)
kernel = torch.FloatTensor(kernel2).expand(3,1,5,5)
weight = torch.nn.Parameter(data=kernel2, requires_grad=False)
img=torch.nn.functional.conv2d(img.permute(2,0,1).unsqueeze(0),weight2,groups=3)
#opencv写法:
kernel = np.ones((5,5),np.float32)/25
img = cv2.filter2D(img,-1,kernel)
也叫高斯模糊,一个参数核大小,另一个sigma是标准偏差, 如果输入一个数,就固定,如果像上面一样输入区间,则会落在上述随机区间
在opencv中的实现方式是cv2.GaussianBlur(img, (21, 21), 0) 这里21是核大小(奇数),后面的0是X方向标准差,你还可以指定Y方向的
这两个滤波我暂时没看到官方torchvision中有,就贴一个opencv的方法:
img_mean = cv2.blur(img, (5,5)) ## 均值滤波,和上面卷积一样,5是卷积核大小
img_median = cv2.medianBlur(img, 5) ##中值滤波 5是卷积核大小(奇数)
img_bilater = cv2.bilateralFilter(img,9,75,75) # 双边滤波 9是领域直径,75是空间高斯和灰度相似性的标准差
pad就是打黑边,这个不知道建议重修一下深度学习基础,padding的输入可以是一个值来填充4边,或者是两个值(横竖),或者4个值(单独指定四个边黑框)
pad
谷歌发表的论文,依靠类似于强化学习去生成智能体自动选取适合特定数据集的数据增强策略
AutoAugment
参数中policy目前有三种可用 IMAGENET, CIFAR10 and SVHN(如AutoAugmentPolicy.IMAGENET)
这一部分去噪,模糊等,故分开说一下
腐蚀的作用是清除边界,原理是用卷积核扫图片,用核内最小值替代当前值
膨胀相反,作用是用最大值代替当前值,opencv使用方式:
kernel = np.ones((5, 5), np.uint8) #定义卷积核
erosion = cv2.erode(img, kernel, iterations=1) #腐蚀
dilation = cv2.dilate(img,kernel,iterations=1) #膨胀
顺带一提,开闭运算,形态学梯度,礼帽,黑帽都是介于原图像和腐蚀膨胀的关系,具体关系如下:
开运算: 先腐蚀 后膨胀 cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
闭运算: 先膨胀 后腐蚀 cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
形态学梯度:膨胀和腐蚀差别 .morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
礼帽: 原图像-开运算 cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
黑帽: 闭运算-原图像 cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)