目标
在这篇文章中,我们将学习
要找到轮廓的不同特征,比如面积,周长,质心,边界框等等
您将看到许多与等高线相关的函数。
1距
图像时刻帮助你计算一些特征比如物体的重心,物体的面积等等。在图像时刻查看维基百科页面
函数cv.moments()给出了计算的所有力矩值的字典。见下文:
import numpy as np
import cv2 as cv
img = cv.imread('wjx.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 )
{'m00': 2.0, 'm10': 912.0, 'm01': 1198.0, 'm20': 415872.3333333333, 'm11': 546288.0, 'm02': 717602.3333333333, 'm30': 189638088.0, 'm21': 249107527.66666666, 'm12': 327226664.0, 'm03': 429844197.0, 'mu20': 0.3333333333139308, 'mu11': 0.0, 'mu02': 0.3333333332557231, 'mu30': 2.9802322387695312e-08, 'mu21': 1.6880221664905548e-09, 'mu12': 3.5390257835388184e-08, 'mu03': 1.1920928955078125e-07, 'nu20': 0.0833333333284827, 'nu11': 0.0, 'nu02': 0.08333333331393078, 'nu30': 5.268356063861754e-09, 'nu21': 2.984029801796697e-10, 'nu12': 6.256172825835833e-09, 'nu03': 2.1073424255447017e-08} |
从这一刻起,你就可以提取出有用的数据,比如面积,中心id等等。中心id是由关系给出的,
可以这样做:
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
2。轮廓面积
轮廓区域由函数cv.contourArea()或从力矩,M 00'给出。
area = cv.contourArea(cnt)
import numpy as np
import cv2 as cv
img = cv.imread('black.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)
cnt = contours[0]
M = cv.moments(cnt)
area = cv.contourArea(cnt)
print(area)
cv.imshow("img2",img)
cv.waitKey(0)
26514.0
3。轮廓周长
它也被称为弧长。可以通过cv.arcLength()函数找到它。第二个参数指定形状是否是一个封闭的轮廓(如果传递为真),或者仅仅是一条曲线。
perimeter = cv.arcLength(cnt,True)
import numpy as np
import cv2 as cv
img = cv.imread('black.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)
cnt = contours[0]
M = cv.moments(cnt)
perimeter = cv.arcLength(cnt,True)
print(perimeter)
cv.imshow("img2",img)
cv.waitKey(0)
1289.4329804182053
轮廓近似
它近似于一个轮廓形状到另一个形状,根据我们所指定的精度,它的顶点数较少。它是道格拉斯-peucker算法的实现。检查维基百科页面的算法和演示。
要理解这一点,假设您正在尝试在图像中找到一个正方形,但是由于图像中的一些问题,您没有得到一个完美的正方形,而是一个“坏的形状”(如下面的第一张图所示)。现在你可以用这个函数来近似这个形状。在这个过程中,第二个参数叫做epsilon,它是距离等高线到近似等高线的最大距离。它是一个精度参数。为了得到正确的输出,需要明智地选择epsilon。
epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)
在下图中,绿线显示了epsilon=10%弧长的近似曲线。第三张图显示的是相同的弧长。第三个参数指定了曲线是否闭合。
5。凸包
凸壳看起来与等值线近似,但它不是(在某些情况下,两者都可能提供相同的结果)。在这里,cv.凸壳()函数检查凸性缺陷的曲线并修正它。一般来说,凸曲线是总是凸出的曲线,或者至少是平的。如果它在里面膨胀,就叫做凸性缺陷。例如,检查下面的手的图像。红线显示的是手的凸壳。双侧箭头标志着凸性缺陷,即船体与轮廓的最大偏差。
参数说明:
点是我们传递的轮廓。
船体是输出,通常我们会避开它。
顺时针方向:面向国旗。如果是真的,输出凸壳是顺时针方向的。否则,它是逆时针方向的。
返回点:默认情况下是正确的。然后它返回船体点的坐标。如果是假的,它会返回对应于船体点的等值线的指数。
所以要得到一个凸壳,就像上面的图像一样,下面是充分的:
import numpy as np
import cv2 as cv
img = cv.imread('shou.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)
cnt = contours[0]
M = cv.moments(cnt)
hull = cv.convexHull(cnt)
print(hull )
cv.imshow("img2",img)
cv.waitKey(0)
但是如果你想找到凸性缺陷,你需要通过返回点=False。为了理解它,我们将使用上面的矩形图像。首先我发现它的轮廓是cnt。现在我找到了它的凸壳,带着返回点=True,我得到了下面的值:234 202,51 202,51 79,234 79这是矩形的四个角点。如果对returnPoints=False,我得到如下结果:129、67、0、142。这些是等高线的对应点的指数。例如,检查第一个值:cnt 129=234,202,这和第一个结果是一样的(对其他人也是如此)。
当我们讨论凸性缺陷时,你们会再次看到它。
6。检查凸性
有一个函数来检查曲线是否是凸的,cv.iscontour凸()。它只是返回是真还是假。不是一个大问题。
import numpy as np
import cv2 as cv
img = cv.imread('shou.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)
cnt = contours[0]
M = cv.moments(cnt)
k = cv.isContourConvex(cnt)
print(k)
cv.imshow("img2",img)
cv.waitKey(0)
================= RESTART: C:\Users\ty\Desktop\qwe\teas11.py =================
False
7。边界矩形
有两种类型的边界矩形。
7.。直边界矩形
它是一个直的矩形,它不考虑物体的旋转。所以边界矩形的面积不会是最小的。它是由函数cv.boundingRect()找到的。
让(x,y)是矩形的左上坐标(w,h)是它的宽度和高度。
-
9。拟合椭圆
ellipse = cv.fitEllipse(cnt) cv.ellipse(img,ellipse,(0,255,0),2)
import numpy as np import cv2 as cv img = cv.imread('bbwp.png',0) ret,thresh = cv.threshold(img,127,255,0) im2,contours,hierarchy = cv.findContours(thresh, 1, 5) cnt = contours[0] M = cv.moments(cnt) ellipse = cv.fitEllipse(cnt) cv.ellipse(img,ellipse,(0,255,0),2) cv.imshow("img2",img) cv.waitKey(0)
-
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)