YOLOv7输出层之间的热力图

news2024/9/20 14:43:07

我们经常看到一些论文里绘制了不同的热力图,来直观的感受其模型的有效性。特别是使用了注意力模块的网络,热力图就可以验证注意力机制是否真正聚焦到了预期的重要特征上,以便对模型的有效性和合理性进行评估。

例如Centralized Feature Pyramid for Object Detection这篇文章中展示的,就很能够表达作者改进后的模型相比之前模型的一个优越性。

在这里插入图片描述
本文就来记录一下如何使用python脚本来输出YOLOv7层之间的热力图。

添加步骤

1️⃣ 在本地的YOLOv7项目的根目录下新建heatmap.py,将以下代码复制到其中

import warnings
warnings.filterwarnings('ignore')
warnings.simplefilter('ignore')
import torch, yaml, cv2, os, shutil
import torch.nn as nn
import numpy as np
np.random.seed(0)
import matplotlib.pyplot as plt
from tqdm import trange
from PIL import Image
from models.yolo import Model
from utils.torch_utils import intersect_dicts
from utils.datasets import letterbox
from utils.general import xywh2xyxy
from pytorch_grad_cam import GradCAMPlusPlus, GradCAM, XGradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
from pytorch_grad_cam.activations_and_gradients import ActivationsAndGradients

