【yolov5】改进系列——特征图可视化(V7.0 的一个小bug)

news2024/11/26 12:48:04

文章目录

  • 前言
  • 一、特征图可视化
    • 1.1 V7.0的小bug
  • 二、可视化指定层
  • 三、合并通道可视化
  • 总结


前言

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

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


一、特征图可视化

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

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

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

在这里插入图片描述

1.1 V7.0的小bug

我给官方提了个issue,回复应该是源码出错了,不应该把visualize赋值给save_dir

针对这个可视化的代码其实有个疑问:可视化的代码是在models/yolo.py文件下调用的,下面是调用特征图可视化的代码,在类BaseModel中定义了模型的前向传播过程,这里的visualize参数是一个bool类型,用于判断是否要可视化特征图,但是在可视化函数feature_visualization(x, m.type, m.i, save_dir=visualize)却把visualize传给了save_dir,save_dir应该是特征图的保存路径而不是bool,所以这里其实应该做一个更改否则会报错。

这里可以选择不传入save_dir,特征图会默认保存到runs/detect/exp 路径下,否则可以传入指定路径,比如:
save_dir=Path('../feature_map')

......
# models/yolo.py文件

class BaseModel(nn.Module):
    # YOLOv5 base model
    def forward(self, x, profile=False, visualize=False):
        return self._forward_once(x, profile, visualize)  # single-scale inference, train

    def _forward_once(self, x, profile=False, visualize=False):
        y, dt = [], []  # outputs
        for m in self.model:
            if m.f != -1:  # if not from previous layer
                x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
            if profile:
                self._profile_one_layer(m, x, dt)
            x = m(x)  # run
            y.append(x if m.i in self.save else None)  # save output
            """
            这里的visualize是一个bool类型,但是却传给了save_dir,save_dir应该是特征图的保存路径
            所以这里其实应该做一个更改否则会报错
            """
            if visualize:
                # 更改前	 
                # feature_visualization(x, m.type, m.i, save_dir=visualize)
                
				#更改后 
                feature_visualization(x, m.type, m.i)
        return x
......

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


# utils/plots.py

