目标
在这里,将学习提取一些常用的物体属性
- 坚实度(image solidity)
- 等效直径(Equivalent Diameter)
- 掩模图像(mask)
- 平均强度(Mean Intensity)
长宽比( Aspect Ratio)
长宽比是对象边界矩形的宽度与高度的比值
A s p e c t R a t i o = W i d t h H e i g h t Aspect \;Ratio=\frac{Width}{Height} AspectRatio=HeightWidth
#长宽比
import cv2
import numpy as np
img = cv2.imread('approx.png', 0)
rows, cols = img.shape
ret, thresh = cv2.threshold(img, 127, 250, 0)
cnts, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
x, y, w, h = cv2.boundingRect(cnts[0])
aspect_ratio = float(w)/h # 1.09
范围(Extent)
范围是轮廓区域与边界矩形区域的比值
E x t e n t = O b j e c t A r e a B o u n d i n g R e c t a n g l e A r e a Extent=\frac{Object \;Area}{Bounding \;Rectangle \;Area} Extent=BoundingRectangleAreaObjectArea
area = cv2.contourArea(cnts[0])
x, y, w, h = cv2.boundingRect(cnts[0])
rect_area = w * h
extent = float(area)/rect_area # 0.298
坚实度(Solidity)
坚实度是等高线面积与其凸包面积之比
S o l i d i t y = C o n t o u r A r e a C o n v e x H u l l A r e a Solidity=\frac{Contour\;Area}{Convex\;Hull\;Area} Solidity=ConvexHullAreaContourArea
# 坚实度
area = cv2.contourArea(cnts[0])
hull = cv2.convexHull(cnts[0])
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area # 0.82
等效直径(Equivalent Diameter)
等效直径是面积与轮廓面积相同的圆的直径
E q u i v a l e n t D i a m e t e r = 4 × C o n t o u r A r e a π Equivalent \; Diameter=\sqrt\frac{4 \times Contour \;Area}{\pi} EquivalentDiameter=π4×ContourArea
area = cv2.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi) # 97.3 area = pi*(d/2)^2
取向
取向是物体指向的角度。以下方法还给出了主轴和副轴的长度
(x,y),(MA,ma),angle = cv2.fitEllipse(cnts[0])
# 167.77357482910156, 166.88461303710938, 60.207035064697266, 210.24307250976562, 136.4932098388672
掩码和像素点
在某些情况下,可能需要构成该对象的所有点。可以按照以下步骤完成:
mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[cnts[0]], 0, 255, -1)
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv2.findNonZero(mask)
'''
array([[108, 158],
[108, 159],
[108, 160],
...,
[258, 255],
[258, 256],
[258, 257]], dtype=int64), lenth=7664
'''
这里提供了两个方法,
- 使用Numpy函数
- 使用OpenCV函数(最后的注释行)。
结果也是一样的,只是略有不同。Numpy给出的坐标是(行、列)格式,而OpenCV给出的坐标是(x,y)格式。所以基本上答案是可以互换的。注意,row = x, column = y
最大值,最小值及其位置
可以使用掩码图像找到这些参数
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(img, mask=mask)
# (128.0, 255.0, (138, 116), (158, 108))
平均颜色或平均强度
使用掩码可以找到对象的平均颜色,或者可以是灰度模式下物体的平均强度
mean_val = cv2.mean(img, mask = mask)
# (251.65057411273483, 0.0, 0.0, 0.0), 各个通道的均值
极端点
极点是指对象的最顶部,最底部,最右侧和最左侧的点
leftmost = tuple(cnts[0][cnts[0][:,:,0].argmin()][0])
rightmost = tuple(cnts[0][cnts[0][:,:,0].argmax()][0])
topmost = tuple(cnts[0][cnts[0][:,:,1].argmin()][0])
bottommost = tuple(cnts[0][cnts[0][:,:,1].argmax()][0])
# ((94, 137), (258, 257), (158, 108), (254, 258))
cv2.circle(img, leftmost, 5, (255,0,0))
cv2.circle(img, rightmost, 5, (255,0,0))
cv2.circle(img, topmost, 5, (255,0,0))
cv2.circle(img, bottommost, 5, (255,0, 0))
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
可以看到最右点与最下点比较重合