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

YOLOv5血细胞检测实战:从训练到部署

YOLOv5血细胞检测实战:从训练到部署

在医院的检验科里,每天都有成千上万张血液涂片等待显微镜下的逐帧分析。传统的血细胞计数依赖人工标注——医生需要在视野中识别红细胞、白细胞和血小板,并手动圈出每一个目标。这项工作不仅耗时费力,还容易因疲劳导致漏检或误判。一个熟练技师完成一张图像的完整标注可能要花上几分钟,而AI模型可以在不到一秒内给出结果。

这正是深度学习介入医学影像的理想切入点。近年来,基于YOLO系列的目标检测技术因其出色的实时性与精度平衡,在工业界迅速落地。特别是YOLOv5,由Ultralytics团队打造的这一PyTorch实现版本,凭借其极简的接口设计和强大的工程化支持,已经成为许多医疗AI项目的首选框架。

我们不妨设想这样一个场景:一台连接显微镜的边缘设备,能够实时捕获血液图像并立即返回细胞分布热力图与数量统计。这种系统的核心,往往就是一个经过定制训练的小型化目标检测模型。本文将以开源的BCCD(Blood Cell Count Dataset)数据集为基础,带你亲手构建一个可运行的血细胞识别系统,覆盖从原始数据处理到最终部署的全流程。


整个流程中最关键的第一步,是让模型“看得懂”我们的数据。BCCD数据集提供了约360张标注图像,采用PASCAL VOC格式存储,每张图片对应一个XML文件,记录了每个细胞的位置和类别信息。但YOLOv5并不直接读取XML,它要求标签以归一化的xywh格式保存为.txt文件,且目录结构需明确区分训练集与验证集。

我们需要做的是三件事:解析XML、转换坐标、划分数据集。以下是核心代码逻辑:

import os import xml.etree.ElementTree as ET from glob import glob import pandas as pd from sklearn.model_selection import train_test_split import shutil # 扫描所有XML文件 annotations = sorted(glob('BCCD/Annotations/*.xml')) data = [] for file in annotations: filename = os.path.basename(file).replace('.xml', '.jpg') tree = ET.parse(file) root = tree.getroot() for obj in root.findall('object'): cls = obj.find('name').text.strip() bbox = obj.find('bndbox') xmin = int(bbox.find('xmin').text) ymin = int(bbox.find('ymin').text) xmax = int(bbox.find('xmax').text) ymax = int(bbox.find('ymax').text) data.append([filename, cls, xmin, ymin, xmax, ymax]) df = pd.DataFrame(data, columns=['filename', 'class', 'xmin', 'ymin', 'xmax', 'ymax']) print(f"共加载 {len(df)} 个标注")

接下来进行坐标归一化处理。注意,BCCD图像统一为640x480分辨率,因此可以直接使用固定尺寸进行缩放:

IMG_WIDTH, IMG_HEIGHT = 640, 480 class_mapping = {'Platelets': 0, 'RBC': 1, 'WBC': 2} df['cls_id'] = df['class'].map(class_mapping) df['width'] = df['xmax'] - df['xmin'] df['height'] = df['ymax'] - df['ymin'] df['x_center'] = (df['xmin'] + df['width'] / 2) / IMG_WIDTH df['y_center'] = (df['ymin'] + df['height'] / 2) / IMG_HEIGHT df['width_norm'] = df['width'] / IMG_WIDTH df['height_norm'] = df['height'] / IMG_HEIGHT

最后将数据划分为训练集和验证集,并组织成YOLOv5期望的标准目录结构:

train_files, val_files = train_test_split(df['filename'].unique(), test_size=0.2, random_state=42) os.makedirs('dataset/images/train', exist_ok=True) os.makedirs('dataset/images/val', exist_ok=True) os.makedirs('dataset/labels/train', exist_ok=True) os.makedirs('dataset/labels/val', exist_ok=True) def save_labels_and_images(file_list, img_dir, label_dir): for fname in file_list: src_img = f'BCCD/JPEGImages/{fname}' dst_img = os.path.join(img_dir, fname) if os.path.exists(src_img): shutil.copy(src_img, dst_img) rows = df[df['filename'] == fname] label_path = os.path.join(label_dir, fname.replace('.jpg', '.txt')) with open(label_path, 'w') as f: for _, row in rows.iterrows(): line = f"{row['cls_id']} {row['x_center']:.6f} {row['y_center']:.6f} " \ f"{row['width_norm']:.6f} {row['height_norm']:.6f}\n" f.write(line) save_labels_and_images(train_files, 'dataset/images/train', 'dataset/labels/train') save_labels_and_images(val_files, 'dataset/images/val', 'dataset/labels/val') print("✅ 数据预处理完成!") print(f"训练集:{len(train_files)} 张图像") print(f"验证集:{len(val_files)} 张图像")

这一步完成后,我们就拥有了符合YOLOv5输入规范的数据集。


进入模型训练阶段前,先克隆官方仓库并安装依赖:

git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt

然后创建配置文件data/bccd.yaml,告诉模型去哪里找数据以及有哪些类别:

