之前我们讨论了轮廓的各种特征,OpenCV中关于图像的轮廓特征还是非常之多的。今天将讨论轮廓的一些简单的属性。

长宽比

它是对象边界矩形的宽度与高度的比,我们在之前的教程中已经介绍了获取图像轮廓的x,y,w,h,它们由函数:

x,y,w,h = cv.boundingRect(cnt)

得到,当然,我们在这里谈论的是图像的边界矩形,并非是最小边界矩形。

现在来计算长宽比,公式:

python cv2 mat使用 python cv2 rectangle_python cv2 mat使用

代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
x,y,w,h = cv2.boundingRect(cnt)  
cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)  
aspect_ratio = float(w)/h  
print(aspect_ratio)  
cv2.imshow('res', img)  
cv2.waitKey()

python cv2 mat使用 python cv2 rectangle_图像识别_02


python cv2 mat使用 python cv2 rectangle_opencv_03

大小比

它是轮廓区域与边界矩形区域的比,公式:

python cv2 mat使用 python cv2 rectangle_边缘检测_04

代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
area = cv2.contourArea(cnt)  
x,y,w,h = cv2.boundingRect(cnt)  
rect_area = w*h  
extent = float(area)/rect_area  
print(extent)  
cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),2)  
cv2.imshow('res', img)  
cv2.waitKey()

仍然是上面那个图像,我们来看输出结果:

python cv2 mat使用 python cv2 rectangle_图像识别_05

密实比

密实比是轮廓区域与其凸包区域的比,凸包区域我们在前面已经讲过:

python cv2 mat使用 python cv2 rectangle_边缘检测_06

代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
area = cv2.contourArea(cnt)  
hull = cv2.convexHull(cnt)  
hull_area = cv2.contourArea(hull)  
solidity = float(area)/hull_area  
print(solidity)  
lengh = len(hull)  
for i in range(len(hull)):  
    cv2.line(img,tuple(hull[i][0]),tuple(hull[(i+1)%lengh][0]),  
             (0,0,255),2)  
  
cv2.imshow('res', img)  
cv2.waitKey()

python cv2 mat使用 python cv2 rectangle_图像识别_07


python cv2 mat使用 python cv2 rectangle_计算机视觉_08

等效直径

等效直径是圆的直径,其面积与轮廓面积相同:

python cv2 mat使用 python cv2 rectangle_计算机视觉_09


代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
area = cv2.contourArea(cnt)  
equi_diameter = np.sqrt(4*area/np.pi)  
print(equi_diameter)  
cv2.waitKey()

python cv2 mat使用 python cv2 rectangle_python cv2 mat使用_10

方向

其实际上就是指物体指向的角度,我们在之前的椭圆拟合里就讲过,它会返回三个参数:主轴和短轴长度以及角度,我们来看代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
(x,y),(MA,ma),angle = cv2.fitEllipse(cnt)  
print(angle)  
cv2.waitKey(0)

python cv2 mat使用 python cv2 rectangle_计算机视觉_11

掩模和像素点

在某些情况下,我们可能需要包含该对象的所有点,本质相当于用另一层图层覆盖当前的轮廓,代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
mask = np.zeros(img.shape,np.uint8)  
cv2.drawContours(mask,[cnt],0,255,-1)  
pixelpoints = np.transpose(np.nonzero(mask))  
print(pixelpoints)  
cv2.imshow("img",img)  
cv2.imshow("res",mask)  
cv2.waitKey(0)

python cv2 mat使用 python cv2 rectangle_边缘检测_12


python cv2 mat使用 python cv2 rectangle_python cv2 mat使用_13


python cv2 mat使用 python cv2 rectangle_边缘检测_14

可以看到,轮廓内的图形都被蓝色的图层覆盖了,这在以后的综合项目中将非常有用,可以消除不必要的噪声。

最大值,最小值及其位置

我们可以使用以下函数找到图像矩阵的最大值、最小值以及它们相应的索引位置:

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(gray)

gray指代图像的灰度图像,我们直接来看代码:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
mask = np.zeros(img.shape,np.uint8)  
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(gray)  
print(min_val, max_val, min_loc, max_loc)  
cv2.imshow("img",img)  
cv2.imshow("res",mask)  
cv2.waitKey(0)

python cv2 mat使用 python cv2 rectangle_python cv2 mat使用_15

事实上,该方法被广泛的应用在OpenCV的模板匹配中,这个我们将在后面详述。

极点

极值点表示对象的最顶部,最底部,最右侧和最左侧的点。,我们同样可以通过代码实现:

view plaincopy to clipboardprint?
import cv2  
import numpy as np  
  
# 读取图片并转至灰度模式  
img = cv2.imread("tubao.png", 1)  
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  
  
# 二值化,取阈值为235  
ret, thresh = cv2.threshold(gray, 235, 255, cv2.THRESH_BINARY)  
  
# 寻找图像中的轮廓  
contours, hierarchy = cv2.findContours(thresh, 2, 1)  
  
cnt = contours[0]  
leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])  
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])  
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])  
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])  
cv2.circle(img,leftmost,2,(0,0,255),5)  
cv2.circle(img,rightmost,2,(0,255,255),5)  
cv2.circle(img,topmost,2,(255,0,255),5)  
cv2.circle(img,bottommost,2,(255,0,122),5)  
cv2.imshow("img",img)  
cv2.waitKey(0)

python cv2 mat使用 python cv2 rectangle_opencv_16