OpenCV-Python:如何合并垂直对齐的字符轮廓并生成整体凸包
解决僧伽罗语字符轮廓合并与整体凸包绘制问题
我明白你的困扰——僧伽罗语字符的核心部分和垂直修饰符会被识别成独立轮廓,导致最终的凸包分散开。要解决这个问题,我们需要先把垂直对齐的相关轮廓分组合并,再针对合并后的点集计算整体凸包,而不是单独处理每个轮廓。下面是具体的实现步骤和代码:
核心思路
- 先获取图像中所有轮廓(而非仅最外层),确保不会遗漏修饰符这类独立小轮廓
- 根据轮廓的水平位置(边界框的x轴范围)分组:僧伽罗语的修饰符与核心字符的左右范围通常重叠或接近,以此作为分组依据
- 合并同一组内的所有轮廓点,再对合并后的点集计算凸包
- 最后绘制合并后的整体凸包
完整代码实现
import cv2 import numpy as np # 1. 读取图像并预处理 img = cv2.imread('input.png', -1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 若你的图像是白底黑字,用THRESH_BINARY_INV更易提取轮廓;黑底白字则改用THRESH_BINARY ret, threshed_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) # 2. 获取所有轮廓(RETR_LIST模式获取所有层级的轮廓) contours, hier = cv2.findContours(threshed_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # 3. 计算每个轮廓的边界框与中心坐标,方便后续分组 contour_info = [] for cnt in contours: x, y, w, h = cv2.boundingRect(cnt) center_x = x + w / 2 contour_info.append({ 'contour': cnt, 'bbox': (x, y, w, h), 'center_x': center_x }) # 按x轴中心排序,让水平位置接近的轮廓排在一起 contour_info.sort(key=lambda x: x['center_x']) # 4. 对轮廓进行分组:将水平范围重叠/接近的轮廓归为一组 groups = [] current_group = [contour_info[0]] if contour_info else [] for info in contour_info[1:]: # 取当前组第一个轮廓的x轴范围 group_x_start = current_group[0]['bbox'][0] group_x_end = group_x_start + current_group[0]['bbox'][2] # 取当前轮廓的x轴范围 curr_x_start = info['bbox'][0] curr_x_end = curr_x_start + info['bbox'][2] # 检查两个轮廓的x范围是否重叠,或中心间距小于阈值(可根据字符大小调整) overlap = min(group_x_end, curr_x_end) - max(group_x_start, curr_x_start) if overlap > 0 or abs(info['center_x'] - current_group[0]['center_x']) < 20: current_group.append(info) else: groups.append(current_group) current_group = [info] # 加入最后一组轮廓 if current_group: groups.append(current_group) # 5. 合并每组轮廓并绘制凸包 for group in groups: # 合并组内所有轮廓的点集 merged_points = np.concatenate([info['contour'] for info in group]) # 计算合并点集的凸包 hull = cv2.convexHull(merged_points) # 绘制凸包(红色,线宽1) cv2.drawContours(img, [hull], -1, (0, 0, 255), 1) # 保存结果 cv2.imwrite("output.png", img)
关键细节说明
- 阈值化调整:代码中用
THRESH_BINARY_INV适配白底黑字的字符图像,如果你的原图是黑底白字,改回THRESH_BINARY即可 - 分组阈值:
abs(info['center_x'] - current_group[0]['center_x']) < 20这个数值可以根据字符大小灵活调整——若修饰符与核心字符间距较大,适当调大阈值 - 轮廓获取模式:使用
RETR_LIST替代RETR_EXTERNAL,确保能捕获到所有修饰符轮廓,哪怕是独立的小轮廓
这样处理后,垂直对齐的核心字符和修饰符会被合并为一个整体,计算出的凸包就是你想要的完整轮廓效果啦!
内容的提问来源于stack exchange,提问作者Ishara Dayarathna
相关产品推荐
相关产品推荐

