OpenVINO场景文字检测与识别

gloomyfish
领域专家: Java技术领域
2020-10-16 12:29:27
OpenVINO提供的场景文字检测模型准确率是非常的高,完全可以达到实用级别,其实OpenVINO还提供了另外一个场景文字识别的模型,总体使用下来的感觉是没有场景文字检测那么靠谱,而且只支持英文字母与数字识别,不支持中文,不得不说是一个小小遗憾,但是对比较干净的文档图像,它的识别准确率还是相当的高,速度也比较快,基本上都在毫秒基本出结果。

模型介绍
文本识别(OCR)模型采用的网络架构为基础网络+双向LSTM,其中基础网络选择的是VGG16,字母识别是非大小写敏感的,26个字母+10个数字总计36个字符。其网络结构类似如下:

模型输入结构为:
[BxCxHxW]=1x1x32x120

其中B表示批次、C表示通道、H表示高度、W表示宽度
模型输出结果为:
[WxBxL] = 30x1x37

其中B表示批次、W表示输出序列长度、L表示各个37个字符各自得分,其中第37个是#
输出部分的解析基于CTC贪心解码方式。
代码实现

加载模型
# 加载IR
log.info("Reading IR...")
net = IENetwork(model=model_xml, weights=model_bin)
text_net = IENetwork(model=text_xml, weights=text_bin)


场景文字检测
# image = cv2.imread("D:/images/openvino_ocr.png");
image = cv2.imread("D:/images/cover_01.jpg");
cv2.imshow("image", image)
inf_start = time.time()
in_frame = cv2.resize(image, (w, h))
in_frame = in_frame.transpose((2, 0, 1)) # Change data layout from HWC to CHW
in_frame = in_frame.reshape((n, c, h, w))
exec_net.infer(inputs={input_blob: in_frame})


ROI截取与文字识别
x, y, width, height = cv2.boundingRect(contours[c])
roi = image[y-5:y+height+10,x-5:x+width+10,:]
gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
text_roi = cv2.resize(gray, (tw, th))
text_roi = np.expand_dims(text_roi, 2)
text_roi = text_roi.transpose((2, 0, 1))
text_roi = text_roi.reshape((tn, tc, th, tw))
text_exec_net.infer(inputs={input_blob: text_roi})
text_out = text_exec_net.requests[0].outputs[text_out_blob]


CTC解析结果
# 解析输出text
ocrstr = ""
prev_pad = False;
for i in range(text_out.shape[0]):
ctc = text_out[i]
ctc = np.squeeze(ctc, 0)
index, prob = ctc_soft_max(ctc)
if alphabet[index] == '#':
prev_pad = True
else:
if len(ocrstr) == 0 or prev_pad or (len(ocrstr) > 0 and alphabet[index] != ocrstr[-1]):
prev_pad = False
ocrstr += alphabet[index]


