You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV提取灯泡数字并优化OCR识别效果?

基于OpenCV优化灯泡数字提取与OCR识别方案

问题背景

需要从灯泡图片中提取数字区域并送入OCR识别,但现有OpenCV处理代码输出效果不佳,无法让OCR准确识别。

原始灯泡图片:
灯泡原始图片

待提取的数字区域:
待提取的数字区域

现有代码生成的带框定位图:
带框定位的原始图片

现有处理后图片:
裁剪处理后的图片

现有代码问题分析

  1. 自适应阈值的块大小和偏移量参数设置不合理,导致数字与背景对比度不足
  2. 线条去除的核尺寸过大,误删了数字的部分笔画
  3. 形态学操作的核太小,无法有效增强数字的连通性
  4. 仅保留最大轮廓,会丢失多个数字的个体区域

优化后的实现方案

以下是调整后的预处理代码,优化了降噪、阈值、线条去除和轮廓筛选逻辑,确保输出的数字区域更适合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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:52:07