如何计算图像中的错误?

时间:2013-01-25 22:05:11

标签: python image-processing computer-vision

我有一张如下图所示的图片,我想计算一下用Python显示的错误数量(连续的颜色/灰色斑点)。我怎么能做到最好?

Bugs on a noisy background

我到目前为止看过ImageChops,SciPy和PIL,但我不确定我能/应该使用什么......

我想我可以使用ndimage.gaussian_filter()然后scipy.ndimage.measurements.label()我还不确定如何使用后者来计算高斯化图像中的蓝点......它看起来像enter image description here


好,

上面的图片我现在得到了这段代码:

#! /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个数字,但这并不是很糟糕,但我需要更准确,我想看到两个。我怎样才能做到这一点?在应用高斯滤波器之前是否有助于模糊图像?

感谢您的帮助!

罗恩

2 个答案:

答案 0 :(得分:13)

你的高斯滤波已经很好了,但你正在考虑比任务所需的半径更大的半径。例如,让我们考虑半径为15的内核作为示例。以下是我们得到的内容:

enter image description here

有两个清晰的山谷(是的,显示为峰值),滤波图像的直方图显示大部分可用数据现在接近可能的最大值。

enter image description here

只考虑直方图的一部分,我们可以更好地看到我们感兴趣的数据部分:较暗的斑点。

enter image description here

所以,在0.5处有一个简单的阈值,这就是结果(匹配错误的位置):

enter image description here

根据您实现的方式(或您使用的库实现)相关功能,此阈值将有所不同。但通过查看直方图,您将能够发现一个良好的阈值。现在,如果您不想通过查看直方图来猜测此阈值,那么您需要预处理超出高斯滤波的图像。通过以良好的方式执行此步骤,您的图像变得足够简单,像Otsu给出的方法可以自动找到您所追求的阈值。执行形态学关闭,然后进行形态学开放,然后通过Otsu进行二值化,这是我们得到的结果:

enter image description here

形状更接近初始形状,因为我们不依赖线性低通滤波器,最多会模糊轮廓。

编辑:

由于问题现在包含一些代码,我觉得有必要解释为什么使用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)

这是计算机视觉的任务,您可以使用流行的OpenCV来解决这个问题。

您可能需要考虑使用某些形态操作(例如opening)处理图像以消除噪点。也许那时你可以计算出面积超过某个阈值的连续斑点的数量。


要研究的一些资源: