【数据集管理】使用 Fiftyone 管理数据集,大型数据集也不在话下!
- 1. Fiftyone 安装
- 2. 数据集的加载与导出
- 2.1 本地数据集操作
- 2.1.1 创建 session
- 2.1.2 加载数据集
- 2.1.2.1 加载 YOLO 格式的数据集
- 2.1.2.2 加载本地数据库中的数据集
- 2.1.2.3 同时加载数据集 train 和 val
- 2.1.3 数据集导出
- 2.1.3.1 YOLO 格式数据集导出
- 2.1.3.2 Fiftyone 格式数据集导出
- 2.1.4 查看及删除本地数据集
- 2.2 远程操作数据集
- 3. 对数据进行打标签操作
- 3.1 图像打标签(单个/批量)
- 3.1.1 session 中单个打标签
- 3.1.2 使用脚本给已知路径的数据批量打标签
- 3.2 图像删除标签(单个/多个)
- 3.3 匹配标签数据筛选
- 4. 踩坑记录
- 4.1 浏览器页面白屏-已解决
链接: Fiftyone 官网
1. Fiftyone 安装
# 要求 python 版本 ≥3.7,≤3.10
# 直接使用 pip 指令安装即可# TODO 网页版安装指令
pip install fiftyone
# TODO 桌面版安装指令
pip install fiftyone-desktop
2. 数据集的加载与导出
Fiftyone 工作流程是打开一个 Python Shell 并加载一个 Datasets,通过 Sessions 进行交互。
2.1 本地数据集操作
2.1.1 创建 session
import fiftyone as fo# 使用桌面版 APP
# session = fo.launch_app(desktop=True)
# session.wait() # 保持 APP 登录状态,直到手动退出# 使用网页版
session = fo.launch_app(port=5151) # 默认端口为 5151
创建成功的 session 展示
2.1.2 加载数据集
2.1.2.1 加载 YOLO 格式的数据集
使用 fo.Dataset.from_dir()
加载本地文件夹中的数据集
import fiftyone as foname = 'my_test'
dataset_dir = r"D:\fiftyone\test"
dataset_type = fo.types.YOLOv5Dataset # * 加载YOLO格式的数据集
# dataset_type=fo.types.FiftyOneDataset # * 加载FiftyOne格式的数据集dataset = fo.Dataset.from_dir(dataset_dir = dataset_dir,dataset_type = dataset_type,name = name,
)dataset.persistent = True # * 持久化保存数据集,防止关闭session后数据集删除
session = fo.launch_app(dataset, port=5151) # * 默认端口为5151
2.1.2.2 加载本地数据库中的数据集
使用 fo.load_dataset(name)
加载本地数据库中数据集(通过 Fiftyone 保存在本地的数据集)
import fiftyone as foname = 'SmokeFire_test'
dataset = fo.load_dataset(name)
session.dataset = dataset
2.1.2.3 同时加载数据集 train 和 val
使用dataset = fo.Dataset(name)
加载空数据集后使用dataset.add_dir()
追加多个子数据集
import fiftyone as foname = 'Person_car_hard_ver002'
dataset_dir = r"/media/gll/fiftyone/XingRenHeCheLiangJianCe_detection_hard_samples_20240531_802_ver002"
dataset_type = fo.types.YOLOv5Dataset # * 加载YOLO格式的数据集splits = ["train", "val"]dataset = fo.Dataset(name)
for split in splits:dataset.add_dir(dataset_dir = dataset_dir , dataset_type = fo.types.YOLOv5Dataset, split = split,tags = split)dataset.persistent = True # * 持久化保存数据集,防止关闭session后数据集删除
session = fo.launch_app(dataset, remote=True)
数据集加载成功展示
2.1.3 数据集导出
2.1.3.1 YOLO 格式数据集导出
使用YOLO格式导出指定名称数据集到指定路径下
import fiftyone as fo
dataset = fo.load_dataset("my_test")export_dir = r"D:\fiftyone\my_test_export_yolo"
export_format = fo.types.YOLOv5Dataset
dataset.export(export_dir=export_dir, dataset_type=export_format)
但上述导出方式不会保存如 Sample tags 等的元数据信息,若需全部保存,则需使用 Fiftyone 格式导出。
2.1.3.2 Fiftyone 格式数据集导出
import fiftyone as fo
dataset = fo.load_dataset("SmokeFire_val_test")export_dir = r"D:\fiftyone\SmokeFire_val_test_export_fiftyone"
export_format = fo.types.FiftyOneDataset
dataset.export(export_dir=export_dir, dataset_type=export_format)
导出数据集格式如下:
2.1.4 查看及删除本地数据集
# 查看本地数据库数据集
print(fo.list_datasets())# 删除指定名称数据集
fo.delete_dataset(dataset_name)
2.2 远程操作数据集
若要在远程服务器上使用 fiftyone 进行数据集管理,则需要远程连接数据集。在登录 session 界面时使用remote=True
实现远程控制
import fiftyone as foname = 'Person_ver001'
dataset_dir = "/media/gll/fiftyone/ver001"
dataset_type = fo.types.YOLOv5Dataset # * 加载YOLO格式的数据集dataset = fo.Dataset.from_dir(dataset_dir = dataset_dir,dataset_type = dataset_type,name = name,
)dataset.persistent = True # * 持久化保存数据集,防止关闭session后数据集删除
session = fo.launch_app(dataset, remote=True)
上述代码执行后,数据集成功加载结果展示如下:
但此时还不能通过 session 直接访问数据集,还需要在本地终端中运行指令ssh -N -L 5151:127.0.0.1:5151 username@hostname
,使用 ssh 实现远程连接
连接成功后在浏览器打开默认端口localhost:5151
,即可以看到已经成功加载的远程数据集。
3. 对数据进行打标签操作
3.1 图像打标签(单个/批量)
3.1.1 session 中单个打标签
- 选中图像后批量添加标签,在 Samples 下新建或选择已有 tags 并应用即可为选定图像打上标签。
3.1.2 使用脚本给已知路径的数据批量打标签
下述示例代码假设图像名称存储在指定 txt 文件中
import fiftyone as fo
import os# 1. 读取txt文件,获取图像名称列表
def read_image_names_from_txt(txt_file_path):with open(txt_file_path, 'r') as file:image_names = [line.strip() for line in file.readlines()]return image_names# 2. 加载Fiftyone格式的本地数据库
def load_fiftyone_dataset(dataset_name):return fo.load_dataset(dataset_name)# 3. 匹配图像名称并添加tags
def match_and_tag_images(txt_file_path, dataset_name, tags):image_names = read_image_names_from_txt(txt_file_path)dataset = load_fiftyone_dataset(dataset_name)matched_samples = []for sample in dataset:if sample.filepath.split(os.sep)[-1] in image_names:sample.tags.extend(tags)sample.save()matched_samples.append(sample.filepath.split(os.sep)[-1] )return matched_samplestxt_file_path = r"E:\project\0_Tools\fiftyone\SmokeFire_val.txt"
dataset_name = "fiftyone_test"
tags_to_add = ["test_tags"]matched_and_tagged_images = match_and_tag_images(txt_file_path, dataset_name, tags_to_add)
# print(f"Matched and tagged images: {[sample for sample in matched_and_tagged_images]}")
print(f"Number of matched and tagged images: {len(matched_and_tagged_images)}")
- 未打标签前展示
- 打标签后展示
3.2 图像删除标签(单个/多个)
import fiftyone as fo# 1. 加载本地数据库
def load_dataset(dataset_name):return fo.load_dataset(dataset_name)# 2. 筛选图像并移除tags
def remove_tags(dataset_name, tags_to_del):dataset = load_dataset(dataset_name)view = dataset.match_tags(tags_to_del)print(f"Number of samples: {len(view)}")for sample in view:# print(sample.filepath, sample.tags)for tag in tags_to_del:if tag in sample.tags:sample.tags.remove(tag)sample.save()# 打印筛选结果以验证view_after = dataset.match_tags(tags_to_del)print(f"Filtered samples: {len(view_after)}")for sample in view_after:print(sample.filepath, sample.tags)dataset_name = "fiftyone_test"
tags_to_del = ["test_tags", "test_tags1"]
remove_tags(dataset_name, tags_to_del)
3.3 匹配标签数据筛选
在界面中选择多个 tags标签查看时,筛选结果为所选 tags 的并集,故需使用下述代码筛选符合 tags 匹配的交集数据。
# 加载数据库
dataset = fo.load_dataset("SmokeFire_val_test")# 筛选tag为"场景-开源P图", "季节-春天", "时间-下午"的图像
view = dataset.match_tags(["场景-开源P图", "季节-春天", "时间-下午"], all=True) # all 为选择匹配图像的交集# 或者获取满足条件的图像的样本
matching_samples = list(view)
matching_samples_paths = [s.filepath for s in matching_samples]with open("matching_samples_paths.txt", "w") as f:for path in matching_samples_paths:f.write(path + "\n")print('nums --> ', len(matching_samples_paths))
- 筛选示例如下
4. 踩坑记录
4.1 浏览器页面白屏-已解决
- 问题分析:通过查看浏览器 ‘检查’ 项,发现 MIME 类型不匹配
- 解决方案:https://github.com/voxel51/fiftyone/issues/2010
按上述方法修改后重启,并未解决 - 修改
计算机\HKEY_CLASSES_ROOT.js
的Content Type
为text/javascript
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.js
中添加Content Type
为text/javascript
修改后可以在浏览器中正常显示加载 session