152层的 Resnet的图片输入尺寸为224*224,那对于大多数情况,图片的分辨率都是大于这个数值,那么该如何把图片的尺寸裁剪到这样一个尺寸,又如何进行数据增强呢?
第一,调整尺寸(Rescaling)
先将图片较短的那条边,随机缩放到[256,480]这样一个范围内。注意,此时的图片是等比例缩放的。举个例子,原始图片的尺寸为[1000,800,3],假设图片短边缩放到256,那么此时图片的尺寸即为[320,256,3],即图片的长宽比例是不变的。
第二,裁剪(Cropping)
将图片进行水平翻转,然后从原图片和翻转后的图片中,随机裁剪出224*224的图片。那到底裁几张呢?Resnet没有明说。。。我觉得还是看自己计算机的配置。因为从理论上来说,假设裁剪过后的图片尺寸为[256,256,3],如果按照步长为1,最多可以裁剪出(256-224)*(256-224) = 1024张,再加上水平翻转的图片,还要乘以个2,也就是2048张图片。一张图片扩展了2048倍,肯定是非常夸张了,那所以,我的做法是随机裁剪个10张,就差不多了。
第三,归一化(Normalizing)
具体做法就是对于整个训练集图片,每个通道分别减去训练集该通道平均值。
第四,颜色抖动(color shifting)
这里resnet 引用的是Alexnet 2012年提出的做法,对于每张图片,每个通道的数据先由二维转成一维(例如256*256*3,转成65536*3),再对该图片(65536*3)三个通道求出协方差矩阵(3*3),再求出协方差矩阵的特征向量p和特征值λ,最后按照下图这样一个公式进行转换进行变换, 这里α是一个服从均值为0,方差为0.1的随机变量(简单来说就是一个很小的随机数),[p1,p2,p3]是一个3*3的矩阵,[λ1,λ2,λ3]的转置是一个3*1的矩阵,最后矩阵相乘的结果也是个3*1的矩阵,刚好可以和原图片3个通道相加,这里执行的是python中的广播机制,即图片每个通道65536个像素点都加上同一个数。
这样就完成了颜色的随机抖动,不过我一直想不明白特征值乘以特征向量有着什么样的数学解释,如果您知道,请联系我(QQ380922457,知乎ID:梁航铭)
第五,测试方法
先抽取测试集图像的四个角以及中间的224×224部分,还包括镜像共有10个部分(Patch)结果,再对这10个输入的测试结果做平均作为我们对该测试集图片的最终测试结果。
代码如下
from random import normalvariate
import numpy as np
import os
from PIL import Image
from random import randint
IMAGE_PATH ="/Users/lianghangming/Desktop/"
# 等比例地把图片较短的一边缩放到区间[256,480]
def rescale(image):
w = image.size[0]
h = image.size[1]
sizeMax =480
sizeMin =256
random_size = randint(sizeMin,sizeMax)
if w < h:
return image.resize((random_size,round(h/w * random_size)))
else:
return image.resize((round(w/h * random_size),random_size))
# 随机裁剪图片
def random_crop(image):
w = image.size[0]
h = image.size[1]
size =224
new_left = randint(0,w - size)
new_upper = randint(0,h - size)
return image.crop((new_left,new_upper,size+new_left,size+new_upper))
# 水平翻转图片
def horizontal_flip(image):
returnimage.transpose(Image.FLIP_LEFT_RIGHT)
# 图片均值归一化
def nomalizing(image,mean_value,add_num):
image = np.array(image)
# image = image.astype(float)
for i in range(3):
add_num = add_num.astype(int)
image[:,:,i] = (image[:,:,i] - mean_value[i] + add_num[i])#/std[i]
return image
# 求整个训练集图片的均值
def mean(image_dir):
for file in os.listdir(image_dir):
iffile.endswith("jpg"):
file = os.path.join(image_dir,file)
image = np.array(Image.open(file))
image = np.reshape(image,[-1,3])
try:
image_array = np.concatenate((image_array,image),0)# 第一张图片不存在image_array
except:
image_array = image
mean_value = image_array.mean(0)
# std_value = image_array.std(0)
return mean_value
# 求整个训练集图片的PCA
def pca(image_dir,mean_value):
for file in os.listdir(image_dir):
iffile.endswith("jpg"):
file = os.path.join(image_dir,file)
image = np.array(Image.open(file))
image = np.reshape(image,[-1,3])
image = image.astype(float)
image -= mean_value# 零均值化
# image = image/255.0
try:
image_array = np.concatenate((image_array,image),0)# 第一张图片不存在image_array
except:
image_array = image
# 求协方差矩阵
image_cov = np.cov([image_array[:,0],image_array[:,1],image_array[:,2]])
lambd,p = np.linalg.eig(image_cov)
alpha0 = normalvariate(0,0.1)
alpha1 = normalvariate(0,0.1) alpha2 = normalvariate(0,0.1)
v = np.transpose((alpha0*lambd[0],alpha1*lambd[1],alpha2*lambd[2]))
add_num = np.dot(v,np.transpose(p))
return add_num
如有错误,欢迎指正