当前位置: 首页 > article >正文

从训练到评估:手搓一个Hovernet推理结果评估脚本(附完整Python代码)

从训练到评估手搓一个Hovernet推理结果评估脚本附完整Python代码当你终于跑通了Hovernet模型的训练和推理流程看着生成的.mat预测文件可能会陷入新的困惑这些预测结果到底有多准确官方代码没有提供评估脚本而学术论文中的指标又显得遥不可及。本文将带你从零构建一个完整的评估系统不仅提供可直接运行的Python代码更会深入解析每一行背后的计算逻辑。1. 评估脚本的设计哲学在病理图像分割领域评估不是简单的像素对比。我们需要考虑细胞实例的完整性、边界准确性以及检测的可靠性。传统语义分割的评估指标在这里往往力不从心这就是为什么Hovernet这类模型需要特殊的评估方式。评估脚本的核心任务可以分解为三个层次像素级准确率预测的细胞区域与真实标注的重合程度实例级完整性每个细胞实例是否被完整检测拓扑结构保持细胞间的接触关系是否被正确保留# 基础评估流程框架 def evaluate(pred, gt): # 1. 二值化处理 pred_bin (pred 0).astype(np.uint8) gt_bin (gt 0).astype(np.uint8) # 2. 连通域分析 pred_labeled label(pred_bin) gt_labeled label(gt_bin) # 3. 指标计算 metrics calculate_metrics(pred_labeled, gt_labeled) return metrics注意评估脚本需要与Hovernet的输出特性严格匹配。模型生成的inst_map中每个细胞实例都有唯一的ID值背景为0。2. 环境准备与数据加载评估环节的依赖相对简单主要需要以下几个科学计算库库名称用途说明最低版本scipy加载.mat格式的预测结果1.6.0scikit-image连通域分析0.18.0scikit-learn指标计算0.24.0numpy数组操作1.20.0数据加载部分需要特别注意.mat文件的结构def load_inst_map(file_path): 加载.mat格式的实例标注图 Args: file_path: .mat文件路径 Returns: numpy.ndarray: 二维数组每个细胞实例有唯一ID mat loadmat(file_path) return mat[inst_map] # Hovernet标准输出格式常见问题排查如果遇到KeyError: inst_map检查.mat文件是否来自Hovernet推理输出出现TypeError时确认scipy版本是否支持该.mat格式3. 核心评估指标实现评估指标的计算需要分阶段进行我们先从二值化处理开始3.1 二值化与连通域分析def binarize_and_label(inst_map): 将实例图转换为二值图并进行连通域标记 Args: inst_map: 原始实例图背景为0每个实例有唯一ID Returns: tuple: (二值图, 连通域标记图) binary (inst_map 0).astype(np.uint8) labeled label(binary) return binary, labeled这个阶段有几个关键技术点二值化阈值简单使用0作为阈值也可根据需求调整连通域算法skimage.measure.label使用高效的并查集算法边界处理8连通或4连通会影响细小突起的细胞形态3.2 指标计算模块我们主要计算三个核心指标from sklearn.metrics import f1_score, precision_score, recall_score def calculate_metrics(pred, gt): 计算评估指标 Args: pred: 预测结果的连通域图 gt: 真实标注的连通域图 Returns: tuple: (F1, Precision, Recall) pred_flat pred.flatten() gt_flat gt.flatten() f1 f1_score(gt_flat 0, pred_flat 0) precision precision_score(gt_flat 0, pred_flat 0) recall recall_score(gt_flat 0, pred_flat 0) return f1, precision, recall指标解释Precision预测为细胞的区域中真正是细胞的比例Recall真实细胞区域中被正确预测出来的比例F1 ScorePrecision和Recall的调和平均数4. 批量评估与结果可视化单个图像的评估结果参考价值有限我们需要对整个测试集进行批量评估def eval_folder(pred_dir, gt_dir): 评估整个文件夹的预测结果 Args: pred_dir: 预测结果.mat文件目录 gt_dir: 真实标注.mat文件目录 f1_list, p_list, r_list [], [], [] for fname in os.listdir(pred_dir): if not fname.endswith(.mat): continue pred_path os.path.join(pred_dir, fname) gt_path os.path.join(gt_dir, fname) if not os.path.exists(gt_path): print(f警告缺少{fname}的标注文件) continue f1, p, r eval_single_image(pred_path, gt_path) f1_list.append(f1) p_list.append(p) r_list.append(r) print(f[{fname}] F1: {f1:.4f}, P: {p:.4f}, R: {r:.4f}) print(\n 整体指标 ) print(f平均F1分数: {np.mean(f1_list):.4f} ± {np.std(f1_list):.4f}) print(f平均精确率: {np.mean(p_list):.4f} ± {np.std(p_list):.4f}) print(f平均召回率: {np.mean(r_list):.4f} ± {np.std(r_list):.4f})结果可视化建议使用箱线图展示各指标在不同图像上的分布绘制Precision-Recall曲线分析模型表现对指标异常的图像进行个案分析5. 高级评估技巧基础指标之外我们还可以实现更专业的评估方法5.1 实例匹配评估from scipy.spatial import distance_matrix def instance_matching(pred_inst, gt_inst): 基于中心点的实例匹配 Args: pred_inst: 预测实例图 gt_inst: 真实实例图 Returns: dict: 匹配统计结果 pred_props regionprops(pred_inst) gt_props regionprops(gt_inst) pred_centers np.array([prop.centroid for prop in pred_props]) gt_centers np.array([prop.centroid for prop in gt_props]) dist_mat distance_matrix(pred_centers, gt_centers) matched (dist_mat 10) # 10像素距离阈值 tp np.sum(matched.any(axis1)) fp len(pred_props) - tp fn len(gt_props) - np.sum(matched.any(axis0)) return {TP: tp, FP: fp, FN: fn}5.2 边界敏感评估细胞分割特别关注边界准确性我们可以实现边界加权评估from skimage.segmentation import find_boundaries def boundary_weighted_metrics(pred, gt): 边界加权的评估指标 Args: pred: 预测图 gt: 真实图 Returns: tuple: (边界F1, 边界Precision, 边界Recall) pred_boundary find_boundaries(pred, modeinner) gt_boundary find_boundaries(gt, modeinner) # 给边界像素3倍权重 weights np.ones_like(pred, dtypenp.float32) weights[pred_boundary] 3.0 weights[gt_boundary] 3.0 f1 f1_score(gt 0, pred 0, sample_weightweights.flatten()) precision precision_score(gt 0, pred 0, sample_weightweights.flatten()) recall recall_score(gt 0, pred 0, sample_weightweights.flatten()) return f1, precision, recall6. 完整评估脚本集成将上述模块整合成完整的评估系统import os import numpy as np from scipy.io import loadmat from skimage.measure import label, regionprops from sklearn.metrics import f1_score, precision_score, recall_score class HovernetEvaluator: def __init__(self, pred_dir, gt_dir): self.pred_dir pred_dir self.gt_dir gt_dir self.metrics { F1: [], Precision: [], Recall: [], TP: [], FP: [], FN: [] } def evaluate_all(self): for fname in os.listdir(self.pred_dir): if not fname.endswith(.mat): continue pred_path os.path.join(self.pred_dir, fname) gt_path os.path.join(self.gt_dir, fname) if not os.path.exists(gt_path): print(f跳过{fname}缺少标注文件) continue results self.evaluate_single(pred_path, gt_path) self._update_metrics(results, fname) self._print_summary() def evaluate_single(self, pred_path, gt_path): pred loadmat(pred_path)[inst_map] gt loadmat(gt_path)[inst_map] # 基础指标 f1, precision, recall self._basic_metrics(pred, gt) # 实例匹配 match_stats self._instance_matching(pred, gt) return { filename: os.path.basename(pred_path), F1: f1, Precision: precision, Recall: recall, **match_stats } def _basic_metrics(self, pred, gt): pred_bin (pred 0).astype(np.uint8) gt_bin (gt 0).astype(np.uint8) pred_labeled label(pred_bin) gt_labeled label(gt_bin) f1 f1_score(gt_bin.flatten(), pred_bin.flatten()) precision precision_score(gt_bin.flatten(), pred_bin.flatten()) recall recall_score(gt_bin.flatten(), pred_bin.flatten()) return f1, precision, recall def _instance_matching(self, pred, gt): pred_props regionprops(label(pred 0)) gt_props regionprops(label(gt 0)) if not pred_props or not gt_props: return {TP: 0, FP: len(pred_props), FN: len(gt_props)} pred_centers np.array([prop.centroid for prop in pred_props]) gt_centers np.array([prop.centroid for prop in gt_props]) dist_mat distance_matrix(pred_centers, gt_centers) matched (dist_mat 10) tp np.sum(matched.any(axis1)) fp len(pred_props) - tp fn len(gt_props) - np.sum(matched.any(axis0)) return {TP: tp, FP: fp, FN: fn} def _update_metrics(self, results, fname): print(f[{fname}] F1: {results[F1]:.4f}, fP: {results[Precision]:.4f}, fR: {results[Recall]:.4f}, fTP: {results[TP]}, FP: {results[FP]}, FN: {results[FN]}) for key in self.metrics: self.metrics[key].append(results[key]) def _print_summary(self): print(\n 整体评估结果 ) for metric, values in self.metrics.items(): if metric in [TP, FP, FN]: print(f总{metric}: {np.sum(values)}) else: print(f平均{metric}: {np.mean(values):.4f} ± {np.std(values):.4f}) # 使用示例 if __name__ __main__: evaluator HovernetEvaluator( pred_dirpath/to/predictions, gt_dirpath/to/ground_truth ) evaluator.evaluate_all()这个评估系统在实际项目中表现出色特别是在处理CoNSeP数据集时能够准确反映模型在细胞核分割任务上的真实性能。

