如题,TensorFlow官方为我们提供了数据读取的标准格式:TFRecord,本文主要阐述了该数据格式的制作、读取及验证三个具体操作过程。
简要介绍:tfrecord数据文件是一种将图像数据和标签统一存储的二进制文件,能更好的利用内存,在tensorflow中快速的复制,移动,读取,存储等。tfrecord文件包含了tf.train.Example 协议缓冲区(protocol buffer,协议缓冲区包含了特征 Features)。你可以写一段代码获取你的数据, 将数据填入到Example协议缓冲区(protocol buffer),将协议缓冲区序列化为一个字符串,并且通过tf.python_io.TFRecordWriter class写入到TFRecords文件。
我们很容易就能在网上找到相关的一大堆代码(比如看这里),所以一些基本的操作这里就先不讲。这里是我的代码
其实在实际运行过程中,最容易出现问题的地方就是数组之间shape的转换,甚至没有之一,形如(__,__,__),下面详细说
要点:
1.图像大小、分辨率、位深之间的关系
以BMP图像为例说明计算方法: 1、大小=分辨率*位深/8; 2、分辨率=宽*高(如:1024*768,640*480); 3、位深:如24位,16位,8位; 4、/8计算的是字节数。
特别地,在制作数据集时,若同时存在不同位深的图像时,最好先统一化,利用PS即可
2.读取tfrecord格式到图片时,根据之前保存的原图片的通道数(一般channels=3或1),选择'RGB'或者'L'
example, l = sess.run([image,label])#在会话中取出image和label
img=Image.fromarray(example, 'L')
#这里特别注意'L'的选择
函数原型:PIL.Image.
fromarray
(obj, mode=None),关于此处mode的选择官方的说法如下:
3.经过如下操作,resize()并不改变图像的channels,example对象封装后channels=3的原始图片格式已经变成(width*height*channels, )
img=Image.open(img_path)
img= img.resize((128,128))
img_raw=img.tobytes()#将图片转化为二进制格式
example = tf.train.Example(features=tf.train.Features(feature={
"label": tf.train.Feature(int64_list=tf.train.Int64List(value=[index])),
'img_raw': tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
})) #example对象对label和image数据进行封装
writer.write(example.SerializeToString()) #序列化为字符串
此时再进行读取时,下面代码显然会出错
image = tf.decode_raw(features['img_raw'], tf.uint8)
print(image)
image = tf.reshape(image, [128, 128])#
#这里显然无法将128*128*3的对象reshape成128*1284. 多标签分配问题:按classes文件夹首字母的先后顺序依次分配0,1,2......