因为在做目标追踪方面,一直在matlab中写代码,不得不说改代码改的又复杂又难改,优化难做啊。就把图像预处理过程直接放到tensorflow中学习吧。
对于数据量较小而言,可能一般选择直接将数据加载进内存,然后再分batch输入网络进行训练(tip:使用这种方法时,结合yield 使用更为简洁,之前我一直用的这个方法)。 如果数据量较大,这样的方法就不适用了,因为太耗内存,所以这时最好使用tensorflow提供的队列queue,也就是第二种方法 从文件读取数据。对于一些特定的读取,比如csv文件格式,官网有相关的描述,在这儿我介绍一种比较通用,高效的读取方法(官网介绍的少),即使用tensorflow内定标准格式——TFRecords。这种方式也对图像文件比较友好,主要是图像的都比较大。
不多说,直接贴代码,有些写在注释里了。 读取TFRecord中的样例,以队列的形式。
#-*-encoding:UTF-8 -*- import tensorflow as tf #创建一个reader来读取TFRecord中的样例 reader = tf.TFRecordReader() #创建一个临时队列用于维护输入文件列表 filename_queue = tf.train.string_input_producer(["path/to/output.tfrecords"]) #从文件中读取一个样例。read_up_to函数用于一次性读取多个样例 _,serialized_example = reader.read(filename_queue) #解析读入的样例。如果需要解析多个样例,用parse_example features = tf.parse_single_example(serialized_example,features={ #TensorFlow提供了两种属性解析方法 #1.tf.FixedLenFeature解析结果为Tensor. #2.tf.VarLenFeature,这种解析方法解析为一个SparseTensor,用于处理稀疏矩阵 #格式需要与上面的写入数据的格式相一致 'image_raw':tf.FixedLenFeature([],tf.string), 'pixels':tf.FixedLenFeature([],tf.int64), 'label':tf.FixedLenFeature([],tf.int64), }) #tf.decode_raw将字符串解析为对应的像素数组 images = tf.decode_raw(features['image_raw'],tf.uint8) labels = tf.cast(features['label'],tf.int32) pixels = tf.cast(features['pixels'],tf.int32) sess = tf.Session() #启动多线程处理输入数据 coord = tf.train.Coordinator() threads = tf.train.start_queue_runners(sess=sess,coord=coord) #每次读取一个样例,当所有样例读取完之后,从头读取。 for i in range(10): image,label,pixel = sess.run([images,labels,pixels])那么如何将已经存在的数据存储为TFRecord呢? 以mnist的数据集为例,
获取你的数据将数据填入到Example协议内存块(protocol buffer)将数据中的信息feature写入这个结构之后,通过tf.python_io.TFRecordWriter 写入到TFRecords文件 # -*- coding: UTF-8 -* import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import numpy as np #生成整数型的属性 def _int64_feature(value): return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) #生成字符串的属性 def _bytes_feature(value): return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) mnist = input_data.read_data_sets("../MNIST_data/", dtype=tf.uint8,one_hot=True) images = mnist.train.images labels = mnist.train.labels pixels = images.shape[1] #像素值可以作为Example的一个属性 num_examples = mnist.train.num_examples #输出TFRecord文件的地址 filename = "path/to/output.tfrecords" #创建一个writer来写TFRecord文件 writer = tf.python_io.TFRecordWriter(filename) for index in range(num_examples): #将图像转化为字符串 image_raw = images[index].tostring() #将一个样例转化为Example Protocol Buffer,并将所有信息写入这个结构 example = tf.train.Example(features = tf.train.Features(feature={ 'pixels':_int64_feature(pixels), 'label':_int64_feature(np.argmax(labels[index])), 'image_raw':_bytes_feature(image_raw) })) #写入TFRecord writer.write(example.SerializeToString()) writer.close()图像预处理有很多过程。这里只介绍函数。方便使用。
图像读取原始 tf.gfile.FastGFile().read()图像格式的编码解码 :图像不直接记录图像上的不同位置,不同颜色的亮度。而是记录压缩编码之后的结果。所以要还原成三维矩阵,需要解码。 tf.image.decode_jpeg()tf.image.encode_jpeg()转换函数 tf.image.convert_image_dtype图像大小调整 tf.image.resize_images(image,[size],method)method 0:双线性插值 1:最近邻居法 2: 双三次插值法 3:面积差值法tf.image.resize_image_with_crop_pad 自动裁剪或者填充图像翻转 tf.image.flip_up_down()tf.image.filp_left_right()tf.image.transpose_image()图像色彩调整 亮度调整 tf.image.adjust_brightness(image,brightness)随机亮度调整 tf.image.random_brightness(image,max_delta)同理调整,tf.image.adjust_contrast,tf.image.adjust_hue,tf.image. saturation.图像标准化 tf.image.per_image_whitening(image)标注框
tf.image.draw_bounding_boxes(batch,boxes) 这个函数要求图像矩阵的数字为实数,而且输入是一个batch的数据,即多张图像组成的四维矩阵,所以将编码后的图像矩阵加一维。tf.expand_dims() 这个加的维度大家自己要看api去理解tf.image.sample_distorted_bounding_box(size,boxes) 随机截取图像信息
随机翻转图像,随机调整颜色,随机截图图像中的有信息含量的部分,这些事提高模型健壮性的一种方式。这样可以使是训练得到的模型不受被识别物体大小的影响。 下面贴出完整代码:
# -*- coding: UTF-8 -* import tensorflow as tf import numpy as np import matplotlib.pyplot as plt def distort_color(image,color_ordering=0): if color_ordering == 0: image = tf.image.random_brightness(image,max_delta=32./255.)#亮度 image = tf.image.random_saturation(image,lower=0.5,upper=1.5)#饱和度 image = tf.image.random_hue(image,max_delta=0.2)#色相 image = tf.image.random_contrast(image,lower=0.5,upper=1.5)#对比度 elif color_ordering == 1: image = tf.image.random_brightness(image, max_delta=32. / 255.) # 亮度 image = tf.image.random_hue(image, max_delta=0.2) # 色相 image = tf.image.random_saturation(image, lower=0.5, upper=1.5) # 饱和度 image = tf.image.random_contrast(image, lower=0.5, upper=1.5) # 对比度 return tf.clip_by_value(image,0.0,1.0) #将张量值剪切到指定的最小值和最大值 def preprocess_for_train(image,height,width,bbox): #如果没有提供标注框,则认为整个图像就是需要关注的部分 if bbox is None: bbox = tf.constant([0.0,0.0,1.0,1.0],dtype=tf.float32,shape=[1,1,4]) #转换图像张量的类型 if image.dtype != tf.float32: image = tf.image.convert_image_dtype(image,dtype=tf.float32) #随机截取图像,减少需要关注的物体大小对图像识别的影响 bbox_begin,bbox_size,_ = tf.image.sample_distorted_bounding_box(tf.shape(image), bounding_boxes=bbox) distort_image = tf.slice(image,bbox_begin,bbox_size) #将随机截图的图像调整为神经网络输入层的大小。大小调整的算法是随机的 distort_image = tf.image.resize_images( distort_image,[height,width],method=np.random.randint(4) ) #随机左右翻转图像 distort_image = tf.image.random_flip_left_right(distort_image) #使用一种随机的顺序调整图像色彩 distort_image = distort_color(distort_image,np.random.randint(1)) return distort_image image_raw_data = tf.gfile.FastGFile("../cat.jpg",'r').read() with tf.Session() as Sess: ima_data = tf.image.decode_jpeg(image_raw_data) boxes = tf.constant([[[0.05,0.05,0.9,0.7],[0.35,0.47,0.5,0.56]]]) #运行6次获得6中不同的图像,在图中显示效果 for i in range(6): #将图像的尺寸调整为299*299 result = preprocess_for_train(ima_data,299,299,boxes) plt.imshow(result.eval()) plt.show()