如何从物体边界直接得到物体质心?

2024-06-09 18:12:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有2个分割图像。一种是大津二进制,另一种是由大津的外边界得到的

大津二进制:

Otsu binary

对象边界:

Object boundary

找到质心的代码如下:

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))]

但是,这段代码似乎只适用于otsu。结果如下:

大津二进制:

Otsu binary

对象边界:

Object boundary

那么,如何从物体边界找到物体质心呢?在

注意:我不想使用内置函数,因为我想学习算法是如何工作的。在


Tags: 对象代码inimgfornp二进制range
3条回答

算法很简单:只需平均所有边界像素坐标。然而,这并不是真正的质心。要找到真正的像素,平均对象中包含的所有像素(不仅是边界)。在

如果对象是凸的,则平均边界是可行的。凸面物体是指两个内部点之间的连接不会与其边界相交的物体。将一个对象分解成这样的组件的最简单方法可能是将其拆分为不重叠的矩形,同时尽量将矩形的数量保持在最小值。矩形的质心的平均值(乘以矩形的面积)就是物体的质心。在

这个错误很简单。由于这种情况,您的算法只处理黑色像素:if (img[x,y] == 0):。边界的图像包含很大比例的黑色像素。可以安全地假设这样的图像中所有黑色像素的质心将非常接近图像的中心。在

该图像宽402像素,高302像素。你的算法给我们(x=201, y=151)作为质心,这与期望相符。在

要正确处理对象边界,我们需要使边界为黑色,其他所有对象为白色。这很简单,只需反转图像(例如255 - img)。然后您的算法返回(x=165, y=123),这就更有意义了。在

代码

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)

样本输出

注:红色为原始图像的质心,绿色为反向图像的质心。在

Sample output image

相关问题 更多 >