0

I'm 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 : Input

I get a very blobby result :

Result

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.

1 Answer 1

2

One way of removing the dots which are not well-rounded and which are small is to use the opening operation (that you are already using) with a circular structuring element of the minimum dot size that you want (every dot smaller than the structuring element will be removed). In the following images there is a similar example to your problem where the small dots are removed this way (source: https://homepages.inf.ed.ac.uk/rbf/HIPR2/open.htm). Also, OpenCV has an implementation of this operation (https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html).

enter image description here

In fact, you already use this operation, but in my opinion the structuring element defined in the following line seems to be too small:

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))

Also, as you are apparently using images with different resolutions, you can adapt the size of the structuring element depending on the resolution of the image.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.