如何用OpenCV提取灯泡数字并优化OCR识别效果?
基于OpenCV优化灯泡数字提取与OCR识别方案
问题背景
需要从灯泡图片中提取数字区域并送入OCR识别,但现有OpenCV处理代码输出效果不佳,无法让OCR准确识别。
原始灯泡图片:
待提取的数字区域:
现有代码生成的带框定位图:
现有处理后图片:
现有代码问题分析
- 自适应阈值的块大小和偏移量参数设置不合理,导致数字与背景对比度不足
- 线条去除的核尺寸过大,误删了数字的部分笔画
- 形态学操作的核太小,无法有效增强数字的连通性
- 仅保留最大轮廓,会丢失多个数字的个体区域
优化后的实现方案
以下是调整后的预处理代码,优化了降噪、阈值、线条去除和轮廓筛选逻辑,确保输出的数字区域更适合OCR识别:
import cv2 import numpy as np def img_process(frame): original_frame = frame.copy() rected = frame.copy() add_rect(rected) # 保留原有的定位框绘制逻辑 croped = crop(frame) # 保留原有的裁剪逻辑 # 高斯模糊降噪,减少干扰 blurred = cv2.GaussianBlur(croped, (3, 3), 0) frame_grey = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY) # 调整自适应阈值参数,增强数字与背景对比度 thr = cv2.adaptiveThreshold( frame_grey, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 3 ) # 改进线条去除逻辑,避免误删数字笔画 final = remove_lines(thr) # 用更大的核做闭运算,增强数字连通性 final = cv2.morphologyEx(final, cv2.MORPH_CLOSE, np.ones((3, 3)), iterations=1) # 筛选数字轮廓,按宽高比和面积过滤非数字区域 cnts, hierarchy = cv2.findContours(final, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) digit_contours = [] for cnt in cnts: x, y, w, h = cv2.boundingRect(cnt) area = cv2.contourArea(cnt) # 数字的宽高比大致在0.3-1.2之间,面积根据实际场景调整 if 20 < area < 500 and 0.3 < (w/h) < 1.2: digit_contours.append(cnt) cv2.rectangle(rected, (x, y), (x+w, y+h), (0, 255, 0), 2) cv2.rectangle(final, (x, y), (x+w, y+h), (255, 0, 0), 1) return rected, final def remove_lines(img_thr): # 去除水平线:调整核尺寸,只针对较粗的水平线条 horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 2)) detected_lines = cv2.morphologyEx(img_thr, cv2.MORPH_OPEN, horizontal_kernel, iterations=1) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(img_thr, [c], -1, (0, 0, 0), -1) # 去除垂直线:同理缩小核尺寸 vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 8)) detected_lines = cv2.morphologyEx(img_thr, cv2.MORPH_OPEN, vertical_kernel, iterations=1) cnts = cv2.findContours(detected_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] for c in cnts: cv2.drawContours(img_thr, [c], -1, (0, 0, 0), -1) return img_thr
OCR适配建议
处理后的单数字区域可以直接送入Tesseract OCR,建议添加以下配置提升识别准确率:
- 设置白名单仅识别数字:
tesseract_config = '--psm 10 --oem 3 -c tessedit_char_whitelist=0123456789' - 对每个数字区域做轻微缩放,确保字符大小符合OCR要求
内容的提问来源于stack exchange,提问作者Ali Pirpiran
相关产品推荐
相关产品推荐

