基于OpenCV实现无需OCR的图像单词区域外接矩形标注问题

需求是不运行OCR技术的前提下检测图中的每个单词,为每个单词绘制外接矩形,效果参考如下:
实现方案
问题分析
现有代码无法达到预期效果的核心原因是没有对文字区域做连通性合并:单个字母会被识别为独立轮廓,无法把同一单词的多个字母合并为同一个检测区域。同时HSV颜色阈值的适配性较差,容易引入不必要的噪点。
优化思路
- 先将图像转为灰度图后做自动二值化,更稳定地提取黑色文字区域
- 使用闭运算(先膨胀后腐蚀)将同一单词内字母的间隙填充,让整个单词变成一个连通区域
- 检测连通区域的外接矩形,过滤掉面积过小的噪点区域
优化后代码
import numpy as np import cv2 image = cv2.imread('Capture.JPG') original = image.copy() # 转灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 反色二值化让文字变成白色区域便于检测,用OTSU自动计算阈值适配不同场景 _, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 形态学核可根据实际文字大小调整,宽度适配单词字母间距,高度适配行高 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (12, 5)) # 闭运算合并同一单词的分散字母 closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=1) # 查找外部轮廓 cnts = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] total_area = 0 for c in cnts: area = cv2.contourArea(c) # 过滤面积过小的噪点,阈值可根据实际情况调整 if area < 20: continue total_area += area x, y, w, h = cv2.boundingRect(c) # 随机生成矩形颜色 color = list(np.random.randint(0, 256, size=3)) cv2.rectangle(original, (x, y), (x + w, y + h), color, 2) print(f"有效文字区域总面积:{total_area}") cv2.imshow('二值化结果', binary) cv2.imshow('闭运算合并结果', closed) cv2.imshow('检测结果', original) cv2.waitKey(0) cv2.destroyAllWindows()
参数调整说明
- 形态学核的
(12,5)参数:如果文字偏大、字母间距宽可以调大宽度值,文字偏小则调小 - 面积过滤阈值
20:如果存在小噪点被误检可以调大阈值,如果小文字被漏检可以调小阈值
内容的提问来源于stack exchange,提问作者Koushik
相关产品推荐
相关产品推荐

