计算图像中的单元格数
问题描述
我需要计算图像中细胞数量的代码,并且只计算粉红色的细胞.我使用了阈值法和分水岭法.
I need code for counting the number of cells in the image and only the cells that are in pink color should be counted .I have used thresholding and watershed method.
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)
我无法正确分割粉色单元格.在某些地方,两个粉色单元格连接在一起,它们也应该分开.
I am not able to segment the pink cells properly.At some places two pink cells are attached together those also should be separated.
输出:
解决方案
由于细胞的可见性似乎与细胞核(深紫色)和背景(浅粉色)不同,因此颜色阈值应该在这里起作用.想法是将图像转换为 HSV 格式,然后使用上下颜色阈值来隔离细胞.这将为我们提供一个二进制掩码,我们可以使用它来计算单元格的数量.
Since the cells seem to be visibility different from the nucleus (dark purple) and the background (light pink), color thresholding should work here. The idea is to convert the image to HSV format then use a lower and upper color threshold to isolate the cells. This will give us a binary mask which we can use to count the number of cells.
我们首先将图像转换为 HSV 格式,然后使用较低/较高的颜色阈值来创建二进制蒙版.从这里我们执行形态学操作来平滑图像并去除少量噪声.
We begin by converting the image to HSV format then use a lower/upper color threshold to create a binary mask. From here we perform morphological operations to smooth the image and remove small bits of noise.
现在我们有了掩码,我们使用 cv2.RETR_EXTERNAL
参数查找轮廓,以确保我们只获取外部轮廓.我们定义了几个区域阈值来过滤掉细胞
Now that we have the mask, we find contours with the cv2.RETR_EXTERNAL
parameter to ensure that we only take the outer contours. We define several area thresholds to filter out the cells
minimum_area = 200
average_cell_area = 650
connected_cell_area = 1000
minimum_area
阈值确保我们不计算单元格的微小部分.由于一些单元格是连接的,一些轮廓可能有多个连接的单元格表示为单个轮廓,因此为了更好地估计单元格,我们定义了一个 average_cell_area
参数来估计单个单元格的面积.connected_cell_area
参数检测连接的单元格,其中在连接的单元格轮廓上使用 math.ceil()
来估计该轮廓中的单元格数量.为了计算单元格的数量,我们遍历轮廓并根据它们的面积对轮廓求和.这是检测到的以绿色突出显示的单元格
The minimum_area
threshold ensures that we do not count tiny sections of a cell. Since some of the cells are connected, some contours may have multiple connected cells represented as a single contour so to estimate the cells better, we define an average_cell_area
parameter which estimates the area of a single cell. The connected_cell_area
parameter detects connected cells where use math.ceil()
on a connected cell contour to estimate the number of cells in that contour. To count the number of cells, we iterate through the contours and sum up the contours based on their area. Here's the detected cells highlighted in green
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()
相关文章