相关文章:

从训练到评估:手搓一个Hovernet推理结果评估脚本(附完整Python代码)

从训练到评估:手搓一个Hovernet推理结果评估脚本(附完整Python代码) 当你终于跑通了Hovernet模型的训练和推理流程,看着生成的.mat预测文件,可能会陷入新的困惑:这些预测结果到底有多准确?官方代…...

动手模拟:用Python和NumPy理解MRI的T1/T2加权与图像对比度生成

用Python和NumPy模拟MRI的T1/T2加权图像生成:从物理模型到可视化实战 磁共振成像(MRI)作为现代医学影像的支柱技术,其独特的软组织对比度能力源于对氢原子核弛豫特性的精妙捕捉。但教科书式的理论讲解往往让学习者止步于抽象概念。…...

Spring AI RAG实战:从基础问答到高级检索增强生成

1. 为什么需要RAG技术? 最近两年大语言模型(LLM)发展迅猛,但实际应用中经常会遇到三个头疼的问题:模型知识更新不及时、回答缺乏事实依据、对特定领域理解不深。比如你问ChatGPT"今年最新发布的iPhone有什么新功能…...

Clock Gating技术解析:如何有效降低芯片动态功耗

1. 为什么芯片需要Clock Gating技术? 当你把手机放在口袋里一整天,回家发现电量还剩70%时,可能没想过这要归功于芯片里一个叫Clock Gating的技术。简单来说,它就像你家空调的智能开关——没人在房间时自动关闭送风,但温…...

