我有一张如下图所示的图片,我想计算一下用Python显示的错误数量(连续的颜色/灰色斑点)。我怎么能做到最好?
我到目前为止看过ImageChops,SciPy和PIL,但我不确定我能/应该使用什么......
我想我可以使用ndimage.gaussian_filter()
然后scipy.ndimage.measurements.label()
我还不确定如何使用后者来计算高斯化图像中的蓝点......它看起来像
好,
上面的图片我现在得到了这段代码:
#! /usr/bin/python
import numpy as np
import scipy
import pylab
import pymorph
import mahotas
from PIL import Image
import PIL.ImageOps
from scipy import ndimage
image = Image.open('bugs.jpg')
inverted_image = PIL.ImageOps.invert(image)
inverted_image.save('in_bugs.jpg')
dna = mahotas.imread('in_bugs.jpg')
#pylab.imshow(dna)
pylab.gray()
#pylab.show()
T = mahotas.thresholding.otsu(dna)
pylab.imshow(dna > T)
#pylab.show()
dnaf = ndimage.gaussian_filter(dna, 8)
T = mahotas.thresholding.otsu(dnaf)
pylab.imshow(dnaf > T)
#pylab.show()
labeled,nr_objects = ndimage.label(dnaf > T)
print nr_objects
pylab.imshow(labeled)
pylab.jet()
pylab.show()
问题是,这给了我5个数字,但这并不是很糟糕,但我需要更准确,我想看到两个。我怎样才能做到这一点?在应用高斯滤波器之前是否有助于模糊图像?
感谢您的帮助!
罗恩
答案 0 :(得分:13)
你的高斯滤波已经很好了,但你正在考虑比任务所需的半径更大的半径。例如,让我们考虑半径为15的内核作为示例。以下是我们得到的内容:
有两个清晰的山谷(是的,显示为峰值),滤波图像的直方图显示大部分可用数据现在接近可能的最大值。
只考虑直方图的一部分,我们可以更好地看到我们感兴趣的数据部分:较暗的斑点。
所以,在0.5
处有一个简单的阈值,这就是结果(匹配错误的位置):
根据您实现的方式(或您使用的库实现)相关功能,此阈值将有所不同。但通过查看直方图,您将能够发现一个良好的阈值。现在,如果您不想通过查看直方图来猜测此阈值,那么您需要预处理超出高斯滤波的图像。通过以良好的方式执行此步骤,您的图像变得足够简单,像Otsu给出的方法可以自动找到您所追求的阈值。执行形态学关闭,然后进行形态学开放,然后通过Otsu进行二值化,这是我们得到的结果:
形状更接近初始形状,因为我们不依赖线性低通滤波器,最多会模糊轮廓。
编辑:
由于问题现在包含一些代码,我觉得有必要解释为什么使用Otsu作为代码所做的错误。 Otsu给出的用于阈值处理的方法实际上期望数据是双峰的,但是如上面的直方图所示,这不是这里的情况。大津将提供一个太接近右边巨大峰值的门槛,而0.5的好点距离那里很远。要复制本答案中显示的第一个结果,这里有一些基本代码:
import sys
import numpy
from PIL import Image
from scipy.ndimage import gaussian_filter, label
img = Image.open(sys.argv[1]).convert('L')
im = numpy.array(img)
im_g = gaussian_filter(im, 3)
im_norm = (im_g - im_g.min()) / (float(im_g.max()) - im_g.min())
im_norm[im_norm < 0.5] = 0
im_norm[im_norm >= 0.5] = 1
result = 255 - (im_norm * 255).astype(numpy.uint8)
print u"Objects: %d" % label(result)[1]
Image.fromarray(result).save(sys.argv[2])
请注意,此代码使用sigma = 3
(虽然最初使用7.5)用于高斯内核,scipy
内部构建一个半径比其大4倍的窗口。对于这个特定的图像,大范围的sigma
同样适用,从2到10开始应该给出相同的结果 - 检测到2个对象。
答案 1 :(得分:3)