基于OpenCV的白细胞(WBC)轮廓检测与计数实现方案咨询
白细胞(WBCs)轮廓检测与计数实现
完成二值化闭运算操作后,按「轮廓提取→有效轮廓筛选→计数可视化」三步即可完成目标,具体实现如下:
现有预处理代码的问题修正
你当前代码中HSV空间转灰度的参数错误,cv2.COLOR_BGR2GRAY仅适用于BGR三通道图转灰度,HSV图直接调用该参数会得到色彩失真的灰度结果,修正后预处理逻辑稳定性会明显提升。
核心实现步骤
1. 轮廓检测
对闭运算得到的二值图调用轮廓检测接口,选择仅检测外轮廓模式,避免把细胞内部的暗区/孔洞识别为独立细胞:
# 检测轮廓,兼容OpenCV3/4版本返回值格式 contours, hierarchy = cv2.findContours(closing.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
2. 有效轮廓过滤
预处理后残留的噪点、图像边缘的杂质团块会被识别为轮廓,需要通过面积阈值过滤无效目标:
- 面积过小:滤波残留的噪点,直接丢弃
- 面积过大:多个细胞粘连的团块、背景大块杂质,可根据需求选择标记或做二次分割
valid_wbc = [] # 面积阈值需根据你的图像分辨率、拍摄倍率调整,以下为参考值 min_area = 200 max_area = 3000 for cnt in contours: area = cv2.contourArea(cnt) if min_area < area < max_area: valid_wbc.append(cnt)
如果你处理的样本存在大量细胞粘连的情况,可在轮廓检测前增加距离变换+分水岭分割步骤,拆分粘连细胞后再计数,准确率会更高。
3. 结果可视化与计数
遍历所有有效轮廓,在原图上绘制标记、统计总数:
wbc_count = len(valid_wbc) for i, cnt in enumerate(valid_wbc, 1): # 绘制细胞轮廓 cv2.drawContours(output, [cnt], -1, (0,255,0), 2) # 标记细胞序号 M = cv2.moments(cnt) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) cv2.putText(output, str(i), (cX-10, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,255), 2) # 在图上标注总计数 cv2.putText(output, f"WBC Count: {wbc_count}", (20,40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255,0,0), 3) # 保存结果 cv2.imwrite("wbc_count_result.jpg", output) print(f"检测到白细胞总数:{wbc_count}")
完整可运行代码
把修正后的预处理和后续逻辑整合后代码如下:
import cv2 import numpy as np # 读取图像 im = cv2.imread("images/image.jpg") output = im.copy() # 修正:正确的灰度转换逻辑 gray_image = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) blurM = cv2.medianBlur(gray_image, 5) cv2.imwrite("gray.jpg",gray_image) # 阈值反二值化+形态学闭运算 res,thresh_img=cv2.threshold(blurM,135,255,cv2.THRESH_BINARY_INV) kernel = np.ones((5,5),np.uint8) closing= cv2.morphologyEx(thresh_img,cv2.MORPH_CLOSE,kernel,iterations=2) cv2.imwrite("result3.jpg",closing) # 轮廓检测 contours, hierarchy = cv2.findContours(closing.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 有效轮廓过滤 valid_wbc = [] min_area = 200 max_area = 3000 for cnt in contours: area = cv2.contourArea(cnt) if min_area < area < max_area: valid_wbc.append(cnt) # 可视化与计数 wbc_count = len(valid_wbc) for i, cnt in enumerate(valid_wbc, 1): cv2.drawContours(output, [cnt], -1, (0,255,0), 2) M = cv2.moments(cnt) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) cv2.putText(output, str(i), (cX-10, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,255), 2) cv2.putText(output, f"WBC Count: {wbc_count}", (20,40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255,0,0), 3) cv2.imwrite("wbc_count_result.jpg", output) print(f"检测到白细胞总数:{wbc_count}")
注意:代码中
min_area、max_area、二值化阈值135都需要根据你自己的数据集调整,调整到和人工计数结果误差最小时即可固定参数批量处理。
内容的提问来源于stack exchange,提问作者Mohamed Ragih
相关产品推荐
相关产品推荐

