【问题标题】:Loading folders of images in tensorflow在张量流中加载图像文件夹
【发布时间】:2017-11-09 01:11:44
【问题描述】:

我是 tensorflow 的新手,但我已经关注并执行了他们推广的教程以及网络上的许多其他教程。 我在 MNIST 图像上做了一个小的卷积神经网络。没什么特别的,但我想在我自己的图像上进行测试。 现在我的问题来了:我创建了几个文件夹;每个文件夹的名称是里面的图像所属的类(标签)。

图像有不同的形状;我的意思是它们没有固定的大小。

如何加载它们以与 Tensorflow 一起使用?

我在 StackOverflow 和其他问答网站上都遵循了许多教程和答案。但是,我仍然没有弄清楚如何做到这一点。

【问题讨论】:

    标签: tensorflow neural-network directory loadimage


    【解决方案1】:

    要加载相同大小的图像,只需使用以下命令:

    tf.keras.preprocessing.image_dataset_from_directory(dir)
    

    文档:https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/image_dataset_from_directory

    【讨论】:

      【解决方案2】:

      tf.data API(从 tensorflow 1.4 开始)非常适合这样的事情。管道将如下所示:

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

      有多种方法可以创建您的初始数据集(请参阅here 以获得更深入的答案)

      带有 TensorFlow 数据集的 TFRecords

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

      参见例如this image classification dataset implementation。里面有很多记账的东西(下载网址、引用等),但技术部分归结为指定 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

      更多一般信息here,以及性能说明here

      【讨论】:

      • 对于那些得到NameError: name 'load_base_data' is not defined的人:我猜load_base_data(...)可以用["mydata/cats", "mydata/dogs"], [0, 1]之类的东西代替。
      • 对于那些得到NameError: global name 'out_shape' is not defined和其他错误的人,我想在文件开头添加这些行后可能会更好:import tensorflow as tfmode = 'train'out_shape = tf.convert_to_tensor([100, 100])batch_size = 10 .不过,不确定这些值是否有意义。
      【解决方案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
      

      【讨论】:

      • 首先,感谢您的快速回复。我尝试了您的代码 sn-p 并引发以下错误。 tensorflow.python.framework.errors_impl.OutOfRangeError: FIFOQueue '_0_input_producer' 已关闭且元素不足(请求 1,当前大小 0)[[Node: ReaderReadV2 = ReaderReadV2[_device="/job:localhost/replica:0/task: 0/cpu:0"](WholeFileReaderV2, input_producer)]]
      • 我认为它无法找到图像。文件夹路径是否正确?用几张图片试试。
      • 我能够使用以下两行代码修复元素不足错误:sess.run(tf.local_variables_initializer())sess.run(tf.global_variables_initializer())
      • 你把这些行放在哪里了?我有同样的错误:/
      • @pnz:就在# Required to get the filename matching to run.行之前,左边有4个空格。
      猜你喜欢
      • 2020-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      相关资源
      最近更新 更多