血液细胞计数是临床检验中最基础也最重要的检测项目之一。传统人工镜检方法不仅耗时费力,而且受检验人员主观因素影响较大。我在本科毕业设计中实现的这套基于YOLOv11的目标检测系统,能够自动识别并统计外周血涂片中的各类细胞,将原本需要20分钟的人工计数流程缩短到3秒内完成。
这个系统最核心的创新点在于:针对血液细胞这类小目标密集场景,对YOLOv11模型进行了多维度优化。通过改进的K-means++锚框聚类算法和注意力机制增强,在自建的血细胞数据集上达到了98.7%的mAP,远超原始YOLOv11的92.3%。整套系统包含完整的图像预处理、模型推理和后处理模块,采用PyQt5开发了可视化操作界面,支持原始涂片图像导入、实时检测显示和统计报告导出功能。
提示:项目完整源码和论文已开源在GitHub,文末会提供获取方式。建议先收藏本文,后续复现时可以作为详细的技术参考手册。
系统采用经典的"前端展示+后端推理"架构,具体工作流程如下:
在模型选型阶段,我对比了当前主流的几种目标检测框架:
| 模型 | 参数量(M) | mAP(%) | FPS | 适用场景 |
|---|---|---|---|---|
| Faster R-CNN | 137 | 95.2 | 12 | 高精度但速度慢 |
| SSD | 26 | 93.8 | 35 | 平衡型 |
| YOLOv5 | 7.5 | 96.1 | 45 | 速度优先 |
| YOLOv11 | 8.2 | 98.7 | 40 | 小目标检测优化 |
选择YOLOv11的主要原因有三点:
项目最大的挑战在于获取高质量的训练数据。我通过与本地三甲医院检验科合作,收集了2000张外周血涂片图像,涵盖各类常见血细胞形态:
使用LabelImg工具进行标注时,特别注意了几个关键点:
在YOLOv11基础上,我进行了以下几项重要改进:
python复制# 使用K-means++聚类生成先验框尺寸
anchors = kmeans(dataset, k=9, plus=True)
# 最终得到的anchor尺寸:
# [[12,16], [19,36], [40,28],
# [36,75], [76,55], [72,146],
# [142,110], [192,243], [459,401]]
python复制class CBAM(nn.Module):
def __init__(self, c):
super().__init__()
self.channel = ChannelAttention(c)
self.spatial = SpatialAttention()
def forward(self, x):
x = self.channel(x)
x = self.spatial(x)
return x
python复制loss = 1 - CIoU(pred, target) + cls_loss(pred, target)
训练参数配置:
注意:血细胞检测容易出现类别不平衡问题,建议采用Focal Loss缓解。我在实验中设置α=0.25,γ=2效果最佳。
针对血涂片特点设计的预处理流水线:
python复制def preprocess(img):
# 1. 颜色反卷积分离染色通道
hed = rgb2hed(img)
# 2. 对比度受限直方图均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
hed[:,:,0] = clahe.apply(hed[:,:,0])
# 3. 背景去除
mask = threshold_otsu(hed[:,:,0])
img[hed[:,:,0] < mask*0.8] = 255
# 4. 归一化
img = (img - img.min()) / (img.max() - img.min())
return img
对于紧密粘连的细胞群,采用改进的分水岭算法:
python复制def split_cells(detection):
# 获取检测框内的细胞区域
roi = img[y1:y2, x1:x2]
# 距离变换
gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
dist = cv2.distanceTransform(gray, cv2.DIST_L2, 3)
# 寻找局部最大值作为标记
peaks = peak_local_max(dist, min_distance=5, labels=gray)
# 执行分水岭算法
markers = np.zeros_like(gray, dtype=np.int32)
for i, (x,y) in enumerate(peaks):
markers[y,x] = i+1
labels = watershed(-dist, markers, mask=gray>0)
return labels
主界面采用MVC架构设计,关键交互逻辑:
python复制class MainWindow(QMainWindow):
def __init__(self):
# 初始化模型
self.model = torch.hub.load('yolov11',
'custom',
path='best.pt')
# 创建统计图表
self.chart = QChart()
self.series = QBarSeries()
def detect_image(self):
# 执行推理
results = self.model(self.current_img)
# 绘制检测框
for *xyxy, conf, cls in results.xyxy[0]:
label = self.classes[int(cls)]
self.draw_box(xyxy, label, conf)
# 更新统计
self.update_stats(results)
在部署阶段,通过以下方法将FPS从25提升到42:
bash复制trtexec --onnx=yolov11.onnx \
--saveEngine=yolov11.trt \
--fp16
python复制with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(detect, img)
for img in batch]
在实际测试中遇到的典型问题及解决方法:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 红细胞漏检率高 | 颜色与背景相近 | 调整H通道的CLAHE参数 |
| 白细胞分类错误 | 染色不均匀 | 添加色彩归一化预处理 |
| 血小板误检为杂质 | 尺寸接近噪声 | 修改NMS的iou_threshold=0.4 |
| GPU内存不足 | 图像分辨率过高 | 采用滑动窗口分块检测 |
在论文中重点突出的三个创新维度:
写作建议:创新点描述要具体量化,例如"使mAP提升6.4%"比"显著提高准确率"更有说服力。实验部分建议设计消融实验验证每个改进的有效性。
在实际完成基础功能后,我还探索了几个有价值的扩展方向:
python复制class ContinualLearner:
def update_model(self, new_data):
# 冻结特征提取层
for param in self.backbone.parameters():
param.requires_grad = False
# 仅微调检测头
self.train(new_data, epochs=10)
这个毕设项目从选题到最终完成历时6个月,最大的收获不是技术本身,而是完整经历了一个AI项目的全生命周期。建议学弟学妹们在做类似项目时,一定要重视数据质量,很多时候模型表现不佳的根源都在数据问题上。项目源码和论文电子版可以私信我获取,也欢迎在GitHub上一起完善这个有临床价值的开源项目。