二、实现TFRecord向图片jpg格式的转换
假设经过前一篇博文的流程,在"G:/Exercise/Python/tfrecord/data"文件夹中得到了data.tfrecords这一TFRecord格式的文件。怎样将它还原为jpg图片格式的两张图片呢?
(1)新建命名为“Tfrecord2Img.py”的python文件,用于编程实现TFRecord格式向jpeg格式的转换。
(2)Tfrecord2Img.py的具体内容为:
# -*- coding:utf-8 -*- __author__="David Chow" # 从 TFRecord 中读取并保存图片 import tensorflow as tf import numpy as np savedir="G:/Exercise/Python/tfrecord/data/data.tfrecords" def load(width,height): reader=tf.TFRecordReader() filename_queue=tf.train.string_input_producer([savedir]) # 从 TFRecord 读取内容并保存到 serialized_example 中 _,serialize_example=reader.read(filename_queue) # 读取 serialized_example 的格式 features=tf.parse_single_example(\ serialize_example,\ features={'imge_raw':tf.FixedLenFeature([],tf.string),\ 'label':tf.FixedLenFeature([],tf.int64),}) # 解析从 serialized_example 读取到的内容 images=tf.decode_raw(features['imge_raw'],tf.uint8) labels=tf.cast(features['label'],tf.int64) with tf.Session() as sess: # 启动多线程 coord=tf.train.Coordinator() threads=tf.train.start_queue_runners(sess=sess,coord=coord) # 因为我这里只有 2 张图片,所以下面循环 2 次 for i in range(2): # 获取一张图片和其对应的类型 label,image =sess.run([labels,images]) # 这里特别说明下: # 因为要想把图片保存成 TFRecord,那就必须先将图片矩阵转换成 string,即: # pic2tfrecords.py 中 image_raw = image.tostring() 这行 # 所以这里需要执行下面这行将 string 转换回来,否则会无法 reshape 成图片矩阵,请看下面的小例子: # a = np.array([[1, 2], [3, 4]], dtype=np.int64) # 2*2 的矩阵 # b = a.tostring() # # 下面这行的输出是 32,即: 2*2 之后还要再乘 8 # # 如果 tostring 之后的长度是 2*2=4 的话,那可以将 b 直接 reshape([2, 2]),但现在的长度是 2*2*8 = 32,所以无法直接 reshape # # 同理如果你的图片是 500*500*3 的话,那 tostring() 之后的长度是 500*500*3 后再乘上一个数 # print len(b) # # 但在网上有很多提供的代码里都没有下面这一行,你们那真的能 reshape ? image=np.fromstring(image,dtype=np.float32) image=tf.reshape(image,[height,width,3]) ## reshape 成图片矩阵 image=tf.image.convert_image_dtype(image,dtype=tf.uint8) #因为要保存图片,所以将其转换成 uint8 image=tf.image.encode_jpeg(image) # 按照 jpeg 格式编码 # 保存图片,图片格式为pic_*。jpg,'*'表示图片的标签 with tf.gfile.GFile('G:/Exercise/Python/tfrecord/pic_%d.jpg' % label,'wb') as f: f.write(sess.run(image)) load(650,434)
运行后会产生一个警告:
_1_input_producer: Skipping cancelled enqueue attempt with queue not closed
这主要是主线程已经关闭,但是读取数据入队线程还在执行入队。
可以通过使用下面的模式手动停止线程来避免它们。
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
<do stuff>
coord.request_stop()
coord.join(threads)
将这两篇博文涉及到的程序及图片上传至百度云:https://pan.baidu.com/s/1JDeN8nRDWfoma8mQQTYFuw
(Password: hkm6)