目标检测热力图的生成代码(基于GridCam)生成的

不好之处就是这种方法不能最大程度还原最后的热图,会产生很多噪声,不过大体区域还是接近的,代码如下:

import cv2
import os
import numpy as np
from PIL import Image
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import sys
import time
import shutil
import argparse
import json
from torch.utils.data import DataLoader
from utils import set_logger, update_lr, get_pck_with_sigma, get_pred_coordinates, save_images, save_limb_images

# ================== Grad-CAM ==================
class GradCAM:
    def __init__(self, model, target_layer):
        self.model = model
        self.target_layer = target_layer
        self.gradients = None  # 存储梯度
        self.activations = None  # 存储激活值

        # 绑定梯度钩子
        self.hook_layers()

    def hook_layers(self):
        """ 绑定 hook,提取梯度和特征图 """
        def forward_hook(module, input, output):
            self.activations = output  # 存储前向传播的特征图

        def backward_hook(module, grad_in, grad_out):
            self.gradients = grad_out[0]  # 存储反向传播的梯度

        self.target_layer.register_forward_hook(forward_hook)
        self.target_layer.register_backward_hook(backward_hook)

    def forward(self, image, joint_index):
        """ 计算 Grad-CAM(针对某个关键点)"""
        self.model.eval()  # 进入评估模式
        image = image.requires_grad_(True)  # 需要梯度信息
        output = self.model(image)  # 形状 (1, num_joints, H, W)

        # 选择某个关键点的热图进行梯度计算
        heatmap = output[:, joint_index, :, :]  # (1, H, W)
        loss = heatmap.sum()  # 让 loss 与该热图相关
        self.model.zero_grad()
        loss.backward()  # 计算梯度

        # 计算 Grad-CAM 权重(对梯度做全局平均池化)
        gradients = self.gradients.mean(dim=(2, 3), keepdim=True)  # (1, C, 1, 1)
        activations = self.activations  # (1, C, H, W)
        cam = (activations * gradients).sum(dim=1, keepdim=True)  # (1, 1, H, W)
        cam = F.relu(cam)  # 保证非负
        cam = cam.squeeze().cpu().detach().numpy()  # (H, W)
        return cam

    def overlay_heatmap(self, image, cam):
        """ 叠加 Grad-CAM 热图,使用默认颜色 """
        # image 为 BGR 格式
        cam = cv2.resize(cam, (image.shape[1], image.shape[0]))  # 调整大小
        cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8)  # 归一化到 0-1
        heatmap = cv2.applyColorMap(np.uint8(255 * cam), cv2.COLORMAP_JET)
        overlay = cv2.addWeighted(image, 0.5, heatmap, 0.5, 0)
        return overlay

def remove_module_prefix(state_dict):
    new_state_dict = {}
    for k, v in state_dict.items():
        if k.startswith("module."):
            new_state_dict[k[7:]] = v  # 去掉前面的 'module.'
        else:
            new_state_dict[k] = v
    return new_state_dict

