У меня есть изображение из 30 ячеек. Я хотел бы обнаружить 30 клеток на этом изображении, отслеживая конкретно их ядра (синие). Я думаю, что идея состоит в том, чтобы либо сгруппировать определенное количество синих пикселей и считать их одним ядром (всего 30), либо подсчитать только самые синие пиксели (опять же, всего 30).
Следующий код получает координаты всех синих пикселей.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
control = mpimg.imread('jpeg.jpg')
ys = control.shape[0]
xs = control.shape[1]
blue = np.nonzero(control[:,:,2])
print(blue[0], len(blue[0]))
print(blue[1], len(blue[1]))
plt.imshow(control,cmap = plt.get_cmap('gray'),interpolation='none')
plt.show()
Этот код возвращает:
[ 0 0 0 ... 447 447 447] 19031
[112 113 114 ... 381 382 383] 19031
Ясно, что 19031 слишком велико. Я хочу только 30.
Это изображение [1]: https://i.stack.imgur.com/VhX5o.jpg
На вашем изображении 200 000 пикселей, и ваш алгоритм поиска синих пикселей считает, что 10% из них синие, так что это то, что нужно решить в первую очередь. Если вы знаете максимальный размер ядра, вы можете взять первую пару координат и добавить их в список ядер, а затем обнулить все оставшиеся координаты, находящиеся на расстоянии меньше этого расстояния. Затем перейдите к следующей ненулевой координате и повторите.
То, что вы ищете, это 30 капель, а не пикселей. Использовать Hough Circles приятно и легко.
import cv2
import numpy as np
import matplotlib.pyplot as plt
# load image
img = plt.imread('VhX5o.jpg')
# convert image to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# median blur
gray = cv2.medianBlur(gray, 5)
# Detect circles
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 10,
param1=200,
param2=30,
minRadius=0,
maxRadius=0)
print(len(circles)) # 30
circles = np.uint16(np.around(circles))
# filtered image returns just the (blue) nucleus blobs
filt_img = np.zeros(img.shape)
for i in circles[0,:]:
cv2.circle(filt_img,(i[0],i[1]),2,(0,0,255), 3)
cv2.circle(img,(i[0],i[1]),2,(0,0,255), 3)
# plot filt_img
plt.figure()
plt.imshow(filt_img)
# plot with circles drawn over original image
plt.imshow(img)
Вы можете использовать положения круга в качестве центроидов для каждого из ядер.
Надеюсь, это поможет!
Для будущих случаев я бы также рекомендовал scipy.ndimage.measurements.label() для обнаружения больших двоичных объектов.
Обнаруженные капли накладываются на исходное изображение Если бы кто-нибудь мог порекомендовать мне, как загрузить оба изображения в рамках этого поста, это было бы здорово!
Ах. В этом случае ОП может просто использовать ndi.measurements.label(img[:, :, 1]) и быстро написать что-нибудь, чтобы получить круги посередине. Или просто перепишите код OpenCV с нуля, проверив их исходный код, если это для школьной работы или что-то в этом роде.
Спасибо. На самом деле у меня есть 60 таких изображений, показывающих движущиеся клетки. С помощью opencv могу ли я хранить координаты каждой конкретной ячейки в списке?
Не беспокойтесь вообще! Да, ты можешь. С приведенным выше кодом круги уже это; список центроидов для каждой ячейки. Если вы довольны моим ответом, я был бы очень признателен, если бы вы его приняли :)
Не уверен, что возражает против OpenCV, но, возможно, попробуйте
scikit-image
scikit-image.org/docs/dev/auto_examples/segmentation/…