CVPR 2024 热门数据集解析与应用指南

1. CVPR 2024热门数据集全景扫描 计算机视觉领域每年都会涌现大量新数据集,但真正能经得起时间考验的往往具备三个特征:标注质量高、任务覆盖广、基准价值大。今年CVPR会议上,ImageNet-1K、MS COCO 2017和ADE20K这三个"老将"依然保…...

ComfyUI IPAdapter Plus插件:3分钟掌握图像风格迁移终极技巧

ComfyUI IPAdapter Plus插件:3分钟掌握图像风格迁移终极技巧 【免费下载链接】ComfyUI_IPAdapter_plus 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI_IPAdapter_plus 想要将参考图像的风格、构图甚至人物面部特征完美融入AI生成图像中吗&#xff1…...

如何快速解密SWF文件:JPEXS逆向工具的完整指南

如何快速解密SWF文件:JPEXS逆向工具的完整指南 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款专业的开源SWF解密工具,专门用…...

md2pptx:当Markdown遇见PowerPoint的优雅解法

md2pptx:当Markdown遇见PowerPoint的优雅解法 【免费下载链接】md2pptx Markdown To PowerPoint converter 项目地址: https://gitcode.com/gh_mirrors/md/md2pptx 在技术写作与演示制作之间,似乎总存在一道难以逾越的鸿沟。一边是程序员钟爱的纯…...

Cursor Pro激活工具终极指南:高效解锁AI编程全功能体验

Cursor Pro激活工具终极指南:高效解锁AI编程全功能体验 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: Youve reached your tr…...

C语言实现 简易计算器教程