# ========== 测试模型和 Grad-CAM ==========
if __name__ == "__main__":
    # 1. 初始化模型(关键点数 16)
    num_joints = 16
    model = Your_model(num_joints, False)

    # 2. 加载模型参数
    state_dict = torch.load('model.pth')#你训练出的模型的路径
    model.load_state_dict(remove_module_prefix(state_dict['model_state_dict']))

    # 3. 选择目标层:绑定到模块中的某一层
    target_layer = model.layer
    # 4. 初始化 Grad-CAM
    grad_cam = GradCAM(model, target_layer)

    # 5. 读取测试图像并预处理
    img = cv2.imread("test.jpg")  # 读取图片(BGR 格式)
    img = cv2.resize(img, (224, 224))  # 调整大小
    # 转换为 RGB 格式,再转为 Tensor
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img_tensor = torch.tensor(img_rgb.transpose(2, 0, 1), dtype=torch.float32).unsqueeze(0) / 255.0

    # 6. 分别计算 0-16 号关键点的 Grad-CAM 热图(进行叠加)
    cams = []
    for joint_index in range(0,16):
        cam_joint = grad_cam.forward(img_tensor, joint_index)  # 每个 cam 的尺寸约为 40x40
        # 将每个热图归一化到 0-1,并调整大小到原图尺寸
        cam_joint = cv2.resize(cam_joint, (img.shape[1], img.shape[0]))
        cam_joint = (cam_joint - cam_joint.min()) / (cam_joint.max() - cam_joint.min() + 1e-8)
        cams.append(cam_joint)
    cams = np.stack(cams, axis=0)  # 形状 (16, H, W)

    # 7. 合并 16 个关键点热图:逐像素取所有关键点中响应的最大值(不区分颜色,仅保留默认热图色调)
    combined_cam = np.max(cams, axis=0)
    combined_cam = (combined_cam - combined_cam.min()) / (combined_cam.max() - combined_cam.min() + 1e-8)

    # 8. 生成叠加图(使用默认颜色映射)
    overlay = grad_cam.overlay_heatmap(img, combined_cam)
    plt.imshow(cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB))
    plt.axis("off")
    plt.title("Combined Grad-CAM for Keypoints 0-20")
    plt.show()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DMR协议空中接口部分

文章目录 前言DMR 空中接口协议栈模型无线空中接口发送与接收参考模型DMR的TDMA结构帧结构突发结构数据与控制突发语音突发公共广播信道突发 数据信息传送时序语音信息传送时序帧同步 调制解调4-CPFSK正交调制4-CPFSK解调基带成型滤波 信道编码类型参考 前言 DMR 协议的标准号主…

专题二串联所有单词的子串

1.题目 题目分析: 有一个字符串s和字符串数组,如何字符串数组里面的元素可以组成一个字符串,然后要在字符串里面找到连续子串跟组成的字符串一样,返回起始地址。 2.算法原理 这道题可以把字符串数组的元素string看出char&#x…

uniapp或者vue 使用serialport

参考https://blog.csdn.net/ykee126/article/details/90440499 版本是第一位:否则容易编译失败 node 版本 18.14.0 npm 版本 9.3.1 electron 版本 30.0.8 electron-rebuild 版本 3.2.9 serialport 版本 10.0.0 需要python环境 main.js // Modules to control app…

编程题-计算器(中等)

题目: 给定一个包含正整数、加()、减(-)、乘(*)、除(/)的算数表达式(括号除外),计算其结果。 表达式仅包含非负整数,, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。 解法一(栈&…

数据增强术:如何利用大模型(LLMs)来模拟不同的扰动类型以增强信息提取任务的鲁棒性

一、对抗样本库构建 1. 基于LLMs的领域针对性扰动设计对抗样本生成 替换实体、三元组和触发器(Replace Entity, Triple, and Trigger) 使用LLMs(如GPT-4)来替换句子中的实体、关系三元组或事件触发器,同时保持其类型不…

深入了解Linux —— git三板斧

版本控制器git 为了我们方便管理不同版本的文件,就有了版本控制器; 所谓的版本控制器,就是能够了解到一个文件的历史记录(修改记录);简单来说就是记录每一次的改动和版本迭代的一个管理系统,同…

Windows编程----进程的当前目录

进程的当前目录 Windows Api中有大量的函数在调用的时候,需要传递路径。比如创建文件,创建目录,删除目录,删除文件等等。拿创建文件的CreateFile函数做比喻,如果我们要创建的文件路径不是全路径,那么wind…

MyBatis-Plus分页控件使用及使用过程发现的一个坑

最近维护一个旧项目的时候,出现了一个BUG,经排查后发现是Mybatis-plus分页控件使用的时候需要注意的一个问题,故在本地使用MybatisPlus模拟出现了一下这个问题。 首先,先说一下MyBatis-Plus的使用: 1)引入…

