常用图像增广方法主要有:左右翻转(上下翻转对于许多目标并不常用),随机裁剪,变换颜色(亮度,对比度,饱和度和色调)等等,我们拟用opencv-python实现部分数据增强方法。
结构如下:
class FunctionClass: def __init__(self, parameter): self.parameter=parameter def __call__(self, img):
一. 图片输出案例
先进行展示图片正常显示案例:
import cv2 import numpy as np from matplotlib import pyplot as plt %matplotlib inline #记得修改为自己图片所在路径 filename = '1.jpg' #[Load an image from a file] img = cv2.imread(filename) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.imshow(img)
输出如图:
查看图片的结构形状:
print(img.shape)
输出如下:
(269, 270, 3)
可知:形状为三个参数,分别为图片的长、图片的宽和图片为三通道。
补充说明:三通道为RGB,此外还有四通道RGBA,也就是加上透明色
二. 五个作业实现
五个作业要求:
- 验证增强效果
- 可自选实现其他增强效果
1 图片缩放
注意:图片缩放,不是单指缩小 ,是缩小和放大
通过cv2.resize()
进行功能实现
class Resize: def __init__(self, size): self.size=size def __call__(self, img): # 此处插入代码 return cv2.resize(img,self.size) resize=Resize( (600, 600)) img2=resize(img) plt.imshow(img2)
实现效果如图:
2 图片翻转
通过cv2.flip()
进行功能实现
class Flip: def __init__(self, mode): self.mode=mode def __call__(self, img): # 此处插入代码 return cv2.flip(img, self.mode) flip=Flip(mode=0) img2=flip(img) plt.imshow(img2)
实现效果如图:
3 图片旋转
通过cv2.getRotationMatrix2D()
和cv2.warpAffine()
进行功能实现
cv2.getRotationMatrix2D():
主要用于获得图像绕着 某一点的旋转矩阵
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
Point2f center:表示旋转的中心点
double angle:表示旋转的角度
double scale:图像缩放因子
cv2.warpAffine():意思是仿射变化
cv2.warpAffine()函数主要是利用变换矩阵M对图像进行如旋转、仿射、平移等变换,只需要我们提供一个2*3的变换矩阵M,就可以对图像进行变换。它一般是和cv2.getRotationMatrix2D和cv.GetAffineTransform两个函数在一起使用,这两个函数是用来获取变换矩阵M,这样就不需要我们自己设置M
cv2.warpAffine(src, M, dsize,dst,flags,borderMode,borderValue) → dst
src: 输入源图像
M:变换矩阵,一般反映平移或旋转的关系,为InputArray类型的2×3变换矩阵。
dsize: 输出图像的大小
flags: 插值方法的组合(int 类型)
borderMode:边界像素模式(int 类型)
borderValue:边界填充值; 默认情况下,它为0,也就是边界填充默认是黑色。
上述参数中:
M作为仿射变换矩阵,一般反映平移或旋转的关系,为InputArray类型的2×3的变换矩阵。
flags表示插值方式
默认为 flags=cv2.INTER_LINEAR,表示线性插值,
此外还有:cv2.INTER_NEAREST(最近邻插值)
cv2.INTER_AREA (区域插值)
cv2.INTER_CUBIC(三次样条插值)
cv2.INTER_LANCZOS4(Lanczos插值)
日常进行仿射变换时,在只设置前三个参数的情况下,如 :
cv2.warpAffine(img,M,(rows,cols))
可以实现基本的仿射变换效果,但可以出现“黑边”现象,我们的实现图出现黑色的原因
class Rotate: def __init__(self,degree,size): self.degree=degree self.size=size def __call__(self, img): # 此处插入代码 rows, cols,x = img.shape M = cv2.getRotationMatrix2D(((cols - 1) / 2.0, (rows - 1) / 2.0), self.degree, self.size) return cv2.warpAffine(img, M, (cols, rows)) rotate=Rotate(45, 0.7) img2=rotate(img) plt.imshow(img2)
4 图片亮度调节
通过np.zeros()
和cv2.addWeighted()
进行功能实现
np.zeros()用于生成一个全零的矩阵,需要导入numpy库
通常导入方式为import numpy as np不再细说numpy了,自行百度这个zeros函数很简单
zeros(shape, dtype=float, order=‘C’)
cv2.addWeigthted()可用于粗略的调整图像的亮度/对比度
dst=cv2.addWeigthted(src1,a,src2,b,c)
可以将上式理解为“结果图像=图像1×系数1+图像2×系数2+亮度调节量”
注意:src1和src2尺寸相同,文件类型必须相同,a,b,c之间没有必然关系,不存在a+b+c要等与1,c一定要写,可以写0,即不调节亮度。
c决定了亮度, c越大,各像素整体都变大,亮度提升了
集合题意,本人揣摩给出的0.6是除以100的数值,所以我乘了100
class Brightness: def __init__(self,brightness_factor): self.brightness_factor=brightness_factor def __call__(self, img): # 此处插入代码 rows, cols, x = img.shape a = 1 blank = np.zeros([rows, cols, x], img.dtype) return cv2.addWeighted(img, a, blank, 1-a, self.brightness_factor * 100) brightness=Brightness(0.6) img2=brightness(img) plt.imshow(img2)
5 图片随机擦除一块
这个在Ai studio 中paddleclas案例可以找到,自行细看吧
原理就是划取区域裁减掉
import random import math class RandomErasing(object): def __init__(self, EPSILON=0.5, sl=0.02, sh=0.4, r1=0.3, mean=[0., 0., 0.]): self.EPSILON = EPSILON self.mean = mean self.sl = sl self.sh = sh self.r1 = r1 def __call__(self, img): if random.uniform(0, 1) > self.EPSILON: return img for attempt in range(100): area = img.shape[0] * img.shape[1] target_area = random.uniform(self.sl, self.sh) * area aspect_ratio = random.uniform(self.r1, 1 / self.r1) h = int(round(math.sqrt(target_area * aspect_ratio))) w = int(round(math.sqrt(target_area / aspect_ratio))) # 此处插入代码 if w < img.shape[0] and h < img.shape[1]: x1 = random.randint(0, img.shape[1] - h) y1 = random.randint(0, img.shape[0] - w) if img.shape[2] == 3: img[ x1:x1 + h, y1:y1 + w, 0] = self.mean[0] img[ x1:x1 + h, y1:y1 + w, 1] = self.mean[1] img[ x1:x1 + h, y1:y1 + w, 2] = self.mean[2] else: img[x1:x1 + h, y1:y1 + w,0] = self.mean[0] return img return img erase = RandomErasing() img2=erase(img) plt.imshow(img2)
结果如下:每次运行代码擦除的部位不同,甚至不擦除