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

Python优化视频帧ROI区域内黑白混合时间戳OCR提取的方案咨询

Python优化视频帧ROI区域内黑白混合时间戳OCR提取的方案咨询

看起来你已经在处理视频ROI里的黑白混合时间戳OCR上做了不少尝试了——Canny边缘检测、自适应阈值、甚至分段提取都试过,但Tesseract还是没能输出精准的结果。针对这种文字颜色不固定(黑/白混合)、背景多变的时间戳场景,我整理了几个针对性的优化方向,你可以挨个尝试:


1. 先统一文字与背景的色调(核心优化!)

Tesseract对规整的二值图(黑字白底或白底黑字)识别率最高,而你当前的问题核心之一就是文字颜色混杂。先把所有文字统一成同一个色调,背景反过来:

import cv2
import numpy as np
import pytesseract

# 裁剪ROI后,先做灰度转换
gray_roi = cv2.cvtColor(roi_frame, cv2.COLOR_BGR2GRAY)

# 用自适应阈值生成二值图(自动适配局部背景的明暗)
thresh = cv2.adaptiveThreshold(
    gray_roi, 255, 
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
    cv2.THRESH_BINARY_INV, 
    11,  # 邻域大小,可根据文字粗细调整
    2    # 阈值偏移量
)

# 统计白色像素占比,判断是否需要反转(确保文字为黑色,背景为白色,符合Tesseract偏好)
white_pixel_ratio = np.count_nonzero(thresh) / (thresh.shape[0] * thresh.shape[1])
if white_pixel_ratio > 0.5:
    # 白色占比过高,说明原文字是白色、背景黑色,反转成黑字白底
    thresh = cv2.bitwise_not(thresh)

# 用膨胀操作修复文字边缘的小断裂
kernel = np.ones((2, 2), np.uint8)
processed_img = cv2.dilate(thresh, kernel, iterations=1)

# 查看处理后的效果
cv2.imshow("Unified Text", processed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 给Tesseract加“识别限制”,过滤噪声字符

时间戳的字符是固定的(数字、-、:、空格、可能的AM/PM),直接给Tesseract设置字符白名单,同时调整PSM模式,让它聚焦于结构化文本:

# 自定义Tesseract配置:
# --oem 3:使用默认OCR引擎
# --psm 6:假设输入是单一统一的文本块
# tessedit_char_whitelist:只允许识别指定字符
custom_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist="0123456789-: APMapm "'

# 用处理后的二值图做OCR
extracted_text = pytesseract.image_to_string(processed_img, lang='eng', config=custom_config)
print("Extracted Text:", extracted_text.strip())

3. 用轮廓定位替代固定间隔的分段提取

你之前用固定spacing_x/spacing_y分段,容易因为视频帧的字符大小差异导致定位偏差。换成轮廓检测自动定位每个字符:

# 从之前的processed_img(统一色调后的二值图)中找轮廓
contours, _ = cv2.findContours(processed_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 过滤掉太小的轮廓(背景噪声)
min_char_area = 50  # 可根据文字大小调整
valid_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_char_area]

# 按x坐标排序(确保从左到右提取字符)
valid_contours = sorted(valid_contours, key=lambda cnt: cv2.boundingRect(cnt)[0])

# 逐个提取字符并统一大小
char_imgs = []
for cnt in valid_contours:
    x, y, w, h = cv2.boundingRect(cnt)
    # 给字符加一点padding,避免裁剪太狠导致文字断裂
    x_pad, y_pad = 2, 2
    x_start = max(0, x - x_pad)
    y_start = max(0, y - y_pad)
    x_end = min(processed_img.shape[1], x + w + x_pad)
    y_end = min(processed_img.shape[0], y + h + y_pad)
    
    # 裁剪单个字符
    char_img = processed_img[y_start:y_end, x_start:x_end]
    # 统一字符大小(比如32x60,和你之前的间隔一致)
    char_img = cv2.resize(char_img, (32, 60), interpolation=cv2.INTER_AREA)
    char_imgs.append(char_img)

# 拼接成完整的时间戳图
final_text_img = np.hstack(char_imgs)

# 再做OCR
extracted_text = pytesseract.image_to_string(final_text_img, lang='eng', config=custom_config)
print("Segmented Extracted Text:", extracted_text.strip())

4. 额外优化:用形态学操作修复模糊/断裂的文字

如果时间戳有轻微模糊或边缘断裂,可以用闭运算(膨胀+腐蚀)填补文字内部的空隙,开运算(腐蚀+膨胀)去除背景噪声:

# 闭运算:填补文字内部小空隙
closed = cv2.morphologyEx(processed_img, cv2.MORPH_CLOSE, np.ones((2,2), np.uint8))
# 开运算:去除背景的小噪声点
opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, np.ones((2,2), np.uint8))

最后再配合你的正则匹配

处理完OCR后,继续用你原来的正则表达式提取时间戳即可:

import re

date_time_match = re.search(r'(\d{2}-\d{2}-\d{4} \w+ \d{2}:\d{2}:\d{2})', extracted_text)
if date_time_match:
    print("Extracted Date & Time:", date_time_match.group(1))
else:
    print("Date & Time not found.")

备注:内容来源于stack exchange,提问作者Andrew Li

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 10:19:49