一、数据来源:
从http://btsd.ethz.ch/shareddata/网站下载比利时交通图标。
( T e s t i n g Testing Testing 文件夹用于做训练集, T r a i n i n g Training Training文件夹用于检测):
二、数据前期处理
将 T e s t i n g Testing Testing文件夹中的 . p p m .ppm .ppm图片转化为 . j p g .jpg .jpg图片:
思路:遍历 T e s t i n g Testing Testing文件夹中各个子文件夹(每个子文件夹中是一种路标的不同图片)。利用PIL库中的函数打开个图片,将图片转化为模型所用的227×227格式后,转c成.jpg格式并存到另一文件夹中。在转存时利用os.path.exists函数来判断路径是否存在,返回的是False,再利用os.makedirs(path)函数来创建路径。
def change(path):
#将《切割好的图片》文件夹中的图片转化为AlexNet模型要求的图片大小
for root,stdirs,filenames in os.walk(path):
#遍历path路径对应的文件夹
for stdir in stdirs:
#遍历文件夹中的子文件夹
i = 0
dir1 = os.path.join(root,stdir)
#获取子文件夹的路径
#print('dir1:', dir1)
#print('filenames:',filenames)
for filename in os.listdir(dir1):
#os.listdir:返回子文件夹中的图片目录
try:
i+=1
dir2=os.path.join(dir1,filename)
#获取图片路径
# print('dir2:', dir2)
#print('*********')
img=Image.open(dir2)
#利用PIL库打开图片
x_s = 227
y_s = 227
out = img.resize((x_s, y_s), Image.ANTIALIAS)
#改变图片的大小;img.resize(1)
dir3_1=dir2.split('\\')[-2]
#将得到的图片地址分割,获取图片的文件夹名
#print('dir3_1',dir3_1)
dir3_2=r"C:\\Users\\abc\\Desktop\\test1\\"
os.path.join(dir3_2,dir3_1)
dir3_3 =dir3_2+dir3_1
folder = os.path.exists(dir3_3)
#os.path.exists:判断"dir3_3"的路径是否存在;若存在则返回True.
if not folder:
os.makedirs(dir3_3)
#递归的创建"dir3_3"对应的多级目录。即:若test1,dir3_1均不存在的话会自动创建
dir3=os.path.join(dir3_3,str(i)+'.jpg')
#dir3 = os.path.join(dir3_2, str(i) + '.jpg')
#print('dir3',dir3)
out.save(dir3)
#将图片按“dir3”的路径存储
except:
print(dir2)
print('------')
#使用try....except格式:当遇到.csv文件时跳过
cv2.waitKey(0)
用到的函数:
(1)img.resize((width,height),Image.ANTIALIAS)
img.resize((width,height),X)
第二个参数X可以是:
Image.NEAREST :低质量
Image.BILINEAR:双线性
Image.BICUBIC :三次样条插值
Image.ANTIALIAS:高质量
(2)os.makedirs(C:\\path1\\path2\\path3)与os.makedir(C:\\path1\\path2\\path3)的区别
os.makedirs(C:\\path1\\path2\\path3):
创建多层目录。即:若path1,path2,path3均不存在,则依次创建path1,path2,path3目录
os.makedir(C:\\path1\\path2\\path3):
仅创建路径中的最后一级目录,即:仅创建path3目录
三、数据集的获取,设置图片标签
'''
输入图片文件夹的路径
输出图片的路径列表和对应的标签列表
'''
def get_file(file_dir):
images = []
# 每张图片的路径组成的列表
temp = []
# 保存文件夹路径
for root, sub_folders, files in os.walk(file_dir):
#各图片的名字保存在files中
for name in files:
images.append(os.path.join(root, name))
#依次将各图片的路径保存在images列表中
for name in sub_folders:
temp.append(os.path.join(root, name))
#依次将各子文件夹的路径保存在temp列表中
labels = []
# 保存标签列表
# 此时temp为根目录下所有文件夹的路径列表 一次取出一个文件夹 对文件夹里面的所有数据图片设置标签
for one_folder in temp:
n_img = len(os.listdir(one_folder))
# 得到“one_folder”文件夹下的图片总数
letter = one_folder.split('\\')[-1]
# 将子文件夹的路径按照“\\”分割 取出最后一个即:得到文件夹的名称
# 标注数据集
labels = np.append(labels, n_img * [int(letter)])
temp = np.array([images, labels])
# 重新创建数组temp;将images 和 labels 做为一对键值对写入temp中
temp = temp.transpose()
# 将temp转置
np.random.shuffle(temp)
# 打乱数据集的顺序
image_list = list(temp[:, 0])
# 取出数组中的第一维 即:图片的路径列表
label_list = list(temp[:, 1])
# 取出数组中的第二维 即:图片的标签列表
label_list = [int(float(i)) for i in label_list]
return image_list, label_list
四、将图片地址的数据集转化为 T e n s o r F l o w TensorFlow TensorFlow 专用格式
'''
输入2.中获得的图片路径列表的对应的标签列表
输出两个张量:
'''
def get_batch(image_list, label_list, img_width, img_height, batch_size, capacity):
"""将图片地址的数据集转化为TensorFlow专用格式"""
image = tf.cast(image_list, tf.string)
#将列表转化为tensor,一个张量元素是一个字节数组
label = tf.cast(label_list, tf.int64)
#将列表转化为tensor,元素转化为64 位有符号整型
input_queue = tf.train.slice_input_producer([image, label])
#创建一个文件名队列,input_queue是文件名队列的名字
label = input_queue[1]
image_contents = tf.read_file(input_queue[0])
#tf.read_file:读取图片
image = tf.image.decode_jpeg(image_contents, channels=3)
#将存储的".jpg"图像还原成一个三维矩阵.解码之后的结果为一个张量,在使用它的取值
#之前需要明确调用运行的过程
image = tf.image.resize_image_with_crop_or_pad(image, 227, 227)
#将图片尺寸转化为227×227
image = tf.image.per_image_standardization(image)
image_batch, label_batch = tf.train.batch([image, label], batch_size=200, num_threads=64, capacity=300)
label_batch = tf.reshape(label_batch, [batch_size])
return image_batch, label_batch
# 输入文件路径 获得两个batch
x_train, y_train = get_file(r'C:\Users\abc\Desktop\test1')
image_batch, label_batch = get_batch(x_train, y_train, 227, 227, 200, 2048)
用到的函数:
(1). tf.train.slice_input_producer
tf.train.slice_input_producer 函数:(创建tf的文件名队列) 一种模型数据的排队输入方法。从tensor列表
[image, label]中按顺序或者随机取出一个tensor放入文件名队列。
(文件名队列存放的是参与训练的文件名,要训练N次,则文件名队列中就含有N个批次的所有文件名)
slice_input_producer(tensor_list, num_epochs=None, shuffle=True, seed=None,capacity=32, shared_name=None, name=None)
- tensor_list:包含一系列tensor的列表,在 [image, label] 中有多少个图片,就应有多少个标签。
- num_epochs:表示迭代次数,若未设置则表示无限次的便利tensor列表
- shuffle: bool类型,设置是否打乱样本的顺序。一般情况下,如果shuffle=True,生成的样本顺序就被打乱了,在批处理的时候不需要再次打乱样本,使用 tf.train.batch函数就可以了;如果shuffle=False,就需要在批处理时候使用 tf.train.shuffle_batch函数打乱样本。
- seed:整数(可选择),当shuffle=True时使用
- capacity:tensor列表的容量
- shared_name:可选参数,如果设置一个‘shared_name’,则在不同的上下文环境(Session)中可以通过这个名字共享生成的tensor。
- name:设置操作的名称(可选)
(2). tf.image.resize_image_with_crop_or_pad
tf.image.resize_image_with_crop_or_pad(image, target_height, target_width):
通过集中裁剪图像或使用零均匀填充图像,将图像大小调整为目标宽度和高度,如果宽度或高度分别大于指定的
目标宽度或目标高度,则此操作将沿该维度集中裁剪。如果宽度或高度分别小于指定的目标宽度或目标高度,
则此操作沿该尺寸以黑色填充
(3). tf.image.per_image_standardization
tf.image.per_image_standardization(image):
图片标准化,将像素做处理
(4). tf.train.batch
tf.train.batch是一个tensor队列生成器,作用是按照给定的tensor顺序,把batch_size个tensor推送到文件队列,
作为训练一个batch的数据,等待tensor出队执行计算
`tf.train.batch(tensor,batch_size,num_thresds=1,capacity=32,enqueue_many=False,shapes=None,
dynamic_pad=False,allow_smaller_final_batch=False,shared_name=None,name=None)
- tensor:一个tensor列表或字典用来入队
- batch_size:设置每次从队列中获取的出队数据的数量
- num_threads:用来控制入队tensors线程的数量,如果num_threads大于1,则batch操作将是非确定性的,输出的batch可能会乱序
- capacity:一个整数,用来设置队列中元素的最大数量
- enqueue_many:在tensors中的tensor是否是单个样本
- shapes:可选,每个样本的shape,默认是tensors的shape
- dynamic_pad:Boolean值.允许输入变量的shape,出队后会自动填补维度,来保持与batch内的shapes相同
- allow_samller_final_batch:可选,Boolean值,如果为True队列中的样本数量小于batch_size时,出队的数量会以最终遗留下来的样本进行出队,如果为Flalse,小于batch_size的样本不会做出队处理
- shared_name:可选,通过设置该参数,可以对多个会话共享队列
- name:可选,操作的名字
tf.train.batch与tf.train.slice_input_producer的区别:
tf.train.slice_input_producer用于创建tf的文件名队列,
tf.train.batch() 按顺序批量读取文件队列中的数据,将读取到的样例组织成batch批量数据的形式返回。
五、 使用 Batch_Normalization 正则化处理数据集
def batch_norm(inputs, is_training, is_conv_out=True, decay=0.999):
scale = tf.Variable(tf.ones([inputs.get_shape()[-1]]))
beta = tf.Variable(tf.zeros([inputs.get_shape()[-1]]))
pop_mean = tf.Variable(tf.zeros(inputs.get_shape()[-1]), trainable=False)
pop_var = tf.Variable(tf.ones(inputs.get_shape()[-1]), trainable=False)
if is_training:
if is_conv_out:
batch_mean, batch_var = tf.nn.moments(inputs, [0, 1, 2])
#tf.nn.moments()函数用于计算均值和方差
else