Fiftyone 可视化

文章结构

  • 导入数据集
  • 打开可视化界面显示
  • 加载自己的预测
  • 数据集评估
  • 结果分析

导入数据集

fiftyone支持许多官方数据集,如coco等。这些数据集的加载方式较为简单。可直接使用官方提供的加载方式:

import fiftyone as fo
import fiftyone.brain as fob
import fiftyone.zoo as foz
import numpy as np
import cv2
import json
from collections import defaultdict
# 加载官方数据集coco2017
dataset = foz.load_zoo_dataset(
    "coco-2017",
    split="validation",
    dataset_name="evaluate-detections-tutorial",
)

但是许多时候我们的数据集存在本地,我们需要加载本地的数据集。这时候可以利用另一种方法:

dataset = fo.Dataset.from_dir(
   dataset_type=fo.types.COCODetectionDataset,
   data_path=image_path,
   labels_path=label_path,
)

这里的image_path为你保存图片的路径。而这里的label_path为你的json文件。注:如果是VOC格式的文件也可以使用一些转换脚本。我们可以使用print来打印数据集的信息:

图1 数据集的一些信息
这里显示数据集中有241张图片。

打开可视化界面显示

fiftyone的强大功能在于他的可视化。虽然我们也能直接读取出预测结果,然后在图片上进行绘制标签。但每当进行一个新的任务时,我们都需要修修改改,很不方便。fiftyone提供了一个可视化界面给我们直接观看预测结果,而不用自己去一张一张的绘制标签。

session = fo.launch_app() # 打开APP
session.dataset = dataset # 添加数据集
图2 fiftyone的可视化APP

我们可以打开每一张图片查看具体信息:

图3 fiftyone的图片详细信息展示

加载自己的预测

上述只是将数据集中的标注可视化,没有实际意义。我们需要加入自己的预测进行对比。官网给出的方式为将数据集中的图片读取出送入预测网络中进行端到端的添加。我们这里已经有预测结果了,需要做出一些改变。直接通过image_id字段添加。

image_path = '/home/xx/桌面/boat-voc/JPEGImages/'
labels_path = '/home/xx/桌面/boat-voc/val.json'
predict_path = '/home/xx/桌面/boat-voc/MSMF.json'

dataset = fo.Dataset.from_dir(
   dataset_type=fo.types.COCODetectionDataset,
   data_path=image_path,
   labels_path=labels_path,
)
# val json
with open(labels_path) as f:
    val = json.load(f)

# prediction json file
with open(predict_path) as f:
    predict_results = json.load(f)

# 建立图片id到预测的映射
id2predict = defaultdict(list)
with fo.ProgressBar() as pb:
    print('generate the id2predict')
    for result in pb(predict_results):
        id2predict[result['image_id']].append(result)

# 建立图像名称到image_info的映射
image2instance = {}
with fo.ProgressBar() as pb:
    print('generate the image2id')
    for result in pb(val['images']):
        image2instance[result['file_name']] = result

# 类别标签
classes = dataset.default_classes
# 需要增加预测的图片
predictions_view = dataset.view()

# 添加预测
with fo.ProgressBar() as pb:
    for sample in pb(predictions_view):
        image_name = sample['filepath'].split('/')[-1]
        image_id = image2instance[image_name]['id']
        w, h = image2instance[image_name]['width'], image2instance[image_name]['height']
        detections_free = []
        for image_result_i in id2predict[image_id]:
            # msmf
            x1, y1, w1, h1 = image_result_i['bbox']
            rel_box = [x1 / w, y1 / h, w1 / w, h1 / h]
            detections_free.append(
                fo.Detection(
                    label=classes[image_result_i['category_id']],
                    bounding_box=rel_box,
                    confidence=image_result_i['score']
                )
            )
            
        sample['FREE'] = fo.Detections(detections=detections_free)
        sample.save()
print("Finished adding predictions")
session = fo.launch_app() # 打开APP
session.dataset = dataset # 添加数据集
session.view = predictions_view # 添加预测

这次打开APP显示之后,你会发现多了一个在ground_truth旁边多了一个字段。这个字段的名字为FREE即为我们添加的预测。

