如何使用python计算图像中的对象?

时间:2016-07-27 17:15:38

标签: python image-processing

我正在尝试计算此图像中的丢弃数量以及这些丢弃所覆盖区域的覆盖率。 我试图将这个图像转换为黑白图像,但这些图像的中心颜色看起来与背景太相似了。所以我只得到第二张图片。 有没有办法解决这个问题或任何更好的想法? 非常感谢。

source image

converted image

3 个答案:

答案 0 :(得分:7)

您可以使用scipy.ndimage.binary_fill_holes填充二进制图像的孔。我还建议使用自动阈值处理方法,例如Otsu(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()))

答案 1 :(得分:6)

我使用以下代码使用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 为了更好地去除另一个轮廓内的轮廓,您需要遍历整个列表并比较和删除内部轮廓。之后,“轮廓”的大小将给你计数

答案 2 :(得分:2)

这个想法是将背景分离成看起来像背景的水滴内部。 因此,我发现背景的连通分量和内部的水滴采用了最大的连通分量,并将其值更改为前景值,这使得我在内部的图像下降为与背景不同的值。 比我使用此图像填写原始阈值图像。 最后使用填充图像我计算了相关值

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)