Counting objects and calculating objects' density in Python


Steve on Image Processing is a great blog with many image-processing recipes in Matlab. Following it for some time, I believe that most of the recipes can be implemented in Python with modern SciPy, OpenCV and Matplotlib libraries.

For example, let's take the recent post on Counting objects without bias, on how to count objects in image, and how to calculate object density per unit area correctly.

We can replace Matlab's bwconncomp with SciPy's label. 8-connectivity used in Steve's example can be achieved in SciPy by using a ones((3,3)) structuring element. I use the same test image as Steve to make sure the results are identical:


img = "images/rice-bw-2.png"
bw = imread(img, True)
labeled, n = label(bw, ones((3,3)))

Variable n gives the number of detected objects. Naive density calculation:

objects_per_unit_area = n * 1.0 / labeled.size

As in the Steve's example, the density ≈ 0.00145.

To maker a better estimate, we should not count objects touching two adjacent edges. Unlike Matlab, SciPy doesn't have a function to remove objects on the boundary. Instead we may pad two borders with white pixels, and all objects touching those borders will be connected, and counted as a single object.

Padding the image with white bottom and right borders:

height, width = bw.shape
pad_south = 255 * ones((1, width))
pad_east = 255 * ones((height + 1, 1))
bw_padded = hstack((vstack((bw, pad_south)), pad_east))

Counting bottom-right boundary objects as one:

labeled2, n2 = label(bw_padded, ones((3,3)))
objects_per_unit_area2 = (n2-1) * 1.0 / bw.size

The value of density ≈ 0.0013, like in the Steve's example.

Unlike with Matlab, you don't need to pay €200 for Image Processing Toolbox and €500 for the Matlab itself, and anyone can run your code, on any number of machines, for any purpose. Python and SciPy are free.

All the code is available in this gist:

If you like this post, you may also learn how to remove circles from an image in Python.