技术求助:使用OpenCV自动为指定6个字母绘制不同颜色矩形框
仅用OpenCV实现指定小写字母的自动标注方案
完全可以仅用OpenCV实现这个需求,不需要依赖第三方OCR库。核心思路是利用形态学预处理+轮廓提取+Hu矩形状匹配来识别目标字符,以下是具体实现方案和代码:
核心实现步骤
1. 图片预处理
- 灰度化:将彩色图片转为灰度图,减少计算维度
- 自适应二值化:通过高斯自适应阈值实现文本与背景的分离,适配不同光照条件的图片
- 形态学降噪:用开操作(先腐蚀后膨胀)去除小噪点,同时保留字符的完整形状
2. 字符轮廓提取
使用cv2.findContours提取图片中的字符轮廓,通过面积过滤掉非字符的小区域,获取每个字符的外接矩形。
3. 模板匹配(基于Hu矩)
针对a、b、c、d、e、f每个字母,准备对应风格的模板图片(可从待处理图中抠取),提取模板的Hu矩——这是一种形状不变特征,不受缩放、旋转、平移影响。将检测到的字符轮廓Hu矩与模板对比,通过相似度阈值判断是否匹配。
4. 彩色标注
为每个字母分配独特颜色,匹配成功后用cv2.rectangle在原图上绘制对应颜色的矩形框。
完整代码示例
import cv2 import numpy as np # 为每个目标字母定义专属标注颜色 COLORS = { 'a': (0, 255, 0), # 绿色 'b': (255, 0, 0), # 蓝色 'c': (0, 0, 255), # 红色 'd': (255, 255, 0), # 青色 'e': (255, 0, 255), # 品红 'f': (0, 255, 255) # 黄色 } def preprocess_image(img_path): # 读取原图 img = cv2.imread(img_path) # 灰度转换 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化(突出文本) thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 形态学开操作降噪 kernel = np.ones((2,2), np.uint8) thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) return img, thresh def get_template_hu_moments(template_paths): # 加载模板并提取Hu矩 template_hu = {} for char, path in template_paths.items(): template = cv2.imread(path, 0) _, template_thresh = cv2.threshold(template, 127, 255, cv2.THRESH_BINARY_INV) # 提取模板字符的轮廓 contours, _ = cv2.findContours(template_thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: cnt = max(contours, key=cv2.contourArea) # 计算Hu矩并做对数转换,提升匹配稳定性 moments = cv2.moments(cnt) hu_moments = cv2.HuMoments(moments) template_hu[char] = -np.sign(hu_moments) * np.log10(np.abs(hu_moments)) return template_hu def match_char(contour, template_hu, threshold=0.3): # 计算当前字符轮廓的Hu矩 moments = cv2.moments(contour) if moments['m00'] == 0: return None hu_moments = cv2.HuMoments(moments) hu_moments = -np.sign(hu_moments) * np.log10(np.abs(hu_moments)) # 与模板逐一比对,找到最相似的字符 min_diff = float('inf') matched_char = None for char, template_hu_val in template_hu.items(): diff = np.sum(np.abs(hu_moments - template_hu_val)) if diff < min_diff and diff < threshold: min_diff = diff matched_char = char return matched_char def process_image(img_path, template_hu): img, thresh = preprocess_image(img_path) # 提取所有字符轮廓 contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: # 过滤过小的非字符轮廓 area = cv2.contourArea(cnt) if area < 50: continue # 获取字符外接矩形 x, y, w, h = cv2.boundingRect(cnt) # 匹配目标字符 char = match_char(cnt, template_hu) if char: # 绘制标注框 cv2.rectangle(img, (x, y), (x+w, y+h), COLORS[char], 2) # 保存标注后的图片 result_path = f"annotated_{img_path.split('/')[-1]}" cv2.imwrite(result_path, img) print(f"图片 {img_path} 标注完成,结果保存至 {result_path}") return img if __name__ == "__main__": # 替换为你的模板路径(每个模板为单独的字母图片) template_paths = { 'a': 'a_template.png', 'b': 'b_template.png', 'c': 'c_template.png', 'd': 'd_template.png', 'e': 'e_template.png', 'f': 'f_template.png' } # 加载模板的Hu矩特征 template_hu = get_template_hu_moments(template_paths) # 替换为待处理的图片路径列表(至少5张) image_paths = ['text_img1.jpg', 'text_img2.jpg', 'text_img3.jpg', 'text_img4.jpg', 'text_img5.jpg'] for path in image_paths: process_image(path, template_hu)
关键优化细节
- 模板适配:模板需与待处理图片的字符字体、大小尽量一致,可直接从待处理图中抠取单个字母作为模板,大幅提升匹配准确率。
- 阈值调整:
match_char函数中的threshold参数可根据实际情况微调,值越小匹配越严格,值越大容错性越高。 - 倾斜矫正:若图片存在字符倾斜,可在预处理阶段通过
cv2.minAreaRect获取旋转角度,再用cv2.warpAffine矫正,进一步优化识别效果。
内容的提问来源于stack exchange,提问作者Đặng Viết Trung
相关产品推荐
相关产品推荐