输出文字检测与识别结果
# 显示识别结果
print("result: %s"%ocrstr)
cv2.drawContours(image, [box], 0, (0, 255, 0), 2)
cv2.putText(image, ocrstr, (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.75, (255, 0, 0), 1)

最后送上整个演示代码
def demo():
# 加载MKLDNN - CPU Target
log.basicConfig(format="[ %(levelname)s ] %(message)s", level=log.INFO, stream=sys.stdout)
plugin = IEPlugin(device="CPU", plugin_dirs=plugin_dir)
plugin.add_cpu_extension(cpu_extension)

# 加载IR
log.info("Reading IR...")
net = IENetwork(model=model_xml, weights=model_bin)
text_net = IENetwork(model=text_xml, weights=text_bin)

if plugin.device == "CPU":
supported_layers = plugin.get_supported_layers(net)
not_supported_layers = [l for l in net.layers.keys() if l not in supported_layers]
if len(not_supported_layers) != 0:
log.error("Following layers are not supported by the plugin for specified device {}:\n {}".
format(plugin.device, ', '.join(not_supported_layers)))
log.error("Please try to specify cpu extensions library path in demo's command line parameters using -l "
"or --cpu_extension command line argument")
sys.exit(1)

# 获取输入输出层
input_blob = next(iter(net.inputs))
outputs = iter(net.outputs)

# 获取多个输出层名称
out_blob = next(outputs)
second_blob = next(outputs)
log.info("Loading IR to the plugin...")
print("pixel output: %s, link output: %s \n"%(out_blob, second_blob))

text_input_blob = next(iter(text_net.inputs))
text_out_blob = next(iter(text_net.outputs))
print("text_out_blob : %s"%text_out_blob)

# 创建可执行网络
exec_net = plugin.load(network=net)
text_exec_net = plugin.load(network=text_net)

# Read and pre-process input image
n, c, h, w = net.inputs[input_blob].shape
tn, tc, th, tw = text_net.inputs[text_input_blob].shape
del net
del text_net

log.info("Starting inference in async mode...")
log.info("To switch between sync and async modes press Tab button")
log.info("To stop the demo execution press Esc button")

image = cv2.imread("D:/images/openvino_ocr.png");
# image = cv2.imread("D:/images/cover_01.jpg");
cv2.imshow("image", image)
inf_start = time.time()
in_frame = cv2.resize(image, (w, h))
in_frame = in_frame.transpose((2, 0, 1)) # Change data layout from HWC to CHW
in_frame = in_frame.reshape((n, c, h, w))
exec_net.infer(inputs={input_blob: in_frame})
inf_end = time.time()
det_time = inf_end - inf_start

# 获取输出
res1 = exec_net.requests[0].outputs[out_blob]
res2 = exec_net.requests[0].outputs[second_blob]

# 降维
res1 = np.squeeze(res1, 0)
res2 = np.squeeze(res2, 0)

# 矩阵转置
res1 = res1.transpose((1, 2, 0))
res2 = res2.transpose((1, 2, 0))

h, w = res1.shape[:2]
print(res1.shape)
print(res2.shape)

# 文本与非文本像素
pixel_mask = np.zeros((h, w), dtype=np.uint8)

# 解析输出结果
res1 = soft_max(res1)

# 像素分割
for row in range(h):
for col in range(w):
pv2 = res1[row, col, 1]
if pv2 > 0.50:
pixel_mask[row, col] = 255

se = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))
mask = cv2.morphologyEx(pixel_mask, cv2.MORPH_CLOSE, se)
cv2.imshow("text mask", mask)
cv2.imwrite("D:/mask.png", mask)

# 后处理,检测框
h, w = image.shape[:2]
mask = cv2.resize(mask, (w, h))
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in range(len(contours)):
rect = cv2.minAreaRect(contours[c])
box = cv2.boxPoints(rect)
box = np.int0(box)

x, y, width, height = cv2.boundingRect(contours[c])
roi = image[y-5:y+height+10,x-5:x+width+10,:]
gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
text_roi = cv2.resize(gray, (tw, th))
text_roi = np.expand_dims(text_roi, 2)
text_roi = text_roi.transpose((2, 0, 1))
text_roi = text_roi.reshape((tn, tc, th, tw))
text_exec_net.infer(inputs={input_blob: text_roi})
text_out = text_exec_net.requests[0].outputs[text_out_blob]

# 解析输出text
ocrstr = ""
prev_pad = False;
for i in range(text_out.shape[0]):
ctc = text_out[i]
ctc = np.squeeze(ctc, 0)
index, prob = ctc_soft_max(ctc)
if alphabet[index] == '#':
prev_pad = True
else:
if len(ocrstr) == 0 or prev_pad or (len(ocrstr) > 0 and alphabet[index] != ocrstr[-1]):
prev_pad = False
ocrstr += alphabet[index]

# 显示识别结果
print("result: %s"%ocrstr)
cv2.drawContours(image, [box], 0, (0, 255, 0), 2)
cv2.putText(image, ocrstr, (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.75, (255, 0, 0), 1)

inf_time_message = "Inference time: {:.3f} ms, FPS:{:.3f}".format(det_time * 1000, 1000 / (det_time * 1000))
cv2.putText(image, inf_time_message, (15, 15), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 0), 1)
cv2.imshow("result", image)
cv2.imwrite("D:/result.png", image)
cv2.waitKey(0)

# 释放资源
cv2.destroyAllWindows()
del exec_net
del plugin

演示效果
OCR识别输出 - 效果一

OCR识别输出 - 效果二

总结:
发现对特定的应用场景,特别是一些文档化的图像,这个模型识别还比较准确,对很多其它的应用场景,比如身份证、各种卡号识别,发现误识别率很高,现如这些场景需要专项训练的模型!
...全文
3360 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文围绕“非线性流量的数据驱动Koopman模型预测控制研究”展开,提出一种基于数据驱动的Koopman算子理论方法,用于构建非线性系统的线性化状态空间模型,并结合模型预测控制(MPC)实现对复杂非线性系统的高效控制。研究通过引入扩展动态模态分解(EDMD)等观测函数,将非线性动力学映射至高维特征空间,在该空间中实现近似线性化表征,进而融合线性MPC框架进行优化求解。全文系统阐述了Koopman算子的数学基础、隐式线性化机制及在非线性流量控制中的建模流程,并通过Matlab代码完成了算法实现与仿真实验,验证了该方法在处理无精确物理模型、强非线性、时变动态系统中的有效性与鲁棒性,尤其适用于工业流程控制、能源系统调度等实际工程场景。; 适合人群:具备自动控制理论、非线性系统分析基础,熟悉Matlab编程,从事控制工程、系统辨识、智能优化、能源系统建模等方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于难以建立精确数学模型的复杂非线性系统(如流体动力系统、电力电子系统、机器人动力学等)的建模与实时控制;②实现数据驱动下的模型预测控制,提升系统响应速度与控制精度;③为先进控制策略(如MPC)提供一种可行的线性化建模范式,推动现代控制理论与数据科学、机器学习的深度融合。; 阅读建议:建议读者结合提供的Matlab代码深入理解Koopman方法的具体实现过程,重点关注观测函数构造、核函数选择、矩阵逼近、降维处理及MPC控制器设计等关键技术环节,并尝试将其迁移至其他非线性系统中进行复现实验与性能对比,以全面掌握其适用范围与局限性。
内容概要:本文详细介绍了一种基于Simulink的光伏储能单相逆变器并网仿真模型,系统涵盖了光伏阵列、储能单元、DC-AC单相逆变器及并网接口的完整结构,重点实现了储能环节的能量管理与逆变器并网控制策略的建模仿真。通过Simulink平台构建系统模型,验证了逆变器输出电能质量、并网稳定性以及控制系统的动态响应性能,采用SPWM调制、PI闭环控制等关键技术,确保并网电流与电网电压同频同相,满足并网电能质量要求。该模型不仅可用于分布式能源系统的仿真研究,还可作为新能源并网技术的教学与工程实践工具。; 适合人群:电气工程、自动化、新能源科学与工程等相关专业的高校本科生、研究生、科研人员,以及从事光伏发电系统设计、储能控制与并网技术研发的工程技术人员。; 使用场景及目标:①深入理解光伏储能系统中能量转换、存储与并网控制的整体工作原理;②支持课程设计、毕业设计或科研项目中对单相逆变器控制策略(如SPWM、PI调节、锁相技术等)的仿真验证与参数优化;③为后续研究更复杂的控制算法(如MPPT、低电压穿越、谐波抑制等)提供可扩展的仿真基础平台。; 阅读建议:建议结合MATLAB/Simulink环境动手搭建与调试模型,逐步理解各模块(如光伏建模、储能充放电控制、逆变器驱动、锁相环、PI调节器等)的功能与交互关系,重点关注控制系统的设计逻辑与参数整定过程,并可通过修改负载条件或电网参数测试系统鲁棒性,为进一步拓展至三相系统或多机并网场景奠定基础。

568

社区成员

发帖
与我相关
我的任务
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
  • 英特尔技术社区
  • shere_lin
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