Поиск количества цветных фигур с помощью Python

Моя проблема связана с распознаванием цветов из изображений. Выполняя микробиологию, мне нужно подсчитать количество ячеек клеток, присутствующих на снимке, сделанном с помощью камеры микроскопа. Я использовал GIMP для маркировки ядер красными точками. Теперь мне нужно сделать script в python, который, учитывая изображение, скажет мне, сколько красных точек присутствует. На картинке нет красных изображений, кроме точек.

Я подумал о довольно сложном решении, которое, вероятно, не самое лучшее: сделайте снимок и начните повторять через пиксели, проверяя каждый цвет. Если это красный цвет, проверьте все 8 ближайших пикселей, рекурсивно проверьте каждый красный сосед, пока не будут найдены более соседние красные пиксели. Затем увеличивайте количество ядер на единицу и отметьте пройденные пиксели, чтобы они не повторялись снова. Затем продолжите итерацию с того места, где она остановилась. Кажется, это тяжело, поэтому я подумал, что спрошу, может, кто-то уже более разбирался в подобной проблеме.

С уважением, Sander

Ответы

Ответ 1

Число ядер

Код, адаптированный из Python Image Tutorial. Входное изображение с ядрами из учебника:

nuclei

#!/usr/bin/env python
import scipy
from scipy import ndimage

# read image into numpy array
# $ wget http://pythonvision.org/media/files/images/dna.jpeg
dna = scipy.misc.imread('dna.jpeg') # gray-scale image


# smooth the image (to remove small objects); set the threshold
dnaf = ndimage.gaussian_filter(dna, 16)
T = 25 # set threshold by hand to avoid installing `mahotas` or
       # `scipy.stsci.image` dependencies that have threshold() functions

# find connected components
labeled, nr_objects = ndimage.label(dnaf > T) # `dna[:,:,0]>T` for red-dot case
print "Number of objects is %d " % nr_objects

# show labeled image
####scipy.misc.imsave('labeled_dna.png', labeled)
####scipy.misc.imshow(labeled) # black&white image
import matplotlib.pyplot as plt
plt.imsave('labeled_dna.png', labeled)
plt.imshow(labeled)

plt.show()

Выход

Number of objects is 17 

labeled nuclei

Ответ 2

Я бы сделал это следующим образом:

  • используйте OpenCV (python привязок),
  • возьмите только R-компонент изображения RGB,
  • бинарный порог компонента R, так что он оставляет только красные пиксели,
  • использовать обнаружение объектов/признаков для обнаружения точек, fe. ExtractSURF

Комментарии: он будет не самым быстрым, он не всегда будет точным. Но это будет весело, так как CV всегда весело - и готово в 10 строках кода. Просто сообразительная мысль.

Что касается более готовых к выпуску предложений:

  • На самом деле, я думаю, что ваша идея очень хорошая, и она может быть распараллелирована, если дать какую-то мысль;
  • используйте обнаружение blob в OpenCV (cvBlobsLib).

Но самым изящным решением было бы просто подсчитать помеченные ядра в GIMP, как предложил Ocaso Protal выше. Точный и быстрый. Все остальное будет подвержено ошибкам и намного медленнее, поэтому мои просто свободные идеи, больше удовольствия, чем что-либо.

Ответ 3

Простое решение Numpy/Scipy будет выглядеть примерно так:

import numpy, scipy
a = scipy.misc.imread("rgb.jpg") # Imports RGB to numpy array where a[0] is red, a[1] is blue, a[2] is green...
num_red = numpy.sum((a[:,:,0] == 255) * (a[:,:,1] == 0) * (a[:,:,2] == 0)) # Counts the number of pure red pixels

Вы также можете использовать PIL для чтения изображения.

EDIT: В свете комментариев scipy.ndimage.measurements.label будет полезно, а также вернет значение num_features, которое даст вам счет:

import numpy, scipy
from scipy import ndimage
a = scipy.misc.imread("rgb.jpg")
b = ((a[:,:,0] == 255) * (a[:,:,1] == 0) * (a[:,:,2] == 0))*1
labeled_array, num_features = scipy.ndimage.measurements.label(b.astype('Int8'))