You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计数图像中的衣藻细胞?含明场/暗场图像处理问题

解决衣藻细胞计数中轮廓周长为0导致的程序崩溃问题

问题背景

需要实现两类显微镜图像的衣藻细胞计数:

  • 明场图像:计数所有细胞
  • 暗场(FITC滤光片荧光图像):仅计数发出荧光的细胞

当前明场计数代码计划用圆形度作为筛选条件,但计算轮廓周长时出现0值,添加判断逻辑后程序崩溃,需修复该问题并完善圆形度筛选功能。

问题原因

部分无效轮廓(如单点、退化的1像素轮廓)会导致cv2.arcLength()返回0值,此时计算圆形度公式4π*面积/(周长²)会触发除以0错误;若判断逻辑未提前过滤这类无效轮廓,就会导致程序崩溃。

修复后的明场计数代码

import cv2
import numpy as np
from math import pi

# 加载图像
img_path = 'C:/Users/m_jen/Downloads/Sem 8/Sen lab project/MJ/input_images/0uMCr002.jpg'
image = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)

# 阈值分割(OTSU自动阈值+反二值化)
_, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 提取外轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 筛选参数
min_circularity = 0.4
max_circularity = 1.0
min_area = 400
max_area = 10000

filtered_contours = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    # 先过滤面积不符合的轮廓
    if not (min_area <= area <= max_area):
        continue
    # 计算周长,过滤周长为0的无效轮廓
    perimeter = cv2.arcLength(cnt, closed=True)
    if perimeter <= 0:
        continue
    # 计算圆形度:4π*面积/(周长²),越接近1越圆
    circularity = (4 * pi * area) / (perimeter ** 2)
    # 过滤圆形度不符合的轮廓
    if min_circularity <= circularity <= max_circularity:
        filtered_contours.append(cnt)

# 绘制筛选后的轮廓
img_contours = cv2.drawContours(image.copy(), filtered_contours, -1, (0, 255, 0), 2)

# 显示结果
cv2.namedWindow('Contours', cv2.WINDOW_NORMAL)
res_img_contours = cv2.resize(img_contours, (1280, 720))
cv2.imshow('Contours', res_img_contours)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 输出计数结果
print(f"Number of cells: {len(filtered_contours)}")

关键修复点

  1. 提前过滤无效轮廓:先判断周长是否大于0,避免除以0的数学错误
  2. 完善筛选逻辑:按面积→周长→圆形度的顺序逐步过滤,减少无效计算
  3. 正确计算圆形度:使用闭合轮廓的周长(cv2.arcLength第二个参数设为True),保证圆形度计算准确

暗场(FITC荧光图像)计数思路

暗场图像仅需计数荧光细胞,可按以下步骤实现:

  1. 提取图像的绿色通道(FITC荧光信号通常集中在绿色通道)
  2. 对绿色通道做阈值分割(直接二值化,保留亮的荧光区域)
  3. 用与明场相同的轮廓筛选逻辑(面积+圆形度)计数荧光细胞

示例代码片段:

# 加载暗场图像(彩色)
dark_img = cv2.imread('dark_field_image.jpg')
# 提取绿色通道
green_channel = dark_img[:, :, 1]
# 阈值分割(保留荧光亮区)
_, fluo_thresh = cv2.threshold(green_channel, 50, 255, cv2.THRESH_BINARY)
# 后续轮廓提取、筛选逻辑与明场代码一致

内容的提问来源于stack exchange,提问作者Manasmit Jena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 11:27:28