python-opencv Tutorials 一码人翻译(19)图像处理----轮廓检测 --轮廓特征

目标

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

要找到轮廓的不同特征,比如面积,周长,质心,边界框等等

您将看到许多与等高线相关的函数。

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)

猜你喜欢

转载自blog.csdn.net/qq_41905045/article/details/81430893