【yolov5】改进系列——特征图可视化

文章目录

  • 前言
  • 一、特征图可视化
  • 二、可视化指定层
  • 三、合并通道可视化
  • 总结


前言

对于特征图可视化感兴趣可以参考我的另一篇记录:六行代码实现:特征图提取与特征图可视化,可以实现分类网络的特征图可视化

最近忙论文,想在yolov5上面做一些改进,看源码看了一段时间,动手改改代码做一些改进,所以做个一系列改进的记录。


一、特征图可视化

yolov5最近的版本提供了特征图可视化的功能,在使用detect.py进行推理时,在命令行参数传入--visualize即可。

python detect.py --weights best.pt --conf 0.5 --source ../dog.png --visualize

传入visualize参数后会可视化所有层的特征图,文件默认保存在runs/detect/exp 文件夹下

在这里插入图片描述

yolov5 这里是针对单个通道进行可视化(默认最多可视化32个通道),参考GitHub的相关issue,可以自行修改feature_visualization的各个参数


# utils/plots.pydef feature_visualization(x, module_type, stage, n=32, save_dir=Path('runs/detect/exp')):"""x:              输入即可视化的Tensormodule_type:    Module type 用于命名区分各层特征图stage:          Module stage within model 用于命名区分各层特征图n:              Maximum number of feature maps to plot 可视化的通道个数(通道数太多不可能全部可视化)save_dir:       Directory to save results 特征图的保存路径"""if 'Detect' not in module_type:batch, channels, height, width = x.shape  # batch, channels, height, widthif height > 1 and width > 1:# 文件的命名格式 层名+层的索引 	f = save_dir / f"stage{stage}_{module_type.split('.')[-1]}_features.png"  # filename# 按通道数拆分Tensor# 进行逐通道的可视化blocks = torch.chunk(x[0].cpu(), channels, dim=0)  # select batch index 0, block by channelsn = min(n, channels)  # number of plotsfig, ax = plt.subplots(math.ceil(n / 8), 8, tight_layout=True)  # 8 rows x n/8 colsax = ax.ravel()plt.subplots_adjust(wspace=0.05, hspace=0.05)for i in range(n):ax[i].imshow(blocks[i].squeeze())  # cmap='gray'ax[i].axis('off')LOGGER.info(f'Saving {f}... ({n}/{channels})')plt.savefig(f, dpi=300, bbox_inches='tight')plt.close()np.save(str(f.with_suffix('.npy')), x[0].cpu().numpy())  # npy save

在这里插入图片描述

二、可视化指定层

如果不想可视化所有的特征层,比如只需要可视化第一个卷积层的输出那么只需要修改判断条件即可,
if visualize: 修改为 if m.type == 'models.common.Conv' and m.i == 0:

# models/yolo.py文件class BaseModel(nn.Module):# YOLOv5 base modeldef forward(self, x, profile=False, visualize=False):return self._forward_once(x, profile, visualize)  # single-scale inference, traindef _forward_once(self, x, profile=False, visualize=False):y, dt = [], []  # outputsfor m in self.model:if m.f != -1:  # if not from previous layerx = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layersif profile:self._profile_one_layer(m, x, dt)x = m(x)  # runy.append(x if m.i in self.save else None)  # save output"""可视化指定层只需要更改一下判断条件即可将 if visualize:修改为 if m.type == 'models.common.Conv' and m.i == 0:"""# 修改前# if visualize:# 修改后if m.type == 'models.common.Conv' and m.i == 0:feature_visualization(x, m.type, m.i)return x
......

m.type 表示模块名称,m.i表示层的索引(即第几层),因为有重名的层需要索引加以区分
m.type的命名以 models.common. + 模块名,比如可视化SPPF就是 models.common.SPPF
m.i 即每个层对应得索引,SPPF对应得索引是9
在这里插入图片描述

三、合并通道可视化

如果不想分通道可视化,可以直接可视化整个Tensor。把下面得函数定义加入到utils/plots.py文件下

def feature_visualization_all(x, module_type, stage,  save_dir=Path('runs/detect/exp')):"""x:              Features to be visualizedmodule_type:    Module typestage:          Module stage within modeln:              Maximum number of feature maps to plotsave_dir:       Directory to save results"""if 'Detect' not in module_type:batch, channels, height, width = x.shape  # batch, channels, height, widthif height > 1 and width > 1:f = save_dir / f"stage{stage}_{module_type.split('.')[-1]}_features.png"  # filenameimg = x[0].cpu().transpose(0, 1).sum(1).detach().numpy()plt.imsave(f, img)LOGGER.info(f'Saving {f}...')

