0

我有一个目录,其中包含来自三个不同域的数千张图像

假设文件名是 xxx_A.png 和 yyy_B.png 和 zzz_C.png 每个域都有数千个

os.listdir()将返回目录中所有图像名称的列表

然后我想根据一些百分比过滤这个列表

示例:我指定我想要从这数千张图像中,只有 100 张经过洗牌的图像,其中 30% 来自 domainA,30% 来自 domainB,40% 来自 domainC

所以简单地给定一个数字,我有这些百分比,然后我选择 x 个随机图像(肯定基于图像名称,因为它们已经指定),这将是新列表

例子:

输入:

['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']

我想要 12 张图片,30% 来自域 A,30% 来自域 B,40% 来自域 C

输出:

 ['1_C.png', '10_C.png', '2_B.png', '4_A.png', '3_A.png', '9_C.png', '7_C.png', '6_A.png', '8_B.png', '10_B.png', '3_C.png', '5_C.png']

我怎样才能做到这一点?

4

3 回答 3

1

下面是我定义的一个函数。正如 Martin 所说,math.ceil 可能是用于获取文件数量的最佳函数(因此您获得的文件数量不会少于您想要的数量)。此外,您将希望在不替换的情况下进行采样(这意味着您不想重复文件名),因此您不应像 Rakesh 那样使用 random.choice(作为带有替换的 random.choice 样本)。random.shuffle 避免了这个问题。

输入:

import random
import math
os_dir_list= ['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']       
def shuffle_pick(os_dir_list,length, tuple_list):
    shuffled_list = []
    for letter,percent in tuple_list:
        sub_list = [img for img in os_dir_list if img.endswith(letter + '.png')]
        random.shuffle(sub_list)
        num = int(math.ceil(len(sub_list)*percent/100))
        shuffled_list += sub_list[:num]
    return shuffled_list[:length]

print(shuffle_pick(os_dir_list, 12, [('A',30),('B',30),('C',60)]))

输出:

['1_A.png', '5_A.png', '3_A.png', '6_A.png', '1_B.png', '7_B.png', '9_B.png', '5_B.png', '10_C.png', '4_C.png', '3_C.png', '9_C.png']

您还可以random.shuffle(shuffled_list)在 return 语句之前调用以打乱输出列表。

于 2018-09-25T08:17:39.413 回答
0

这是一种可能的方法:

  1. 首先使用 . 将所有文件名拆分为基于字母的域defaultdict(list)。例如一个看起来像的字典:

    {'A' : ['file1_A.jpg', 'file2_A.jpg'], 'B' : ['file1_B.jpg']}
    
  2. 对于每个域,用于random.sample()从域中随机抽取所需数量的文件到输出列表中。 math.ceil()用于通过向上舍入来确保始终存在足够的文件。

  3. 最后,打乱组合输出列表(如果需要)并确保存在正确的文件总数。

这将导致输出具有来自每个域的随机元素的精确分布。

from collections import defaultdict
import random
import math

domains = defaultdict(list)

files = ['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']

for file in files:
    domains[file[-5]].append(file)

total_required = 12
output = []    

for key, percentage in (('A', 30.0), ('B', 30.0), ('C', 40.0)):
    len_required = int(math.ceil(percentage * total_required / 100.0))
    output.extend(random.sample(domains[key], len_required))

random.shuffle(output)
output = output[:total_required]

print(len(output), output)

给出可能的输出:

12 ['6_B.png', '2_B.png', '3_B.png', '10_A.png', '1_A.png', '6_A.png', '2_C.png', '1_B.png', '1_C.png', '3_C.png', '2_A.png', '10_C.png']    

在 Python 3.6.6 上测试

于 2018-09-25T07:57:19.293 回答
0

这是一种方法。我正在使用字典将图像从不同的域中分离出来,然后计算每个域所需的图像数量。

演示:

import random    

inputData = ['1_A.png', '2_A.png', '3_A.png', '4_A.png', '5_A.png', '6_A.png', '7_A.png', '8_A.png', '9_A.png', '10_A.png', '1_B.png', '2_B.png', '3_B.png', '4_B.png', '5_B.png', '6_B.png', '7_B.png', '8_B.png', '9_B.png', '10_B.png', '1_C.png', '2_C.png', '3_C.png', '4_C.png', '5_C.png', '6_C.png', '7_C.png', '8_C.png', '9_C.png', '10_C.png']

d = {"A": [], "B":[], "C":[]}
#for i in os.listdir("path"):
for i in inputData:           #Group images by domain. 
    if "A" in i:
        d["A"].append(i)
    elif "B" in i:
        d["B"].append(i)
    else:
        d["C"].append(i)

percentage = {"A": 30, "B": 30, "C": 60} 

res = []
for k, v in d.items():
    res.extend([random.choice(v) for i in range(int((percentage[k] * len(v)) / 100.0))])
print(res) 

输出:

['7_A.png', '8_A.png', '9_A.png', '6_C.png', '8_C.png', '9_C.png', '7_C.png', '9_C.png', '7_C.png', '1_B.png', '6_B.png', '2_B.png']
于 2018-09-25T08:03:55.700 回答