二、实现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)