获取文字长度_OpenVINO场景文字检测与识别

本文介绍了OpenVINO的场景文字检测模型,该模型基于VGG16和双向LSTM,能高效识别英文和数字,但不支持中文。虽然在某些干净的文档图像上识别准确,但在复杂场景中误识别率较高,适用于特定应用。
摘要由CSDN通过智能技术生成

点击上方↑↑↑“OpenCV学堂”关注我

OpenVINO系列文章见文末-推荐阅读

概述

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

模型介绍

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

f2f59e47d698e823676de151334032e8.png

模型输入结构为:

[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识别输出 - 效果一

188bf4eb6511b2857dedcd10211f60ce.pngOCR识别输出 - 效果二

b31a83dd91afdd6d13fd43c7cd7c3bc2.png

总结:

发现对特定的应用场景,特别是一些文档化的图像,这个模型识别还比较准确,对很多其它的应用场景,比如身份证、各种卡号识别,发现误识别率很高,现如这些场景需要专项训练的模型!

0933db5461472c1a33e1440a4aaedaf5.png 0933db5461472c1a33e1440a4aaedaf5.png

OpenVINO系列文章

  • 场景文字检测模型PixelLink详解与使用….

  • 首发 | OpenVINO开发配套视频教程发布了

  • OpenVINO开发系列文章汇总

  • OpenVINO开发教程之八 – 道路分割

关注【OpenCV学堂】

长按或者扫码即可关注

ba238225106223f078377f312a61c76c.png

-点击右下角 告诉大家你“在看”-

手把手讲授如何搭建成功OpenVINO框架,并且使用预训练模型快速开发超分辨率、道路分割、汽车识别、人脸识别、人体姿态和行人车辆分析。得益于OpenVINO框架的强大能力,这些例子都能够基于CPU达到实时帧率。课程的亮点在于在调通Demo的基础上更进一步:一是在讲Demo的时候,对相关领域问题进行分析(比如介绍什么是超分辨率,有什么作用)、预训练模型的来龙去脉(来自那篇论文,用什么训练的)、如何去查看不同模型的输入输出参数、如何编写对应的接口参数进行详细讲解;二是基本上对所有的代码进行重构,也就是能够让例子独立出来,并且给出了带有较详细注释的代码;三是注重实际运用,将Demo进一步和实时视频处理框架融合,形成能够独立运行的程序,方便模型落地部署;四是重难点突出、注重总结归纳,对OpenVINO基本框架,特别是能够提高视频处理速度的异步机制和能够直接部署解决实际问题的骨骼模型着重讲解,帮助学习理解;五是整个课程准备精细,每一课都避免千篇一律,前一课有对后一课的预告,后一课有对前一课的难点回顾,避免学习过程中出现突兀;六是在适当的时候拓展衍生,不仅讲OpenVINO解决图像处理问题,而且还补充图像处理的软硬选择、如何在手机上开发图像处理程序等内容,帮助拓展视野,增强对行业现状的了解。基本提纲:1、课程综述、环境配置2、OpenVINO范例-超分辨率(super_resolution_demo)3、OpenVINO范例-道路分割(segmentation_demo)4、OpenVINO范例-汽车识别(security_barrier_camera_demo)5、OpenVINO范例-人脸识别(interactive_face_detection_demo)6、OpenVINO范例-人体姿态分析(human_pose_estimation_demo)7、OpenVINO范例-行人车辆分析(pedestrian_tracker_demo)8、NCS和GOMFCTEMPLATE9、课程小结,资源分享
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值