图像形状特征提取

  • 简单形状特征
  • 矩形度
  • 球状性
  • 圆形性
  • 质心坐标 cv.moments()
  • 中心距
  • Opencv中图像轮廓拟合
  • 轮廓的查找与绘制
  • OpenCV中轮廓的周长与面积
  • 几何图形的最小外包与拟合
  • 最小外包矩形 cv.minAreaRect()
  • 最小外包圆形 cv. minEnclosingCircle () cv.circle()
  • 最小外包三角形 cv.minEnclosingTriangle() cv.line()
  • 最小外包椭圆 cv. fitEllipse() cv.ellipse()
  • 最优拟合直线 cv. fitLine()


简单形状特征

矩形度

矩形度体现物体对其外接矩形的充满程度,反映一个物体与矩形相似程度的一个参数。用物体的面积与其最小外接矩形的面积之比描述,即:

图像识别箭头朝向_OpenCV


AO是该物体的面积,而AMER是其外接矩形的面积。当物体为矩形时,R取得最大值1.0;圆形物体的R取值为π/4;细长的、弯曲的物体的R的取值变小。

与矩形度相关的辅助特征为长宽比:

图像识别箭头朝向_OpenCV_02


其中W表示物体外接矩形的宽度,L表示外接矩形的长度。利用长宽比可以将细长的物体与圆形或方形的物体区分开。

球状性

球状性(Sphericity)既可以描述二维目标,也可以描述三维目标,其定义为:

图像识别箭头朝向_外包_03


图像识别箭头朝向_OpenCV_04


描述二维目标时,ri表示目标区域内切圆的半径,rc表示目标区域外接圆的半径,两个圆的圆心都在区域的重心上。

可知S的取值范围为0<S≤1。当目标区域为圆形时,目标的球状性值S达到最大值1,当目标区域为其他形状时,S<1。显然,S不受区域平移、旋转和尺度变化的影响。

圆形性

目标圆形性(Doularity)是指用目标区域R的所有边界点定义的特征量,其定义式为:

图像识别箭头朝向_图像识别箭头朝向_05


设(xi,yi)为图像边界点坐标,([插图])为图像的重心坐标,其中μR是从区域重心到边界点([插图])的平均距离,定义为:


图像识别箭头朝向_图像识别箭头朝向_06


而σR是从区域重心到边界点的距离均方差,定义为:


图像识别箭头朝向_外包_07


针对灰度图像,区域重心可以定义为:


图像识别箭头朝向_图像识别箭头朝向_08

质心坐标 cv.moments()

由于图像区域的某些矩对于平移、旋转、尺度等几何变换具有一些不变的特性,使得矩的表示方法在物体的分类与识别方面具有重要的意义。对于二元有界函数f(x,y),它的(j+k)阶矩为:

图像识别箭头朝向_图像识别箭头朝向_09


二值图像中一个物体的质心坐标为:


图像识别箭头朝向_拟合_10

下面代码的图例后面可以看到。

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
plt.imshow(binary,'gray')
plt.show()
row,col = img.shape[:2]
contours,hierarchy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
dic = cv.moments(contours[0])
print('正方形的矩的质心为:{}'.format((dic['m10']/dic['m00'],dic['m01']/dic['m00'])))

该矩的质心为:(627.5, 264.5)

中心距

为了获得矩的不变特征,往往采用中心矩以及归一化的中心距。中心距的定义为:

图像识别箭头朝向_拟合_11


中心矩以质心作为原点进行计算,因此它具有位置无关性。

Opencv中图像轮廓拟合

轮廓的查找与绘制

在OpenCV中提供了cv2.findContours()和cv2.drawContours()函数来实现对图像轮廓的查找与绘制。

  • 方法说明
  1. cv2.findContours()

img,contours,hierarchy = cv.fingContours(image,mode,method)
参数说明:
1、image表示8位单通道二值图像。
2、mode表示轮廓检索模式
3、method表示轮廓的近似方法
返回值说明:
1、image表示8位单通道原始图像
2、contours表示返回的轮廓
3、hierarchy表示轮廓的层次信息

  1. cv2.drawContours()

image = cv2.drawContours(image,contours,contourIdx,color,[,thickness ,lineType,hierarchy,maxLevel,offset])
参数说明:
1、image表示待绘制轮廓的图像
2、 contours表示需要绘制的轮廓。
3、contourIdx表示需要绘制的边缘索引,一般填-1
4、color表示绘制的轮廓颜色
5、thickness表示绘制轮廓的粗细
6、lineType表示绘制轮廓所选用的线型
7、hierarchy对应cv2.findContours()函数中同样参数的信息
8、maxLevel控制所绘制轮廓层次的深度
9、offset表示轮廓的偏移程度

  • 绘制一幅图像内的轮廓
filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
plt.imshow(binary,'gray')
plt.show()
contours,hierarchy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
print(len(contours))   # 2
img1 = cv.drawContours(img,contours,-1,(0,255,0),3)
plt.imshow(img1)
plt.show()

图像识别箭头朝向_外包_12


图像识别箭头朝向_外包_13

  • 利用查找绘制轮廓的方法提取出一幅图像的前景信息
filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
mask = np.zeros(img.shape,np.uint8)  #制作掩膜
img1 = cv.drawContours(mask,contours,-1,(255,255,255),-1)
log_img = cv.bitwise_and(img,mask)  #取前景

OpenCV中轮廓的周长与面积

在OpenCV中,当查找并绘制出图像的轮廓后,可以通过cv2.arcLength()函数和cv2. contourArea()函数计算轮廓的周长与面积。

  • 周长 cv2.arcLength()

ret = cv2.arcLength(contour,booled)
参数说明:
1、ret表示返回的轮廓周长
2、contour表示输入的轮廓
3、 booled表示轮廓的封闭性

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    print("第%d个轮廓的周长为:%f"%(i+1,cv.arcLength(contours[i],True)))

第1个轮廓的周长为:944.000000
第2个轮廓的周长为:1079.016364

  • 面积计算 cv.contourArea()

ret = cv.contourArea(contour[,booled])

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
plt.imshow(binary,'gray')
plt.show()
contours,hierarchy = cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    print("第%d个轮廓的面积为:%f"%(i+1,abs(cv.contourArea(contours[i],True))))

第1个轮廓的面积为:55671.000000
第2个轮廓的面积为:23783.500000

几何图形的最小外包与拟合

最小外包矩形 cv.minAreaRect()

在OpenCV中提供了cv2.minAreaRect()函数用来绘制轮廓的最小外包矩形框,其一般格式为:
ret = cv2.minAreaRect(contours)
ret表示返回的矩形特征信息

  • 注意

返回值ret的结构不符合cv2.drawContours()函数的参数结构要求。因此,必须使用cv2.boxPoints()函数将上述返回值ret转换为符合要求的结构。
point = cv.boxPoints(box)
1、box表示cv2.minAreaRect()函数返回值类型的值。
2、points表示返回的符合结构的矩形特征信息。

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
rect = cv.minAreaRect(contours[1])
points = cv.boxPoints(rect)
points = np.int0(points)  #取整
img1 = cv.drawContours(img,[points],0,(0,0,255),2)
plt.imshow(img1)
plt.show()

图像识别箭头朝向_OpenCV_14

最小外包圆形 cv. minEnclosingCircle () cv.circle()

在OpenCV中提供了cv2. minEnclosingCircle ()函数来绘制轮廓的最小外包圆形,其一般格式为:
center,radius = cv2. minEnclosingCircle(point)

在绘制圆形外包时会用到cv.circle()函数。

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
(x,y),r = cv.minEnclosingCircle(contours[0])
center = (int(x),int(y))
r = int(r)
img1 = cv.circle(img,center,r,(0,0,255),4)
plt.imshow(img1)
plt.show()

图像识别箭头朝向_外包_15

最小外包三角形 cv.minEnclosingTriangle() cv.line()

在OpenCV中提供了cv2.minEnclosingTriangle()函数来绘制轮廓的最小外包三角形,其一般格式为:
ret,triangle = cv2.minEnclosingTriangle(point)
1、ret表示最小外包三角形的面积。
2、triangle表示最小外包三角形的三个顶点集。 shape为(3, 1, 2)

在绘制三角形外包时会用到cv.line()函数。

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
area,trg = cv.minEnclosingTriangle(contours[0])
for i in range(0,3):
    cv.line(img,tuple(trg[i][0]),tuple(trg[(i+1)%3][0]),(0,0,255),4)
plt.imshow(img)
plt.show()

图像识别箭头朝向_图像识别箭头朝向_16

最小外包椭圆 cv. fitEllipse() cv.ellipse()

在OpenCV中提供了cv. fitEllipse()函数来绘制轮廓的最小外包椭圆,其一般格式为:
ret = cv. fitEllipse(points)
ret表示返回的椭圆特征信息,包括中心点、轴长度和旋转角等,元组类型,如:((224.43301391601562, 268.66680908203125),
(214.72067260742188, 235.9137420654297),
1.1991876363754272)

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
contours,hierarchy = cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
a = cv.fitEllipse(contours[1])
cv.ellipse(img,a,(0,0,255),4)
plt.imshow(img)
plt.show()

图像识别箭头朝向_OpenCV_17

最优拟合直线 cv. fitLine()

在OpenCV中提供了cv2. fitLine()函数来绘制轮廓的最优拟合直线,其一般格式为:
line = cv. fitLine(points,distType,param,reps,aeps)
参数说明:
1、line表示返回的最优拟合直线参数。 [a,b,c,d]
2、distType表示距离类型。
3、param表示距离参数,与所用距离类型相关。
4、reps表示最优拟合直线的径向精度,一般为0.01。
5、aeps表示最优拟合直线的角度精度,一般为0.01。

filename = 'rang.jpg'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)

row,col = img.shape[:2]
contours,hierarchy = cv.findContours(binary,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
[vx,vy,x,y] = cv.fitLine(contours[1],cv.DIST_L2,0,0.01,0.01)
#计算直线绘制参数
ly = int((-x*vy/vx)+y)
ry = int(((col-x)*vy/vx)+y)
cv.line(img,(col-1,ry),(0,ly),(0,0,255),4)
plt.imshow(img)
plt.show()

图像识别箭头朝向_外包_18