(二十七)mmdetection实用工具: Visualization

2023-09-21 10:42:52

一、基础绘制接口

可视化器(Visualizer):可视化器负责对模型的特征图、预测结果和训练过程中产生的结构化日志进行可视化,支持 Tensorboard 和 WanDB 等多种可视化后端。

import torch
import mmcv
from mmengine.visualization import Visualizer
image = mmcv.imread('/home/mby/图片/cat_and_dog.jpg',
                    channel_order='rgb')
 #可视化器初始化
visualizer = Visualizer(image=image)
# 绘制单个检测框, xyxy 格式
visualizer.draw_bboxes(torch.tensor([80, 200, 600, 650]))
# 绘制多个检测框
visualizer.draw_bboxes(torch.tensor([[640, 50, 1550, 650], [80, 200, 600, 650]]))
visualizer.show()
#为Visualizer设置绘制的图像
visualizer.set_image(image=image)
visualizer.draw_texts("cat and dog", torch.tensor([10, 20]))
visualizer.draw_bboxes(torch.tensor([80, 200, 600, 650]),
                       edge_colors='r',
                       line_widths=3)
visualizer.draw_bboxes(torch.tensor([[640, 50, 1550, 650]]),line_styles='--')
visualizer.show()

draw_bboxes()函数定义:

def draw_bboxes(
    self,
    bboxes: Union[np.ndarray, torch.Tensor],
    edge_colors: Union[str, tuple, List[str], List[tuple]] = 'g',
    line_styles: Union[str, List[str]] = '-',
    line_widths: Union[Union[int, float], List[Union[int, float]]] = 2,
    face_colors: Union[str, tuple, List[str], List[tuple]] = 'none',
    alpha: Union[int, float] = 0.8,#矩形框的透明度
) -> 'Visualizer':
import mmcv
from mmengine.visualization import Visualizer
import numpy as np
from torchvision.models import resnet18
from torchvision.transforms import Compose, Normalize, ToTensor
#预处理
def preprocess_image(img, mean, std):
    preprocessing = Compose([
        ToTensor(),
        Normalize(mean=mean, std=std)
    ])
    return preprocessing(img.copy()).unsqueeze(0)
#模型
model = resnet18(pretrained=True)
#前向过程:
def _forward(x):
    x = model.conv1(x)
    x = model.bn1(x)
    x = model.relu(x)
    x = model.maxpool(x)

    x1 = model.layer1(x)
    x2 = model.layer2(x1)
    x3 = model.layer3(x2)
    x4 = model.layer4(x3)
    return x4
image = mmcv.imread('/home/mby/图片/cat_and_dog0.jpeg',
                    channel_order='rgb')
model.forward = _forward

image_norm = np.float32(image) / 255
input_tensor = preprocess_image(image_norm,
                                mean=[0.485, 0.456, 0.406],
                                std=[0.229, 0.224, 0.225])
feat = model(input_tensor)[0]

visualizer = Visualizer()
drawn_img = visualizer.draw_featmap(feat, channel_reduction='select_max')
visualizer.show(drawn_img)

draw_featmap()函数定义

def draw_featmap(featmap: torch.Tensor,		#特征图(C, H, W).
                 overlaid_image: Optional[np.ndarray] = None,#显示的图像,特征图会叠加到 image 上绘制
                 channel_reduction: Optional[str] = 'squeeze_mean',# 多个通道压缩为单通道的策略
                 topk: int = 20,# 可选择激活度最高的 topk 个特征图显示
                 arrangement: Tuple[int, int] = (4, 5),# 多通道展开为多张图时候布局
                 resize_shape: Optional[tuple] = None, # 可以指定 resize_shape 参数来缩放特征图
                 alpha: float = 0.5					#特征图的透明度
                 ) -> np.ndarray:

官方解释:
输入的 Tensor 一般是包括多个通道的,channel_reduction 参数可以将多个通道压缩为单通道,然后和图片进行叠加显示
squeeze_mean 将输入的 C 维度采用 mean 函数压缩为一个通道,输出维度变成 (1, H, W)
select_max 从输入的 C 维度中先在空间维度 sum,维度变成 (C, ),然后选择值最大的通道
None 表示不需要压缩,此时可以通过 topk 参数可选择激活度最高的 topk 个特征图显示
在 channel_reduction 参数为 None 的情况下,topk 参数生效,其会按照激活度排序选择 topk 个通道,然后和图片进行叠加显示,并且此时会通过 arrangement 参数指定显示的布局
如果 topk 不是 -1,则会按照激活度排序选择 topk 个通道显示
如果 topk = -1,此时通道 C 必须是 1 或者 3 表示输入数据是图片,否则报错提示用户应该设置 channel_reduction来压缩通道。
考虑到输入的特征图通常非常小,函数支持输入 resize_shape 参数,方便将特征图进行上采样后进行可视化。

