I am trying to compute the area and the center coordinates of objects in a binary mask using opencv. However, I noticed that in some cases I get the wrong result. For example, if I get the contours like this:
import numpy as np
import cv2
binary_mask = np.array([
[0, 0, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1]])
contours, _ = cv2.findContours(
binary_mask.astype(np.uint8),
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
>>> contours
(array([[[0, 3]],
[[5, 3]]], dtype=int32),
array([[[2, 0]],
[[2, 1]],
[[3, 1]],
[[3, 0]]], dtype=int32))
Then I get ZeroDivisionError
for the center calculation:
def get_centroid_from_contour(contour):
M = cv2.moments(contour)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
return (cX, cY)
>>> get_centroid_from_contour(contour)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in get_centroid_from_contour_
ZeroDivisionError: float division by zero
This I think is related to the fact that somehow opencv thinks the 2x2 squared object has zero area:
>>> cv2.contourArea(contours[0])
0.0
It seems something related to "open objects". Indeed the first contour only contains two points that do not close the polygon, but I have no idea how to fix this. I also tried closing the contour as suggested here but it doesn't work.