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
相关产品推荐
相关产品推荐

