有时候,针对某一个应用领域,想要获取大量的图像数据集比较困难,而使用深度学习技术训练一个模型需要一定数量的数据集,对当前有限的数据进行扩充就变得非常必要。
常用的图像增强技术有:
1、颜色增强(color jittering)
利用图像亮度,饱和度,对比度变化来增加数据量
2、尺度增强(random scale)
3、裁剪增强(random crop)
4、主成分分析(PCA Jittering)
按照RGB三个颜色通道计算均值和标准差,然后在整个训练集上计算协方差矩阵,进行特征分解,得到特征向量和特征值。
5、平移变换(shift)
6、水平、垂直翻转(horizontal,vertical flip)
7、旋转,仿射变换(Rotation,Reflection)
8、高斯噪声,模糊处理(Noise)
9、类别不平衡数据增广(Label shuffle)
代码实现(numpy):
#-*- coding:utf-8 -*- ''' 1.flip 2.random crop 3.color jittering 4.shift 5.scale 6.contrast 7.noise 8.rotation,reflection ''' from PIL import Image,ImageEnhance,ImageOps,ImageFile import numpy as np import random import threading,os,time import logging logger=logging.getLogger(__name__) ImageFile.LOAD_TRUNCATED_IMAGES=True class DataAugmentation: def __init__(self): pass @staticmethod def openImage(image): return Image.open(image,mode='r') @staticmethod def randomRotation(image,mode=Image.BICUBIC): '''mode:邻近插值,双线性插值,双三次样条插值(default)''' random_angle=np.random.randint(1,360) return image.rotate(random_angle,mode) @staticmethod def randomcrop(image): image_width=image.size[0] image_height=image.size[1] crop_win_size=np.random.randint(min,max) #min,max为相对值 random_region=(image_width-crop_win_size)>>1,(image_height-crop_win_size)>>1,(image_width+crop_win_size)>>1,(image_height+crop_win_size)>>1) return image.crop(random_region) @staticmethod def randomColor(image): """ 对图像进行颜色抖动 :param image: PIL的图像image :return: 有颜色色差的图像image """ random_factor = np.random.randint(0, 31) / 10. # 随机因子 color_image = ImageEnhance.Color(image).enhance(random_factor) # 调整图像的饱和度 random_factor = np.random.randint(10, 21) / 10. # 随机因子 brightness_image = ImageEnhance.Brightness(color_image).enhance(random_factor) # 调整图像的亮度 random_factor = np.random.randint(10, 21) / 10. # 随机因1子 contrast_image = ImageEnhance.Contrast(brightness_image).enhance(random_factor) # 调整图像对比度 random_factor = np.random.randint(0, 31) / 10. # 随机因子 return ImageEnhance.Sharpness(contrast_image).enhance(random_factor) # 调整图像锐度 @staticmethod def randomGaussian(image, mean=0.2, sigma=0.3): """ 对图像进行高斯噪声处理 :param image: :return: """ def gaussianNoisy(im, mean=0.2, sigma=0.3): """ 对图像做高斯噪音处理 :param im: 单通道图像 :param mean: 偏移量 :param sigma: 标准差 :return: """ for _i in range(len(im)): im[_i] += random.gauss(mean, sigma) return im # 将图像转化成数组 img = np.asarray(image) img.flags.writeable = True # 将数组改为读写模式 width, height = img.shape[:2] img_r = gaussianNoisy(img[:, :, 0].flatten(), mean, sigma) img_g = gaussianNoisy(img[:, :, 1].flatten(), mean, sigma) img_b = gaussianNoisy(img[:, :, 2].flatten(), mean, sigma) img[:, :, 0] = img_r.reshape([width, height]) img[:, :, 1] = img_g.reshape([width, height]) img[:, :, 2] = img_b.reshape([width, height]) return Image.fromarray(np.uint8(img)) @staticmethod def saveImage(image, path): image.save(path) def makeDir(path): try: if not os.path.exists(path): if not os.path.isfile(path): # os.mkdir(path) os.makedirs(path) return 0 else: return 1 except Exception, e: print str(e) return -2 def imageOps(func_name, image, des_path, file_name, times=5): funcMap = {"randomRotation": DataAugmentation.randomRotation, "randomCrop": DataAugmentation.randomCrop, "randomColor": DataAugmentation.randomColor, "randomGaussian": DataAugmentation.randomGaussian } if funcMap.get(func_name) is None: logger.error("%s is not exist", func_name) return -1 for _i in range(0, times, 1): new_image = funcMap[func_name](image) DataAugmentation.saveImage(new_image, os.path.join(des_path, func_name + str(_i) + file_name)) opsList = {"randomRotation", "randomCrop", "randomColor", "randomGaussian"} def threadOPS(path, new_path): """ 多线程处理事务 :param src_path: 资源文件 :param des_path: 目的地文件 :return: """ if os.path.isdir(path): img_names = os.listdir(path) else: img_names = [path] for img_name in img_names: print img_name tmp_img_name = os.path.join(path, img_name) if os.path.isdir(tmp_img_name): if makeDir(os.path.join(new_path, img_name)) != -1: threadOPS(tmp_img_name, os.path.join(new_path, img_name)) else: print 'create new dir failure' return -1 # os.removedirs(tmp_img_name) elif tmp_img_name.split('.')[1] != "DS": # 读取文件并进行操作 image = DataAugmentation.openImage(tmp_img_name) threadImage = [0] * 5 _index = 0 for ops_name in opsList: threadImage[_index] = threading.Thread(target=imageOps, args=(ops_name, image, new_path, img_name,)) threadImage[_index].start() _index += 1 time.sleep(0.2) if __name__ == '__main__': threadOPS("/home/image/train/data_orig", "/home/image/train/data_enhance")
代码实现(tf)
tf.image.random_flip_leftright(image) img_buf=tf.gfile.FastGFile(file,'rb').read() decode=tf.image.decode_jpg(img_buf,channel=3) #flip_up_down(image) #crop #random_hue/contrast/bright/saturation #Save image: scipy.misc.imsave(filename,img) cv2.imwrite(filename) PIL.Image.open(filename) img.save(filename) tf.image.encode_jpg(img) tf.gfile.GFile(file,'wb') as f f.write(img)
参考链接:
1、https://blog.csdn.net/m0_37192554/article/details/94733455