使用 cv2.contourArea 计算面积

问题描述 投票:0回答:1

使用 cv2.contourArea() 计算轮廓面积并没有为我提供正确的数字。 我已经尝试了以下非常简单的正方形和圆形示例,但结果不是预期的结果。关于我做错了什么的任何提示吗?

import cv2
import numpy as np

image = np.zeros((512, 5122,3), np.uint8)
cv2.rectangle(image, (100,100), (200,200), (0,255,0),2 )
cv2.circle(image, (256, 256), 10, (0, 255, 0), 2)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
contours, hierarchy = cv2.findContours(image_gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
superficie = [cv2.contourArea(cnt) for cnt in contours]
perimeter = [cv2.arcLength(cnt, True) for cnt in contours]

for i in range(0, len(superficie)):
    x, y, w, h = cv2.boundingRect(contours[i])
    print(f'contour {i} area: {superficie[i] } bounding area {w*h}  perimeter: {round(perimeter[i],2)}')

正方形(轮廓 3)和圆形(轮廓 1)的结果不是预期的:

轮廓 0 面积:248.0 边界面积:361 周长:57.94 轮廓 1 面积:386.0 边界面积:529 周长:73.94 轮廓 2 面积:9602.0 边界面积:9801 周长:389.66 轮廓 3 面积:10402.0 边界面积:10609 周长:405.66

我试图得到正方形面积的值等于 100100=10000,它的周长等于 4**100 =400。然而,我得到的面积为 10402,周长为 405.66。 同样,对于圆,我期望 PI1010 = 314.1,我得到 386;对于周长,我期望 2PI10 = 62.8,我得到 73.94

我还得到了正方形边界矩形的不同值

python area
1个回答
0
投票

我不太完全理解您上传的代码,但请确保考虑到 cv2.contourArea() 的一些功能。

  1. 第一个是 cv2.contourArea() 不会以我们计算真实连续事物的面积的方式返回精确的面积。它返回的值是相应轮廓内的像素数。因此,虽然对于真实的东西,您可以获得具有无限小数精度的面积,但在这种方法中,它们可能会出现一些近似误差,因为圆线不是完美的连续线,实际上它是具有小步长的线。

  2. 第二件事是 cv2.findContours() 不会返回用 cv2.rectangle() 或 cv2.circle() 绘制的精确线。该函数搜索其值与其各自的邻居存在很大差异的像素。这导致每条简单的线条/图形都有两个轮廓:一个用于线条的外部部分,另一个用于线条的内部部分。如果您可以放大,您可以看到 cv2.findContours 返回其中两个轮廓,因为在图形的外部线条中,白色和黑色像素之间的值变化非常大,内部像素的值变化也很大。

通过这种方法,如果使用外部或内部轮廓进行计算,您会得到不同的面积。

contours, _ = cv2.findContours(image_with_circle_bw, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
image_with_con = cv2.drawContours(cv2.cvtColor(image_with_circle_bw.copy(), cv2.COLOR_GRAY2BGR), contours, 1, (0,0,255), 4)

area_1 = cv2.contourArea(contours[0])
area_2 = cv2.contourArea(contours[1])
area = (area_1+area_2)/2
print(area_1) # Area of the external bound
print(area_2) # Area of the internal bound
print(area) # Mean of the two areas
print(200**2*math.pi) # 200 is because radius is 200

这将打印以下内容:

128058.0 # Area of the external bound
122939.0 # Area of the internal bound
125498.5 # Mean of the two areas
125663.70614359173 # Real area of a circle with radius = 200

如您所见,为了获得近似值,我计算了两个区域之间的平均值。当然,这不是近似这一点的更好方法,但它非常接近真实的方法。 需要理解的是,contourArea()不会返回区域的实际值,它会返回更高或更低的值,因为它不搜索实际的线,它搜索边界像素,其中黑色和白色像素彼此相邻。

© www.soinside.com 2019 - 2024. All rights reserved.