制作简易的算术计算器编写程序实现一个简单的计算器&#xff08;可实现加减乘除即可&#xff09;。要求从键盘输入2个数和一个运算符&#xff0c;输出对应的计算结果。#include <stdio.h>int main(){double num1, num2, result;char symbol;printf("简易计算器\n&qu…...

告别logcat日志洪流:从Unexpected EOF到缓冲区调优实战

1. 当Android日志系统崩溃时你在想什么 "logcat: Unexpected EOF!"这个红色警告突然跳出来的时候&#xff0c;我正在调试一个内存泄漏问题。手机连着电脑疯狂输出日志&#xff0c;突然就像被掐住脖子一样戛然而止&#xff0c;那种感觉就像正在看悬疑片突然停电——关…...

5分钟完成Windows系统优化:Win11Debloat免费工具完整指南

5分钟完成Windows系统优化&#xff1a;Win11Debloat免费工具完整指南 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and…...

如何判断坐标点所在的象限?

判断象限任意输入一个点的X坐标和Y坐标&#xff0c;判断它属于哪个象限并输出。#include <stdio.h> int main(){float x, y;printf("请输入点的X坐标: \n");scanf("%f", &x);printf("请输入点的Y坐标: \n");scanf("%f", &am…...

别再死磕手册了!手把手教你用Vivado配置Aurora 8B10B IP核(Framing模式,附仿真波形分析)

实战指南&#xff1a;Vivado中Aurora 8B10B IP核的Framing模式配置与调试技巧 在FPGA高速串行通信领域&#xff0c;Xilinx的Aurora 8B/10B协议因其轻量级和可扩展性而广受欢迎。然而&#xff0c;当工程师们真正开始在Vivado环境中配置这个IP核时&#xff0c;往往会遇到各种意料…...

YOLOv11模型训练效果不满意?试试这个‘续杯’技巧:灵活调整Epoch数优化模型性能

YOLOv11模型训练效果不满意&#xff1f;试试这个‘续杯’技巧&#xff1a;灵活调整Epoch数优化模型性能 在计算机视觉领域&#xff0c;YOLO系列模型因其高效的检测性能而广受欢迎。当我们完成一轮训练后&#xff0c;常常会遇到一个关键问题&#xff1a;模型表现尚未达到预期&am…...

别再只抄电路图了!手把手教你用RC复位电路,从电容选型到时间计算(附常见坑点)

从零构建可靠复位电路&#xff1a;RC参数设计与避坑指南 当你第一次翻开单片机开发板的原理图&#xff0c;那个看似简单的RC复位电路背后&#xff0c;其实隐藏着一整套精妙的电子学原理。很多初学者会直接照搬现成电路&#xff0c;却不知道不同的电容类型会导致系统稳定性天差地…...

保姆级教程:用PyTorch手把手实现SE注意力模块(附ResNet集成代码)

保姆级教程&#xff1a;用PyTorch手把手实现SE注意力模块&#xff08;附ResNet集成代码&#xff09; 在深度学习模型的优化过程中&#xff0c;注意力机制已经成为提升模型性能的利器。今天&#xff0c;我们将从零开始实现一个完整的SE&#xff08;Squeeze-and-Excitation&#…...

Comics Downloader:跨平台漫画批量下载技术解决方案

Comics Downloader&#xff1a;跨平台漫画批量下载技术解决方案 【免费下载链接】comics-downloader tool to download comics and manga in pdf/epub/cbr/cbz from a website 项目地址: https://gitcode.com/gh_mirrors/co/comics-downloader Comics Downloader 是一款…...

Proteus仿真单片机STM32F103的TCP通信5

使用WIFI模拟器软件实现Proteus与NetAssist进行TCP通信 功能&#xff1a;在同一台电脑上&#xff0c;下位机为Proteus仿真stm32f103单片机作为服务端&#xff0c;上位机使用NetAssist作为客户端&#xff1b;使用WIFI模拟器软件与Proteus通过VSPD虚拟串口以JSON格式数据进行通信…...

别再折腾了!用Conda一键搞定ComfyUI安装与Python 3.12环境配置(附常见错误排查)

别再折腾了&#xff01;用Conda一键搞定ComfyUI安装与Python 3.12环境配置&#xff08;附常见错误排查&#xff09; 在AI绘画和工作流领域&#xff0c;ComfyUI凭借其模块化设计和高效性能赢得了大量用户的青睐。然而对于初学者来说&#xff0c;环境配置往往成为第一道门槛——…...

