2016-07-27 98 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

非常感謝您的幫助。 –