I have an image of 30 cells. I would like to detect the 30 cells in this image by tracking specifically their nuclei (blue). I think the idea is to either group a certain number of blue pixels and consider it as one nucleus (30 total), or only count the bluest pixels (again, 30 total).
The following code gets the coordinates of all of the blue pixels.
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()
This code returns:
[ 0 0 0 ... 447 447 447] 19031
[112 113 114 ... 381 382 383] 19031
Clearly, 19031 is too big. I only want 30.
This is the image [1]: https://i.sstatic.net/VhX5o.jpg
What you're looking for are 30 blobs, rather than pixels. Using Hough Circles is nice and easy.
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)
You can use the circle positions as the centroids for each of the nuclei.
Hope that helps!
For future cases, I'd also recommend scipy.ndimage.measurements.label() for detecting blobs.
Blobs detected are overlayed onto original image If anyone could recommend me how to upload both images as part of this post that would be great!