Подсчитать количество клеток в изображении - PullRequest
5 голосов
/ 07 ноября 2019

Мне нужен код для подсчета количества ячеек на изображении, и должны учитываться только ячейки розового цвета. Я использовал метод определения порогов и водораздела.

enter image description here

import cv2
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
import numpy as np
import imutils

image = cv2.imread("cellorigin.jpg")

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
    cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cv2.imshow("Thresh", thresh)


D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=20,
    labels=thresh)
cv2.imshow("D image", D)

markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) -     1))

for label in np.unique(labels):
    # if the label is zero, we are examining the 'background'
    # so simply ignore it
    if label == 0:
        continue

    # otherwise, allocate memory for the label region and draw
    # it on the mask
    mask = np.zeros(gray.shape, dtype="uint8")
    mask[labels == label] = 255

    # detect contours in the mask and grab the largest one
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    c = max(cnts, key=cv2.contourArea)

    # draw a circle enclosing the object
    ((x, y), r) = cv2.minEnclosingCircle(c)
    cv2.circle(image, (int(x), int(y)), int(r), (0, 255, 0), 2)
    cv2.putText(image, "#{}".format(label), (int(x) - 10, int(y)),
        cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)



cv2.imshow("input",image

cv2.waitKey(0)

Я не могу правильно разделить розовые ячейки. В некоторых местах две розовые ячейки соединены вместе, и их тоже следует разделить.

вывод:

enter image description here

1 Ответ

4 голосов
/ 08 ноября 2019

Поскольку видимость ячеек отличается от ядра (темно-фиолетовый) и фона (светло-розовый), здесь должно работать определение цвета. Идея состоит в том, чтобы преобразовать изображение в формат HSV, а затем использовать нижний и верхний цветовой порог для изоляции ячеек. Это даст нам двоичную маску, которую мы можем использовать для подсчета количества ячеек.


Мы начинаем с преобразования изображения в формат HSV, затем используем нижний / верхний порог цвета для создания двоичной маски. Отсюда мы выполняем морфологические операции, чтобы сгладить изображение и удалить небольшие биты шума.

enter image description here

Теперь, когда у нас есть маска, мы находим контуры сcv2.RETR_EXTERNAL параметр, чтобы гарантировать, что мы берем только внешние контуры. Мы определяем несколько пороговых значений площади для фильтрации ячеек

minimum_area = 200
average_cell_area = 650
connected_cell_area = 1000

Порог minimum_area гарантирует, что мы не будем считать крошечные участки ячейки. Поскольку некоторые из ячеек связаны, некоторые контуры могут иметь несколько соединенных ячеек, представленных в виде одного контура, поэтому для лучшей оценки ячеек мы определяем параметр average_cell_area, который оценивает площадь одной ячейки. Параметр connected_cell_area определяет подключенные ячейки, для которых используется math.ceil() в контуре соединенных ячеек для оценки количества ячеек в этом контуре. Чтобы подсчитать количество ячеек, мы перебираем контуры и суммируем контуры в зависимости от их площади. Вот обнаруженные ячейки, выделенные зеленым цветом

enter image description here

Cells: 75

Код

import cv2
import numpy as np
import math

image = cv2.imread("1.jpg")
original = image.copy()
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

hsv_lower = np.array([156,60,0])
hsv_upper = np.array([179,115,255])
mask = cv2.inRange(hsv, hsv_lower, hsv_upper)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=2)

cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

minimum_area = 200
average_cell_area = 650
connected_cell_area = 1000
cells = 0
for c in cnts:
    area = cv2.contourArea(c)
    if area > minimum_area:
        cv2.drawContours(original, [c], -1, (36,255,12), 2)
        if area > connected_cell_area:
            cells += math.ceil(area / average_cell_area)
        else:
            cells += 1
print('Cells: {}'.format(cells))
cv2.imshow('close', close)
cv2.imshow('original', original)
cv2.waitKey()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...