Gradle仓库配置优化:用阿里云镜像替代mavenCentral()、jcenter()和google()

1. 为什么需要替换Gradle默认仓库 如果你在国内做Android开发&#xff0c;大概率遇到过Gradle构建时卡在"Downloading..."的情况。我刚开始接触Android开发时&#xff0c;每次同步项目都要等上十几分钟&#xff0c;甚至经常因为网络问题直接失败。后来才发现&#xf…...

如何在3分钟内为Windows 11 24H2 LTSC系统一键安装微软商店:完整免费解决方案指南

如何在3分钟内为Windows 11 24H2 LTSC系统一键安装微软商店&#xff1a;完整免费解决方案指南 【免费下载链接】LTSC-Add-MicrosoftStore Add Windows Store to Windows 11 24H2 LTSC 项目地址: https://gitcode.com/gh_mirrors/ltscad/LTSC-Add-MicrosoftStore 对于选择…...

PX4飞控固件编译调试避坑实录:从GCC版本冲突到Python模块缺失的完整解决流程

PX4飞控固件编译调试避坑实录&#xff1a;从GCC版本冲突到Python模块缺失的完整解决流程 当你在深夜的办公室里&#xff0c;面对着满屏红色错误提示的终端窗口&#xff0c;PX4固件编译又一次失败了——这可能是每个无人机开发者都经历过的噩梦时刻。不同于简单的"复制粘贴…...

如何用EZCard快速批量制作桌游卡牌:400%效率提升的终极指南

如何用EZCard快速批量制作桌游卡牌&#xff1a;400%效率提升的终极指南 【免费下载链接】CardEditor 一款专为桌游设计师开发的批处理数值填入卡牌生成器/A card batch generator specially developed for board game designers 项目地址: https://gitcode.com/gh_mirrors/ca…...

【2026年阿里巴巴集团暑期实习- 4月15日-算法岗-第二题- 何物为真】(题目+思路+JavaC++Python解析+在线测试)

题目内容 你在玩一个 “真假话” 游戏。一共有 nnn 句话,部分句子的真假你已经知道,其余句子未知。我们用 111 表示真话、000</...

【2026年阿里巴巴集团暑期实习- 4月15日-算法岗-第一题- 富豪】(题目+思路+JavaC++Python解析+在线测试)

题目内容 给定一个长度为 nnn 的数组 { a1​,a2​,…,ana_1​,a_2​,…,a_na...

【2026年华为暑期实习-非AI方向(通软嵌软测试算法数据科学)-4月15日-第三题(100分)- 实现一个窗口系统】(题目+思路+JavaC++Python解析+在线测试)

题目内容 实现一个简单的窗口系统。首先初始化一个给定宽高的屏幕,并建立图像坐标系,以屏幕左上角 (0, 0) 为坐标原点。 窗口系统可以容纳窗口,窗口有以下属性: 窗口名 窗口宽高 窗口左上角坐标 窗口层级 支持的操作 窗口系统支持以下操作: 创建窗口 移除窗口 resizere…...

【2026年华为暑期实习-非AI方向(通软嵌软测试算法数据科学)-4月15日-第二题(100分)- 异或树】(题目+思路+JavaC++Python解析+在线测试)

题目内容 老师为孩子们设计了一个使用异或树的游戏。游戏在一棵有 nnn 个节点的树上进行,节点编号从 111 到 nnn...

多模态视觉-语言-时序融合建模,深度解析沃尔玛中国区销量预测误差下降41%的核心架构,

第一章&#xff1a;多模态大模型在零售中的应用 2026奇点智能技术大会(https://ml-summit.org) 多模态大模型正深刻重构零售行业的感知、理解与决策范式。通过联合建模文本、图像、视频、语音及结构化销售数据&#xff0c;模型可实现跨模态语义对齐&#xff0c;支撑从商品识别…...

读懂言外之意,破解模糊困境——如何理解人类意图和模糊指令

日常生活中&#xff0c;我们常常被模糊的表达包围&#xff1a;家人说“帮我拿个东西”&#xff0c;朋友说“有空聚聚”&#xff0c;领导说“这个方案再完善一下”。这些看似简单的指令&#xff0c;背后却隐藏着复杂的人类意图&#xff0c;若无法准确解读&#xff0c;轻则造成误…...