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

如何优化pytesseract视频帧文本提取性能?实现无裁剪准确识别

性能优化与文本识别问题

我一直在查找相关帖子,试图优化以下脚本的性能,但效果甚微。测试发现每次调用pytesseract.image_to_data耗时约0.2秒,请问有明显的提速方法吗?我希望无需将图像裁剪为3个独立区域就能提取所有文本,但不裁剪的话识别结果总是错误。试过适配不同字符大小的psm模式,但效果不佳。我在该领域经验不足,可能存在操作误区,恳请各位提供建议。

示例图像(裁剪后):
example image (after cropping)

预处理函数代码

def preprocess(frame, xy):
    _frame = cv.pyrUp(frame[xy['y1']:xy['y2'], xy['x1']:xy['x2']])
    _frame = cv.cvtColor(_frame, cv.COLOR_BGR2GRAY)
    _frame = cv.GaussianBlur(_frame, (3, 3), 0)
    _frame = cv.threshold(_frame, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
    _frame = cv.morphologyEx(_frame, cv.MORPH_OPEN, kernel, iterations=1)
    _frame = 255 - _frame
    return np.dstack([_frame, _frame, _frame])

文本提取函数代码

def to_data(frame):
    img_data = pytesseract.image_to_data(frame, config='--oem 3 --psm 7', output_type=Output.DICT)
    return img_data.get('text', [-1])[-1]

主函数代码

def run(file_name, network, interval, show):
    file = pathlib.Path(PLAYBACK_PATH.format(str(file_name)))
    cap = cv.VideoCapture(str(file), 0)
    fps = int(cap.get(cv.CAP_PROP_FPS))

    dataset = []

    ix = 0
    while True:
        ret, frame = cap.read()
        if frame is None:
            break
        if ix % (fps * interval) == 0:
            row = []
            for lookup, xy in NETWORKS[network].items():
                _frame = preprocess(frame, xy)
                _data = to_data(_frame)
                row.append(_data)
                if show:
                    cv.imshow('frame', _frame)
                    cv.waitKey(1)

            row.append(ix)
            dataset.append(row)
        else:
            pass

        ix += 1

    cap.release()
    cv.destroyAllWindows()
    return dataset

优化建议与解决方案

一、性能提速方法

  1. 替换更快的OCR引擎
    尝试easyocr或paddleocr,轻量模型的单区域识别耗时能压缩到0.05秒以内,比Tesseract效率更高。如果坚持用Tesseract,将--oem 3改为--oem 1(纯LSTM引擎),速度会明显提升,对清晰文本识别效果影响极小。

  2. 精简预处理步骤

    • Tesseract支持直接识别灰度图,删掉np.dstack([_frame, _frame, _frame]),直接返回灰度图,节省内存和转换时间。
    • 评估pyrUp的必要性:若原裁剪区域文本足够清晰,放大操作会增加图像尺寸拖慢识别,可尝试移除或替换为更轻量的cv.resize。
  3. 并行处理多区域
    用concurrent.futures.ThreadPoolExecutor并行处理多个裁剪区域的识别,利用多核CPU资源,示例修改如下:

    from concurrent.futures import ThreadPoolExecutor
    
    def process_single(xy):
        _frame = preprocess(frame, xy)
        return to_data(_frame)
    
    # 替换主循环中的for循环
    with ThreadPoolExecutor(max_workers=3) as executor:
        row = list(executor.map(process_single, NETWORKS[network].values()))
    

二、不裁剪实现正确识别的方法

  1. 精准配置Tesseract参数

    • 明确指定字符白名单,比如仅识别数字和字母:添加-c tessedit_char_whitelist=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ到config,缩小识别范围提升准确率和速度。
    • 尝试--psm 6(假设文本为单一均匀块)或--psm 11(稀疏文本识别),配合字符白名单使用。
  2. 全局预处理+坐标筛选
    不对原图裁剪,先对整图做预处理(转灰度、阈值二值化、形态学操作),调用image_to_data获取所有文本的坐标和内容,再通过原xy区域的坐标范围筛选目标文本。

  3. 自动文本区域定位
    用OpenCV轮廓检测自动定位文本区域,替代手动裁剪:

    def find_text_regions(frame):
        gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        blur = cv.GaussianBlur(gray, (3,3), 0)
        thresh = cv.threshold(blur, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]
        contours, _ = cv.findContours(thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
        regions = []
        for cnt in contours:
            x,y,w,h = cv.boundingRect(cnt)
            if w > 20 and h > 20: # 过滤小噪声轮廓
                regions.append({'x1':x, 'y1':y, 'x2':x+w, 'y2':y+h})
        return regions
    

    用该函数定位所有文本区域后逐个识别,比手动裁剪更灵活。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:44:54