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

KI-67 IHC染色显微图像细胞计数Python代码优化求助

问题描述

我正在编写Python代码,用于计数KI-67 IHC染色显微图像中的癌细胞与正常细胞——癌细胞呈棕色,正常细胞呈蓝色。目前代码存在两个问题:

  • 无法精准识别所有棕色细胞
  • 受亮度影响,无法计数蓝色细胞

原代码

import cv2
import numpy as np
import math
from skimage import io

# Load the image and create a copy for further processing
image = cv2.imread("images/NET1.jpg")
original = image.copy()

# Convert the image to the HSV color space for color analysis
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# Define the HSV range to target brown colors
hsv_lower = np.array([0, 0, 0])
hsv_upper = np.array([20, 255, 255])

# Create a binary mask based on the specified HSV range
mask = cv2.inRange(hsv, hsv_lower, hsv_upper)

# Create a kernel for morphological operations
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))

# Perform morphological opening and closing operations to refine the mask
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=2)

# Display the processed mask
io.imshow(close)

# Find contours in the processed binary image
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

# Define parameters for cell counting
minimum_area = 10
average_cell_area = 100
connected_cell_area = 100
cells = 0

# Loop through the contours and count cells based on their area
for c in cnts:
    area = cv2.contourArea(c)
    if area > minimum_area:
        cv2.drawContours(original, [c], -1, (36, 255, 12), 2)
        if area > connected_cell_area:
            cells += math.ceil(area / average_cell_area)
        else:
            cells += 1

# Print the total number of detected cells
print('Cells: {}'.format(cells))

# Display the processed mask and the original image
cv2.imshow('close', close)
cv2.imshow('original', original)

# Wait for user input to exit
cv2.waitKey()

样本图像

  • NEC tissue
  • NET1 tissue

解决方案

1. 优化棕色细胞识别(HSV范围调整+预处理)

原HSV范围过于宽泛,会包含大量非目标区域。针对KI-67染色的棕色,调整HSV阈值,同时增加图像预处理步骤(去噪)提升识别精度。

2. 蓝色细胞计数(解决亮度不均问题)

蓝色细胞受亮度影响大,切换到LAB色彩空间分离蓝色相关通道,结合自适应直方图均衡化处理亮度不均,再通过阈值提取目标区域,最后用形态学操作修复掩码断裂。

修改后的完整代码

import cv2
import numpy as np
import math

def count_brown_cells(image_path):
    # 加载图像并高斯去噪
    image = cv2.imread(image_path)
    original = image.copy()
    blur = cv2.GaussianBlur(image, (5,5), 0)
    
    # 转换到HSV空间,优化棕色阈值
    hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
    # 适配KI-67染色的棕色HSV范围
    hsv_lower_brown = np.array([5, 30, 30])
    hsv_upper_brown = np.array([30, 200, 200])
    mask_brown = cv2.inRange(hsv, hsv_lower_brown, hsv_upper_brown)
    
    # 形态学操作优化掩码
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
    opening_brown = cv2.morphologyEx(mask_brown, cv2.MORPH_OPEN, kernel, iterations=2)
    close_brown = cv2.morphologyEx(opening_brown, cv2.MORPH_CLOSE, kernel, iterations=3)
    
    # 计数棕色细胞
    cnts_brown = cv2.findContours(close_brown, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
    min_area_brown = 15
    avg_area_brown = 120
    brown_cells = 0
    for c in cnts_brown:
        area = cv2.contourArea(c)
        if area > min_area_brown:
            cv2.drawContours(original, [c], -1, (0, 0, 255), 2)
            # 合并细胞按平均面积拆分计数
            brown_cells += math.ceil(area / avg_area_brown) if area > avg_area_brown * 1.5 else 1
    return original, brown_cells, close_brown

def count_blue_cells(image_path):
    image = cv2.imread(image_path)
    # 转换到LAB空间,处理亮度不均
    lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
    l, a, b = cv2.split(lab)
    
    # CLAHE自适应直方图均衡化,解决局部亮度差异
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    l_clahe = clahe.apply(l)
    lab_clahe = cv2.merge((l_clahe, a, b))
    
    # 提取蓝色细胞的LAB阈值
    lower_blue = np.array([0, 100, 0])
    upper_blue = np.array([255, 255, 120])
    mask_blue = cv2.inRange(lab_clahe, lower_blue, upper_blue)
    
    # 形态学操作修复掩码
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2,2))
    opening_blue = cv2.morphologyEx(mask_blue, cv2.MORPH_OPEN, kernel, iterations=1)
    close_blue = cv2.morphologyEx(opening_blue, cv2.MORPH_CLOSE, kernel, iterations=2)
    
    # 计数蓝色细胞
    cnts_blue = cv2.findContours(close_blue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
    min_area_blue = 10
    avg_area_blue = 100
    blue_cells = 0
    for c in cnts_blue:
        area = cv2.contourArea(c)
        if area > min_area_blue:
            blue_cells += math.ceil(area / avg_area_blue) if area > avg_area_blue*1.2 else 1
    return blue_cells, close_blue

# 示例调用
image_path = "images/NET1.jpg"
marked_image, brown_count, brown_mask = count_brown_cells(image_path)
blue_count, blue_mask = count_blue_cells(image_path)

print(f"棕色癌细胞数量: {brown_count}")
print(f"蓝色正常细胞数量: {blue_count}")

# 显示结果
cv2.imshow("标记后图像", marked_image)
cv2.imshow("棕色细胞掩码", brown_mask)
cv2.imshow("蓝色细胞掩码", blue_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键优化说明

  • 棕色细胞识别:
    • 增加高斯模糊去除背景噪点,减少误识别
    • 缩小HSV阈值范围,精准匹配KI-67染色的棕色区域
    • 调整形态学操作迭代次数,更好地修复细胞掩码的断裂与粘连
  • 蓝色细胞计数:
    • 使用LAB色彩空间+CLAHE自适应均衡,解决局部亮度不均问题
    • 针对蓝色通道设置专属阈值,有效提取正常细胞区域
    • 优化面积计数逻辑,降低合并细胞的计数误差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:26:02