train: ../dataset/images/train val: ../dataset/images/val nc: 3 names: ['Platelets', 'RBC', 'WBC']

YOLOv5提供多个模型尺寸供选择。对于血细胞这类小目标密集的场景,我建议优先尝试yolov5syolov5m。前者参数量仅720万,适合部署在边缘设备;后者性能更强,适合服务器端高精度任务。

启动训练命令如下:

python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data bccd.yaml \ --cfg models/yolov5s.yaml \ --weights '' \ --name yolov5_bccd_s \ --cache

其中--cache参数非常关键——由于BCCD数据量较小(约360张),开启缓存可将图像预加载至内存,显著提升训练速度,通常能提速2倍以上。

训练过程中可通过TensorBoard监控指标:

tensorboard --logdir runs/train

重点关注以下几个指标:
-Precision(精确率):预测为正样本中有多少是真的
-Recall(召回率):真实正样本中有多少被成功检出
-mAP@0.5:IoU阈值0.5下的平均精度,反映整体检测能力
-mAP@0.5:0.95:多阈值综合评分,更严格地评估定位准确性

当训练结束时,典型输出可能如下:

Epoch gpu_mem box obj cls total targets img_size 99/99 2.30G 0.0318 0.0584 0.0102 0.1004 233 640 Class Images Instances P R mAP@.5 mAP@.5:.95 all 120 489 0.921 0.887 0.902 0.615

只要mAP@0.5 > 0.85,就可以认为模型已经具备实用价值。此时权重文件会保存在runs/train/yolov5_bccd_s/weights/best.pt


模型训练完成后,下一步是验证其实际表现。YOLOv5自带的detect.py脚本极大简化了推理流程。

对单张图像进行预测:

python detect.py \ --source dataset/images/val/BloodImage_00000.jpg \ --weights runs/train/yolov5_bccd_s/weights/best.pt \ --conf-thres 0.4 \ --iou-thres 0.5 \ --save-txt \ --save-conf \ --exist-ok

批量处理整个验证集也只需更改--source路径即可:

python detect.py \ --source dataset/images/val/ \ --weights runs/train/yolov5_bccd_s/weights/best.pt \ --device 0

输出结果默认保存在runs/detect/exp/目录下,包含带框图像和对应的.txt标签文件。若想进一步处理这些检测结果(例如裁剪细胞区域送入分类网络),可以编写后处理函数读取坐标信息:

import cv2 import matplotlib.pyplot as plt def load_yolo_predictions(txt_path, img_shape): if not os.path.exists(txt_path): return [] predictions = [] img_h, img_w = img_shape[:2] with open(txt_path, 'r') as f: for line in f.readlines(): parts = list(map(float, line.strip().split())) cls_id, xc, yc, w, h = parts[:5] xc *= img_w; yc *= img_h w *= img_w; h *= img_height x1 = int(xc - w / 2) y1 = int(yc - h / 2) w = int(w); h = int(h) predictions.append([int(cls_id), x1, y1, w, h]) return predictions # 可视化示例 img = cv2.imread('dataset/images/val/BloodImage_00000.jpg') img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) preds = load_yolo_predictions('runs/detect/exp/BloodImage_00000.txt', img.shape) plt.figure(figsize=(10, 8)) ax = plt.gca() colors = {0: 'green', 1: 'red', 2: 'blue'} labels = {0: 'Platelets', 1: 'RBC', 2: 'WBC'} for cls_id, x, y, w, h in preds: rect = plt.Rectangle((x, y), w, h, fill=False, color=colors[cls_id], linewidth=2) ax.add_patch(rect) ax.text(x, y, labels[cls_id], color='white', fontsize=12, bbox=dict(facecolor=colors[cls_id], alpha=0.7)) plt.imshow(img_rgb) plt.axis('off') plt.title("YOLOv5 血细胞检测结果") plt.show()

这段代码不仅能展示检测效果,也为后续构建自动化分析流水线打下了基础。


真正决定一个AI项目成败的,往往是部署方式的选择。实验室里的.pt模型只是起点,生产环境中的推理需求千差万别——有的需要低延迟响应,有的受限于硬件资源,还有的必须跨平台运行。

方案一:脚本调用式部署

最简单的方式是封装detect.py为子进程服务:

import subprocess def predict_image(image_path): result = subprocess.run([ 'python', 'yolov5/detect.py', '--source', image_path, '--weights', 'best.pt', '--save-txt', '--nosave' ], capture_output=True, text=True) output_dir = 'runs/detect/exp' txt_file = os.path.join(output_dir, os.path.basename(image_path).replace('.jpg','.txt')) return load_yolo_predictions(txt_file, cv2.imread(image_path).shape)

这种方式适合一次性批处理任务,但在高频请求下会有较大的启动开销。

方案二:编程式推理(推荐)

更高效的做法是直接加载模型进行推理:

