OpenCV 例程200篇 总目录-202206更新
【youcans 的 OpenCV 例程200篇】199.轮廓的外接边界框
文章目录
- 【youcans 的 OpenCV 例程200篇】199.轮廓的外接边界框
- 2. 轮廓的特征描述
- 2.3 轮廓的外接边界框
- 2.3.1 轮廓的垂直矩形边界框
- 2.3.2 轮廓的最小矩形边界框
- 2.3.3 轮廓的最小外接圆
- 2.3.4 轮廓的最小外接三角形
- 2.3.5 轮廓的最小拟合椭圆
- 2.3.6 轮廓的拟合直线
- 2.3.7 形状相似度检测
- 例程 12.5:轮廓的外接边界框
2. 轮廓的特征描述
在对实际图像进行轮廓查找时,得到的轮廓数量很多。获取轮廓后,通常基于轮廓的特征进行筛选、识别和处理。例如,基于轮廓的周长和面积对轮廓进行筛选,然后绘制筛选的目标轮廓或其最小外接矩形。
常用的轮廓特征,包括图像距、轮廓周长、轮廓近似、凸包、边界矩形、拟合图形等特征。
2.3 轮廓的外接边界框
通过轮廓的外接矩形、外接圆或椭圆,计算几何形状的横纵比、面积、周长,可以实现特定几何形状轮廓的查找与过滤, 为后续的处理与分析筛选目标。
2.3.1 轮廓的垂直矩形边界框
垂直矩形边界框是指平行于图像侧边的矩形框。用于不考虑旋转,垂直边界框不是轮廓的最小矩形边界框。
函数 cv2. boundingRect() 可以获得轮廓的垂直矩形边界框。
函数说明:
cv.boundingRect(array) → retval
参数说明:
- array:灰度图像,或顶点构成的二维向量组(如轮廓列表 contours 中的一个轮廓)
- retval:返回值结构 (x, y, w, h),矩形左上顶点坐标 x, y,矩形的宽度 w,高度 h
2.3.2 轮廓的最小矩形边界框
轮廓的最小矩形边界框是面积最小的轮廓外接矩形框,最小矩形边界框通常与图像侧边有旋转角。
函数 cv2. minAreaRect () 可以获得轮廓的最小矩形边界框,函数 cv2.boxPoints() 计算旋转矩形的顶点。
函数说明:
cv.minAreaRect(points) → retval
cv.boxPoints(box[, points]) → points
参数说明:
- points:二维点向量集 (x,y)
- retval = [(x,y), (w,h), ang]: Box2D 结构,矩形中心点坐标 (x,y),矩形宽高 (w,h),旋转角度 ang
- box: Box2D 结构,旋转矩形(如函数 cv.minAreaRect() 的输出)
注意事项:
水平轴逆时针旋转,直到矩形的第一条边,该边与水平轴的夹角为旋转角度 ang,这条边的边长为 width。
当数据接近包含的元素边界时,返回的 RotatedRect 可以包含负索引。
2.3.3 轮廓的最小外接圆
轮廓的最小外接圆是面积最小的轮廓外接圆。
函数 cv2. minAreaRect() 可以获得轮廓的最小外接圆。
函数说明:
cv.minEnclosingCircle(points) → center, radius
参数说明:
- points:二维点向量集
- center:外接圆的圆心坐标 (Cx, Cy),浮点数
- radius:外接圆的半径,浮点数
2.3.4 轮廓的最小外接三角形
轮廓的最小外接三角形是面积最小的轮廓外接三角形。
函数 cv2. minEnclosingTriangle () 可以获得轮廓的最小外接圆。
函数说明:
cv.minEnclosingTriangle(points[, triangle]) → retval, triangle
参数说明:
- points:二维点向量集,数据类型为 CV_32S 或 CV_32F
- retval:三角形的面积,浮点数
- triangle:三角形的顶点坐标,形状 (3,1,2),数据类型为 CV_32F
2.3.5 轮廓的最小拟合椭圆
函数 cv2. fitEllipse() 根据一组二维点向量拟合椭圆。
函数说明:
cv.fitEllipse(points) → retval
参数说明:
- points:二维点向量集
- retval = [(x,y), (a,b), ang],椭圆中心点坐标 (x,y),椭圆短轴、长轴长度 (a,b),旋转角度 ang
旋转角度 ang 表示短轴 a 与水平轴的夹角,顺时针为正。
2.3.6 轮廓的拟合直线
函数 cv2. fitLine() 用一条直线拟合到一组二维点向量。
函数说明:
cv.fitLine(points, distType, param, reps, aeps[, line] ) → line
参数说明:
- points:二维或三维点向量集
- line:拟合直线,(vx, vy, x0, y0),(vx,vy) 是与直线共线的归一化向量,(x0,y0) 是直线上的点
- distType:距离类型, cv.DIST_L1、cv.DIST_L2、cv.DIST_C、cv.DIST_L12
- param:某些类型距离的参数(C),0 表示选择最佳值
- reps:距离精度,原点与直线的间距
- aeps:角度精度,推荐值 0.01
2.3.7 形状相似度检测
函数 cv2.matchShapes() 基于 Hu 不变矩检测两个形状之间的相似度,返回值越小表明形状越相似。
函数说明:
cv.matchShapes(contour1, contour2, method, parameter) → retval
参数说明:
- contour1:第 1 个轮廓,或灰度图像
- contour2:第 2 个轮廓,或灰度图像
- method:比较方法,可选项:cv.CONTOURS_MATCH_I1、cv.CONTOURS_MATCH_I2、cv.CONTOURS_MATCH_I3
例程 12.5:轮廓的外接边界框
# 12.5 轮廓的外接边界框img = cv2.imread("../images/seagull01.png", flags=1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图像plt.figure(figsize=(9, 6))plt.subplot(231), plt.axis('off'), plt.title("Origin")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))# HSV 色彩空间图像分割hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 将图片转换到 HSV 色彩空间lowerBlue, upperBlue = np.array([100, 43, 46]), np.array([124, 255, 255]) # 蓝色阈值segment = cv2.inRange(hsv, lowerBlue, upperBlue) # 背景色彩图像分割kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) # (5, 5) 结构元binary = cv2.dilate(cv2.bitwise_not(segment), kernel=kernel, iterations=3) # 图像膨胀# 寻找二值化图中的轮廓# binary, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # OpenCV3contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # OpenCV4~# # 绘制全部轮廓,contourIdx=-1 绘制全部轮廓for i in range(len(contours)): # 绘制第 i 个轮廓if hierarchy[0][i][3]==-1: # 最外层轮廓rect = cv2.minAreaRect(contours[i]) # 最小外接矩形x, y = int(rect[0][0]), int(rect[0][1]) # 最小外接矩形的中心(x,y)text = "{}:({},{})".format(i, x, y)img = cv2.drawContours(img, contours, i, (255, 255, 255), -1) # 绘制第 i 个轮廓, 内部填充img = cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255))cnt = contours[1]moments = cv2.moments(cnt) # 返回字典,几何矩 mpq, 中心矩 mupq 和归一化矩 nupqcx = round(moments['m10'] / moments['m00'])cy = round(moments['m01'] / moments['m00'])cv2.circle(img, (cx, cy), 5, (0, 0, 255), -1) # 在轮廓的质心上绘制圆点print("Centroid of contour: ({}, {})".format(cx, cy))# 轮廓的垂直矩形边界框# boundingBoxes = [cv2.boundingRect(cnt) for cnt in contours] # 所有轮廓的外接垂直矩形x, y, w1, h1 = cv2.boundingRect(cnt) # 矩形左上顶点的坐标 x, y, 矩形宽度 w, 高度 hprint("Vertical rectangle: (x,y)={}, (w,h)={}".format((x, y), (w1, h1)))img1 = img.copy()cv2.rectangle(img1, (x, y), (x+w1, y+h1), (0, 0, 255), 2) # 绘制垂直矩形边界框# 轮廓的最小矩形边界框rect = cv2.minAreaRect(cnt) # 中心点 (x,y), 矩形宽度高度 (w,h), 旋转角度 ang(x, y), (w2, h2), ang = np.int32(rect[0]), np.int32(rect[1]), round(rect[2], 1)box = np.int32(cv2.boxPoints(rect)) # 计算旋转矩形的顶点, (4, 2)cv2.drawContours(img1, [box], 0, (0, 0, 255), 2) # # 将旋转矩形视为一个轮廓进行绘制print("Minimum area rectangle: (Cx,Cy)={}, (w,h)={}, ang={})".format((x, y), (w2, h2), ang))plt.subplot(232), plt.axis('off'), plt.title("Rectangle bounding")plt.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))# 轮廓的最小外接圆(x, y), r = cv2.minEnclosingCircle(cnt) # 圆心 (x,y), 半径 rCx, Cy, radius = int(x), int(y), int(r)img2 = img.copy()cv2.circle(img2, (Cx, Cy), radius, (0, 255, 0), 2)print("Minimum circle: (Cx,Cy)=({},{}), r={}".format(Cx, Cy, radius))plt.subplot(233), plt.axis('off'), plt.title("Circumcircle ")plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))# 轮廓的最小外接三角形area, triangle = cv2.minEnclosingTriangle(cnt) # area 三角形面积, triangle 三角形顶点 (3,1,2)intTri = np.int32(triangle)img3 = img.copy()cv2.polylines(img3, [intTri], True, (255, 0, 0), 2)plt.subplot(234), plt.axis('off'), plt.title("Circumscribed triangle")plt.imshow(cv2.cvtColor(img3, cv2.COLOR_BGR2RGB))# 轮廓的拟合椭圆ellipse = cv2.fitEllipse(cnt) # 椭圆中心点 (x,y), 宽度高度 (w,h), 旋转角度 ang(x, y), (w3, h3), ang = np.int32(ellipse[0]), np.int32(ellipse[1]), round(ellipse[2], 1)print("Fitted ellipse: (Cx,Cy)={}, (w,h)={}, ang={})".format((x, y), (w3, h3), ang))img4 = img.copy()cv2.ellipse(img4, ellipse, (0, 255, 255), 2)plt.subplot(235), plt.axis('off'), plt.title("Fitted ellipse")plt.imshow(cv2.cvtColor(img4, cv2.COLOR_BGR2RGB))# # 拟合直线rows, cols = img.shape[:2][vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L1, 0, 0.01, 0.01)lefty = int((-x * vy/vx) + y)righty = int(((cols - x) * vy/vx) + y)img5 = img.copy()cv2.line(img5, (0,lefty), (cols-1,righty), (255, 0, 0), 2)plt.subplot(236), plt.axis('off'), plt.title("Fitted line")plt.imshow(cv2.cvtColor(img5, cv2.COLOR_BGR2RGB))print("area of contour[1]: ", cv2.contourArea(cnt)) # 轮廓的面积print("area of VerticalRectangle: ", w1*h1) # 轮廓垂直外接矩形的面积print("area of MinAreaRectangle: ", w2*h2) # 轮廓最小外接矩形的面积print("area of MinAreaTriangle: ", int(area)) # 轮廓最小外接三角形的面积plt.tight_layout()plt.show()
运行结果:
Centroid of contour: (227, 263)
Vertical rectangle: (x,y)=(168, 173), (w,h)=(132, 156)
Minimum area rectangle: (Cx,Cy)=(215, 267), (w,h)=(178, 106), ang=60.6)
Minimum circle: (Cx,Cy)=(246,250), r=89
Fitted ellipse: (Cx,Cy)=(225, 265), (w,h)=(101, 173), ang=155.4)
area of contour[1]: 9302.5
area of VerticalRectangle: 20592
area of MinAreaRectangle: 18868
area of MinAreaTriangle: 13913
(本节完)
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125024042)
Copyright 2022 youcans, XUPT
Crated:2022-5-28
欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中
欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中
更多内容,请见:
【OpenCV 例程200篇 总目录-202206更新】
194.寻找图像轮廓(cv.findContours)
195.绘制图像轮廓(cv.drawContours)
196.图像的矩和不变矩(cv.moments)
197.轮廓的基本特征
198.基于不变矩的形状相似性检测
199.轮廓的外接边界框
200.轮廓的基本属性