使用 OpenCV 从图像中提取轮廓文本

信息处理 图像处理 opencv 文本识别
2022-02-04 14:32:37

我有一些视频帧,我想从中提取一些文本(用于从硬字幕视频制作软字幕以进行学习)。有问题的文本主要是已知字体(看起来像 SimHei)的中文脚本(一些数字和拉丁字母),是白色(ish)和黑色(ish)边框,并且在恒定位置左对齐。我想要实现的是文本的“整洁”黑白图像。

示例输入,像这样,背景不受控制,也可以像文本一样白。

在此处输入图像描述

我想要实现的是可以提供给 OCR 的类似这样的东西:

期望的输出

我正在使用 Python 和 OpenCV。仅对图像进行阈值处理的幼稚第一次尝试是不够的,因为它(可预测地)在白色背景区域(例如,在本示例中的第一个和第二个字符下方)产生伪影。

边缘检测也具有挑战性,因为您可以为白黑边缘获得一个不错的“内边缘”,但您可能会或可能不会获得黑色背景边界的外边缘(如果背景很暗),或者您可能只会获得部分或未闭合的轮廓。一些背景非常嘈杂,因此也可能存在很多虚假边缘(这有点做作,因为没有进行过滤,并且 Canny 光圈太大,但双边缘可见):

在此处输入图像描述

我曾尝试使用拉普拉斯金字塔过滤器(基于此示例)过滤图像,但很难找到一个过滤器可以在白色文本上不经常将背景中的噪音吹成纯白色。例如,右侧是一个在阈值处理后看起来非常“text-y”的特征。

在此处输入图像描述

过滤“小”轮廓也具有挑战性,因为中文中有有效的小笔划,以及句号和逗号等标点符号。

对这样的文本进行稳健过滤的正确(或好)方法是什么?是否有一种“标准”技术可以锁定这种轮廓?我希望坚持图像处理和基本启发式,而不是像机器学习这样更高级的辨别。


这里还有一些帧,并非所有帧都有文本,表明图像中存在一些不太适合一刀切处理的特征:

在此处输入图像描述

1个回答

您可以通过以高强度对图像进行阈值处理(因为您的文本始终显示为白色)并执行关闭操作来关闭间隙,从而获得相当不错的结果:

# convert to grayscale
img = cv2.imread('OCR.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshhold
ret,bin = cv2.threshold(gray,245,255,cv2.THRESH_BINARY)

# closing
kernel = np.ones((3,3),np.uint8)
closing = cv2.morphologyEx(bin, cv2.MORPH_CLOSE, kernel)

# invert black/white
inv = cv2.bitwise_not(closing)

结果:

在此处输入图像描述

您可能可以通过反转图像的打开操作来清理大多数背景伪影。这应该已经产生了很好的 OCR 结果。