基于OpenCV Python的凸包坐标实现字符分割(含垂直重叠场景)
基于凸包坐标的重叠字符分割实现方案
当前已完成的前置工作
你已经搞定了最关键的准备步骤:
- 拿到了包含重叠字符的原始图像
- 通过OpenCV提取了字符轮廓并计算出每个字符的凸包,还画出了红色的凸包轮廓
- 已经获取到单个字符的凸包坐标数据
先贴一下你用到的轮廓与凸包提取代码(方便其他开发者参考):
import cv2 img = cv2.imread('test.png', -1) ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY) image, contours, hier = cv2.findContours(threshed_img, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) for cnt in contours: # 计算字符的凸包 hull = cv2.convexHull(cnt) # 绘制凸包轮廓(红色,线宽1) cv2.drawContours(img, [hull], -1, (0, 0, 255), 1) print(hull) cv2.imwrite("contours.jpg", img)
对应的图像效果:
- 原始字符图像:

- 绘制凸包后的图像:

已经获取到的单个字符凸包坐标示例:
[[[546 134]] [[534 149]] [[532 151]] [[527 153]] [[523 154]] [[522 154]] [[520 109]] [[521 107]] [[524 106]] [[533 106]] [[539 111]] [[543 117]] [[546 122]]]
核心需求与选择凸包的原因
咱们的目标是把每个字符单独分割出来,效果示例如下:

...
为什么必须用凸包坐标?因为很多字符图像存在垂直空间重叠的情况,比如这样:
常规的基于行/列的分割方法根本无法精准拆分这类重叠字符,而凸包能准确包裹每个字符的完整边界,刚好解决这个痛点。
基于凸包坐标的分割实现思路
利用每个凸包的边界坐标裁剪原始图像即可,步骤很清晰:
- 对每个字符的凸包坐标,用
cv2.boundingRect(hull)快速计算出包围该凸包的最小外接矩形(得到x,y,w,h四个参数) - 用这个矩形坐标从原始图像(或二值化图像)中裁剪出对应区域
- 将裁剪后的区域保存为单独的字符图像
具体代码片段可以这样写:
# 假设已经有原始图像img,以及存储所有凸包的hulls列表 for idx, hull in enumerate(hulls): # 获取凸包的外接矩形 x, y, w, h = cv2.boundingRect(hull) # 裁剪字符区域 char_img = img[y:y+h, x:x+w] # 保存单个字符图像 cv2.imwrite(f"char_{idx}.png", char_img)
这样就能完美分割出每个字符,包括垂直重叠的情况!
内容的提问来源于stack exchange,提问作者Ishara Dayarathna
相关产品推荐
相关产品推荐

