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()
样本图像
解决方案
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
相关产品推荐
相关产品推荐



