数据增广
计算机视觉有七类分类问题:
不同的视角,不同的大小,物体的形变问题,物体的遮挡问题,光照条件,背景复杂的问题,每一类中有多种形态的问题。
而数据增广的思路也就是解决这个问题。数据增广如何增广就要从实际的问题出发,比如医学的图片基本上拍摄的时候视角是固定的,所以就不需要不同视角的增广。木纹检测中视角是不固定的,就需要不同的视角,不同的大小的增广,还需要应不同的光照条件对数据进行增广。
在不改变图像类别的情况下,增加数据量,能提高模型的泛化能力
自然图像的数据增广方式包括很多,如常用的水平翻转(horizontally flipping),一定程度的位移或者裁剪和颜色抖动(color jittering)。此外还可以尝试多种操作的组合, 例如同时做旋转和随机尺度变换,此外还可以把每个patch中所有像素在HSV颜色空间中的饱和度和明度提升0.25-4次幂方,乘以0.7-1.4之间的一个因子,再加一个-0.1-0.1之间的值。同样你可以在色调通道(H)对每张图片或patch的所有像素增加一个-0.1-0.1之间的值。
数据增广很重要,好的数据增广可以提高2-3个百分点,但是要注意方式,比如在我服装检测问题上没有必要对图像上下反转。深度学习框架一般能够提供的图像增广方法很有限,需要使用额外的库进行,推荐imgaug,神器
增广代码_来自博客:
def customizedImgAug(input_img): rarely = lambda aug: iaa.Sometimes(0.1, aug) sometimes = lambda aug: iaa.Sometimes(0.25, aug) often = lambda aug: iaa.Sometimes(0.5, aug) seq = iaa.Sequential([ iaa.Fliplr(0.5), often(iaa.Affine( scale={"x": (0.9, 1.1), "y": (0.9, 1.1)}, translate_percent={"x": (-0.1, 0.1), "y": (-0.12, 0)}, rotate=(-10, 10), shear=(-8, 8), order=[0, 1], cval=(0, 255), )), iaa.SomeOf((0, 4), [ rarely( iaa.Superpixels( p_replace=(0, 0.3), n_segments=(20, 200) ) ), iaa.OneOf([ iaa.GaussianBlur((0, 2.0)), iaa.AverageBlur(k=(2, 4)), iaa.MedianBlur(k=(3, 5)), ]), iaa.Sharpen(alpha=(0, 0.3), lightness=(0.75, 1.5)), iaa.Emboss(alpha=(0, 1.0), strength=(0, 0.5)), rarely(iaa.OneOf([ iaa.EdgeDetect(alpha=(0, 0.3)), iaa.DirectedEdgeDetect( alpha=(0, 0.7), direction=(0.0, 1.0) ), ])), iaa.AdditiveGaussianNoise( loc=0, scale=(0.0, 0.05 * 255), per_channel=0.5 ), iaa.OneOf([ iaa.Dropout((0.0, 0.05), per_channel=0.5), iaa.CoarseDropout( (0.03, 0.05), size_percent=(0.01, 0.05), per_channel=0.2 ), ]), rarely(iaa.Invert(0.05, per_channel=True)), often(iaa.Add((-40, 40), per_channel=0.5)), iaa.Multiply((0.7, 1.3), per_channel=0.5), iaa.ContrastNormalization((0.5, 2.0), per_channel=0.5), iaa.Grayscale(alpha=(0.0, 1.0)), sometimes(iaa.PiecewiseAffine(scale=(0.01, 0.03))), sometimes( iaa.ElasticTransformation(alpha=(0.5, 1.5), sigma=0.25) ), ], random_order=True), iaa.Fliplr(0.5), iaa.AddToHueAndSaturation(value=(-10, 10), per_channel=True) ], random_order=True) # apply augmenters in random order output_img = seq.augment_image(input_img) return output_img
还可做一些其他处理:
2、shuffle,打乱数据进行训练是必须的,防止相邻样本有较强相关性。
3、图像标准化,计算数据集的std与mean,而不是直接使用imagenet的std与mean
4、增大图像的输入尺寸可获得客观的提升,本例最终使用了480*480的输入尺寸
4、选择合适的迁移学习方式,本例进行全局finetune比只训练最后1层或几层好很多
5、可以先用Adam快速收敛,后面阶段用SGD慢慢调
6、模型融合,举办方在复赛限制最多只能用两个模型是明智的,初赛都有队伍用接近10个模型进行融合,如此刷分就没意义了
7、对测试集图片进行增强,比如镜像,旋转,再预测并取平均。可以得到更鲁棒的结果。这里没有用到tencrop,因为样本有些特征在顶部或者底部,tencrop会将特征截走,导致成绩降低。
参考样例:
addpath('test');addpath('train');fid = fopen('C:\Users\Byte\Desktop\data.txt','wt')file_path = 'C:\Users\Byte\Desktop\test_label\'; %图像文件夹路径save_path = 'C:\Users\Byte\Desktop\cc_test\'; %图像文件夹路径% img_path_list = dir(strcat(file_path,'*.jpg')); %获取文件夹中所有jpg格式图像img_path_list = dir(strcat(file_path,'*.png'));img_num = length(img_path_list); %获取总数if img_num > 0 for j = 1 : img_num img_name = img_path_list(j).name; image = imread(strcat(file_path,img_name)); img_name_core = img_name(1:end-4); %除去后缀名 fprintf('%d %d %s\n',i,j,strcat(file_path,img_name)); fprintf('%s\n',strcat(file_path,img_name(1:end-4))); %图像增广
%翻转flipdim img_u = flipdim(image,1); img_r = flipdim(image,2); img_ur = flipdim(img_r,1); imwrite(img_u,strcat(save_path,img_name_core,'_u.png')); imwrite(img_r,strcat(save_path,img_name_core,'_r.png')); imwrite(img_ur,strcat(save_path,img_name_core,'_ur.png')); %亮度调节 %img_bright = imadjust(image,[0,1],[0,1],0.5); img_dark = imadjust(image,[0,1],[0,1],1.5); %imwrite(img_bright,strcat(save_path,img_name_core,'_b.jpg')); imwrite(img_dark,strcat(save_path,img_name_core,'_d.png')); %img_ub = imadjust(img_u,[0,1],[0,1],0.5); img_ud = imadjust(img_u,[0,1],[0,1],1.5); %imwrite(img_ub,strcat(save_path,img_name_core,'_ub.jpg')); imwrite(img_ud,strcat(save_path,img_name_core,'_ud.png')); %img_rb = imadjust(img_r,[0,1],[0,1],0.5); img_rd = imadjust(img_r,[0,1],[0,1],1.5); %imwrite(img_rb,strcat(save_path,img_name_core,'_rb.jpg')); imwrite(img_rd,strcat(save_path,img_name_core,'_rd.png')); %img_urb = imadjust(img_ur,[0,1],[0,1],0.5); img_urd = imadjust(img_ur,[0,1],[0,1],1.5); %imwrite(img_urb,strcat(save_path,img_name_core,'_urb.jpg')); imwrite(img_urd,strcat(save_path,img_name_core,'_urd.png')); %旋转 for k = 1:5 img_u = imrotate(img_u,72,'bilinear','loose'); img_u = imcrop(img_u,[67 67 511 511]); imwrite(img_u,strcat(save_path,img_name_core,'_',num2str(k),'_u.png')); img_ur = imrotate(img_ur,72,'bilinear','loose'); img_ur = imcrop(img_ur,[67 67 511 511]); imwrite(img_ur,strcat(save_path,img_name_core,'_',num2str(k),'_ur.png')); img_r = imrotate(img_r,72,'bilinear','loose'); img_r = imcrop(img_r,[67 67 511 511]); imwrite(img_r,strcat(save_path,img_name_core,'_',num2str(k),'_r.png')); image = imrotate(image,72,'bilinear','loose'); image = imcrop(image,[67 67 511 511]); imwrite(image,strcat(save_path,img_name_core,'_',num2str(k),'.png')); end endend