import torch from models.common import DetectMultiBackend from utils.augmentations import letterbox from utils.general import non_max_suppression, scale_coords model = DetectMultiBackend('best.pt', device='cpu') model.warmup(imgsz=(1, 3, 640, 640)) def infer_single_image(img_path): img0 = cv2.imread(img_path) img = letterbox(img0, 640, stride=32)[0] img = img.transpose((2, 0, 1))[None] img = torch.from_numpy(img).float() / 255.0 pred = model(img, augment=False) pred = non_max_suppression(pred, conf_thres=0.4, iou_thres=0.5) results = [] det = pred[0] if len(det): scale_coords(img.shape[2:], det[:, :4], img0.shape) for *xyxy, conf, cls in det: xyxy = [int(x) for x in xyxy] results.append({ 'class': int(cls), 'confidence': float(conf), 'bbox': xyxy }) return results

这种方式响应更快,便于集成进Web API或桌面应用。

方案三:高性能导出(ONNX/TensorRT)

对于嵌入式设备或实时系统,应考虑模型导出优化:

# 导出为 ONNX(通用性强) python export.py --weights best.pt --include onnx --img 640 # 导出为 TensorRT 引擎(极致性能) python export.py --weights best.pt --include engine --img 640 --device 0

YOLOv5支持多种导出格式:
-torchscript:适用于 PyTorch 生态内部部署
-onnx:跨平台通用,可在 Windows/Linux/macOS 上运行
-engine:TensorRT 加速,推理速度提升可达3~5倍
-tflite/coreml:移动端专用,适配 Android/iOS

尤其在边缘计算场景中,将模型转为 TensorRT 后配合 Jetson 设备,可实现每秒数十帧的稳定推理,完全满足显微镜视频流分析的需求。


回过头看,这个看似简单的血细胞检测项目,实际上串联起了现代AI工程开发的完整链条:从非标准数据的清洗转换,到模型训练中的超参调试,再到多样化的部署策略选择。而YOLOv5之所以能在众多框架中脱颖而出,正是因为它把每一个环节都做到了“够用、好用、能用”。

更重要的是,这类技术正在真实改变医疗工作的效率边界。想象一下,未来医生不再需要盯着屏幕数细胞,而是由AI先行完成初筛,他们只需复核异常样本——这种人机协同模式,才是AI赋能专业领域的正确打开方式。

随着YOLOv8等新架构引入分割能力,我们甚至可以期待更精细的应用:比如自动测量红细胞直径分布、计算血小板聚集程度,进而辅助诊断贫血或凝血功能障碍。技术的演进,始终服务于临床价值的深化。

如果你也在探索AI+医疗的可能性,不妨就从这样一个小而完整的项目开始。它不只是一次代码实践,更是理解“如何让算法走出实验室”的第一课。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.jsqmd.com/news/99175/

相关文章:

  • PaddlePaddle动态图编程入门:git下载示例代码并导入conda环境
  • 大专营销人跨领域突围难?基础薄弱也能啃下 AI 硬骨头!CAIE 认证成逆袭密码
  • Dify开源LLM应用开发平台本地部署指南
  • FaceFusion:领先的人脸融合技术平台使用指南
  • 如何在ComfyUI中加载GPT-SoVITS节点进行语音生成?
  • Qwen3-VL-30B实现航空航天器高精度识别
  • anything-llm Docker本地部署指南
  • Qwen-Image微调实战:让模型学会新车图生成
  • 《60天AI学习计划启动 | Day 05: 项目实战 - 简单聊天机器人》
  • ACE-Step:开源高效音乐生成大模型解析
  • 35、【Ubuntu】【远程开发】内网穿透:连接可靠性(三) - 指南
  • 【每日算法】LeetCode 19. 删除链表的倒数第 N 个结点
  • 2025-2026 北京靠谱工程律所指南:权威评测与核心解决方案对比 - 苏木2025
  • 16、Linux系统下外设使用指南
  • 2025年度北京五大靠谱大平层设计品牌企业推荐:资质齐全的大 - 工业品牌热点
  • Claude Code最佳助手Serena入门指南
  • LobeChat能否评估项目风险?提前预警潜在问题
  • 当毕业论文从“熬出来的任务”变为“走出来的路径”:一位本科生如何在AI协研工具的陪伴下,完成一次有方法、有规范、有成长的学术初旅?
  • TensorRT-LLM离线环境搭建与Bloom模型量化推理
  • FLUX.1-dev本地部署与镜像下载全指南
  • 腾讯混元开源HunyuanVideo-Foley:实现声画合一的AI音效革命
  • Excalidraw应用案例与最佳实践解析
  • 《60天AI学习计划启动 | Day 04: 流式响应实现 - 打造流畅的AI对话体验》
  • 抢占AI流量入口:深度云海如何以全链路GEO方案赋能企业增长 - 深度智识库
  • EmotiVoice:开源多情感TTS重塑声音表达
  • 2025隐形车衣厂家TOP5权威推荐:甄选靠谱制造厂助力爱车 - 工业推荐榜
  • 期末复习分析+改错
  • LobeChat能否标记不确定性?避免过度自信输出
  • 22、Perl正则表达式与程序交互全解析
  • LobeChat能否连接AR眼镜?增强现实对话