首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >opencv(4.5.3)-python(十九)--轮廓线的特征

opencv(4.5.3)-python(十九)--轮廓线的特征

作者头像
用户9875047
发布2022-12-07 10:18:33
8220
发布2022-12-07 10:18:33
举报
文章被收录于专栏:机器视觉全栈er机器视觉全栈er

翻译及二次校对:cvtutorials.com

在这篇文章中,我们将学习

  • • 找到轮廓的不同特征,如面积、周长、中心点、边界盒等。
  • • 你会看到很多与轮廓线有关的函数。

1. 矩

图像矩帮助你计算一些特征,如物体的质心、物体的面积等。

函数cv.ments()给出了一个所有计算出的矩的字典。见下文:

import numpy as np
import cv2 as cv
img = cv.imread('star.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
M = cv.moments(cnt)
print(M)

从这个矩,你可以提取有用的数据,如面积、中心点等。中心点是由Cx=M10/M00和Cy=M01/M00的关系给出的。这可以按以下方式进行。

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

2. 轮廓线面积

轮廓线面积由函数cv.contourArea()或从矩M['m00']给出。

area = cv.contourArea(cnt)

3. 轮廓线周长

它也被称为弧长。它可以用cv.arcLength()函数计算出来。第二个参数指定形状是一个封闭的轮廓(如果传递的是True),还是只是一条曲线。

perimeter = cv.arcLength(cnt,True)

4. 轮廓逼近

它根据我们指定的精度,将一个轮廓形状逼近到另一个顶点数量较少的形状。它是Douglas-Peucker算法的一个实现。

为了理解这一点,假设你试图在图像中找到一个正方形,但由于图像中的一些问题,你没有得到一个完美的正方形,而是一个 "坏形状"(如下图所示)。现在,你可以用这个函数来近似地处理这个形状。在这个函数中,第二个参数叫做epsilon,它是轮廓到近似轮廓的最大距离。它是一个精度参数。为了得到正确的输出,需要明智地选择epsilon。

epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)

下面,在第二张图片中,绿线显示了epsilon为弧长的10%时的近似曲线。第三张图显示的是epsilon为弧长的1%时的情况。第三个参数指定曲线是否是封闭的。

5. 凸面体

凸面体看起来与轮廓逼近相似,但它不是(两者在某些情况下可能提供相同的结果)。在这里,cv.convexHull()函数检查曲线是否有凸性缺陷并进行修正。一般来说,凸形曲线是指总是凸出来的曲线,或者至少是平的。而如果是向内隆起,则被称为凸性缺陷。例如,请看下面的手的图片。红线表示手的凸体。双面的箭头标志显示了凸性缺陷,这是局部最大凸包与轮廓的偏差。

关于它的语法,有一点需要讨论。

hull = cv.convexHull(point[, hull[, clockwise[, returnPoints])

参数细节:

  • • points是我们传入的轮廓线。
  • • hull是输出,通常我们避免使用它。
  • • clockwise:方向标志。如果它是True,输出的凸面体是顺时针方向的。否则,它的方向是逆时针的。
  • • returnPoints : 默认为 "真"。然后,它返回凸包点的坐标。如果是False,它返回与凸包点对应的轮廓点的索引。

因此,要得到上图中的凸包,只需按以下方法即可:

hull = cv.convexHull(cnt)

但是如果你想找到凸性缺陷,你需要传递returnPoints = False。为了理解它,我们将采取上面的矩形图像。首先,我发现它的轮廓为cnt。现在我用returnPoints = True找到了它的凸面,我得到了以下值。[[234 202]], [[51 202]], [[51 79]], [[234 79]]是矩形的四个角点。现在如果用returnPoints = False做同样的事情,我得到的结果是:[[129], [67], [0], [142]]。这些是轮廓线中相应的点的索引。例如,检查第一个值:cnt[129] = [[234, 202]],这与第一个结果相同(其他的也是如此)。

当我们讨论凸性缺陷时,你会再次看到它。

6. 检查凸性

有一个函数可以检查一条曲线是否是凸的,即cv.isContourConvex()。它只是返回True或False。没什么大不了的。

k = cv.isContourConvex(cnt)

7. 边界矩形

有两种类型的边界矩形。

7.a. 直线边界矩形

这是一个直线矩形,它不考虑物体的旋转。因此,边界矩形的面积不会是最小的。它是由函数cv.boundingRect()找到的。

(x,y)为矩形的左上角坐标,(w,h)为其宽度和高度。

x,y,w,h = cv.boundingRect(cnt)
cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

7.b. 旋转的矩形

这里,边界矩形是以最小面积绘制的,所以它也考虑了旋转。使用的函数是cv.minAreaRect()。它返回一个包含以下细节的Box2D结构--(中心(x,y),(宽度,高度),旋转的角度)。但是要画这个矩形,我们需要矩形的4个角。它可以通过函数cv.boxPoints()获得

rect = cv.minAreaRect(cnt)
box = cv.boxPoints(rect)
box = np.int0(box)
cv.drawContours(img,[box],0,(0,0,255),2)

两个矩形都显示在一张图片上。绿色矩形显示的是正常的边界矩形。红色矩形是旋转后的矩形。

8. 最小包围圈

接下来,我们使用cv.minEnclosingCircle()函数找到一个物体的圆。它是一个以最小面积完全覆盖物体的圆。

(x,y),radius = cv.minEnclosingCircle(cnt)
center = (int(x),int(y))
半径 = int(radius)
cv.circle(img,center,radius,(0,255,0),2)

9. 拟合椭圆

下一个是将一个椭圆拟合到一个物体上。它返回旋转后的矩形以及内接的椭圆。

ellipse = cv.fitEllipse(cnt)
cv.ellipse(img,ellipse,(0,255,0),2)

10. 拟合直线

同样地,我们可以将一条线拟合到一组点上。下面的图片包含一组白色的点。我们可以对它进行近似的直线拟合。

rows,cols = img.shape[:2] 。
[vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cv.line(img,(cols-1,righty),(0,lefty),(0,255,0) ,2)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器视觉全栈er 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档