2016-07-27 52 views
-3

我正在尝试计算此图像中的滴数以及这些滴图所覆盖区域的覆盖百分比。 我试图将这个图像转换成黑色和白色,但这些滴的中心颜色似乎与背景太相似。所以我只有第二张照片。 有什么办法来解决这个问题或任何更好的想法? 非常感谢。如何使用python来计算图像中的对象?

source image

converted image

+1

您可以使用[霍夫圈(HTTP://文档.opencv.org/2.4/modules/imgproc/doc/feature_detection.html?highlight = houghcircles#houghcircles)对于其中大多数 – Pedro

回答

3

我用下面的代码来检测使用opencv和python图像中轮廓的数量。

img = cv2.imread('ba3g0.jpg') 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
ret,thresh = cv2.threshold(gray,127,255,1) 
contours,h = cv2.findContours(thresh,1,2) 
for cnt in contours: 
    cv2.drawContours(img,[cnt],0,(0,0,255),1) 

Result 对于furthur删除另一个轮廓内的轮廓,你需要遍历整个列表比较,并删除内部轮廓。之后,“轮廓”的大小会给你计数

+0

嗨我得到错误的行: 轮廓s,h = cv2.findContours(thresh,1,2) ValueError:太多的值解压缩(预期2)“ – Ajay

+0

我想我得到了由于Opencv版本差异的过高错误。 这是新版本: im2,轮廓,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) – Ajay

+0

您可能正在使用Python 3.x与opencv 3.正确吗? – Saurav

1

这个想法是隔离背景形式的内部看起来像背景的滴。 因此,我发现连接组件的背景和内部下降采取了最大的连接组件,并将其值改变为像前景值,这留给我一个图像,他内部下降作为一个不同的背景值。 比我用这张图片来填写原始的门槛图像。 最终使用填充图像我计算了相关的值

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 

# Read image 
I = cv2.imread('drops.jpg',0); 

# Threshold 
IThresh = (I>=118).astype(np.uint8)*255 

# Remove from the image the biggest conneced componnet 

# Find the area of each connected component 
connectedComponentProps = cv2.connectedComponentsWithStats(IThresh, 8, cv2.CV_32S) 

IThreshOnlyInsideDrops = np.zeros_like(connectedComponentProps[1]) 
IThreshOnlyInsideDrops = connectedComponentProps[1] 
stat = connectedComponentProps[2] 
maxArea = 0 
for label in range(connectedComponentProps[0]): 
    cc = stat[label,:] 
    if cc[cv2.CC_STAT_AREA] > maxArea: 
     maxArea = cc[cv2.CC_STAT_AREA] 
     maxIndex = label 


# Convert the background value to the foreground value 
for label in range(connectedComponentProps[0]): 
    cc = stat[label,:] 
    if cc[cv2.CC_STAT_AREA] == maxArea: 
     IThreshOnlyInsideDrops[IThreshOnlyInsideDrops==label] = 0 
    else: 
     IThreshOnlyInsideDrops[IThreshOnlyInsideDrops == label] = 255 

# Fill in all the IThreshOnlyInsideDrops as 0 in original IThresh 
IThreshFill = IThresh 
IThreshFill[IThreshOnlyInsideDrops==255] = 0 
IThreshFill = np.logical_not(IThreshFill/255).astype(np.uint8)*255 
plt.imshow(IThreshFill) 

# Get numberof drops and cover precntage 
connectedComponentPropsFinal = cv2.connectedComponentsWithStats(IThreshFill, 8, cv2.CV_32S) 
NumberOfDrops = connectedComponentPropsFinal[0] 
CoverPresntage = float(np.count_nonzero(IThreshFill==0)/float(IThreshFill.size)) 

# Print 
print "Number of drops = " + str(NumberOfDrops) 
print "Cover precntage = " + str(CoverPresntage) 
+0

这是什么语言? MATLAB?围绕你的答案的一些背景将会有所帮助。还要记住这个问题是用Python标记的。提出问题的人可能无法使用其他语言的解决方案。 –

+0

我修复它。谢谢你的评论。 –

+0

非常清晰,大大改善。谢谢。 –

1

您可以填写你的二值图像的使用scipy.ndimage.binary_fill_holes孔。我还推荐使用自动阈值方法,如Otsu's(可在scikit-image中找到)。 enter image description here

from skimage import io, filters 
from scipy import ndimage 
import matplotlib.pyplot as plt 

im = io.imread('ba3g0.jpg', as_grey=True) 
val = filters.threshold_otsu(im) 
drops = ndimage.binary_fill_holes(im < val) 
plt.imshow(drops, cmap='gray') 
plt.show() 

对于您可以使用scikit-image

from skimage import measure 
labels = measure.label(drops) 
print(labels.max()) 

另一个功能下降的数量和覆盖面

print('coverage is %f' %(drops.mean())) 
+0

非常感谢您的帮助。 –

相关问题