在TensorFlow中加载图像文件夹

22

我是新手,已经按照推广的教程以及其他网站上的许多教程跟着做了。我在MNIST图像上建立了一个小型的卷积神经网络。虽然很普通,但我想要在自己的图像上测试。

现在我面临的问题是:我创建了几个文件夹,每个文件夹的名字都是图像所属的类(标签)。

这些图像具有不同的形状,也就是说它们没有固定的大小。

我该如何加载它们以便用Tensorflow使用?

我按照StackOverflow和其他Q/A网站上的许多教程和答案尝试过了,但仍然没有找到如何做到这一点的方法。

4个回答

12

tf.data API (从tensorflow 1.4版本开始) 对于像这样的任务非常出色。管道将如下所示:

  • 创建一个最初的tf.data.Dataset对象,遍历所有样例
  • (如果是训练)shuffle/repeat 数据集;
  • map 通过某个函数,使所有图像大小相同;
  • batch;
  • (可选) prefetch 告诉您的程序在网络处理当前批次数据时收集预处理后续批次数据;以及
  • 并获取输入。

有多种方法可以创建初始数据集(详见此处的更详细的答案)

使用Tensorflow Datasets进行TFRecords

支持tensorflow版本1.12及以上版本,Tensorflow datasets提供了一个相对简单的API用于创建tfrecord数据集,还自动处理数据下载、分片、统计生成和其他功能。

例如,请参见此图像分类数据集实现。其中有很多簿记事项(下载url、引文等),但技术部分归结为指定features和编写一个_generate_examples函数。

features = tfds.features.FeaturesDict({
            "image": tfds.features.Image(shape=(_TILES_SIZE,) * 2 + (3,)),
            "label": tfds.features.ClassLabel(
                names=_CLASS_NAMES),
            "filename": tfds.features.Text(),
        })

...

def _generate_examples(self, root_dir):
  root_dir = os.path.join(root_dir, _TILES_SUBDIR)
  for i, class_name in enumerate(_CLASS_NAMES):
    class_dir = os.path.join(root_dir, _class_subdir(i, class_name))
    fns = tf.io.gfile.listdir(class_dir)

    for fn in sorted(fns):
      image = _load_tif(os.path.join(class_dir, fn))
      yield {
          "image": image,
          "label": class_name,
          "filename": fn,
      }

使用更底层的操作,您也可以生成tfrecords

通过tf.data.Dataset.maptf.py_func(tion)加载图像

或者您可以在tf.data.Dataset.map中使用以下方式从文件名中加载图像文件。

image_paths, labels = load_base_data(...)
epoch_size = len(image_paths)
image_paths = tf.convert_to_tensor(image_paths, dtype=tf.string)
labels = tf.convert_to_tensor(labels)

dataset = tf.data.Dataset.from_tensor_slices((image_paths, labels))

if mode == 'train':
    dataset = dataset.repeat().shuffle(epoch_size)


def map_fn(path, label):
    # path/label represent values for a single example
    image = tf.image.decode_jpeg(tf.read_file(path))

    # some mapping to constant size - be careful with distorting aspec ratios
    image = tf.image.resize_images(out_shape)
    # color normalization - just an example
    image = tf.to_float(image) * (2. / 255) - 1
    return image, label


# num_parallel_calls > 1 induces intra-batch shuffling
dataset = dataset.map(map_fn, num_parallel_calls=8)
dataset = dataset.batch(batch_size)
# try one of the following
dataset = dataset.prefetch(1)
# dataset = dataset.apply(
#            tf.contrib.data.prefetch_to_device('/gpu:0'))

images, labels = dataset.make_one_shot_iterator().get_next()

我从未在分布式环境下工作过,但使用这种方法与tfrecords相比并没有注意到性能损失。如果您需要更多自定义的加载函数,也可以查看tf.py_func

有关更一般的信息,请在此处查看,在此处查看性能说明。