二、基础存储接口

任何一个可视化器都可以配置任意多个存储后端,可视化器会循环调用配置好的多个存储后端,从而将结果保存到多后端中。
本地后端存储:

visualizer = Visualizer(image=image,
                        vis_backends=[dict(type='LocalVisBackend')],
                        save_dir='temp_dir')
visualizer.draw_bboxes(torch.tensor([[33, 120, 209, 220], [72, 13, 179, 147]]))
visualizer.draw_texts("cat and dog", torch.tensor([10, 20]))
visualizer.draw_circles(torch.tensor([40, 50]), torch.tensor([20]))

# 会生成 temp_dir/vis_data/vis_image/demo_0.png
visualizer.add_image('demo', visualizer.get_image())
其中生成的后缀 0 是用来区分不同 step 场景

# 会生成 temp_dir/vis_data/vis_image/demo_1.png
visualizer.add_image('demo', visualizer.get_image(), step=1)
# 会生成 temp_dir/vis_data/vis_image/demo_3.png
visualizer.add_image('demo', visualizer.get_image(), step=3)

其他后端存储:
这里需要注意,如果没有存储成功,需要安装下面两个库
文件保存位置:temp_dir/vis_data/events.out.tfevents.xxx

pip install tensorboard
pip install wandb

WandbVisBackend后端可能使用失败,因为需要你在wandb网站创建一个帐户。使用的时候需要指定你的Wandb API密钥

# TensorboardVisBackend
visualizer = Visualizer(image=image,
                        vis_backends=[dict(type='TensorboardVisBackend')],
                        save_dir='temp_dir')
# 或者 WandbVisBackend
visualizer = Visualizer(image=image,
                        vis_backends=[dict(type='WandbVisBackend')],
                        save_dir='temp_dir')

保存标量数据:
会将内容追加到 temp_dir/vis_data/scalars.json

# 保存 loss
visualizer.add_scalar('loss', 0.2, step=0)
visualizer.add_scalar('loss', 0.1, step=1)
# 保存 acc
visualizer.add_scalar('acc', 0.7, step=0)
visualizer.add_scalar('acc', 0.8, step=1)
#也可以一次性保存多个标量数据
visualizer.add_scalars({'loss': 0.3, 'acc': 0.8}, step=3)

保存配置文件:

from mmengine import Config
cfg=Config.fromfile('tests/data/config/py_config/config.py')
# 会生成 temp_dir/vis_data/config.py
visualizer.add_config(cfg)

多后端存储:

visualizer = Visualizer(image=image,
                        vis_backends=[dict(type='TensorboardVisBackend'),
                                      dict(type='LocalVisBackend')],
                        save_dir='temp_dir')
# 会生成 temp_dir/vis_data/events.out.tfevents.xxx 文件
visualizer.draw_bboxes(torch.tensor([[33, 120, 209, 220], [72, 13, 179, 147]]))
visualizer.draw_texts("cat and dog", torch.tensor([10, 20]))
visualizer.draw_circles(torch.tensor([40, 50]), torch.tensor([20]))

visualizer.add_image('demo', visualizer.get_image())

如果多个存储后端中存在同一个类的多个后端,那么必须指定 name 字段,否则无法区分是哪个存储后端。

visualizer = Visualizer(
    image=image,
    vis_backends=[
        dict(type='TensorboardVisBackend', name='tb_1', save_dir='temp_dir_1'),
        dict(type='TensorboardVisBackend', name='tb_2', save_dir='temp_dir_2'),
        dict(type='LocalVisBackend', name='local')
    ],
    save_dir='temp_dir')

三、任意点位进行可视化

MMEngine 设计的可视化器支持在任意点位获取同一个可视化器然后进行可视化的功能。 用户只需要在初始化时候通过 get_instance 接口实例化可视化对象,此时该可视化对象即为全局可获取唯一对象,后续通过 Visualizer.get_current_instance() 即可在代码任意位置获取

# 在程序初始化时候调用
visualizer1 = Visualizer.get_instance(
    name='vis',
    vis_backends=[dict(type='LocalVisBackend')]
)

# 在任何代码位置都可调用
visualizer2 = Visualizer.get_current_instance()
visualizer2.add_scalar('map', 0.7, step=0)

assert id(visualizer1) == id(visualizer2)

通过字段配置方式全局初始化

from mmengine.registry import VISUALIZERS

visualizer_cfg = dict(type='Visualizer',
                      name='vis_new',
                      vis_backends=[dict(type='LocalVisBackend')])
