Как посчитать объекты на изображении с помощью Python?

Я пытаюсь подсчитать количество капель на этом изображении и процент покрытия области, покрытой этими каплями. Я пытался преобразовать это изображение в черно-белое, но центральный цвет этих капель кажется слишком похожим на фон. Так что я получил только что-то вроде второй картинки. Есть ли способ решить эту проблему или есть идеи получше? Большое спасибо.

 Pedro27 июл. 2016 г., 19:21
Ты можешь использоватьHough Circles для большинства из них

Ответы на вопрос(3)

Идея состоит в том, чтобы изолировать фон внутри капель, которые выглядят как фон. Поэтому я обнаружил, что подключенные компоненты для фона и внутренние капли взяли самый большой связанный компонент и изменили его значение так, чтобы оно соответствовало значению переднего плана, которое оставило мне изображение, которое он внутри перетаскивает, как значение, отличное от фона. Затем я использовал это изображение, чтобы заполнить исходное пороговое изображение. В конце, используя заполненное изображение, я рассчитал соответствующие значения

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)
 Rocketq26 апр. 2019 г., 19:53
всегда возвращает 2, даже если объекта намного больше, чем 2
 Lex Scarisbrick29 июл. 2016 г., 17:36
Очень ясно и значительно улучшено. Спасибо.
 Lex Scarisbrick29 июл. 2016 г., 00:01
Какой это язык? MATLAB? Некоторый контекст вокруг вашего ответа будет полезен. Также имейте в виду, что вопрос был помечен с помощью Python. Решение на другом языке не может быть использовано человеком, который задал вопрос.
 Amitay Nachmani29 июл. 2016 г., 07:23
Я чиню это. Спасибо за замечание.

Я использовал следующий код для определения количества контуров в изображении, используя 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)

Для дальнейшего удаления контуров внутри другого контура необходимо выполнить итерацию по всему списку, сравнить и удалить внутренние контуры. После этого размер «контуров» даст вам счет

 Ajay Sant11 сент. 2017 г., 16:52
Привет я получаю сообщение об ошибке для строки: contours, h = cv2.findContours (thresh, 1,2) ValueError: слишком много значений для распаковки (ожидается 2) "
 Ajay Sant11 сент. 2017 г., 17:26
Я думаю, что получаю ошибку выше из-за различий в Opencv версии. Вот новая версия: im2, контур, иерархия = cv2.findContours (thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
 Saurav12 сент. 2017 г., 07:18
Возможно, вы используете Python 3.x с OpenCV 3. правильно?

Вы можете заполнить отверстия вашего двоичного изображения, используяscipy.ndimage.binary_fill_holes, Я также рекомендую использовать метод автоматического определения порога, такой как Otsu's (доступно вscikit-image).

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()))
 JIAHAO HUANG02 авг. 2016 г., 21:41
Большое вам спасибо, это очень полезно.

Ваш ответ на вопрос