Ask Your Question

Revision history [back]

Count cells on image using python and OpenCV

Hello the OpenCV community :)

I trying to write an algorithm to count dots (cells) on an image.

Here is the script I've made so far :

import numpy as np
import cv2
import os

for dirname in os.listdir("images/"):

    for filename in os.listdir("images/" + dirname + "/"):

        # Image read
        img = cv2.imread("images/" + dirname + "/" + filename, 0)

        # Denoising
        denoisedImg = cv2.fastNlMeansDenoising(img);

        # Threshold (binary image)
        # thresh – threshold value.
        # maxval – maximum value to use with the THRESH_BINARY and THRESH_BINARY_INV thresholding types.
        # type – thresholding type
        th, threshedImg = cv2.threshold(denoisedImg, 200, 255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU) # src, thresh, maxval, type

        # Perform morphological transformations using an erosion and dilation as basic operations
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
        morphImg = cv2.morphologyEx(threshedImg, cv2.MORPH_OPEN, kernel)

        # Find and draw contours
        contours, hierarchy = cv2.findContours(morphImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        contoursImg = cv2.cvtColor(morphImg, cv2.COLOR_GRAY2RGB)
        cv2.drawContours(contoursImg, contours, -1, (255,100,0), 3)

        cv2.imwrite("results/" + dirname + "/" + filename + "_result.tif", contoursImg)
        textFile = open("results/results.txt","a")
        textFile.write(filename + " Dots number: {}".format(len(contours)) + "\n")
        textFile.close()

Here is my input image : Input

Here is my result : Result

For now this script works pretty well with that input but when I switch to other inputs like this one :

image description

I get a very blobby result :

image description

I would like to be able to only keep the dots which are :

  • Well rounded

Or :

  • Which are in the top 10% of the other dots in terms of brightness
  • Which are "big" enough (relative to the image so let's say eliminate dots which are in the bottom 10% in terms of surface).

I read things about creating a "is_contour_bad" function which I could use to determine if a contour is bad and should be removed.

https://www.pyimagesearch.com/2015/02/09/removing-contours-image-using-python-opencv/

I tried to implement it but didn't get any results. Still, the idea seems good to me.

I also though of adjusting the threshold and erosions/dilatations depending of the image but really the best would be to be able to act on each parameters enumerated before. Still if you have ideas to automatically find the useful properties of an image to apply the right filters on it, it can be interesting.

If you have any idea or piece of code, even small, to help me reach that goal it would be awesome.

Thanks in advance for your help.