5

I am getting a Zero Division Error with some images (Even though a lot of them work just fine) :

Here's the code :

image = skimage.io.imread('test.png', False)
image_gray = skimage.io.imread('test.png', True)
blurred = cv2.GaussianBlur(img_as_ubyte(image_gray), (5, 5), 0)
thresh = threshold_li(blurred)
binary = blurred > thresh
binary_cv2 = img_as_ubyte(binary)

# find contours in the thresholded image
cnts = cv2.findContours(binary_cv2.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]

# loop over the contours
for c in cnts:
    # compute the center of the contour
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])

    # draw the contour and center of the shape on the image
    cv2.drawContours(img_as_ubyte(image), [c], -1, (0, 255, 0), 2)
    cv2.circle(img_as_ubyte(image), (cX, cY), 7, (255, 255, 255), -1)
    cv2.putText(img_as_ubyte(image), "center", (cX - 20, cY - 20),
    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

viewer = ImageViewer(image)
viewer.show()

Traceback (most recent call last):
  File "Center.py", line 26, in <module>
    cX = int(M["m10"] / M["m00"])
ZeroDivisionError: float division by zero

Thanks in advance!

3 Answers3

6

Error is self-evident. You cannot divide a number by zero. If M["m00"] is zero, then you need to handle it appropriately. Check for 0 values in M["m00"].

if M["m00"] != 0:
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
else:
    # set values as what you need in the situation
    cX, cY = 0, 0
Ian Price
  • 7,416
  • 2
  • 23
  • 34
  • 10
    I think this is not rigorous. If m00 is zero, the area of your shape is zero and you should decide to either consider the shape as invalid (i.e. skip it) or measure the center in another way, but not return (0, 0). – mimo Jun 06 '18 at 09:10
6

Probably you have bad contours

Note Since the contour moments are computed using Green formula, you may get seemingly odd results for contours with self-intersections, e.g. a zero area (m00) for butterfly-shaped contours.

steel.ne
  • 665
  • 5
  • 6
1

Calculate the the center of mass, e.g.:

cx = 0
cy = 0
for p in contour:
    cx += p[0][0]
    cy += p[0][1]
cx = int(cx/len(contour))
cy = int(cy/len(contour))

or look into boundingRect() (3.4.3).

Related: Finding the center of a contour using opencv and visual c++

handle
  • 5,859
  • 3
  • 54
  • 82