文本检测实战:使用OpenCV实现文本检测(EAST 文本检测器)

use the geometry volume to derive the width and height of

the bounding box

h = xData0[x] + xData2[x]

w = xData1[x] + xData3[x]

compute both the starting and ending (x, y)-coordinates for

the text prediction bounding box

endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))

endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))

startX = int(endX - w)

startY = int(endY - h)

add the bounding box coordinates and probability score to

our respective lists

rects.append((startX, startY, endX, endY))

confidences.append(scoresData[x])

对于每一行,我们开始遍历列。 我们需要通过忽略概率不够高的区域来过滤掉弱文本检测。

当图像通过网络时,EAST 文本检测器自然会减小体积大小——我们的体积大小实际上比我们的输入图像小 4 倍,因此我们乘以 4 以将坐标带回原始图像。

提取角度数据。 然后我们分别更新我们的矩形和置信度列表。 我们快完成了! 最后一步是对我们的边界框应用非极大值抑制来抑制弱重叠边界框,然后显示结果文本预测:

apply non-maxima suppression to suppress weak, overlapping bounding

boxes

boxes = non_max_suppression(np.array(rects), probs=confidences)

loop over the bounding boxes

for (startX, startY, endX, endY) in boxes:

scale the bounding box coordinates based on the respective

ratios

startX = int(startX * rW)

startY = int(startY * rH)

endX = int(endX * rW)

endY = int(endY * rH)

draw the bounding box on the image

cv2.rectangle(orig, (startX, startY), (endX, endY), (0, 255, 0), 2)

show the output image

cv2.imshow(“Text Detection”, orig)

cv2.waitKey(0)

正如我在上一节中提到的,我无法在我的 OpenCV 4 安装 (cv2.dnn.NMSBoxes) 中使用非最大值抑制,因为 Python 绑定没有返回值,最终导致 OpenCV 出错。我无法完全在 OpenCV 3.4.2 中进行测试,因此它可以在 v3.4.2 中运行。

相反,我使用了 imutils 包(第 114 行)中提供的非最大值抑制实现。结果看起来还是不错的;但是,我无法将我的输出与 NMSBoxes 函数进行比较以查看它们是否相同。 循环我们的边界框,将坐标缩放回原始图像尺寸,并将输出绘制到我们的原始图像。原始图像会一直显示,直到按下某个键。

作为最后的实现说明,我想提一下,我们用于循环分数和几何体的两个嵌套 for 循环将是一个很好的例子,说明您可以利用 Cython 显着加速您的管道。我已经使用 OpenCV 和 Python 在快速优化的“for”像素循环中展示了 Cython 的强大功能。

OpenCV 文本检测结果

========================================================================

您准备好将文本检测应用于图像了吗?

下载frozen_east_text_detection,地址:

oyyd/frozen_east_text_detection.pb (github.com)

。 从那里,您可以在终端中执行以下命令(注意两个命令行参数):

$ python text_detection.py --image images/lebron_james.jpg \

–east frozen_east_text_detection.pb

您的结果应类似于下图:

在这里插入图片描述

在勒布朗·詹姆斯身上标识了三个文本区域。 现在让我们尝试检测商业标志的文本:

$ python text_detection.py --image images/car_wash.png \

–east frozen_east_text_detection.pb

使用 OpenCV 检测视频中的文本

现在我们已经了解了如何检测图像中的文本,让我们继续使用 OpenCV 检测视频中的文本。 这个解释将非常简短; 请根据需要参阅上一节了解详细信息。 打开 text_detection_video.py 并插入以下代码:

import the necessary packages

from imutils.video import VideoStream

from imutils.video import FPS

from imutils.object_detection import non_max_suppression

import numpy as np

import argparse

import imutils

import time

import cv2

我们首先导入我们的包。 我们将使用 VideoStream 访问网络摄像头和 FPS 来对这个脚本的每秒帧数进行基准测试。 其他一切都与上一节相同。

为方便起见,让我们定义一个新函数来解码我们的预测函数——它将在每一帧中重复使用,并使我们的循环更清晰:

def decode_predictions(scores, geometry):

grab the number of rows and columns from the scores volume, then

initialize our set of bounding box rectangles and corresponding

confidence scores

(numRows, numCols) = scores.shape[2:4]

rects = []

confidences = []

loop over the number of rows

for y in range(0, numRows):

extract the scores (probabilities), followed by the

geometrical data used to derive potential bounding box

coordinates that surround text

scoresData = scores[0, 0, y]

xData0 = geometry[0, 0, y]

xData1 = geometry[0, 1, y]

xData2 = geometry[0, 2, y]

xData3 = geometry[0, 3, y]

anglesData = geometry[0, 4, y]

loop over the number of columns

for x in range(0, numCols):

if our score does not have sufficient probability,

ignore it

if scoresData[x] < args[“min_confidence”]:

continue

compute the offset factor as our resulting feature

maps will be 4x smaller than the input image

(offsetX, offsetY) = (x * 4.0, y * 4.0)

extract the rotation angle for the prediction and

then compute the sin and cosine

angle = anglesData[x]

cos = np.cos(angle)

sin = np.sin(angle)

use the geometry volume to derive the width and height

of the bounding box

h = xData0[x] + xData2[x]

w = xData1[x] + xData3[x]

compute both the starting and ending (x, y)-coordinates

for the text prediction bounding box

endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))

endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))

startX = int(endX - w)

startY = int(endY - h)

add the bounding box coordinates and probability score

to our respective lists

rects.append((startX, startY, endX, endY))

confidences.append(scoresData[x])

return a tuple of the bounding boxes and associated confidences

return (rects, confidences)

定义了 decode_predictions 函数。

该函数用于提取: 文本区域的边界框坐标 和一个文本区域检测的概率 此专用函数将使代码在此脚本中稍后更易于阅读和管理。 让我们解析我们的命令行参数:

construct the argument parser and parse the arguments

ap = argparse.ArgumentParser()

ap.add_argument(“-east”, “–east”, type=str, required=True,

help=“path to input EAST text detector”)

ap.add_argument(“-v”, “–video”, type=str,

help=“path to optinal input video file”)

ap.add_argument(“-c”, “–min-confidence”, type=float, default=0.5,

help=“minimum probability required to inspect a region”)

ap.add_argument(“-w”, “–width”, type=int, default=320,

help=“resized image width (should be multiple of 32)”)

ap.add_argument(“-e”, “–height”, type=int, default=320,

help=“resized image height (should be multiple of 32)”)

args = vars(ap.parse_args())

命令行参数解析:

–east : EAST 场景文本检测器模型文件路径。

–video :我们输入视频的路径。 可选 — 如果提供了视频路径,则不会使用网络摄像头。

–min-confidence :确定文本的概率阈值。 可选, default=0.5 。

–width :调整后的图像宽度(必须是 32 的倍数)。 可选的 default=320 。

–height :调整后的图像高度(必须是 32 的倍数)。 可选的 default=320 。

与上一节中的纯图像脚本相比(在命令行参数方面)的主要变化是我用 --video 替换了 --image 参数。 重要提示:EAST 文本要求您的输入图像尺寸是 32 的倍数,因此如果您选择调整 --width 和 --height 值,请确保它们是 32 的倍数! 接下来,我们将执行模仿前一个脚本的重要初始化:

initialize the original frame dimensions, new frame dimensions,

and ratio between the dimensions

(W, H) = (None, None)

(newW, newH) = (args[“width”], args[“height”])

(rW, rH) = (None, None)

define the two output layer names for the EAST detector model that

we are interested – the first is the output probabilities and the

second can be used to derive the bounding box coordinates of text

layerNames = [

“feature_fusion/Conv_7/Sigmoid”,

“feature_fusion/concat_3”]

load the pre-trained EAST text detector

print(“[INFO] loading EAST text detector…”)

net = cv2.dnn.readNet(args[“east”])

高度/宽度和比率初始化将允许我们稍后正确缩放边界框。 我们的输出层名称已定义,加载我们预先训练的 EAST 文本检测器。 以下块设置我们的视频流和每秒帧数计数器:

if a video path was not supplied, grab the reference to the web cam

if not args.get(“video”, False):

print(“[INFO] starting video stream…”)

vs = VideoStream(src=0).start()

time.sleep(1.0)

otherwise, grab a reference to the video file

else:

vs = cv2.VideoCapture(args[“video”])

start the FPS throughput estimator

fps = FPS().start()

我们的视频流设置为: 网络摄像头 或视频文件

初始化每秒帧数计数器并开始循环传入帧:

loop over frames from the video stream

while True:

grab the current frame, then handle if we are using a

VideoStream or VideoCapture object

frame = vs.read()

frame = frame[1] if args.get(“video”, False) else frame

check to see if we have reached the end of the stream

if frame is None:

break

resize the frame, maintaining the aspect ratio

frame = imutils.resize(frame, width=1000)

orig = frame.copy()

if our frame dimensions are None, we still need to compute the

ratio of old frame dimensions to new frame dimensions

if W is None or H is None:

(H, W) = frame.shape[:2]

rW = W / float(newW)

rH = H / float(newH)

resize the frame, this time ignoring aspect ratio

frame = cv2.resize(frame, (newW, newH))

遍历视频/网络摄像头帧。 我们的框架被调整大小,保持纵横比。 从那里,我们获取维度并计算缩放比例。 然后我们再次调整框架的大小(必须是 32 的倍数),这次忽略纵横比,因为我们已经存储了安全保存的比率。 推理和绘制文本区域边界框发生在以下几行:

construct a blob from the frame and then perform a forward pass

of the model to obtain the two output layer sets

blob = cv2.dnn.blobFromImage(frame, 1.0, (newW, newH),

(123.68, 116.78, 103.94), swapRB=True, crop=False)

net.setInput(blob)

(scores, geometry) = net.forward(layerNames)

decode the predictions, then apply non-maxima suppression to

suppress weak, overlapping bounding boxes

(rects, confidences) = decode_predictions(scores, geometry)

boxes = non_max_suppression(np.array(rects), probs=confidences)

loop over the bounding boxes

for (startX, startY, endX, endY) in boxes:

scale the bounding box coordinates based on the respective

ratios

startX = int(startX * rW)

startY = int(startY * rH)

endX = int(endX * rW)

endY = int(endY * rH)

draw the bounding box on the frame

cv2.rectangle(orig, (startX, startY), (endX, endY), (0, 255, 0), 2)

在这个区块中,我们:

通过创建 blob 并将其传递到网络,使用 EAST 检测文本区域 。

解码预测并应用 NMS。 我们使用之前在此脚本中定义的 decode_predictions 函数和我的 imutils non_max_suppression 便利函数。

循环边界框并将它们绘制在框架上。 这涉及按之前收集的比率缩放框。

从那里我们将关闭帧处理循环以及脚本本身:

update the FPS counter

fps.update()

show the output frame

cv2.imshow(“Text Detection”, orig)

key = cv2.waitKey(1) & 0xFF

if the q key was pressed, break from the loop

if key == ord(“q”):

break

stop the timer and display FPS information

fps.stop()

print(“[INFO] elasped time: {:.2f}”.format(fps.elapsed()))

print(“[INFO] approx. FPS: {:.2f}”.format(fps.fps()))

if we are using a webcam, release the pointer

if not args.get(“video”, False):

vs.stop()

otherwise, release the file pointer

else:

vs.release()

close all windows

cv2.destroyAllWindows()

我们在循环的每次迭代中更新我们的 fps 计数器,以便在我们跳出循环时可以计算和显示计时。 我们在第 165 行显示 EAST 文本检测的输出并处理按键。 如果“q”被按下以“退出”,我们就会跳出循环并继续清理和释放指针。

视频文字检测结果

===================================================================

打开一个终端并执行以下命令(这将启动您的网络摄像头,因为我们没有通过命令行参数提供 --video):

python text_detection_video.py --east frozen_east_text_detection.pb

总结

在今天的博文中,我们学习了如何使用 OpenCV 的新 EAST 文本检测器来自动检测自然场景图像中文本的存在。

文本检测器不仅准确,而且能够在 720p 图像上以大约 13 FPS 的速度近乎实时地运行。

为了提供 OpenCV 的 EAST 文本检测器的实现,我需要转换 OpenCV 的 C++ 示例;但是,我遇到了许多挑战,例如:

  • 无法使用 OpenCV 的 NMSBoxes 进行非最大值抑制,而必须使用 imutils 中的实现。

  • 由于缺少 RotatedRect 的 Python 绑定,无法计算真正的旋转边界框。

跳出循环时可以计算和显示计时。 我们在第 165 行显示 EAST 文本检测的输出并处理按键。 如果“q”被按下以“退出”,我们就会跳出循环并继续清理和释放指针。

视频文字检测结果

===================================================================

打开一个终端并执行以下命令(这将启动您的网络摄像头,因为我们没有通过命令行参数提供 --video):

python text_detection_video.py --east frozen_east_text_detection.pb

总结

在今天的博文中,我们学习了如何使用 OpenCV 的新 EAST 文本检测器来自动检测自然场景图像中文本的存在。

文本检测器不仅准确,而且能够在 720p 图像上以大约 13 FPS 的速度近乎实时地运行。

为了提供 OpenCV 的 EAST 文本检测器的实现,我需要转换 OpenCV 的 C++ 示例;但是,我遇到了许多挑战,例如:

  • 无法使用 OpenCV 的 NMSBoxes 进行非最大值抑制,而必须使用 imutils 中的实现。

  • 由于缺少 RotatedRect 的 Python 绑定,无法计算真正的旋转边界框。

最后

🍅 硬核资料:关注即可领取PPT模板、简历模板、行业经典书籍PDF。
🍅 技术互助:技术群大佬指点迷津,你的问题可能不是问题,求资源在群里喊一声。
🍅 面试题库:由技术群里的小伙伴们共同投稿,热乎的大厂面试真题,持续更新中。
🍅 知识体系:含编程语言、算法、大数据生态圈组件(Mysql、Hive、Spark、Flink)、数据仓库、Python、前端等等。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值