服务端和客户端通信(TCP)

服务端 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks;namespace TeachTcpServer {class Program{static void Main(string[] args){#region 知识点一 …

Windows下配置Flutter移动开发环境以及AndroidStudio安装和模拟机配置

截止 2025/3/9 ,版本更新到了 3.29.1 ,但是为了防止出现一些奇怪的bug,我安装的还是老一点的,3.19,其他版本的安装同理。AndroidStudio用的是 2024/3/1 版本。 — 1 环境变量(Windows) PUB_H…

C++11中的Condition_variable

C11中的condition_variable 在C11中,条件变量(std::condition_variable)是线程同步机制之一,用于在多线程环境中实现线程间的通信和协调。它允许一个或多个线程在某个条件尚未满足时等待,直到其他线程通知条件已经满足…

ROS2-话题学习

强烈推荐教程: 《ROS 2机器人开发从入门到实践》3.2.2订阅小说并合成语音_哔哩哔哩_bilibili 构建功能包 # create package demo_python_pkg ros2 pkg create --build-type ament_python --license Apache-2.0 demo_python_pkg 自己写的代码放在./demo_python_pkg/…

深度学习模型Transformer核心组件—前馈网络FFN

第一章:人工智能之不同数据类型及其特点梳理 第二章:自然语言处理(NLP):文本向量化从文字到数字的原理 第三章:循环神经网络RNN:理解 RNN的工作机制与应用场景(附代码) 第四章:循环神经网络RNN、LSTM以及GR…

Helm安装chart包到k8s报错“不能重复使用名称,名称已被使用”

一、报错提示如下 “Error: INSTALLATION FAILED: cannot re-use a name that is still in use”,意思是安装chart时提供的名称已存在,不能重复使用同一个名称。 登录后复制 rootiZ:/usr/local/src/my-helm-repo/charts# helm install mymemcached3 memcached -n te…

容器编排革命:从 Docker Run 到 Docker Compose 的进化之路20250309

容器编排革命:从 Docker Run 到 Docker Compose 的进化之路 一、容器化部署的范式转变 在 Docker 生态系统的演进中,容器编排正从“手动操作”走向“自动化管理”。根据 Docker 官方 2023 年开发者调查报告,78% 的开发者已采用 Docker Compo…

对开源VLA sota π0的微调——如何基于各种开源数据集、以及你自己的私有数据集微调π0(含我司的微调实践)

前言 25年2.4日,几个月前推出π0的公司Physical Intelligence (π)宣布正式开源π0及π0-FAST,如之前所介绍的,他们对用超过 10,000 小时的机器人数据进行了预训练 该GitHub代码仓库「 π0及π0-FAST的GitHub地址:github.com/Ph…

VBA使用fso对象合并指定路径的txt文件(含子目录)

图(1) 前几天我跟大家分享了在VBA中如何获取指定类型文件的路径的方法,其中最重要的一个思路就是在处理完当前目录的文件后,再调用程序自身来对子目录进行处理,以此来实现对子目录的无限循环,直至所有文件都处理完毕为止。按照此设…

nginx反向代理功能

如上图所示,当配置好nginx反向代理服务器的时候,客户端向nginx反向代理服务器发送请求,nginx反向代理服务器再向真实服务器转发请求。 nginx作为反向代理就是利用nginx高并发,速度快的特性,让nginx能够承受更多的链接…

deepseek在pycharm中的配置和简单应用

对于最常用的调试python脚本开发环境pycharm,如何接入deepseek是我们窥探ai代码编写的第一步,熟悉起来总没坏处。 1、官网安装pycharm社区版(免费),如果需要安装专业版,需要另外找破解码。 2、安装Ollama…

【江协科技STM32】ADC数模转换器-学习笔记

ADC简介 ADC(Analog-Digital Converter)模拟-数字转换器ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁,ADC是一种将连续的模拟信号转换为离散的数字信号的设备或模块12位逐次逼近型…