python求形心,轮廓的质心是否始终是其几何中心? (OpenCV,Python)

I am working with OpenCV+Python and I want to find the geometrical centre of the following contour:

b7cc78bda8f58b13d2715cc1244d82bb.png

The OpenCV documentation suggests the following to find the centroid of a contour:

import numpy as np

import cv2 as cv

img = cv.imread('star.jpg',0)

ret,thresh = cv.threshold(img,127,255,0)

im2,contours,hierarchy = cv.findContours(thresh, 1, 2)

cnt = contours[0]

M = cv.moments(cnt)

print( M )

#Centroid

cx = int(M['m10']/M['m00'])

cy = int(M['m01']/M['m00'])

If I am right, according to this formula the centroid is calculated as the mean (or the average?) of all the points of the contour.

However, if for example fewer points are detected at the upper part of the contour than at the lower part of the contour then the centroid will be a bit higher than the actual geometrical centre of the (fully detected) contour.

Am I right?

If so, then is it better to calculate the average of the extreme points of the contour to find the geometrical centre of the contour and in this way to not depend at all on if the points of the contour are uniformly detected?

解决方案Am I right?

No. The OpenCV function moments() uses Green's theorem as mentioned in the OpenCV moments() docs. Green's theorem is indeed a correct way to find the center of mass of a shape. Green's theorem specifically relates integrals about some shape to integrals about the shape's border. As such, it doesn't at all matter how many points define the border or not.

I say center of mass specifically, because you can pass in a single-channel image array into moments() as well to compute the moments and not just a point array. However for an image array, if the array is just binary, then the center of mass is the centroid. And with an array of points (from your contours), there is no array to tell the pixel values inside, so the result is similarly still the centroid.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是使用PythonOpenCV获取二值图像轮廓中心点坐标的代码: ```python import cv2 # 读取图像 img = cv2.imread('image.png') # 转为灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 获取轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 获取中心点坐标 for contour in contours: M = cv2.moments(contour) if M['m00'] != 0: cx = int(M['m10']/M['m00']) cy = int(M['m01']/M['m00']) print("中心点坐标:({}, {})".format(cx, cy)) # 绘制轮廓中心点 cv2.drawContours(img, contours, -1, (0, 255, 0), 2) cv2.circle(img, (cx, cy), 5, (0, 0, 255), -1) # 显示图像 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 其中,`cv2.findContours()` 函数用于获取图像轮廓,返回值为轮廓列表和层次结构信息。`cv2.moments()` 函数可用于计算轮廓的矩,从而获取中心点坐标。最后,通过 `cv2.drawContours()` 和 `cv2.circle()` 函数绘制轮廓中心点。 ### 回答2: 使用PythonOpenCV库可以很方便地获取二值图像轮廓中心点坐标。以下是一个用Python编写的示例代码: ```python import cv2 # 读取二值图像 image = cv2.imread('binary_image.png', 0) # 寻找轮廓 contours, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历每个轮廓 for contour in contours: # 计算轮廓的矩 M = cv2.moments(contour) # 计算轮廓中心点坐标 cx = int(M['m10'] / M['m00']) cy = int(M['m01'] / M['m00']) # 在图像上绘制中心点 cv2.circle(image, (cx, cy), 5, (0, 255, 0), -1) # 显示图像轮廓 cv2.imshow('image', image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在代码中,首先使用`cv2.imread()`函数读取二值图像,并将其灰度化(参数设为0)。然后使用`cv2.findContours()`函数寻找图像中的轮廓,第一个返回值是轮廓的列表,第二个返回值是层级信息,我们可以使用下划线来忽略。 接下来,我们使用一个循环遍历每个轮廓。对于每个轮廓,我们使用`cv2.moments()`函数计算轮廓的矩,然后通过矩的计算公式计算轮廓中心点坐标。最后,我们使用`cv2.circle()`函数在图像上绘制中心点。 最后,使用`cv2.imshow()`函数显示带有轮廓中心点的图像,并使用`cv2.waitKey()`和`cv2.destroyAllWindows()`函数来等待用户关闭窗口。 请确保将代码中的`binary_image.png`替换为实际的二值图像文件路径。 ### 回答3: 要使用PythonOpenCV获取二值图像轮廓中心点坐标,可以按以下步骤进行。 首先,导入必要的库,包括opencv-python和numpy。 ```python import cv2 import numpy as np ``` 接下来,读取图片并进行预处理。通常需要将彩色图像转换为灰度图像,并应用二值化操作,使图像只包含黑白两种颜色。 ```python image = cv2.imread('image.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, threshold = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY) ``` 然后,使用OpenCV的findContours函数来查找图像中的轮廓。 ```python contours, _= cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ``` 接下来,计算每个轮廓形心,并存储所有形心坐标。 ```python centroids = [] for contour in contours: M = cv2.moments(contour) cx = int(M["m10"] / M["m00"]) cy = int(M["m01"] / M["m00"]) centroids.append((cx, cy)) ``` 最后,可以将轮廓形心坐标绘制到图像上,以便进行可视化显示。 ```python cv2.drawContours(image, contours, -1, (0, 255, 0), 2) for centroid in centroids: cv2.circle(image, centroid, 5, (0, 0, 255), -1) ``` 完整代码如下所示: ```python import cv2 import numpy as np image = cv2.imread('image.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, threshold = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) centroids = [] for contour in contours: M = cv2.moments(contour) cx = int(M["m10"] / M["m00"]) cy = int(M["m01"] / M["m00"]) centroids.append((cx, cy)) cv2.drawContours(image, contours, -1, (0, 255, 0), 2) for centroid in centroids: cv2.circle(image, centroid, 5, (0, 0, 255), -1) cv2.imshow('Result', image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 请记得将'image.jpg'替换为您自己的图像文件的路径。运行此代码后,将显示包含轮廓形心图像
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值