1
对于那些出现“NameError: name 'load_base_data' is not defined”错误的人:我猜可以用类似于["mydata/cats", "mydata/dogs"], [0, 1]的东西来替换load_base_data(...) - Nicolas Raoul
对于那些出现“NameError: global name 'out_shape' is not defined”和其他错误的人,我猜在文件开头添加以下几行代码可能会更好:import tensorflow as tfmode = 'train'out_shape = tf.convert_to_tensor([100, 100])batch_size = 10。虽然不确定这些值是否有意义。 - Nicolas Raoul
验证集怎么样? - Rasoul

3

以下是示例输入管道脚本,用于从目录加载图像和标签。在此之后,您可以进行预处理(调整图像大小等)。

import tensorflow as tf
filename_queue = tf.train.string_input_producer(
tf.train.match_filenames_once("/home/xxx/Desktop/stackoverflow/images/*/*.png"))

image_reader = tf.WholeFileReader()
key, image_file = image_reader.read(filename_queue)
S = tf.string_split([key],'/')
length = tf.cast(S.dense_shape[1],tf.int32)
# adjust constant value corresponding to your paths if you face issues. It should work for above format.
label = S.values[length-tf.constant(2,dtype=tf.int32)]
label = tf.string_to_number(label,out_type=tf.int32)
image = tf.image.decode_png(image_file)

# Start a new session to show example output.
with tf.Session() as sess:
    # Required to get the filename matching to run.
    tf.initialize_all_variables().run()

    # Coordinate the loading of image files.
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(coord=coord)

    for i in xrange(6):
        # Get an image tensor and print its value.
        key_val,label_val,image_tensor = sess.run([key,label,image])
        print(image_tensor.shape)
        print(key_val)
        print(label_val)


    # Finish off the filename queue coordinator.
    coord.request_stop()
    coord.join(threads)

文件目录

./images/1/1.png
./images/1/2.png
./images/3/1.png
./images/3/2.png
./images/2/1.png
./images/2/2.png

输出:

 (881, 2079, 3)
 /home/xxxx/Desktop/stackoverflow/images/3/1.png
 3
 (155, 2552, 3)
 /home/xxxx/Desktop/stackoverflow/images/2/1.png
 2
 (562, 1978, 3)
 /home/xxxx/Desktop/stackoverflow/images/3/2.png
 3
 (291, 2558, 3)
 /home/xxxx/Desktop/stackoverflow/images/1/1.png
 1
 (157, 2554, 3)
 /home/xxxx/Desktop/stackoverflow/images/1/2.png
 1
 (866, 936, 3)
 /home/xxxx/Desktop/stackoverflow/images/2/2.png
 2

首先,感谢您的快速回复。我尝试了您的代码片段,但它引发了以下错误。tensorflow.python.framework.errors_impl.OutOfRangeError: FIFO队列“_0_input_producer”已关闭,并且元素不足(请求1个,当前大小为0) [[节点:ReaderReadV2 = ReaderReadV2 [_device =“/ job:localhost / replica:0 / task:0 / cpu:0”](WholeFileReaderV2,input_producer)]] - SilvioBarra
我认为它无法找到图像。文件夹路径正确吗?尝试使用几张图片。 - Harsha Pokkalla
2
我通过以下两行代码成功解决了元素不足的错误:sess.run(tf.local_variables_initializer())sess.run(tf.global_variables_initializer()) - Timo Denk
你把这些代码放在哪里了?我也遇到了同样的错误 :/ - poetyi
@pnz:在“#需要运行文件名匹配”的那一行之前,左侧有4个空格。 - Nicolas Raoul

1

0

为了加载不同形状的图像,tf 提供了一个管道实现(ImageGenerator):

from tensorflow.keras.preprocessing.image import ImageDataGenerator

TARGET_SHAPE = (500,500)
BATCH_SIZE = 32
train_dir = "train_images_directory" #ex: images/train/
test_dir = "train_images_directory" #ex: images/test/

train_images_generator = ImageDataGenerator(rescale=1.0/255,)
train_data_gen = 
               image_train_gen.flow_from_directory(batch_size=BATCH_SIZE,
                                           directory=train_dir,
                                           target_size=TARGET_SHAPE,
                                           shuffle=True,
                                           class_mode='sparse')

# do the same for validation and test dataset
# 1- image_generator 2- load images from directory with target shape

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接