如何不基于重叠或阈值将cv2矩形边界框合并为多边形?
方案1:生成最小轴对齐外接矩形(最简单)
如果你只需要一个包围所有框的矩形,直接计算所有边界框的坐标极值即可,代码如下:
import numpy as np import cv2 bbox_list = [[195, 3455, 633, 4213], [658, 3427, 1094, 4222], [1120, 3435, 1553, 4473], [295, 3421, 531, 3451], [201, 3313, 1548, 3409]] # 提取所有边界框的极值 x_coords = [] y_coords = [] for bbox in bbox_list: x1, y1, x2, y2 = bbox x_coords.extend([x1, x2]) y_coords.extend([y1, y2]) x_min, x_max = min(x_coords), max(x_coords) y_min, y_max = min(y_coords), max(y_coords) # 绘制外接矩形 image = cv2.imread('63976500-anderson-herald-bulletin-Jun-18-1968-p-64.jpg') cv2.rectangle(image, (x_min, y_min), (x_max, y_max), (0,255,0), 10) cv2.imwrite("axis_aligned_bbox.jpg", image)
方案2:生成贴合的凹多边形边界(匹配示例效果)
如果你需要像示例一样贴合所有框边缘的多边形,用OpenCV的轮廓查找+多边形近似接口即可,步骤如下:
- 先把所有已知边界框画在一张和原图尺寸一致的空白掩膜上
- 提取掩膜的外轮廓
- 对轮廓做近似得到精简的多边形顶点
代码示例:
import numpy as np import cv2 # 边界框列表 bbox_list = [[195, 3455, 633, 4213], [658, 3427, 1094, 4222], [1120, 3435, 1553, 4473], [295, 3421, 531, 3451], [201, 3313, 1548, 3409]] # 原图尺寸,可替换为实际图像的height、width h, w = 5000, 6000 # 生成空白掩膜 mask = np.zeros((h, w), dtype=np.uint8) # 把所有边界框填充到掩膜上 for bbox in bbox_list: x1, y1, x2, y2 = bbox cv2.rectangle(mask, (x1, y1), (x2, y2), 255, -1) # 提取外轮廓 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 若边界框分散导致多个轮廓,先合并所有轮廓点 all_points = [] for cnt in contours: all_points.extend(cnt.tolist()) all_points = np.array(all_points, dtype=np.int32) # 对轮廓做近似,epsilon参数控制近似精度,这里取轮廓周长的0.1%可根据需求调整 epsilon = 0.001 * cv2.arcLength(all_points, True) approx_poly = cv2.approxPolyDP(all_points, epsilon, True) # 绘制最终的多边形边界 image = cv2.imread('63976500-anderson-herald-bulletin-Jun-18-1968-p-64.jpg') cv2.polylines(image, [approx_poly], True, (0,255,0), 10) cv2.imwrite("merged_polygon.jpg", image)
方案说明
- 方案1实现最简单,性能最高,适合只需要整体定位不需要精确贴合边缘的场景
- 方案2可以完全匹配示例效果,不管边界框是否分散、是否重叠都能正常生成贴合的多边形边界,完全满足需求
内容的提问来源于stack exchange,提问作者emilys
相关产品推荐
相关产品推荐

