【问题标题】:Python loop over batch of filesPython循环遍历一批文件
【发布时间】:2019-03-04 10:06:47
【问题描述】:

我想遍历一批文件,以便一次获取每个子目录的 32 张图像(由于内存,我无法加载所有图像)例如加载每个目录的 img 1-32 使用它们然后加载img 33-64 然后 65-96 等等

我的目录:

Rootdir
  - dir1
    - img 1
    - img 2
    - img...
  - dir2
    - img 5000001
    - img 5000002
    - img...
  - dir3
    - img 10000001
    - img 10000002
    - img...

所以我需要在第一个循环中加载 img1,2,..,32, 5000001,...5000032, 1000001,...10000032 然后是 img33,34,..,64, 5000033,...5000064 , 1000033,...10000064 在第二个循环中

有没有办法正确地做到这一点?

我正在尝试使用 os.walk,它允许我循环遍历我的目录,但我不知道如何使这个循环适应我所需的 32 个批次?

for dirName, subdirList, fileList in os.walk(rootdir):
      print('Found directory: %s' % dirName)
      for fname in sorted(fileList):
        img_path = os.path.join(dirName, fname)
        try:
          img = load_img(img_path, target_size=None)
          imgs.append(img)
        except Exception as e:
          print(str(e), fname, i)
      #do something on imgs

编辑

你所有的评论都会给我这样的东西:

dir1/img1.jpg 到 dir1/img32.jpg 然后 dir1/img33.jpg 到 dir1/img64.jpg 然后 ...

然后 dir2/img1.jpg 到 dir1/img32.jpg 然后 dir2/img33.jpg 到 dir2/img64.jpg 然后 ...

然后 dir3/img1.jpg 到 dir3/img32.jpg 然后 dir3/img33.jpg 到 dir3/img64.jpg :(

我想要实现的是:

dir1 numero 1 到 32 的文件 + dir2 numero 1 到 32 的文件 + dir3 numero 1 到 32 的文件然后

dir1 numero 33 到 64 的文件 + dir2 numero 33 到 64 的文件 + dir3 numero 33 到 64 的文件在同一个循环中

【问题讨论】:

标签: python file loops


【解决方案1】:

os.walk 已经返回了一个生成器,该生成器将即时生成一个三元组 (dirpath, dirnames, filenames) 值,因此您只需要以 32 个批次生成文件名数组的切片。强>


这是一个例子:

import os

# Your root directory path
rootdir = r"Root"

#Your batch size
batch_size = 32

def walk_dirs(directory, batch_size):
    walk_dirs_generator = os.walk(directory)
    for dirname, subdirectories, filenames in walk_dirs_generator:
        for i in range(0, len(filenames), batch_size):
            # slice the filenames list 0-31, 32-64 and so on
            yield [os.path.join(dirname, filename) for filename in filenames[i:i+batch_size]]

# Finally iterate over the walk_dirs function which itself returns a generator
for file_name_batch in walk_dirs(rootdir, batch_size):
    for file_name in file_name_batch:
        # Do some processing on the batch now
        print (file_name)
        pass

【讨论】:

  • 再次给我一个目录下的 32 个文件的批次。例如,我有 3 个目录厨房浴室和卧室,使用您的代码我得到 kitchen/img1.jpg 到 kitchen/img32.jpg,然后我得到 kitchen/img33.jpg 到 kitchen/img64.jpg,我不希望我想在同一个循环中将 kitchen/img1.jpg 到 kitchen/img32.jpg + 浴室/img1.jpg 到浴室/img32.jpg + 卧室/img1.jpg 到卧室/img32.jpg
  • 我不知道我想要实现的目标是否明确,但我需要每个目录的第一个文件一次生产,然后每个目录的第二批等
  • @HadrienBerthier 是的,有要求,让我检查一下
【解决方案2】:

你可以看看os.walk()

编辑:简单的反例

counter = 0
for x in mylist:
    # do something with x 
    todo_list.append(x)
    counter += 1
    if counter % 32 == 0: 
        # do something with todo list
        todo_list = [] # empty todo list for next batch

【讨论】:

  • 我更新了我的帖子,我知道 os.walk 的存在,但不知道如何循环 32 个文件和 32 个下一个文件等。
  • 在循环时,您可以保留一个计数器,当它达到 32 时执行某些操作,然后重置
  • 获取每个目录的前 32 个文件是可行的,但对于文件 33-64、65-96 等则不行,因为我的循环会在前 32 个重复。
  • 我无法将所有图像加载到内存中,所以这不起作用,我无法列出所有图像。
  • 您可以每 32 张图片清除一次列表并加载下 32 张不?
【解决方案3】:

如果总是使用相同的 img 列表并在您有 32 张图像时立即处理它呢?

for dirName, subdirList, fileList in os.walk('c:\\Java\\'):
      print('Found directory: %s' % dirName)
      for fname in sorted(fileList):
        img_path = os.path.join(dirName, fname)
        try:
          img = load_img(img_path, target_size=None)
          imgs.append(img)
          if len(imgs) == 32:
            print("Doing what I have to with current imgs list (add your function here)")
            img = [] # cleaning img list
        except Exception as e:
          print(str(e))
      #do something on imgs

如果您需要跟踪所有以前的列表,您可以简单地复制列表内容。

如果你也想要那个实现,请告诉我。

【讨论】:

  • 使用这种方法,我将加载第一个目录的每 32 个图像,然后是第二个目录等我需要 imgs 数组中每个目录的 32 个图像,然后是 img 33-64 等
【解决方案4】:

好的,我找到了一种方法,不是最漂亮的,但它是: 我使用一组来知道我已经看过哪个文件,如果我在上面,我会继续,所以它不算数。

number_of_directory = 17
batch_size = 32
seen = set()
for overall_count in pbar(range(data_number // (batch_size * number_of_directory))):
    imgs = []
    for dirName, subdirList, fileList in os.walk(rootdir):
        count = 0
        for fname in sorted(fileList):
          if fname in seen:
            continue
          if count == batch_size:
            break
          img_path = os.path.join(dirName, fname)
          try:
            img = cv2.imread(img_path, cv2.IMREAD_COLOR)
            img = cv2.resize(img, (img_width, img_height))
            imgs.append(np.array(img))
          except Exception as e:
            print(str(e), fname)
          seen.add(fname)
          count +=1
    #Do something with images

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 2020-06-25
    • 2014-04-10
    相关资源
    最近更新 更多