如何从视频会议画面中分割并裁剪任意数量的矩形视频流区块
你现有方案的核心缺陷是使用了固定尺寸的形态学核,无法适配不同路数下的画面分割线尺寸,同时缺少分割线的后处理逻辑,导致无法自适应不同数量的视频流场景。
优化思路
- 自适应形态学核尺寸:将固定的
(200,1)、(1,200)核替换为随输入图像尺寸动态计算的数值,比如水平核宽度取图像宽度的80%,垂直核高度取图像高度的80%,确保可以适配不同分辨率、不同路数的拼接画面。 - 分割线去重排序:提取到所有水平分割线的y轴坐标、垂直分割线的x轴坐标后,先做重合过滤(坐标差小于5像素的线合并为一条),再分别按升序排序,得到的有序坐标点就是画面的切分边界。
- 直接按坐标批量裁剪:不需要调用
findContours查找瓦片轮廓,排序后的分割线已经天然将画面划分为(m+1)*(n+1)个规整区块(m为水平分割线数量,n为垂直分割线数量),直接按坐标范围裁剪即可,稳定性更高。 - 增加有效性校验:裁剪完成后对所有区块的宽高做一致性校验,若存在宽高与平均尺寸偏差超过10%的区块,可自动微调核尺寸或二值化阈值重新检测,提升适配性。
优化后代码示例
import cv2 import numpy as np # 加载图像 image = cv2.imread(r'你的图片路径') result = image.copy() h, w = image.shape[:2] gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # 自适应核尺寸检测水平分割线 horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (int(w*0.8), 1)) detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] # 提取水平分割线y坐标,去重排序 y_coords = [] for c in cnts: y = int(np.mean(c[:, :, 1])) y_coords.append(y) y_coords = sorted(list(set([round(y/5)*5 for y in y_coords]))) # 补充上下边界 y_coords = [0] + y_coords + [h] # 自适应核尺寸检测垂直分割线 vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, int(h*0.8))) detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2) cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] # 提取垂直分割线x坐标,去重排序 x_coords = [] for c in cnts: x = int(np.mean(c[:, :, 0])) x_coords.append(x) x_coords = sorted(list(set([round(x/5)*5 for x in x_coords]))) # 补充左右边界 x_coords = [0] + x_coords + [w] # 批量裁剪保存 stream_idx = 0 for i in range(len(y_coords)-1): y1, y2 = y_coords[i], y_coords[i+1] for j in range(len(x_coords)-1): x1, x2 = x_coords[j], x_coords[j+1] # 过滤过小的异常区块 if (x2 - x1) < w*0.1 or (y2 - y1) < h*0.1: continue stream_img = image[y1:y2, x1:x2] cv2.imwrite(f'stream_{stream_idx}.jpg', stream_img) stream_idx += 1 # 绘制分割线用于校验 cv2.rectangle(result, (x1, y1), (x2, y2), (36,255,12), 2) cv2.imwrite('result.jpg', result)
内容的提问来源于stack exchange,提问作者Nipon Chanda
相关产品推荐
相关产品推荐