随后在models/yolo.py文件下导入并调用

from models.common import *  # noqa
from models.experimental import *  # noqa
from utils.autoanchor import check_anchor_order
from utils.general import LOGGER, check_version, check_yaml, make_divisible, print_args# 导入feature_visualization_all
from utils.plots import feature_visualization, feature_visualization_all
from utils.torch_utils import (fuse_conv_and_bn, initialize_weights, model_info, profile, scale_img, select_device, time_sync)......class BaseModel(nn.Module):# YOLOv5 base modeldef forward(self, x, profile=False, visualize=False):return self._forward_once(x, profile, visualize)  # single-scale inference, traindef _forward_once(self, x, profile=False, visualize=False):y, dt = [], []  # outputsfor m in self.model:if m.f != -1:  # if not from previous layerx = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layersif profile:self._profile_one_layer(m, x, dt)x = m(x)  # runy.append(x if m.i in self.save else None)  # save output# 修改后if m.type == 'models.common.Conv' and m.i == 0:feature_visualization_all(x, m.type, m.i)return x......

原图及检测效果:
在这里插入图片描述
合并通道特征图可视化:
在这里插入图片描述

总结

对于特征图可视化感兴趣可以参考我的另一篇记录:六行代码实现:特征图提取与特征图可视化,可以实现分类网络得特征图可视化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/160658.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java系列 | 如何讲自己的JAR包上传至阿里云maven私有仓库【云效制品仓库】

什么是云效 云效是云原生时代一站式 BizDevOps 平台,产研数字化同行者,支持公共云、专有云和混合云多种部署形态,通过云原生新技术和研发新模式,助力创新创业和数字化转型企业快速实现产研数字化,打造“双敏”组织&…

Python数据挖掘入门进阶与实用案例:自动售货机销售数据分析与应用

文章目录 写在前面01 案例背景02 分析目标03 分析过程04 数据预处理1. 清洗数据2.属性选择3.属性规约 05 销售数据可视化分析1.销售额和自动售货机数量的关系2.订单数量和自动售货机数量的关系3.畅销和滞销商品4.自动售货机的销售情况5.订单支付方式占比6.各消费时段的订单用户…

uni-app 瀑布流布局的实现

方式一&#xff1a;使用纯 CSS 实现 使用 flex 布局方式 <!-- 瀑布流布局 --> <template><view class"container"><viewclass"cont-box":style"{ --layout-width: 100 / flowData.column - flowData.columnSpace % }"v-f…

CatBoost算法模型实现贷款违约预测

前言 此篇文章为整个Boost(提升方法)集成算法模型的终章&#xff0c;前几篇文章依次结合详细项目案例讲解了AdaBoost、GBDT、XGBoost、LighGBM共四个常用的集成算法模型&#xff0c;每一篇文章都包含实战项目以及可运行代码。仅通过看一遍文章不去实践是很难掌握集成算法模型的…

【API篇】三、转换算子API(上)

文章目录 0、demo数据1、基本转换算子&#xff1a;映射map2、基本转换算子&#xff1a;过滤filter3、基本转换算子&#xff1a;扁平映射flatMap4、聚合算子&#xff1a;按键分区keyBy5、聚合算子&#xff1a;简单聚合sum/min/max/minBy/maxBy6、聚合算子&#xff1a;归约聚合re…

maven 新建模块 导入后 按Ctrl 点不进新建模块pom定义

新建的ruoyi-common-mybatisplus 模块,导入一直不正常 画出的模块一直导入不进来 这是提示信息 这是正常的提示信息 加上 <version>3.6.3</version> 后,才一切正常

C++入门之引用与内联函数

一、引用 1、初步理解 引用在语法上的理解就是起别名&#xff0c;用法就是在类型后面加&&#xff0c;例子&#xff1a;int a 1; int& b a; 上例所示&#xff0c;执行后&#xff0c;b就是a的别名&#xff0c;它们代表同一块空间&#xff0c;a的改变会影响b&#xff0…

进阶JAVA篇-如何理解作为参数使用的匿名内部类与 Arrays 类的常用API(九)

