Поскольку видимость ячеек отличается от ядра (темно-фиолетовый) и фона (светло-розовый), здесь должно работать определение цвета. Идея состоит в том, чтобы преобразовать изображение в формат HSV, а затем использовать нижний и верхний цветовой порог для изоляции ячеек. Это даст нам двоичную маску, которую мы можем использовать для подсчета количества ячеек.
Мы начинаем с преобразования изображения в формат HSV, затем используем нижний / верхний порог цвета для создания двоичной маски. Отсюда мы выполняем морфологические операции, чтобы сгладить изображение и удалить небольшие биты шума.
Теперь, когда у нас есть маска, мы находим контуры сcv2.RETR_EXTERNAL
параметр, чтобы гарантировать, что мы берем только внешние контуры. Мы определяем несколько пороговых значений площади для фильтрации ячеек
minimum_area = 200
average_cell_area = 650
connected_cell_area = 1000
Порог minimum_area
гарантирует, что мы не будем считать крошечные участки ячейки. Поскольку некоторые из ячеек связаны, некоторые контуры могут иметь несколько соединенных ячеек, представленных в виде одного контура, поэтому для лучшей оценки ячеек мы определяем параметр average_cell_area
, который оценивает площадь одной ячейки. Параметр connected_cell_area
определяет подключенные ячейки, для которых используется math.ceil()
в контуре соединенных ячеек для оценки количества ячеек в этом контуре. Чтобы подсчитать количество ячеек, мы перебираем контуры и суммируем контуры в зависимости от их площади. Вот обнаруженные ячейки, выделенные зеленым цветом
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()