使用Python从图片中找出彩色形状的数量

15
我的问题与从图片中识别颜色有关。在进行微生物学研究时,我需要计算显微镜相机拍摄的图片上存在的细胞核数量。我使用了GIMP标记红色的点来标记细胞核。现在我需要用Python编写一个脚本,它可以在给定一张图片的情况下告诉我有多少个红色的点存在。除了这些点外,图片中没有其他的红色。
我想到了一个比较复杂的解决方案,可能不是最好的: 拍照后开始迭代每个像素,检查每个像素的颜色。如果是红色的,则检查周围8个最近的像素,递归地检查每个红色像素的邻居,直到找不到更多相邻的红色像素为止。然后将细胞核计数增加1,并标记遍历过的像素,以便不要再次迭代。然后从停止的位置继续迭代。看起来很重,所以我想问问,也许有人已经更优雅地处理了类似的问题。
问候, 桑德尔

1
你在GIMP中标记点吗?为什么不编写一个Python插件来计算你所做的点数呢? - Ocaso Protal
因为我已经有很多已经打好标签的图片了,不想再重新打标签 :)。 - Sander
3
第一项任务:核计数 http://pythonvision.org/basic-tutorial - jfs
相关:https://dev59.com/xHNA5IYBdhLWcg3wn_bD中的机器视觉 - jfs
3个回答

16

核子计数

这段代码是从Python图像教程中改编而来的。下面是该教程中使用的含有核子的输入图像:

nuclei

#!/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 

labeled nuclei


3
翻译:照片上有19个原子核。仍然相当好。 - Tomek Kopczuk
一项分水岭的步骤可以帮助区分错误连接的元素。 - Dschoni

4
我会这样做:
  • 使用 OpenCV Python绑定),
  • 仅取RGB图像的R分量,
  • 对R分量进行二值阈值处理,使其只留下最红的像素,
  • 使用一些物体/特征检测来检测圆点,例如ExtractSURF
注释: 它不会是最快的,它也不会总是准确的。 但做起来很有趣 - 因为CV总是很有趣 - 并且只需10行代码即可完成。只是一个宽松的想法。
至于更适合生产的建议: 实际上我认为你的想法非常好,如果经过一些思考,它可以并行化; 在OpenCV中使用blob检测(cvBlobsLib)。
但最优雅的解决方案就是数GIMP中标记过的细胞核,正如Ocaso Protal上面所建议的那样。准确而快速。其他所有方法都容易出错且慢得多,因此我的想法只是宽松的想法,更多的是为了好玩。

好主意。我会研究一下cvBlobsLib,如果对我不起作用,我会尝试我的每像素想法。 - Sander

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'))

这个程序计算像素的数量,但我的点比一个像素大,所以我需要识别区域/形状。 - Sander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接