目录 目录 API 1.0 Arrays 类的说明 1.1 Arrays 类中的 toString() 静态方法 1.2 Arrays 类中的 copyOfRange(int[] original, int from, int to) 静态方法 1.3 Arrays 类中的 copyOf(int[] original, int newLength) 静态方法 1.4 Arrays 类中的 setAll(do…

深入了解桶排序:原理、性能分析与 Java 实现

桶排序&#xff08;Bucket Sort&#xff09;是一种排序算法&#xff0c;通常用于将一组数据分割成有限数量的桶&#xff08;或容器&#xff09;&#xff0c;然后对每个桶中的数据进行排序&#xff0c;最后将这些桶按顺序合并以得到排好序的数据集。 桶排序原理 确定桶的数量&am…

Unity中用序列化和反序列化来保存游戏进度

[System.Serializable]标记类 序列化 [System.Serializable]是一个C#语言中的属性&#xff0c;用于标记类&#xff0c;表示该类的实例可以被序列化和反序列化。序列化是指将对象转换为字节流的过程&#xff0c;以便可以将其保存到文件、数据库或通过网络传输。反序列化则是将字…

C++桶排序算法的应用:存在重复元素 III

题目 给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。 找出满足下述条件的下标对 (i, j)&#xff1a; i ! j, abs(i - j) < indexDiff abs(nums[i] - nums[j]) < valueDiff 如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例…

日志技术快速入门

1、创建Maven项目 这里不再说如何创建Maven项目 2、导入相关依赖 <dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.12</version></dependency>3、创建配置文件 在re…

嵌入式系统学习路径:

嵌入式系统学习路径&#xff1a; 00001. 确保扎实的C语言基础&#xff0c;包括高级编程知识和数据结构算法。 00002. 00003. 学习Linux应用层开发&#xff0c;包括并发程序设计、网络编程和数据库开发。 00004. 00005. 探索无线通信领域&#xff0c;如Zigbee、低功…

【java学习—八】对象类型转换Casting(1)

文章目录 1. 数据类型转换1.1 基本数据类型的 Casting1.2. 对 Java 对象的强制类型转换(造型)2. 对象类型转换举例 1. 数据类型转换 数据类型转换分为基本数据类型转换和对象类型转换。 1.1 基本数据类型的 Casting (1) 自动类型转换&#xff1a;小的数据类型可以自动转换成…

使用eBPF加速阿里云服务网格ASM

背景 随着云原生应用架构的快速发展&#xff0c;微服务架构已经成为了构建现代应用的主要方式之一。而在微服务架构中&#xff0c;服务间的通信变得至关重要。为了实现弹性和可伸缩性&#xff0c;许多组织开始采用服务网格技术来管理服务之间的通信。 Istio作为目前最受欢迎的…

mac虚拟机安装homebrew时的问题

安装了mac虚拟机&#xff0c;结果在需要通过“brew install svn”安装svn时&#xff0c;才注意到没有下载安装homebrew。 于是便想着先安装homebrew&#xff0c;网上查的教程大多是通过类似以下命令 “ruby <(curl -fsSkL raw.github.com/mxcl/homebrew/go)” 但是都会出现…

Mac OS m1 下安装Gradle5.1

1. 下载、解压 1.1 下载地址 https://gradle.org 往下翻 选择 5.1 或者选择 任何 你想要的版本 ,点击 binary-only 即可下载 . 1.2 解压到指定目录 2. 配置环境变量 2.1 编辑环境文件 vi ~/.bash_profile #GRADLE相关配置 GRADLE_HOME/Users/zxj/Documents/devSoft/grad…

c语言小白如何入门?

c语言小白如何入门&#xff1f; 作为过来人&#xff0c;我觉得刚开始&#xff0c;先按照课本把每个知识点都弄懂&#xff0c;有不懂的地方&#xff0c;先尝试自己理解或借助互联网先搜一下&#xff0c;还是理解不了&#xff0c;就可以去找学得比较好的同学&#xff0c; 最近很…

HarmonyOS 远端状态订阅开发实例

IPC/RPC 提供对远端 Stub 对象状态的订阅机制&#xff0c; 在远端 Stub 对象消亡时&#xff0c;可触发消亡通知告诉本地 Proxy 对象。这种状态通知订阅需要调用特定接口完成&#xff0c;当不再需要订阅时也需要调用特定接口取消。使用这种订阅机制的用户&#xff0c;需要实现消…

【Leetcode刷题(数据结构)】:三路划分与三数随机取中的思想实现快速排序的再优化

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中 的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&#xff0c;右 子序列中所有元素均…