Kadek Dwi Budi Utama - 1 year ago 129

Python Question

I have 2 segmented images. One is otsu binary, and the other is outer boundary obtains from otsu's.

Otsu binary:

Object boundary:

And code to find centroids like this:

`def getCentroid(img):`

row, col = img.shape

xVal = 0

yVal = 0

n = 0.0

for x in range(0,row):

for y in range(0,col):

if (img[x,y] == 0):

xVal += x

yVal += y

n += 1.0

xVal /= n

yVal /= n

return [np.int64(np.round(xVal)),np.int64(np.round(yVal))]

But, it seems the code only works with otsu's. Here are the results:

Otsu binary:

Object boundary:

So, how to find object centroid from object boundary?

Note: I don't want to use built-in function, cause i want to learn how the algorithm works.

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

The mistake is quite simple. Your algorithm processes only black pixels, due to this condition: `if (img[x,y] == 0):`

. Your image of the boundary contains a large proportion of black pixels. It is safe to assume that the centroid of all the black pixels in such image would be very close to the center of the image.

The image in question is 402 pixels wide, and 302 pixels high. Your algorithm gives us `(x=201, y=151)`

as the centroid -- this matches the expectation.

To correctly process the object boundary, we need to make the boundary black, and everything else white. This is simple, just invert the image (e.g. `255 - img`

). Then your algorithm returns `(x=165, y=123)`

, which makes a lot more sense.

```
import cv2
import numpy as np
def getCentroid(img):
row, col = img.shape
xVal = 0
yVal = 0
n = 0.0
for x in range(0,row):
for y in range(0,col):
if (img[x,y] == 0):
xVal += x
yVal += y
n += 1.0
xVal /= n
yVal /= n
return [np.int64(np.round(xVal)),np.int64(np.round(yVal))]
a = cv2.imread('cnt.png', 0)
c1 = getCentroid(a) # Original
c2 = getCentroid(255 - a) # Inverse
b = cv2.cvtColor(a, cv2.COLOR_GRAY2BGR)
cv2.circle(b, (c1[1], c1[0]), 3, (0,0,255))
cv2.circle(b, (c2[1], c2[0]), 3, (0,255,0))
cv2.imwrite('cnt_out.png', b)
```

Note: Red is the centroid from original image, Green from the inverted image.