VISUALIZERS.build(visualizer_cfg)
更多推荐

基于SpringBoot的教师工作量管理系统

目录前言一、技术栈二、系统功能介绍管理员模块的实现教师模块的实现三、核心代码1、登录模块2、文件上传模块3、代码封装前言随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过分析教师工作量管理系统管理的不足,创建了一个计算机管理教师工作量管理系统

深眸科技迭代深度学习算法,以AI机器视觉技术扩围工业应用场景

智能制造是制造业数智化转型升级的发展方向,在当前以高端装备制造为核心的工业4.0时代背景下,越来越多的制造企业意识到机器视觉对于提高效率、降低成本,从而提升企业效益的意义。目前,机器视觉已成为制造业迈向智能制造过程中极其关键的一项技术,且通过融合人工智能,能够实现该技术的再一次升级,以此切入更多差异化工业应用场景,并以

软件设计模式

1.UML1.1类图表示法uml类图中,类使用包含类名、属性、方法属性或方法前的加好和减号表示了这个方法的可见性,可见性的符号有三种:+表示public-表示private#表示protected1.2类与类之间关系关联关系单向关联双向关系自关联聚合关系聚合关系是关联关系的一种,是强关联关系,是整体和部分的关系聚合关系

海艺互娱与亚马逊云科技合作,在生成式AI领域探索更多的训练方向

面对生成式AI(GenerativeAI)新浪潮,如何把握机遇,加速创新发展,智胜蓝海?通过与亚马逊云科技合作,海艺互娱使用云上便捷部署的生成式AI解决方案,快速构建起可以服务全球用户的seaart.ai艺术创作平台,让用户将灵感快速转化为作品的同时,实现成本优化。当前,随着人工智能的快速发展,生成式AI正以其惊人的创

海外媒体发稿:海外汽车媒体推广9个方式解析

根据下列9个国外汽车媒体推广方式,企业能够在国际范围内突破边界,获得领域关心。这将帮助企业完成国际化发展发展战略,扩展市场占有率和提升盈利空间。【华媒舍】国外全媒体发表文章将会成为企业完成这一目标的重要方式,为企业带来新的机遇与挑战,助推企业与时俱进和成长!1.提升国界线,开拓视野!国外汽车媒体是汽车业务领域散播信息的

play() failed because the user didn‘t interact with the document优化媒体不能自动播放

1.问题谷歌浏览器video元素设置autoplay,我们原意是希望页面加载时自动播放,但实际上并没有自动播放,在控制台报错如下:Uncaught(inpromise)DOMException:play()failedbecausetheuserdidn’tinteractwiththedocumentfirst.这里

前端面试题整理

1.沙箱隔离前端沙箱隔离(Frontendsandboxisolation)是一种安全机制,用于将前端代码与主机环境隔离开来,以保护系统的安全性和稳定性。在Web开发中,前端代码通常由JavaScript编写,而JavaScript是一种强大且灵活的语言,但它也可能存在一些安全风险。例如,恶意用户可能会通过前端代码执行

JavaEE初阶(5)多线程案例(定时器、标准库中的定时器、实现定时器、线程池、标准库中的线程池、实现线程池)

接上次博客:JavaEE初阶(4)(线程的状态、线程安全、synchronized、volatile、wait和notify、多线程的代码案例:单例模式——饿汉懒汉、阻塞队列)_di-Dora的博客-CSDN博客目录多线程案例定时器标准库中的定时器实现定时器线程池标准库中的线程池实现线程池多线程案例定时器定时器(Tim

Qt/C++音视频开发53-本地摄像头推流/桌面推流/文件推流/监控推流等

一、前言编写这个推流程序,最开始设计的时候是用视频文件推流,后面陆续增加了监控摄像头推流(其实就是rtsp视频流)、网络电台和视频推流(一般是rtmp或者http开头m3u8结尾的视频流)、本地摄像头推流(本地USB摄像头或者笔记本自带摄像头等)、桌面推流(将当前运行环境的系统桌面抓拍推流)。按照分类的话其实就是三大类

【Robotframework+python】实现http接口自动化测试

前言下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了bug,所以需要一遍遍回归case,过程一直手工去执行,苦不堪言。所以,对于即将开始的http接口测试需求,立马花了两天时

数据分析:利用gpt建立双11活动的分析框架

promt:您是一名某电商平台的资深数据分析师,首先,您知道什么是双11活动吗?output:当然,双11活动,也称为“光棍节”购物节,是中国最大的在线购物节之一。这个活动最初由阿里巴巴集团于2009年发起,并迅速吸引了其他电商平台的参与。双11活动通常在每年的11月11日进行,因此得名“双11”。这一天,各大电商平台

热文推荐