如何获得轮廓的面积?

时间:2019-04-02 04:37:06

标签: opencv computer-vision

我有这样的照片:
origin picture

然后将其转换为二进制图像,并使用canny来检测图片的边缘:

gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
edge = Image.fromarray(edges)

然后我得到的结果是:
edge pic
我想像这样得到2的面积:
enter image description here


我的解决方案是使用HoughLines在图片中查找线并计算由线形成的三角形的面积。但是,由于封闭区域不是标准三角形,因此这种方法并不精确。如何获得2区的面积?

2 个答案:

答案 0 :(得分:3)

使用floodFillcountNonZero的简单方法可能是以下代码片段。我在帮助中对contourArea的标准报价:

  

该函数计算轮廓区域。与moments类似,使用绿色公式计算面积。因此,如果使用drawContoursfillPoly绘制轮廓,则返回的区域和非零像素数可能会有所不同。此外,对于具有自相交的轮廓,该功能肯定会给出错误的结果。

代码:

import cv2
import numpy as np

# Input image
img = cv2.imread('images/YMMEE.jpg', cv2.IMREAD_GRAYSCALE)

# Needed due to JPG artifacts
_, temp = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY)

# Dilate to better detect contours
temp = cv2.dilate(temp, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))

# Find largest contour
cnts, _ = cv2.findContours(temp, cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_NONE)
largestCnt = []
for cnt in cnts:
    if (len(cnt) > len(largestCnt)):
        largestCnt = cnt

# Determine center of area of largest contour
M = cv2.moments(largestCnt)
x = int(M["m10"] / M["m00"])
y = int(M["m01"] / M["m00"])

# Initiale mask for flood filling
width, height = temp.shape
mask = img2 = np.ones((width + 2, height + 2), np.uint8) * 255
mask[1:width, 1:height] = 0

# Generate intermediate image, draw largest contour, flood filled
temp = np.zeros(temp.shape, np.uint8)
temp = cv2.drawContours(temp, largestCnt, -1, 255, cv2.FILLED)
_, temp, mask, _ = cv2.floodFill(temp, mask, (x, y), 255)
temp = cv2.morphologyEx(temp, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))

# Count pixels in desired region
area = cv2.countNonZero(temp)

# Put result on original image
img = cv2.putText(img, str(area), (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, 255)

cv2.imshow('Input', img)
cv2.imshow('Temp image', temp)

cv2.waitKey(0)

临时图像:

Temporary image

结果图片:

Result image

注意事项:findContours在右侧非常接近,该线条非常靠近底部图像边框,因此可能会省略一些像素。

免责声明:我是Python的新手,尤其是OpenCV(胜利的C ++)的Python API。非常欢迎评论,改进,强调Python的执行!!

答案 1 :(得分:2)

如果您采取示例图片中满足的一些假设,则有一种非常简单的方法来查找该区域:

  1. 要找到的区域由一条线顶部限制
  2. 图像中的其他任何行都在感兴趣的行上方
  3. 该行没有间断

在这种情况下,感兴趣区域的面积由从图像底部到第一组像素的长度之和得出。我们可以这样计算:

INFO  [stdout] (default task-2) EntityManager: org.jboss.as.jpa.container.TransactionScopedEntityManager@54e9b6cd

这将打印import numpy as np import matplotlib.pyplot as pp img = pp.imread('/home/cris/tmp/YMMEE.jpg') img = np.flip(img, axis=0) pos = np.argmax(img, axis=0) area = np.sum(pos) print('Area = %d\n'%area)

Area = 22040在图像的每一列上找到 first 设置像素,并返回索引。首先使用np.argmax,我们翻转该轴,以使第一个像素实际上是底部的像素。索引对应于图像底部和线条之间的像素数(不包括设置的像素)。

因此,我们正在计算线下 的面积。如果您需要将该行本身包括在该区域中,请在该区域中添加np.flip(即列数)。