基于 PySide6 实现一个可手动绘制的深度学习热力图 UI,效果类似 Grad-CAM

张开发
2026/4/21 2:52:52 15 分钟阅读

分享文章

基于 PySide6 实现一个可手动绘制的深度学习热力图 UI,效果类似 Grad-CAM
一、简介最近在做深度学习中的热力图效果可视化时我一开始是想通过 Grad-CAM 输出模型关注区域但效果很差难以应用在论文、课程设计中的效果图展示。因此我希望能手动绘制热力图区域并且渲染效果接近 Grad-CAM 的伪彩色热图。于是我用 PySide6 NumPy 做了一个小工具支持加载图片、手动涂抹热区、实时生成类似 Grad-CAM 的热力图叠加效果同时还能导出结果图以支持科研绘图。二、原理虽然这不是模型真正计算出来的 Grad-CAM但显示思路非常接近用户在图像上手动绘制一个灰度热度图 heat然后对 heat 做高斯模糊使热度扩散更自然进一步将归一化后的热度映射到 JET 伪彩色再与原图做 alpha blending 叠加最终显示效果就会比较接近常见的 Grad-CAM 可视化结果。三、关键问题与踩坑记录在开发过程中我遇到了几个比较典型的问题。def_widget_pos_to_image_xy(self,pos:QPoint)-tuple[int,int]|None:运行后报错TypeError:typeobjectisnotsubscriptable这是因为当前环境中的 Python 版本较低不支持tuple[int, int]与| None改成兼容写法fromtypingimportOptional,Tupledef_widget_pos_to_image_xy(self,pos:QPoint)-Optional[Tuple[int,int]]:四、代码importnumpyasnpimportcv2defbuild_jet_lut(n256):xnp.linspace(0,1,n)rnp.clip(1.5-np.abs(4*x-3),0,1)gnp.clip(1.5-np.abs(4*x-2),0,1)bnp.clip(1.5-np.abs(4*x-1),0,1)lutnp.stack([r,g,b],axis1)return(lut*255).astype(np.uint8)JET_LUTbuild_jet_lut(256)defapply_colormap_jet(gray01):idxnp.clip((gray01*255.0).round().astype(np.int32),0,255)returnJET_LUT[idx]defmake_brush(radius):yy,xxnp.mgrid[-radius:radius1,-radius:radius1].astype(np.float32)dist2xx*xxyy*yy sigmamax(1.0,radius/2.5)brushnp.exp(-dist2/(2*sigma*sigma))brush/(brush.max()1e-8)returnbrush.astype(np.float32)defdab_heatmap(heat,x,y,radius30,strength0.35):h,wheat.shape brushmake_brush(radius)x0,x1x-radius,xradius1y0,y1y-radius,yradius1sx0,sy00,0sx1,sy1brush.shape[1],brush.shape[0]ifx00:sx0-x0 x00ify00:sy0-y0 y00ifx1w:sx1-(x1-w)x1wify1h:sy1-(y1-h)y1hifx0x1ory0y1:returnheat patchbrush[sy0:sy1,sx0:sx1]*strength heat[y0:y1,x0:x1]patch heat[y0:y1,x0:x1]np.clip(heat[y0:y1,x0:x1],0.0,10.0)returnheatdefrender_heatmap_overlay(image_rgb,heat,blur_sigma8,alpha0.55):heat_blurcv2.GaussianBlur(heat,(0,0),sigmaXblur_sigma,sigmaYblur_sigma)pnp.percentile(heat_blur,99.0)ifheat_blur.max()1e-8else0.0denommax(p,1e-8)heat01np.clip(heat_blur/denom,0.0,1.0)coloredapply_colormap_jet(heat01)baseimage_rgb.astype(np.float32)/255.0colcolored.astype(np.float32)/255.0blendednp.clip((1-alpha)*basealpha*col,0.0,1.0)return(blended*255.0).astype(np.uint8)五、总结本文实现了一个基于 PySide6 的手动热力图绘制工具虽然不是深度学习神经网络模型真实计算出来的类激活Grad-CAM但在视觉效果上已经比较接近并且具备很强的交互性和可控性。相比直接依赖模型可视化这种方式更适合手工标注关注区域制作演示图和论文实验效果图。

更多文章