【问题标题】:How to read images with different size in a TFRecord file如何在 TFRecord 文件中读取不同大小的图像
【发布时间】:2016-01-27 03:12:38
【问题描述】:

我创建了一个数据集并将其保存到 TFRecord 文件中。问题是图片有不同的大小,所以我想保存图片的大小。所以我使用了 TFRecordWriter 并定义了如下特性:

example = tf.train.Example(features=tf.train.Features(feature={
  'rows': _int64_feature(image.shape[0]),
  'cols': _int64_feature(image.shape[1]),
  'image_raw': _bytes_feature(image_raw)}))

我希望我可以使用 TFRecordReader 读取和解码图像,但问题是我无法从文件中获取行和列的值,因为它们是张量。那么我应该如何动态读取大小并相应地重塑图像。谢谢大家

【问题讨论】:

    标签: python deep-learning tensorflow


    【解决方案1】:

    您可以使用动态shape 参数调用tf.reshape

    image_rows = tf.cast(features['rows'], tf.int32)
    image_cols = tf.cast(features['cols'], tf.int32)
    image_data = tf.decode_raw(features['image_raw'], tf.uint8)
    image = tf.reshape(image_data, tf.pack([image_rows, image_cols, 3]))
    

    【讨论】:

    • 它引发了错误“所有形状必须完全定义:1”。从日志来看,它似乎与函数“tf.train.shuffle_batch()”有关。那我该怎么办?
    • batch 需要在图形构建期间知道形状(以便它知道为队列分配多少内存),也许在 tf.batch 之前使用 tf.image.resize_images?如果您使用任何标准的 convnet,则无论如何都需要将图像大小调整为相同的大小
    • +沉彤,因为你是在构建一个batch,所以图片的大小必须一致。如果你事先知道这个尺寸,也许你可以调用image.set_shape([32,32,3]) 之类的东西来完全定义形状。
    • @Yaroslav Bulatov 感谢您的评论,但调整图像大小会扭曲图像,因为我不知道比例。例如,我使用 PASCAL 数据集进行分割,其中图片具有不同的比例和大小。我知道批次中的图像应该具有相同的大小,所以我将随机裁剪图像,例如 500*500。所以对于那些较短尺寸小于 500 的人,比如 400*500,我会将其调整为 500*625 以保持比例。所以我在做解码和整形的时候还是要知道图片的大小。
    • @bgshi 谢谢你的回复。就像我上面说的,图像有不同的大小,这就是问题所在。
    【解决方案2】:

    我建议的工作流程如下:

    TARGET_HEIGHT = 500
    TARGET_WIDTH = 500
    
    image = tf.image.decode_jpeg(image_buffer, channels=3)
    image = tf.image.convert_image_dtype(image, dtype=tf.float32)
    
    # Choose your bbox here.
    bbox_begin = ...  (should be (h_start, w_start, 0))
    bbox_size = tf.constant((TARGET_HEIGHT, TARGET_WIDTH, 3), dtype=tf.int32)
    
    cropped_image = tf.slice(image, bbox_begin, bbox_size)
    

    cropped_image 有一个恒定的张量大小,然后可以被扔进一个随机批次中。

    您可以使用tf.shape(image) 动态访问解码图像的大小。您可以对生成的子元素进行计算,然后使用bbox_begin = tf.pack([bbox_h_start, bbox_y_start, 0]) 之类的东西将它们缝合在一起。只需要在其中插入您自己的逻辑来确定裁剪的起点,以及如果图像开始小于您想要的管道时您想要做什么。

    如果您想在图像小于您的目标尺寸时放大,您将需要使用tf.control_flow_ops.cond 或等效项。但是您可以使用 min 和 max 操作来设置裁剪窗口的大小,以便在它小于请求的尺寸时返回完整的图像,然后无条件地将大小调整为 500x500。裁剪后的图像已经是 500x500,因此调整大小应该成为有效的无操作。

    【讨论】:

    • 此工作流程是否将使用 FIFO 文件队列?现在问题是我想使用 500*500 随机裁剪图片,你的方式似乎裁剪了一个固定区域。现在我已经提前调整了图像的大小,因此最小尺寸等于或大于 500。我面临的唯一一件事是如何从原始字符串中解码图像并将其重塑为原始大小。由于图像的重量和高度不同,我们不能使用固定尺寸。
    • 对,你需要随机选择500x500 bbox的开头。通过将 bbox_size 设置为 [500, 500, 3](3 表示通道数),您将获得 500x500 的裁剪。您必须设置随机裁剪的起点,具体取决于您喜欢的随机裁剪算法。鉴于您已调整大小,您可以简单地执行imageshape = tf.shape(image),然后设置起点、终点,如:h_start = tf.random_uniform([], minval=0, maxval=imageshape[0]-500, dtype=tf.int32) 和类似的 w_start。
    猜你喜欢
    • 2021-04-23
    • 2014-09-10
    • 2020-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    相关资源
    最近更新 更多