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

news/2024/12/4 17:32:58/

目录

  • 一、基础绘制接口
  • 二、基础存储接口
  • 三、任意点位进行可视化

一、基础绘制接口

可视化器(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 = _forwardimage_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 VISUALIZERSvisualizer_cfg = dict(type='Visualizer',name='vis_new',vis_backends=[dict(type='LocalVisBackend')])
VISUALIZERS.build(visualizer_cfg)

http://www.ppmy.cn/news/1119252.html

相关文章

基于51单片机多路DTH11温湿度检测控制系统

一、系统方案 1、本设计采用51单片机作为主控器。 2、DHT11采集温度度,支持3路温度度,液晶1602显示。 3、按键设置报警阀值。 4、系统声光报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 //初始化LCD*********…

虚拟DOM与diff算法

虚拟DOM与diff算法 snabbdom虚拟DOMdiff算法 snabbdom 是什么:snabbdom是著名的虚拟DOM库,是diff算法的鼻祖,Vue源码借鉴了snabbdom 虚拟DOM 是什么:本质上是存在内存里的 JavaScript 对象 作用:用来描述真实DOM的层…

记录一次Flink安装记录

系统Ubuntu18 1.拉取镜像 #默认拉取最新版本 docker pull flink:1.14.4-scala_2.12-java8 #检查镜像 docker images | grep flink 2.编写flink的yaml文件 注意:云服务器需要设置安全策略放行8081端口,否则访问失败 注意2:docker-compose 版…

学习记忆——宫殿篇——记忆宫殿——记忆桩——学校

教室 桶 走道 桌子 暖气 窗台 后背 窗帘 监视器 白盒子 教师 讲台 表 投影仪 音响 窗 喇叭 黑板 门 栏杆 椅子 食堂 桶 刷卡器 柱子 桌子 风扇 灯罩 一列椅子 地面 大门空间 电视 活动室 盘子 纸盒 油桶 称 水桶 展牌 帘子 消防栓 毯子 储物箱 宿舍 梯子 坐垫 挂件 吊兰 君子…

无涯教程-JavaScript - LCM函数

描述 LCM函数返回整数的最小公倍数。最小公倍数是最小的正整数,它是所有整数参数number1,number2等的倍数。使用LCM添加具有不同分母的分数。 语法 LCM (number1, [number2] ...)争论 Argument描述Required/OptionalNumber1, number2... 您想要最小公倍数的1到255个值。 如…

字符串(字符数组)的各种操作功能

利用C语言编程平台以及所学的编程知识,完成以下工作: 采用菜单形成,通过菜单项(1;2;3;......)等选择方式,分别实现以下对字符串(字符数组)的各种…

【MySQL】 MySQL的增删改查(进阶)--壹

文章目录 🛫数据库约束🌴约束类型🎋NOT NULL约束🎍UNIQUE:唯一约束🌳DEFAULT:默认值约束🎄PRIMARY KEY:主键约束🍀FOREIGN KEY:外键约束&#x1f…

QT之QListWidget的介绍

QListWidget常用成员函数 1、成员函数介绍2、例子显示图片和按钮的例子 1、成员函数介绍 1)QListWidget(QWidget *parent nullptr) 构造函数,创建一个新的QListWidget对象。 2)void addItem(const QString &label) 在列表末尾添加一个项目,项目标…