Count the number of cells in an image using OpenCV

Image Analysis

In this post, I am going to show you how to count the number of cells (nuclei) in an image using OpenCV. I will use an image from Broad Bioimage Benchmark Collection (BBBC001) as an example. The image is of human HT29 colon cancer cells, which are stained with Hoechst 33342 for labelling the nuclei.

import cv2
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams["figure.figsize"] = (5.0, 5.0)
matplotlib.rcParams["image.cmap"] = 'gray'
%matplotlib inline

img = cv2.imread("./human_ht29_colon_cancer_1_images/AS_09125_050118150001_A03f05d0.tif", cv2.IMREAD_GRAYSCALE)
plt.imshow(img)

First, binarize the image by thresholding.

th, img_thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
plt.imshow(img_thresh)
kernel_size = 3
element = np.ones((kernel_size,kernel_size), np.uint8)
img_closed = cv2.morphologyEx(img_thresh, cv2.MORPH_CLOSE, element)
img_opened = cv2.morphologyEx(img_closed, cv2.MORPH_OPEN, element)

Assign a label (1, 2, 3, …) for each nuclei. Note that 0 is assigned to the background.

_, img_labels = cv2.connectedComponents(img_opened)
plt.imshow(img_labels)

Now you can get the number of nuclei by checking the maximum value of the label.

np.max(img_labels)

You can color-code the labels like this:

# Get the min and max pixel values and their locations on an image.
(min_val, max_val, min_loc, max_loc) = cv2.minMaxLoc(img_labels)

# Normalize the image so that the min value is 0 and max value is 255.
img_labels = 255 * (img_labels - min_val) / (max_val - min_val)

# Convert the image to 8-bits unsigned type
img_labels = np.uint8(img_labels)

# Apply a color map
img_color_map = cv2.applyColorMap(img_labels, cv2.COLORMAP_JET)
plt.imshow(img_color_map[:,:,::-1])

Comments

Copied title and URL