Reputation: 1
I would like to count cells and cell collonies in an image (shown in link). It has a single cell at about 3 o'clock and a cell collony/blob at about 8 o'clock.
I tried to work with cv2 package:
import cv2
import numpy as np
import math
image = cv2.imread("C:\\Users\\Tadas\\Desktop\\img-r.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret,th = cv2.threshold(image,155,255,cv2.THRESH_BINARY)
cnts,_ = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
minimum_area = 10
average_cell_area = 14
connected_cell_area = 30
large_collony = 100
cells = 0
cells_individual=0
collonies=0
for c in cnts:
area = cv2.contourArea(c)
if area > minimum_area:
cv2.drawContours(th, [c], -1, (255,2,1), 1)
if area > connected_cell_area:
cells += math.ceil(area / average_cell_area)
if area > large_collony:
collonies += 1
else:
cells += 1
cells_individual +=1
print('Cells: {}'.format(cells))
print('Individual cells: {}'.format(cells_individual))
print('Collonies: {}'.format(collonies))
th=cv2.resize(th,(819,819))
cv2.imshow('image', th)
cv2.waitKey()
And it somewhat works if i crop the cells out of this picture. How could i ignore it? And maybe there is a better way to filter the image than the thresholding? Thanks for help!
A single cell at about 3 o'clock and a cell collony/blob at about 8 o'clock.
Upvotes: 0
Views: 110
Reputation: 53164
I would suggest using adaptive thresholding in Python/OpenCV as follows:
import cv2
import numpy as np
import math
# read image
image = cv2.imread("C:\\Users\\Tadas\\Desktop\\img-r.jpg")
# convert to grayscale
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# apply adaptive thresholding and invert
th = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 55, 30)
th = 255 - th
# remove everything outside radius from center using a circle mask
radius = 1900
hh, ww = image.shape[:2]
cx = ww // 2
cy = hh // 2
mask = np.zeros_like(th)
cv2.circle(mask, (cx,cy), radius, 255, -1)
th[mask==0] = 0
# get contours
cnts = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
minimum_area = 10
average_cell_area = 14
connected_cell_area = 30
large_collony = 100
cells = 0
cells_individual=0
collonies=0
# filter contours
for c in cnts:
area = cv2.contourArea(c)
if area > minimum_area:
cv2.drawContours(th, [c], -1, (255,2,1), 1)
if area > connected_cell_area:
cells += math.ceil(area / average_cell_area)
if area > large_collony:
collonies += 1
else:
cells += 1
cells_individual +=1
# report cells
print('Cells: {}'.format(cells))
print('Individual cells: {}'.format(cells_individual))
print('Collonies: {}'.format(collonies))
th=cv2.resize(th,(819,819))
cv2.imshow('image', th)
cv2.waitKey()
Results Reported:
Cells: 25
Individual cells: 1
Collonies: 1
Upvotes: 2