图4 fiftyone添加预测展示
我们可以每一张查看预测的效果。但在很多图片中出现了多余的框,这是由于我们没有调节置信度阈值所导致的。我们可以在APP中直接调节阈值而不用重新生成。我们可以在FREE的下拉列表中调节confidence的值来过滤掉低分的框。也可以在查看图片时在下拉列表里面设置。
图5 fiftyone调整阈值1
图6 fiftyone调整阈值2
设置阈值后,低于阈值的得分将被丢弃,只会显示高于阈值的结果。这样下来整个界面就比较清晰了。
图5 0.5置信度。粉红的为预测,绿色的为真值。

数据集评估

fiftyone 支持许多独特的数据集评估方式。我们可以按照coco数据集的方式去评估预测。对于上一步我们添加的数据集来说我们可以直接使用下面的代码进行评估:

results_FREE = predictions_view.evaluate_detections(
    "FREE",		
    gt_field="ground_truth",	
    eval_key="eval_free",
    compute_mAP=True,
)

FREE为需要评估的预测,gt_field为真值标签。这里的具体值对应我们我们的设置。比如我们在添加预测时使用了这一行代码sample['FREE'] = ......。这说明我们将预测添加后命名为FREE。如果自己不确定名字也可以打开APP查看名字。
得到了评估结果后我们可以根据我们的需求进行查看。在这里实现几个评估:

  • 实现基本的mAP计算。直接打印结果即可:
图6 mAP计算。
  • 打印每一类别详细的报告(左),和只打印具体类别的报告(右):
图7 打印所有类别报告
图8 打印单个类别报告
  • 显示PR曲线。和打印类别报告类似,我们也可以通过classes控制显示的类别:
图9 打印两条PR曲线
图10 打印全部PR曲线
事实上,官方还给出了一种评估方式,但这种评估方式是存在问题的。在前面说道,我们可以设置置信度阈值去丢弃低分的预测。为了评估丢弃后的效果,官方还给出了另一种评估方法:
score_thr = 0.5
high_score_predict = predictions_view.filter_labels("FREE", F("confidence") > score_thr)
high_result = high_score_predict.evaluate_detections(
    "FREE",		
    gt_field="ground_truth",	
    eval_key="eval_free",
    compute_mAP=True,
)
图11 0.5为阈值mAP。
图12 0.9为阈值mAP。
显然,0.9为阈值的mAP与0.5为阈值的mAP不应该呈现如此的情况。事实上在重新生成json文件时,使用0.9为阈值的预测,使用cocoAPI仅仅能够得到小数位的mAP。

错误修订:事实上,官方给的样例是存在问题的。但是fiftyone是支持按照不同阈值来评估mAP的。不过我们需要添加一些参数:

图13 0.9为阈值mAP正确用法。
注意在过滤时我们需要添加`only_matches=False`。否则在过滤后的样本中只会剩下含有预测的样本!!!!。

结果分析

样本级别的分析

fiftyone 提供了样本级别的分析。在评估后,再一次打开APP界面你会发现多了三个字段TP,FP,FN分别对应了True Positive, False Positive,False Negative。再次打开app之后会出现这几个字段:

图14 评估后多出来的字段
我们可以根据这些字段去查看表现最好的样本(最多的TP数量),表现最差的样本(最多的FP数量)
# 按照表现最好的样本排序
session.view = high_score_predict.sort_by('eval_free_tp',reverse=True) # 这里是以0.5为阈值的结果
# 按照表现最差的样本排序
session.view = high_score_predict.sort_by('eval_free_fp',reverse=True) # 这

小目标样本分析

在上诉的view视图中,我们仅仅按照分数大于某个阈值的的条件进行过滤。事实上,view能够完成更多复杂的操作,比如按照区域的大小来过滤。在coco数据集中像素数量少于 3 2 2 32^2 322的作为小样本。在这里我们采用同样的条件过滤:

# 计算,使得我们可以利用图像的宽度,和高
dataset.compute_metadata()
# 这里面的数据构建方式为[left-top-x, left-top-y, normalize-h, normalize-w]
# 使用width*normalize-h, high*normalize-w恢复原来的区域大小.
bbox_area = (
    F("$metadata.width") * F("bounding_box")[2] *
    F("$metadata.height") * F("bounding_box")[3]
)
small_boxes = bbox_area < 32 ** 2
# 注意这里没有only_matches没有使用false。也就是仅仅保留含有预测的图像
small_boxes_view = dataset.filter_labels("FREE", small_boxes)
session.view = small_boxes_view

得到了这个view之后,我们可以利用之前介绍的方法去进行评估和可视化。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值