python - 计算图像中的单元格数
问题描述
我需要计算图像中单元格数量的代码,并且只计算粉红色的单元格。我使用了阈值法和分水岭法。
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
参数的轮廓,以确保我们只取外轮廓。我们定义了几个区域阈值来过滤掉单元格
minimum_area = 200
average_cell_area = 650
connected_cell_area = 1000
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()
推荐阅读
- java - Java AES 加密错误
- .net - .NET RSA 加密不适用于 OpenSSL
- android - android中的Firebase子事件监听器
- python-3.x - PyQT5 如何在 QScrollArea 中处理许多(数千个)自定义样式的小部件
- video-streaming - 如何从 m3u8 文件中提取 mp4 视频
- c# - 如果其中一列为空,则加入返回空
- python-3.x - 升级 tensorflow 后没有任何效果
- javascript - 原型方法和变量之间的区别,变量是javascript中的一种方法
- fonts - 如何正确缩放字体字形轮廓?
- django - 由于 http://testserver 前缀,Django assertRedirects 测试失败