OpenCV入门(二十)快速学会OpenCV 19 对象测量
作者:Xiou
1.对象测量
opencv 中对象测量包括:
如面积,周长,质心,边界框等。
弧长与面积测量;
多边形拟合;
获取轮廓的多边形拟合结果。
python-opencv提供的方法:
cv2.moments() 用来计算图像中的中心矩(最高到三阶),
cv2.HuMoments() 用于由中心矩计算Hu矩,同时配合函数cv2.contourArea()函数计算轮廓面积,和cv2.arcLength()来计算轮廓或曲线长度
cv.approxPolyDP(多边形逼近)
-contour
-epsilon 越小越折 线越逼近真实形状
-close 是否为闭合区域
函数cv2.boundingRect返回四个参数(x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高。 函数cv2.rectangle是绘制矩形函数
函数cv2.minAreaRect返回的是一个 Box2D 结构,
其中包含 :矩形左上角角点的坐标(x,y),矩形的宽和高(w,h),以及旋转角度。
但是要绘制这个矩形需要矩形的 4 个角点,可以通过函数 cv2.boxPoints() 获得,最后绘制得到旋转边界矩形。
函数cv2.minEnclosingCircle可以帮我们找到一个对象的外切圆。它是所有能够完全包括对象的圆中面积最小的一个。
函数cv2.fitEllipse返回值其实就是旋转边界矩形的内切圆。
几何矩计算
一幅M×N的数字图像ƒ(i,j),其p+q阶 几何矩mpq 和 中心矩 μpq为:
2.多边形拟合
步骤:
(1)读取图片;
(2)转换成灰度图;
(3)二值化;
(4)轮廓检测;
(5)计算轮廓周长;
(6)多边形拟合;
格式:
cv2.approxPolyDP(curve, epsilon, closed, approxCurve=None)
参数:
curve: 输入轮廓;
epsilon: 逼近曲率, 越小表示相似逼近越厉害;
closed: 是否闭合。
代码实例:
import cv2
from matplotlib import pyplot as plt
# 读取图片
image = cv2.imread("logo.png")
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv2.threshold(image_gray, 127, 255, cv2.THRESH_OTSU)
# 计算轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 轮廓近似
perimeter = cv2.arcLength(contours[0], True)
approx = cv2.approxPolyDP(contours[0], perimeter * 0.1, True)
# 绘制轮廓
result1 = cv2.drawContours(image.copy(), contours, 0, (0, 0, 255), 2)
result2 = cv2.drawContours(image.copy(), [approx], -1, (0, 0, 255), 2)
# 图片展示
f, ax = plt.subplots(1, 2, figsize=(12, 8))
# 子图
ax[0].imshow(cv2.cvtColor(result1, cv2.COLOR_BGR2RGB))
ax[1].imshow(cv2.cvtColor(result2, cv2.COLOR_BGR2RGB))
# 标题
ax[0].set_title("contour")
ax[1].set_title("approx")
plt.show()
输出结果:
3.计算对象中心
cv2.moments()可以帮助我们得到轮距, 从而进一步计算图片对象的中心。
cv2.moments(array, binaryImage=None)
参数:
array: 轮廓;
binaryImage: 是否把 array 内的非零值都处理为 1, 默认为 None。
代码实例:
import numpy as np
import cv2
# 读取图片
image = cv2.imread("logo.png")
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv2.threshold(image_gray, 0, 255, cv2.THRESH_OTSU)
# 获取轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历每个轮廓
for i, contour in enumerate(contours):
# 面积
area = cv2.contourArea(contour)
# 外接矩形
x, y, w, h = cv2.boundingRect(contour)
# 获取论距
mm = cv2.moments(contour)
print(mm, type(mm)) # 调试输出 (字典类型)
# 获取中心
cx = mm["m10"] / mm["m00"]
cy = mm["m01"] / mm["m00"]
# 获取
cv2.circle(image, (np.int(cx), np.int(cy)), 3, (0, 255, 255), -1)
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
# 图片展示
cv2.imshow("result", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存图片
cv2.imwrite("result1.jpg", image)
输出结果: