使用Python从图片中找到彩色形状的数量
我的问题是关于从图片中识别颜色的。在做微生物学的时候,我需要计算在显微镜拍摄的图片中有多少个细胞核。我用GIMP给细胞核标记了红色的点。现在我想写一个Python脚本,给定一张图片,能告诉我有多少个红点。图片中除了这些点没有其他红色。
我想到了一个比较复杂的解决方案,可能不是最好的:拍一张照片,然后开始逐个检查每个像素的颜色。如果是红色,就检查它周围8个最近的像素,再递归地检查每个红色像素的邻居,直到找不到更多的红色像素为止。然后细胞核的计数加一,并标记已经检查过的像素,以免再次检查。接着从停止的地方继续检查。这个方法感觉有点繁琐,所以我想问问,可能有人已经用更优雅的方法解决过类似的问题。
祝好,
Sander
3 个回答
2
一个简单的 Numpy / Scipy 解决方案可以是这样的:
import numpy, scipy
a = scipy.misc.imread("rgb.jpg") # Imports RGB to numpy array where a[0] is red, a[1] is blue, a[2] is green...
num_red = numpy.sum((a[:,:,0] == 255) * (a[:,:,1] == 0) * (a[:,:,2] == 0)) # Counts the number of pure red pixels
你也可以用 PIL 来读取图片。
补充说明:根据评论的内容,scipy.ndimage.measurements.label
会很有用,它还会返回一个值 num_features
,这个值可以告诉你有多少个特征:
import numpy, scipy
from scipy import ndimage
a = scipy.misc.imread("rgb.jpg")
b = ((a[:,:,0] == 255) * (a[:,:,1] == 0) * (a[:,:,2] == 0))*1
labeled_array, num_features = scipy.ndimage.measurements.label(b.astype('Int8'))
4
我会这样做:
评论:这方法可能不是最快的,也不一定总是准确。 但做这个会很有趣——因为计算机视觉总是很有趣——而且只需要10行代码。只是一个随意的想法。
至于更适合实际应用的建议:
- 其实我觉得你的想法很好,如果认真考虑的话,可以进行并行处理;
- 在OpenCV中使用斑点检测(cvBlobsLib)。
但最优雅的解决方案就是在GIMP中计算标记的细胞核,正如Ocaso Protal上面提到的那样。这样既准确又快。其他方法容易出错,而且慢得多,所以我说的只是一些随意的想法,更多的是为了好玩。
16
计算细胞核数量
这段代码是从Python图像教程中改编而来的。下面是教程中输入的带有细胞核的图像:
#!/usr/bin/env python
import scipy
from scipy import ndimage
# read image into numpy array
# $ wget http://pythonvision.org/media/files/images/dna.jpeg
dna = scipy.misc.imread('dna.jpeg') # gray-scale image
# smooth the image (to remove small objects); set the threshold
dnaf = ndimage.gaussian_filter(dna, 16)
T = 25 # set threshold by hand to avoid installing `mahotas` or
# `scipy.stsci.image` dependencies that have threshold() functions
# find connected components
labeled, nr_objects = ndimage.label(dnaf > T) # `dna[:,:,0]>T` for red-dot case
print "Number of objects is %d " % nr_objects
# show labeled image
####scipy.misc.imsave('labeled_dna.png', labeled)
####scipy.misc.imshow(labeled) # black&white image
import matplotlib.pyplot as plt
plt.imsave('labeled_dna.png', labeled)
plt.imshow(labeled)
plt.show()
输出结果
Number of objects is 17