class yolov7_heatmap:
    def __init__(self, weight, cfg, device, method, layer, backward_type, conf_threshold, ratio):
        device = torch.device(device)
        ckpt = torch.load(weight)
        model_names = ckpt['model'].names
        csd = ckpt['model'].float().state_dict()  # checkpoint state_dict as FP32
        model = Model(cfg, ch=3, nc=len(model_names)).to(device)
        csd = intersect_dicts(csd, model.state_dict(), exclude=['anchor'])  # intersect
        model.load_state_dict(csd, strict=False)  # load
        model.eval()
        print(f'Transferred {len(csd)}/{len(model.state_dict())} items')
        
        target_layers = [eval(layer)]
        method = eval(method)

        colors = np.random.uniform(0, 255, size=(len(model_names), 3)).astype(np.int)
        self.__dict__.update(locals())
    
    def post_process(self, result):
        boxes_ = result[0][..., :4]
        logits_ = []
        for data in result[1]:
            bs, n, w, h, _ = data.size()
            logits_.append(data.reshape((bs, n * w * h, _)))
        logits_ = torch.cat(logits_, dim=1)[..., 4:]
        sorted, indices = torch.sort(logits_[..., 0], descending=True)
        logits_ = logits_[0][indices[0]]
        logits_[:, 0] = torch.sigmoid(logits_[:, 0])
        return logits_, xywh2xyxy(boxes_[0][indices[0]]).cpu().detach().numpy()

    def draw_detections(self, box, color, name, img):
        xmin, ymin, xmax, ymax = list(map(int, list(box)))
        cv2.rectangle(img, (xmin, ymin), (xmax, ymax), tuple(int(x) for x in color), 2)
        cv2.putText(img, str(name), (xmin, ymin - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.8, tuple(int(x) for x in color), 2, lineType=cv2.LINE_AA)
        return img

    def __call__(self, img_path, save_path):
        # remove dir if exist
        if os.path.exists(save_path):
            shutil.rmtree(save_path)
        # make dir if not exist
        os.makedirs(save_path, exist_ok=True)

        # img process
        img = cv2.imread(img_path)
        img = letterbox(img)[0]
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = np.float32(img) / 255.0
        tensor = torch.from_numpy(np.transpose(img, axes=[2, 0, 1])).unsqueeze(0).to(self.device)

        # init ActivationsAndGradients
        grads = ActivationsAndGradients(self.model, self.target_layers, reshape_transform=None)

        # get ActivationsAndResult
        result = grads(tensor)
        activations = grads.activations[0].cpu().detach().numpy()

        # postprocess to yolo output
        post_result, post_boxes = self.post_process(result)
        for i in trange(int(post_result.size(0) * self.ratio)):
            if post_result[i][0] < self.conf_threshold:
                break

            self.model.zero_grad()
            if self.backward_type == 'conf':
                post_result[i, 0].backward(retain_graph=True)
            else:
                # get max probability for this prediction
                score = post_result[i, 1:].max()
                score.backward(retain_graph=True)

            # process heatmap
            gradients = grads.gradients[0]
            b, k, u, v = gradients.size()
            weights = self.method.get_cam_weights(self.method, None, None, None, activations, gradients.detach().numpy())
            weights = weights.reshape((b, k, 1, 1))
            saliency_map = np.sum(weights * activations, axis=1)
            saliency_map = np.squeeze(np.maximum(saliency_map, 0))
            saliency_map = cv2.resize(saliency_map, (tensor.size(3), tensor.size(2)))
            saliency_map_min, saliency_map_max = saliency_map.min(), saliency_map.max()
            if (saliency_map_max - saliency_map_min) == 0:
                continue
            saliency_map = (saliency_map - saliency_map_min) / (saliency_map_max - saliency_map_min)

            # add heatmap and box to image
            cam_image = show_cam_on_image(img.copy(), saliency_map, use_rgb=True)
            #cam_image = self.draw_detections(post_boxes[i], self.colors[int(post_result[i, 1:].argmax())], f'{self.model_names[int(post_result[i, 1:].argmax())]} {post_result[i][0]:.2f}', cam_image)
            cam_image = Image.fromarray(cam_image)
            cam_image.save(f'{save_path}/{i}.png')

def get_params():
    params = {
        'weight': 'runs/train/exp/weights/best.pt',  
        'cfg': 'cfg/training/yolov7_test.yaml',
        'device': 'cuda:0',
        'method': 'GradCAM', # GradCAMPlusPlus, GradCAM, XGradCAM
        'layer': 'model.model[-2]',  
        'backward_type': 'class', # class or conf
        'conf_threshold': 0.6, # 0.6
        'ratio': 0.02 # 0.02-0.1
    }
    return params

if __name__ == '__main__':
    model = yolov7_heatmap(**get_params())
    model('inference/heat_image/001.jpg', 'heat_result')

2️⃣ 修改配置参数

文件中的主要参数配置如下:

在这里插入图片描述

参数解释
weight权重路径,训练完成后的权重文件
cfg模型文件路径,与权重所训练出来的模型文件一致
device运行的设备,和模型训练时的device参数设置一致
method可选择GradCAM,GradCAMPlusPlus和XGradCAM ,可以都试试,效果不同
layer想要输出第几层的热力图就写几,我这里写的的-2,即倒数第二层,可以多换换,看看效果
backward_type反向传播的计算类型,class表示按照类别最大概率进行计算 或 conf 通过置信度计算梯度
conf_threshold置信度阈值,设置成0.6
ratio取前多少数据,设置成0.02

在这里插入图片描述

箭头指向的数据就是行号。

3️⃣ 数据源

在这里插入图片描述
model('inference/heat_image/001.jpg', 'heat_result')中:

第一个参数inference/heat_image/001.jpg表示想要进行热力图绘制的原图像路径。

第二个参数'heat_result'表示绘制完成后输出的文件夹路径。

4️⃣ 调试

在这里插入图片描述
此时就已经绘制完成了,在指定的文件夹下就已经输出了热力图了。进度条还没有满就停止,是因为后面的目标已经不满足置信度conf_threshold的设定值。

这个进度条的长度151是之前设定的参数ratio的结果,其只会选择前0.02的目标进行热力图可视化。

博客参考链接
代码参考链接

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

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

相关文章

青蛙跳台阶与汉诺塔问题

hello&#xff0c;各位小伙伴们上次我们复习了C语言小tip之函数递归&#xff0c;这次我们来使用函数递归来完成青蛙跳台阶和汉诺塔问题&#xff01; 青蛙跳台阶问题 青蛙跳台阶问题&#xff1a;一只青蛙跳n阶台阶&#xff0c;一次可以跳1阶或者两阶&#xff0c;问有多少种情况…

【精选】基于Hadoop的热点事件分析的设计与实现(全网最新定制,独一无二)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Ubuntu 24.04 LTS源码安装doccano

引言 doccano是一款面向机器学习从业者的开源数据标记工具。您可以使用 doccano 执行不同类型的标记任务&#xff0c;支持多种数据格式。要了解 doccano 的功能&#xff0c;请试用doccano 演示版。 1.软件下载 git clone https://github.com/doccano/doccano.git cd doccano …

python学习——爬虫之session请求处理cookie

import requestssessionrequests.session() url"https://passport.17k.com/ck/user/login" data{"loginName": "19139186287","password":"2001022600hzk"} ressession.post(url,datadata) print(res.text)# session通过会话…

vue-创建项目、工程

安装node.js 自己百度 安装vue-cli 在cmd 命令行窗口输入 npm install --global vue-cli,vue-cli是创建脚手架的工具 安装完成之后&#xff0c;输入 vue -V 查看版本号,出现版本号说明安装成功 创建vue项目 默认创建 首先创建一个test测试文件夹 然后在文件内的地址栏输入…

Kimi 化身为你的私人翻译神器

在这个全球化的时代&#xff0c;无论是职场上的无缝沟通、学习资料的快速获取&#xff0c;还是日常生活中的轻松跨语言交流&#xff0c;我们都渴望拥有一个强大且便捷的翻译伙伴。Kimi&#xff0c;正是这样一位值得信赖的翻译神器。今天&#xff0c;就让我们一同探索如何高效地…

使用nvitop来监控 NVIDIA GPU 的使用情况

1.安装nvitop&#xff1a; pip install nvitop2.运行 nvitop: nvitop显示如下&#xff1a; 显示信息含义 1. 顶部信息栏 当前时间&#xff1a;显示当前的系统时间&#xff08;Sat Aug 31 16:33:03 2024&#xff09;。提示信息&#xff1a;提示可以按 h 键获取帮助或按 q 键…

论文4解析(复现):带有初速度的S形路径轨迹规划方法

论文&#xff1a;带有初速度的S形路径轨迹规划方法&#xff0c;史伟民 论文介绍了一种带有初速度的情况下进行轨迹规划的方法。 总得来说&#xff0c;是可以实现在运动过程中重新进行轨迹规划。 指数加减速&#xff1a;..... 直线型加减速&#xff1a;..... S形加减速&…

中仕公考:公务员考试缺考有影响吗?

公务员考试缺考的影响根据考试阶段的不同又所区别&#xff0c;中仕为大家介绍一下&#xff1a; 笔试阶段的缺考后果&#xff1a; 在公务员考试中&#xff0c;若考生未能按时参加笔试&#xff0c;将自动视为放弃该次考试机会。此行为不会对考生的个人信用产生任何负面效应&…

2024最新软件测试面试题(含答案解析+文档)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、软件测试基础面试题 1、阐述软件生命周期都有哪些阶段? 常见的软件生命周期模型有哪些? 软件生命周期是指一个计算机软件从功能确定设计&#xff0c;到…

软件测试面试八股文(答案解析+文档)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、软件测试基础面试题 1、阐述软件生命周期都有哪些阶段? 常见的软件生命周期模型有哪些? 软件生命周期是指一个计算机软件从功能确定设计&#xff0c;到…

LlamaIndex 工作流

LlamaIndex 内部提供了一个简单的工作流引擎&#xff0c;为什么要有工作流引擎&#xff1f;做过 OA 的同学都了解工作流引擎&#xff0c;工作流的优势在于模块化开发&#xff0c;把业务节点进行抽象&#xff0c;流程于业务逻辑分离&#xff0c;方便进行业务节点组装&#xff0c…

还在为低效工作烦恼?Kimi使用指南,让你的效率飞跃提升

在这个信息爆炸的时代&#xff0c;效率成为了我们追求的重要目标。今天&#xff0c;我要为大家介绍一个能够显著提升工作效率的智能助手——Kimi。Kimi不仅能够理解复杂的指令&#xff0c;还能处理多种文件格式&#xff0c;甚至还能进行网页内容解析。这篇文章将带你一文看懂Ki…

如何打开终端?

终端也叫黑窗口&#xff0c;命令行&#xff0c;可以用代码命令的方式控制计算机&#xff0c;如何打开呢&#xff1f; 输入WinR 在左下角输入cmd 点击确定 出现这个界面证明打开

住宅物业满意度计算方式中满意率和满意度指数的区别

满意率和满意度指数是用于计算住宅物业满意度的两种不同方式&#xff0c;它们的区别如下&#xff1a; 1、满意率&#xff1a;满意率是通过计算满意的居民人数与总参与调查的居民人数之间的比例来衡量满意度。它以百分比形式表示&#xff0c;可以直观地了解居民对物业管理的整体…

关于lua调用DLL的c/c++动态库(相关搜索:数据库)

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

8个Python编程进阶常用技巧!

介绍 Python 炫酷功能&#xff08;例如&#xff0c;变量解包&#xff0c;偏函数&#xff0c;枚举可迭代对象等&#xff09;的文章层出不穷。但是还有很多 Python 的编程小技巧鲜被提及。因此&#xff0c;本文会试着介绍一些其它文章没有提到的小技巧&#xff0c;这些小技巧也是…

《黑神话:悟空》:30%抽成真相

《黑神话&#xff1a;悟空》自建服务器出售&#xff1f;揭秘游戏界的30%抽成真相&#xff01; 近年来&#xff0c;随着游戏行业的迅猛发展&#xff0c;游戏开发商与发行平台之间的利益分配问题逐渐成为业界关注的焦点。其中&#xff0c;《黑神话&#xff1a;悟空》作为一款备受…

接口和多态详解,还不快点学?

一、接口和多态基础知识 1. 抽象类 1.1 子类调用父类 现在有IDEA集成开发环境&#xff0c;可以给大家实时提醒哪个地方编译错误&#xff0c;但假如要大家用.txt文件编写程序呢。胡广问&#xff1a;现在这段代码错在了哪&#xff1f; class Base {public Base(String s) {Sy…

接口测试 —— 如何设计高效的测试用例!

摘要&#xff1a; 随着互联网应用的日益复杂化&#xff0c;接口测试已成为保证软件质量不可或缺的一部分。本文将探讨如何有效地设计接口测试用例&#xff0c;并提供实用的建议和示例。 一、引言 接口测试&#xff08;API测试&#xff09;是确保系统各部分之间交互正确性的关键…