文章目录
FiftyOne——数据集、样本等的基础操作
引言
概念
-
样本 sample
指的是某个数据实例,例如一张图片,但注意在FiftyOne只是把sample实例的某个filepath属性指向具体数据的路径,并不把数据载入到程序中。 -
字段 fields
一个字段指的是样本的一个信息,例如 filepath指的是一个sample对应数据的路径。除了filepath外,还有其它的例如id等字段 -
数据集 dataset
指的是FiftyOne创建的抽象数据集概念。指的是一些sample的组织关系。不是指具体的图像数据。
三者的关系就是,
一个dataset是一些sample的组织关系,每个sample里面有多个fields。
数据集 dataset
保存\删除数据集
dataset1.persistent = True # 保存数据集,正常情况下,当退出终端的时候,程序中的数据集将会被自动清空。
dataset1.deleted # 将会从离线和在线中都删除
查看现有数据集
fo.list.datasets()
指定数据集名称
dataset.name = "名称"
数据集信息的记录
每个数据集都由一个info属性,其实就是一个字典,你可以往里面添加你的各种备注的消息,然后保存在里面文件中
import fiftyone as fo
dataset = fo.Dataset()
# Store a class list in the dataset's info
dataset.info = {
"dataset_source": "https://...",
"author": "...",
}
# Edit existing info
dataset.info["owner"] = "..."
dataset.save() # 必须调用这个语句才能保存在硬盘里面
返回样本迭代器
samples = dataset.iter_samples()
样本 sample
载入样本
可以看到,一个sample并不是载入实际的数据,而是记录了他的路径
# An image sample
sample = fo.Sample(filepath="/path/to/image.png")
# A video sample
another_sample = fo.Sample(filepath="/path/to/video.mp4")
将样本添加到数据集中
dataset = fo.Dataset("example_dataset")
dataset.add_sample(sample)
# 或者批量加入
dataset.add_samples(
[
fo.Sample(filepath="/path/to/image1.jpg"),
fo.Sample(filepath="/path/to/image2.jpg"),
fo.Sample(filepath="/path/to/image3.jpg"),
]
)
样本ID
样本被添加到数据集后,在数据集中会自动有一个独立的ID号,便于后续的访问。
print(sample.id)
# 5ee0ebd72ceafe13e7741c42
访问样本
# 遍历访问
for sample in dataset:
print(sample)
#####################
# 最后最初
first_sample = dataset.first()
last_sample = dataset.last()
#######################
# ID或者路径访问
same_sample = dataset[sample.id]
print(same_sample is sample)
# True
also_same_sample = dataset[sample.filepath]
print(also_same_sample is sample)
# True
从数据集中删除样本
可以通过样本唯一的ID号和路径删除样本
dataset.delete_samples(sample_id) # 通过ID
# equivalent to above
del dataset[sample_id] # 通过ID
dataset.delete_samples([sample_id2, sample_id3]) # 批量通过ID
数据集批量随机删除样本
可以采用实例的方式从数据集中删除样本
# Remove a random sample
sample = dataset.take(1).first() # 随机取出1个
dataset.delete_samples(sample)
# Remove 10 random samples
view = dataset.take(10)# 随机取出10个
dataset.delete_samples(view)
字段 fields
一个sample中可以有多个fields,每个field含有sample的信息。
默认字段
访问样本的字段名称
sample.field_names
#('filepath', 'media_type', 'tags', 'metadata')
dataset.get_field_schema() # 数据集的纲要
"""输出
OrderedDict([
('media_type', <fiftyone.core.fields.StringField at 0x11c77add8>),
('filepath', <fiftyone.core.fields.StringField at 0x11c77ae10>),
('tags', <fiftyone.core.fields.ListField at 0x11c790828>),
('metadata', <fiftyone.core.fields.EmbeddedDocumentField at 0x11c7907b8>)
])
"""
访问字段的值
sample.filepath
sample["filepath"] # equivalent
往样本里面添加字段
要求一个数据集里面的样本的同个字段的值的类型是一样的。
如果一个数据集中的样本添加了新的字段,那么这个数据集的所有样本都会生成一个相应的字段,其值被默认为None。
相反的,如果在数据集中删除了一个样本的字段,那么它只会把值变为None。
sample["integer_field"] = 51 # 添加一个新的字段
sample.save() # 需要调用这个命令才会保存样本的更改
del sample["integer_field"] # 删除一个字段
dataset.delete_sample_field("integer_field") #删除数据集中所有样本的同一个字段
标签字段 Tags
这个功能比较好用,字面意思,就是给样本打上标签,方便批量访问注意和Labels区分。
dataset = fo.Dataset("tagged_dataset")
dataset.add_samples(
[
fo.Sample(filepath="/path/to/image1.png", tags=["train"]),
fo.Sample(filepath="/path/to/image2.png", tags=["test", "low_quality"]),
]
)
print(dataset.distinct("tags").values)
# ["test", "low_quality", "train"]
###########################################################
#这个字段是一个列表字段,同一个样本可以添加多个标签
sample.tags.append("new_tag")
sample.save()# 记得调用
标注字段 Labels
这边的Labels 与上面的 Tags的区别在于,Labels相当于我们常说的一张图片是否有标注的那个意思,用于有监督训练。Tags只是方便组织管理样本而已。
这边的标签字段支持以下类型
Provide some default fields
label = fo.Classification(label="cat", confidence=0.98)
Add custom fields
label["int"] = 5
label["float"] = 51.0
label["list"] = [1, 2, 3]
label["bool"] = True
label["dict"] = {"key": ["list", "of", "values"]}
类标签 classification
类标签classification是标签labels的一个类型。是FiftyOne针对分类任务设定的一个默认标签类型。
import fiftyone as fo
sample = fo.Sample(filepath="/path/to/image.png")
sample["ground_truth"] = fo.Classification(label="sunny")
sample["prediction"] = fo.Classification(label="sunny", confidence=0.9)
print(sample)
"""
<Sample: {
'id': None,
'media_type': 'image',
'filepath': '/path/to/image.png',
'tags': [],
'metadata': None,
'ground_truth': <Classification: {
'id': '5f8708db2018186b6ef66821',
'label': 'sunny',
'confidence': None,
'logits': None,
}>,
'prediction': <Classification: {
'id': '5f8708db2018186b6ef66822',
'label': 'sunny',
'confidence': 0.9,
'logits': None,
}>,
}>
"""
####多分类标签
import fiftyone as fo
sample = fo.Sample(filepath="/path/to/image.png")
sample["ground_truth"] = fo.Classifications(
classifications=[
fo.Classification(label="animal"),
fo.Classification(label="cat"),
fo.Classification(label="tabby"),
]
)
sample["prediction"] = fo.Classifications(
classifications=[
fo.Classification(label="animal", confidence=0.99),
fo.Classification(label="cat", confidence=0.98),
fo.Classification(label="tabby", confidence=0.72),
]
)
print(sample)
"""
import fiftyone as fo
sample = fo.Sample(filepath="/path/to/image.png")
sample["ground_truth"] = fo.Classifications(
classifications=[
fo.Classification(label="animal"),
fo.Classification(label="cat"),
fo.Classification(label="tabby"),
]
)
sample["prediction"] = fo.Classifications(
classifications=[
fo.Classification(label="animal", confidence=0.99),
fo.Classification(label="cat", confidence=0.98),
fo.Classification(label="tabby", confidence=0.72),
]
)
print(sample)
"""
目标检测标签 Detections 类
import fiftyone as fo
sample = fo.Sample(filepath="/path/to/image.png")
sample["ground_truth"] = fo.Detections(
detections=[fo.Detection(label="cat", bounding_box=[0.5, 0.5, 0.4, 0.3])]# 矩形框为[左上角的宽x,左上角的高y,宽长w,高长h]
)
sample["prediction"] = fo.Detections(
detections=[
fo.Detection(
label="cat",
bounding_box=[0.480, 0.513, 0.397, 0.288],
confidence=0.96,
),
]
)
print(sample)