我需要代码来计数图像中的细胞数量,并且只应计数粉红色的细胞。我使用了阈值和分水岭方法。
import cv2 from skimage.feature import peak_local_max from skimage.morphology import watershed from scipy import ndimage import numpy as np import imutils image = cv2.imread("cellorigin.jpg") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] cv2.imshow("Thresh", thresh) D = ndimage.distance_transform_edt(thresh) localMax = peak_local_max(D, indices=False, min_distance=20, labels=thresh) cv2.imshow("D image", D) markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0] labels = watershed(-D, markers, mask=thresh) print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1)) for label in np.unique(labels): # if the label is zero, we are examining the 'background' # so simply ignore it if label == 0: continue # otherwise, allocate memory for the label region and draw # it on the mask mask = np.zeros(gray.shape, dtype="uint8") mask[labels == label] = 255 # detect contours in the mask and grab the largest one cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) c = max(cnts, key=cv2.contourArea) # draw a circle enclosing the object ((x, y), r) = cv2.minEnclosingCircle(c) cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2) cv2.putText(image, "#{}".format(label), (int(x) - 10, int(y)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imshow("input",image cv2.waitKey(0)
我无法正确分割粉红色单元格。在某些地方,两个粉红色单元格连接在一起,也应分开。
由于细胞的可见性似乎不同于细胞核(深紫色)和背景(浅粉红色),因此此处应使用颜色阈值。想法是将图像转换为HSV格式,然后使用上下颜色阈值隔离细胞。这将为我们提供一个二进制掩码,我们可以使用它来计数单元格的数量。
我们首先将图像转换为HSV格式,然后使用较低/较高的颜色阈值创建二进制掩码。从这里开始,我们执行形态学操作以平滑图像并去除少量噪声。
现在我们有了遮罩,我们找到了带有cv2.RETR_EXTERNAL参数的轮廓,以确保仅采用外部轮廓。我们定义了几个面积阈值以滤除单元格
cv2.RETR_EXTERNAL
minimum_area = 200 average_cell_area = 650 connected_cell_area = 1000
该minimum_area阈值确保我们不计算单元格的微小部分。由于某些单元是连接的,因此某些轮廓可能会将多个连接的单元表示为单个轮廓,因此为了更好地估计单元,我们定义了一个average_cell_area参数来估计单个单元的面积。该connected_cell_area参数检测连接的单元格,math.ceil()并在连接的单元格轮廓上使用估计该轮廓中的单元格数量。要计算单元格的数量,我们遍历轮廓并根据其面积对轮廓进行汇总。这是检测到的单元格以绿色突出显示
minimum_area
average_cell_area
connected_cell_area
math.ceil()
Cells: 75
码
import cv2 import numpy as np import math image = cv2.imread("1.jpg") original = image.copy() hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) hsv_lower = np.array([156,60,0]) hsv_upper = np.array([179,115,255]) mask = cv2.inRange(hsv, hsv_lower, hsv_upper) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)) opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1) close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=2) cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] minimum_area = 200 average_cell_area = 650 connected_cell_area = 1000 cells = 0 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('Cells: {}'.format(cells)) cv2.imshow('close', close) cv2.imshow('original', original) cv2.waitKey()