TFrecords 比原始 JPEG 图片占用更多 space
TFrecords occupy more space than original JPEG images
我正在尝试将我的 Jpeg 图像集转换为 TFrecords。但是 TFrecord 文件占用的空间几乎是图像集的 5 倍 space。经过大量谷歌搜索后,我了解到当 JPEG 写入 TFrecords 时,它们不再是 JPEG。但是,我还没有找到解决此问题的可理解的代码解决方案。请告诉我应该在下面的代码中进行哪些更改才能将 JPEG 写入 Tfrecords。
def print_progress(count, total):
pct_complete = float(count) / total
msg = "\r- Progress: {0:.1%}".format(pct_complete)
sys.stdout.write(msg)
sys.stdout.flush()
def wrap_int64(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
def wrap_bytes(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def convert(image_paths , labels, out_path):
# Args:
# image_paths List of file-paths for the images.
# labels Class-labels for the images.
# out_path File-path for the TFRecords output file.
print("Converting: " + out_path)
# Number of images. Used when printing the progress.
num_images = len(image_paths)
# Open a TFRecordWriter for the output-file.
with tf.python_io.TFRecordWriter(out_path) as writer:
# Iterate over all the image-paths and class-labels.
for i, (path, label) in enumerate(zip(image_paths, labels)):
# Print the percentage-progress.
print_progress(count=i, total=num_images-1)
# Load the image-file using matplotlib's imread function.
img = imread(path)
# Convert the image to raw bytes.
img_bytes = img.tostring()
# Create a dict with the data we want to save in the
# TFRecords file. You can add more relevant data here.
data = \
{
'image': wrap_bytes(img_bytes),
'label': wrap_int64(label)
}
# Wrap the data as TensorFlow Features.
feature = tf.train.Features(feature=data)
# Wrap again as a TensorFlow Example.
example = tf.train.Example(features=feature)
# Serialize the data.
serialized = example.SerializeToString()
# Write the serialized data to the TFRecords file.
writer.write(serialized)
编辑:有人可以回答这个问题吗?!!
你不应该在 TFRecord 中保存图像数据,只保存文件名。然后,要在记录被送入训练循环时加载图像,您最好使用相对较新的 Dataset
API。来自 docs:
# Reads an image from a file, decodes it into a dense tensor, and resizes it
# to a fixed shape.
def _parse_function(filename, label):
image_string = tf.read_file(filename)
image_decoded = tf.image.decode_jpeg(image_string)
image_resized = tf.image.resize_images(image_decoded, [28, 28])
return image_resized, label
# A vector of filenames.
filenames = tf.constant(["/var/data/image1.jpg", "/var/data/image2.jpg", ...])
# `labels[i]` is the label for the image in `filenames[i].
labels = tf.constant([0, 37, ...])
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.map(_parse_function)
哪种方法更快?这里有很多竞争因素,例如:
- 读取一个大的连续文件可能比打开和读取许多小文件更快。但这对于 SSD、旋转磁盘或网络存储会有所不同。
- 读取许多小文件可能更适合并行化
- 虽然读取 1000 个大小为 x 的文件可能比一个大小为 1000x 的文件慢,但我们实际上讨论的是一个大小为 10 x 1000x 的大文件,因为图像数据是原始像素,而不是 jpeg。
- 但是从像素数据开始可以节省 jpeg 解码步骤
- 如果它实际上不是您的瓶颈,那么优化读取速度可能没有多大意义
因此,最后,了解 不同的方法很重要。如果没有测量,我会倾向于许多小文件解决方案,因为它需要对我们开始时的数据进行较少的处理,并且因为如果它完全不合理,它不太可能用于 Tensorflow 文档。但唯一真正的答案是测量。
我们可以只使用内置的 open
函数来获取字节,而不是将图像转换为数组再返回字节。这样,压缩图像将写入 TFRecord。
替换这两行
img = imread(path)
img_bytes = img.tostring()
和
img_bytes = open(path,'rb').read()
参考:
我正在尝试将我的 Jpeg 图像集转换为 TFrecords。但是 TFrecord 文件占用的空间几乎是图像集的 5 倍 space。经过大量谷歌搜索后,我了解到当 JPEG 写入 TFrecords 时,它们不再是 JPEG。但是,我还没有找到解决此问题的可理解的代码解决方案。请告诉我应该在下面的代码中进行哪些更改才能将 JPEG 写入 Tfrecords。
def print_progress(count, total):
pct_complete = float(count) / total
msg = "\r- Progress: {0:.1%}".format(pct_complete)
sys.stdout.write(msg)
sys.stdout.flush()
def wrap_int64(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
def wrap_bytes(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def convert(image_paths , labels, out_path):
# Args:
# image_paths List of file-paths for the images.
# labels Class-labels for the images.
# out_path File-path for the TFRecords output file.
print("Converting: " + out_path)
# Number of images. Used when printing the progress.
num_images = len(image_paths)
# Open a TFRecordWriter for the output-file.
with tf.python_io.TFRecordWriter(out_path) as writer:
# Iterate over all the image-paths and class-labels.
for i, (path, label) in enumerate(zip(image_paths, labels)):
# Print the percentage-progress.
print_progress(count=i, total=num_images-1)
# Load the image-file using matplotlib's imread function.
img = imread(path)
# Convert the image to raw bytes.
img_bytes = img.tostring()
# Create a dict with the data we want to save in the
# TFRecords file. You can add more relevant data here.
data = \
{
'image': wrap_bytes(img_bytes),
'label': wrap_int64(label)
}
# Wrap the data as TensorFlow Features.
feature = tf.train.Features(feature=data)
# Wrap again as a TensorFlow Example.
example = tf.train.Example(features=feature)
# Serialize the data.
serialized = example.SerializeToString()
# Write the serialized data to the TFRecords file.
writer.write(serialized)
编辑:有人可以回答这个问题吗?!!
你不应该在 TFRecord 中保存图像数据,只保存文件名。然后,要在记录被送入训练循环时加载图像,您最好使用相对较新的 Dataset
API。来自 docs:
# Reads an image from a file, decodes it into a dense tensor, and resizes it
# to a fixed shape.
def _parse_function(filename, label):
image_string = tf.read_file(filename)
image_decoded = tf.image.decode_jpeg(image_string)
image_resized = tf.image.resize_images(image_decoded, [28, 28])
return image_resized, label
# A vector of filenames.
filenames = tf.constant(["/var/data/image1.jpg", "/var/data/image2.jpg", ...])
# `labels[i]` is the label for the image in `filenames[i].
labels = tf.constant([0, 37, ...])
dataset = tf.data.Dataset.from_tensor_slices((filenames, labels))
dataset = dataset.map(_parse_function)
哪种方法更快?这里有很多竞争因素,例如:
- 读取一个大的连续文件可能比打开和读取许多小文件更快。但这对于 SSD、旋转磁盘或网络存储会有所不同。
- 读取许多小文件可能更适合并行化
- 虽然读取 1000 个大小为 x 的文件可能比一个大小为 1000x 的文件慢,但我们实际上讨论的是一个大小为 10 x 1000x 的大文件,因为图像数据是原始像素,而不是 jpeg。
- 但是从像素数据开始可以节省 jpeg 解码步骤
- 如果它实际上不是您的瓶颈,那么优化读取速度可能没有多大意义
因此,最后,了解 不同的方法很重要。如果没有测量,我会倾向于许多小文件解决方案,因为它需要对我们开始时的数据进行较少的处理,并且因为如果它完全不合理,它不太可能用于 Tensorflow 文档。但唯一真正的答案是测量。
我们可以只使用内置的 open
函数来获取字节,而不是将图像转换为数组再返回字节。这样,压缩图像将写入 TFRecord。
替换这两行
img = imread(path)
img_bytes = img.tostring()
和
img_bytes = open(path,'rb').read()
参考: