我有一个目录,其中包含来自三个不同域的数千张图像
假设文件名为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张图像,其中A域占30%,B域占30%,C域占40%
输出:
['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']
我该怎么做?
答案 0 :(得分: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']
您还可以在return语句之前调用random.shuffle(shuffled_list)
,以随机排列输出列表。
答案 1 :(得分:0)
这是一种可能的方法:
首先使用defaultdict(list)
根据字母将所有文件名分成多个域。例如像这样的字典:
{'A' : ['file1_A.jpg', 'file2_A.jpg'], 'B' : ['file1_B.jpg']}
对于每个域,使用random.sample()
将域中所需数量的文件随机放入输出列表中。 math.ceil()
用于通过始终向上舍入来确保始终存在足够的文件。
最后,随机组合合并的输出列表(如果需要),并确保存在正确的文件总数。
这将导致输出具有每个域中随机元素的精确分布。
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上测试
答案 2 :(得分: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']