def feature_visualization(x, module_type, stage, n=32, save_dir=Path('runs/detect/exp')):
    """
    x:              输入即可视化的Tensor
    module_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, width
        if 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 channels
            n = min(n, channels)  # number of plots
            fig, ax = plt.subplots(math.ceil(n / 8), 8, tight_layout=True)  # 8 rows x n/8 cols
            ax = 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 model
    def forward(self, x, profile=False, visualize=False):
        return self._forward_once(x, profile, visualize)  # single-scale inference, train

    def _forward_once(self, x, profile=False, visualize=False):
        y, dt = [], []  # outputs
        for m in self.model:
            if m.f != -1:  # if not from previous layer
                x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
            if profile:
                self._profile_one_layer(m, x, dt)
            x = m(x)  # run
            y.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 visualized
    module_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, width
        if height > 1 and width > 1:
            f = save_dir / f"stage{stage}_{module_type.split('.')[-1]}_features.png"  # filename
            img = 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 model
    def forward(self, x, profile=False, visualize=False):
        return self._forward_once(x, profile, visualize)  # single-scale inference, train

    def _forward_once(self, x, profile=False, visualize=False):
        y, dt = [], []  # outputs
        for m in self.model:
            if m.f != -1:  # if not from previous layer
                x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
            if profile:
                self._profile_one_layer(m, x, dt)
            x = m(x)  # run
            y.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.coloradmin.cn/o/1090206.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BAT023:将当前目录同名文件(不包括扩展名)整理到以其命名的文件夹内

引言:编写批处理程序,实现将当前目录同名文件(不包括扩展名)整理到以其命名的文件夹内。 一、新建Windows批处理文件 参考博客: CSDNhttps://mp.csdn.net/mp_blog/creation/editor/132137544 二、写入批处理代码 1.…

(echarts)热度图封装相关总结及使用

(echarts)热度图封装相关总结及使用 一、封装组件heatChart.vue <template><div :id"id" :class"className" :style"{ height: height, width: width }" /> </template><script> import echarts from "echarts&quo…

GraphQL 查询:一个全面指南

GraphQL GraphQL 是一种 API 查询语言和运行时&#xff0c;用于使用现有数据完成这些查询。它为您的 API 中的数据提供了完整且易于理解的描述&#xff0c;让客户能够准确地询问他们需要什么&#xff0c;更容易随着时间的推移发展 API&#xff0c;并启用强大的开发人员工具。 …

047:mapboxGL本地上传shp文件,在map上解析显示图形

第047个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中本地上传shp文件,利用shapefile读取shp数据,并在地图上显示图形。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共117行)加载shapefile.js方式…

【面试经典150 | 哈希表】存在重复元素 II

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;哈希表方法二&#xff1a;滑动窗口 其他语言python3哈希表python3滑动窗口 写在最后 Tag 【哈希表】【滑动窗口】【数组】 题目来源 219. 存在重复元素 II 题目解读 判断在数组中有没有相同的元素小于一定的距离。 解…

软件开源快速开发框架:降本增效,助力流程化办公!

随着时代的进步和社会的发展&#xff0c;应用软件开源快速开发框架的优势特点&#xff0c;可以让不少客户朋友顺利实现流程化办公&#xff0c;朝着数字化方向迈进。流辰信息是专业研发低代码技术平台的服务商&#xff0c;一直在低代码平台领域深耕细作&#xff0c;努力钻研&…

微服务12-分布式服务理论基础+Seata的认识

文章目录 分布式服务理论基础前言微服务和分布式的区别CAP定理BASE理论 Seata流程&#xff1a;seata部署微服务集成seata 分布式服务理论基础 前言 单体架构&#xff1a; 1.项目过于臃肿&#xff0c;所有服务在一起&#xff0c;一个业务挂了&#xff0c;整个项目就不能用了&…

win redis 配置自启动服务

配置自启动 redis-server --service-install redis.windows-service.conf --loglevel verbose redis.windows-service.conf 配置 Logs 文件夹

nodejs+vue电子病历管理系统

过软件的需求分析已经获得了系统的基本功能需求&#xff0c;根据需求&#xff0c;将电子病历管理系统功能模块主要分为管理员模块。管理员添加科室信息管理、项目分类管理、药品分类管理、公告信息管理、用户管理等操作。 本系统结合计算机系统的结构、概念、模型、原理、方法&…

Go语言介绍与安装

介绍与安装 本教程介绍了 Go&#xff0c;并讨论了选择 Go 相对于其他编程语言的优势。我们还将学习如何在Windows 中安装 Go。 介绍 Go也称为Golang&#xff0c;是由 Google 开发的一种开源、编译型、静态类型的编程语言。 Go创造背后的关键人物是Rob Pike、 Ken Thompson和…

Apache Dubbo 首个 Node.js 3.0-alpha 版本正式发布

作者&#xff1a;蔡建怿 关于Apache Dubbo3 Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架&#xff0c;同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。经过近几年发展&#xff0c;Dubbo3 已在阿里巴巴集团各条业务线实现全面…

【Arduino+ESP32+腾讯云+sg90】强制门户+腾讯云控制开关灯

作者有话说 博主对于Arduino开发并没有基础&#xff0c;但是为了实现更加方便的配网&#xff0c;这几天一直在尝试用ESP32-12F&#xff08;因为手头刚好有一个&#xff0c;其他的也可以&#xff09;来做远程开关灯&#xff01;不知道大家是否注意到&#xff0c;上一篇利用STM32…

【Vivado HLS Bug】Ubuntu环境下Vivado HLS导出IP报错:HLS ERROR: [IMPL 213-28]

Export IP Invalid Argument / Revision Number Overflow Issue (Y2K22) (xilinx.com)一.问题描述&#xff1a; 在Ubuntu20.04环境中使用Vivado HLS导出IP时报错&#xff1a;HLS ERROR: [IMPL 213-28] 二.解决方法&#xff1a; 1.从如下链接中下载官方补丁Export IP Invalid…

Go函数介绍与一等公民

Go函数介绍与一等公民 函数对应的英文单词是 Function&#xff0c;Function 这个单词原本是功能、职责的意思。编程语言使用 Function 这个单词&#xff0c;表示将一个大问题分解后而形成的、若干具有特定功能或职责的小任务&#xff0c;可以说十分贴切。函数代表的小任务可以…

Stable Diffusion 动画SD-Animatediff V2

AI不仅可以生成令人惊叹的图片,还能给这些图片注入生命,让它们动起来。 这就是AnimateDiff要做的事情,一个神奇的工具,能将静态的AI生成图像转换成动画。 本次介绍基于SD如何实现这个神奇的方法。 文章目录 插件安装使用方法参数调整文生动图/视频Controlnet方法SD API方…

ARMv5架构对齐访问异常问题

strh非对齐访问 在ARMv5架构中&#xff0c;对于strh指令&#xff08;Store Halfword&#xff09;&#xff0c;通常是要求对地址进行对齐访问的。ARMv5架构对于半字&#xff08;Halfword&#xff09;的存储操作有对齐要求&#xff0c;即地址必须是2的倍数。 如果尝试使用strh指…

【广州华锐互动】塔吊多人安拆VR互动培训系统

塔吊多人安拆VR互动培训系统由广州华锐互动制作&#xff0c;是一种基于VR技术的模拟实训系统&#xff0c;专门用于培训塔吊驾驶员和操作员。 在现实生活中&#xff0c;塔吊操作具有一定的危险性&#xff0c;尤其是在培训过程中容易发生意外。而使用VR互动实训系统&#xff0c;学…

OCP Java17 SE Developers 复习题05

答案 答案 A, E. Instance and static variables can be marked final, making option A correct. Effectively final means a local variable is not marked final but whose value does not change after it is set, making option B incorrect. Option C is incorrect, a…

JAVA基础(JAVA SE)学习笔记(一)JAVA学习路线、行业了解、开发环境JDK17安装配置

前言 1. 学习视频&#xff1a; 尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备)_哔哩哔哩_bilibili 2023最新Java学习路线 - 哔哩哔哩 2. 一步一个脚印&#xff0c;踏踏实实再学一遍&#xff01; 这个世界上有的人输在不能开始&#xff0c;有的人…

IDEA spring-boot项目启动,无法加载或找到启动类问题解决

问题描述&#xff1a;找不到或无法加载主类 xxx.xxx.xxx.Classname 解决方案&#xff1a; 1.检查启动设置&#xff1a; 启动类所在包运行环境&#xff08;一般选择默认即可&#xff09;设置完成即可进行运行测试 2.如果第一步没有解决问题&#xff0c;试着第二步&#xff1a…