# Counting non-overlapping objects in a semantic segmentation prediction mask

What is a good way to count the number of roofs detected by a CNN in the following output on the right (produced using keras/tensorflow):

I need to count the discrete shaded areas and estimate their area in pixels. I'm a little stumped. It is not strictly an image classification problem.

This could be one of the approaches (if you are looking for the exact solution):

I assume that the image (your prediction) consists of only two values: 0 - black - roof, and 255 - white - other.

Then, this becomes an easy problem of counting the components of a graph:

Start a DFS from some black node which is not visited yet. Traverse all neighboring black nodes which are not visited yet. While moving, keep count of the number of black nodes you visited, and mark them as visited (so that you don't go back ...). Repeat the whole process if there are black nodes to start from (they are not already visited). This way you get the total number of roofs (this is the number of times you started a DFS from non-visited black node) and the total area of roofs (the number of black pixels you visited).

That is classical DFS problem. Here is an example in Python: https://eddmann.com/posts/depth-first-search-and-breadth-first-search-in-python/

This will work well, if you predictions are good. Actually, it will do what I have described, even if your predictions are bad, because it is an exact algorithm. But you have to check if your predictions are fine some other way.

If you are looking for different type of solution (i.e. not exact solution), the interesting approach would be to teach a model to count the number of roofs and estimate their area from an image. In order to do that, you would have to create a dataset with labeled images: for each image the label could be a total number of roofs on the image and the area of all roofs. So, that would be a regression problem.

I think I solved this more elegantly using scipi label function. https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.label.html

from scipy.ndimage import label
p=pred_y[0, :,:, 0] # contains a prediction result
# normalize threshold to 0 or 1
i = p >= 0.5
p[i] = 1
i = p < 0.5
p[i] = 0
labeled_array, num_features = label(p)
plt.imshow(p, cmap=plt.cm.binary)
print(num_features)


Produces an estimate of 15.