记录一次OCR程序开发的尝试

最近工作中涉及到一部分文档和纸质文档的校验工作,就想把纸质文件拍下来,用文字来互相校验。想到之前调用有道智云接口做了文档翻译。看了下OCR文字识别的API接口,有道提供了多种OCR识别的不同接口,有手写体、印刷体、表格、整题识别、购物小票识别、身份证、名片等。干脆这次就继续用有道智云接口做个小demo,把这些功能都试了试,当练手,也当为以后的可能用到的功能做准备了。

调用API接口的准备工作

首先,是需要在有道智云的个人页面上创建实例、创建应用、绑定应用和实例,获取到应用的id和密钥。具体个人注册的过程和应用创建过程详见文章分享一次批量文件翻译的开发过程

开发过程详细介绍

下面介绍具体的代码开发过程:

这次的demo使用python3开发,包括maindow.py,ocrprocesser.py,ocrtools.py三个文件。界面部分,为了简化开发过程,使用python自带的tkinter库,提供选择待识别文件和识别类型、展示识别结果的功能;ocrprocesser.py根据所选类型调用相应api接口,完成识别过程并返回结果;ocrtools.py封装了经整理后的有道ocr 的各类api,实现了分类调用。

  1. 界面部分:

    界面部分代码如下,使用了tkinter的grid来排列元素。

    root=tk.Tk()
    root.title("netease youdao ocr test")
    frm = tk.Frame(root)
    frm.grid(padx='50', pady='50') btn_get_file = tk.Button(frm, text='选择待识别图片', command=get_files)
    btn_get_file.grid(row=0, column=0, padx='10', pady='20')
    text1 = tk.Text(frm, width='40', height='5')
    text1.grid(row=0, column=1) combox=ttk.Combobox(frm,textvariable=tk.StringVar(),width=38)
    combox["value"]=img_type_dict
    combox.current(0)
    combox.bind("<<ComboboxSelected>>",get_img_type)
    combox.grid(row=1,column=1) label=tk.Label(frm,text="识别结果:")
    label.grid(row=2,column=0)
    text_result=tk.Text(frm,width='40',height='10')
    text_result.grid(row=2,column=1) btn_sure=tk.Button(frm,text="开始识别",command=ocr_files)
    btn_sure.grid(row=3,column=1)
    btn_clean=tk.Button(frm,text="清空",command=clean_text)
    btn_clean.grid(row=3,column=2) root.mainloop()

    其中btn_sure的绑定事件ocr_files()将文件路径和识别类型传入ocrprocesser:

    def ocr_files():
    if ocr_model.img_paths:
    ocr_result=ocr_model.ocr_files()
    text_result.insert(tk.END,ocr_result)
    else :
    tk.messagebox.showinfo("提示","无文件")
  2. ocrprocesser中主要方法为ocr_files(),将图片base64处理后调用封装的api。

    def ocr_files(self):
    for img_path in self.img_paths:
    img_file_name=os.path.basename(img_path).split('.')[0]
    #print('==========='+img_file_name+'===========')
    f=open(img_path,'rb')
    img_code=base64.b64encode(f.read()).decode('utf-8')
    f.close()
    print(img_code)
    ocr_result= self.ocr_by_netease(img_code, self.img_type)
    print(ocr_result)
    return ocr_result
  3. 经本人通读整理有道api的文档,大致分为以下四个api入口:手写体/印刷体识别身份证/名片识别表格识别整题识别,每个接口的url不同,请求参数也不全一致,因此demo中首先根据识别类型加以区分:

    # 0-hand write
    # 1-print
    # 2-ID card
    # 3-name card
    # 4-table
    # 5-problem
    def get_ocr_result(img_code,img_type):
    if img_type==0 or img_type==1:
    return ocr_common(img_code)
    elif img_type==2 or img_type==3 :
    return ocr_card(img_code,img_type)
    elif img_type==4:
    return ocr_table(img_code)
    elif img_type==5:
    return ocr_problem(img_code)
    else:
    return "error:undefined type!"

    而后根据接口所需的参数组织data等字段,并针对不同接口的返回值进行简单解析和处理,并返回:

    def ocr_common(img_code):
    YOUDAO_URL='https://openapi.youdao.com/ocrapi'
    data = {}
    data['detectType'] = '10012'
    data['imageType'] = '1'
    data['langType'] = 'auto'
    data['img'] =img_code
    data['docType'] = 'json'
    data=get_sign_and_salt(data,img_code)
    response=do_request(YOUDAO_URL,data)['regions']
    result=[]
    for r in response:
    for line in r['lines']:
    result.append(line['text'])
    return result def ocr_card(img_code,img_type):
    YOUDAO_URL='https://openapi.youdao.com/ocr_structure'
    data={}
    if img_type==2:
    data['structureType'] = 'idcard'
    elif img_type==3:
    data['structureType'] = 'namecard'
    data['q'] = img_code
    data['docType'] = 'json'
    data=get_sign_and_salt(data,img_code)
    return do_request(YOUDAO_URL,data) def ocr_table(img_code):
    YOUDAO_URL='https://openapi.youdao.com/ocr_table'
    data = {}
    data['type'] = '1'
    data['q'] = img_code
    data['docType'] = 'json'
    data=get_sign_and_salt(data,img_code)
    return do_request(YOUDAO_URL,data) def ocr_problem(img_code):
    YOUDAO_URL='https://openapi.youdao.com/ocr_formula'
    data = {}
    data['detectType'] = '10011'
    data['imageType'] = '1'
    data['img'] = img_code
    data['docType'] = 'json'
    data=get_sign_and_salt(data,img_code)
    response=do_request(YOUDAO_URL,data)['regions']
    result = []
    for r in response:
    for line in r['lines']:
    for l in line:
    result.append(l['text'])
    return result

    get_sign_and_salt()为data加入了必要的签名等信息:

    def get_sign_and_salt(data,img_code):
    data['signType'] = 'v3'
    curtime = str(int(time.time()))
    data['curtime'] = curtime
    salt = str(uuid.uuid1())
    signStr = APP_KEY + truncate(img_code) + salt + curtime + APP_SECRET
    sign = encrypt(signStr)
    data['appKey'] = APP_KEY
    data['salt'] = salt
    data['sign'] = sign
    return data

效果展示

手写体结果展示:

印刷体(程序媛拿来代码识别一番):

名片识别,这里我找来了一个名片模板,看起来准度还是可以的:

身份证(同样是模板):

表格识别(这超长的json, >_< emmm......):

整题识别(公式识别也有做,识别结果json比较长,看起来没那么直观,就不在这里贴了):

总结

总的而言,接口功能还是很强大的,各种都支持。就是视觉算法工程师没有做分类功能,需要自己分别对每一类的图像进行分接口调用,而且接口完全不可混用,比如在开发过程中我将名片图片当作身份证提交给api,结果返回了“Items not found!”,对于调用api的开发者来讲有点麻烦,当然这样也在一定程度上提高了识别准确率,而且个人猜测应该也是为了方便分接口计费 : P。

项目地址:https://github.com/LemonQH/WordPicsOCRDemo

记录一次OCR程序开发的尝试的更多相关文章

  1. 微信小程序开发初次尝试-----实验应用制作(一)

    初次尝试微信小程序开发,在此写下步骤以做记录和分享. 1.在网上找了很多资料,发现这位知乎大神提供的资料非常全面. 链接 https://www.zhihu.com/question/50907897 ...

  2. 微信小程序开发 记录

    采坑了 微信小程序--TabBar不出现的一种原因 学习微信小程序中,遇到底部的TabBar不出现的问题.经过多番尝试,终于解决问题.在此记录问题产生的原因和对策.下面先描述错误现象,接着指出错误原因 ...

  3. 第二部分用户交互程序开发,通过paramiko记录ssh会话记录

    需求及任务:实现一个给用户登录的界面(通过ssh登到堡垒机上,然后给它展现一个命令行的页面,然后他选择登哪台机器,一选择就连上去且把日志也记录下来). 先在admin创建几条组数据并与用户关联如下图: ...

  4. 【翻译习作】 Windows Workflow Foundation程序开发-前言

    Windows Workflow Foundation程序开发-基于XAML和C#的WF实战技术与例程 ——C#程序员的WF功能与编程接口技术指导 前言 Windows Workflow Founda ...

  5. 微信小程序开发03-这是一个组件

    编写组件 基本结构 接上文:微信小程序开发02-小程序基本介绍 我们今天先来实现这个弹出层: 之前这个组件是一个容器类组件,弹出层可设置载入的html结构,然后再设置各种事件即可,这种组件有一个特点: ...

  6. Linux及Arm-Linux程序开发笔记(零基础入门篇)

    Linux及Arm-Linux程序开发笔记(零基础入门篇)  作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/bee ...

  7. 微信小程序开发 [00] 写在前面的话,疯狂唠唠

    我总是喜欢在写东西之前唠唠嗑,按照惯例会在博文的开篇写这么一段"写在前面的话",这次却为了这个唠嗑单独开了一篇文,大概预想着要胡说八道的话有点多. 前段时间突然对小程序来了兴趣,说 ...

  8. .Net Core ORM选择之路,哪个才适合你 通用查询类封装之Mongodb篇 Snowflake(雪花算法)的JavaScript实现 【开发记录】如何在B/S项目中使用中国天气的实时天气功能 【开发记录】微信小游戏开发入门——俄罗斯方块

    .Net Core ORM选择之路,哪个才适合你   因为老板的一句话公司项目需要迁移到.Net Core ,但是以前同事用的ORM不支持.Net Core 开发过程也遇到了各种坑,插入条数多了也特别 ...

  9. 微信小程序开发中的二三事之网易云信IMSDK DEMO

    本文由作者邹永胜授权网易云社区发布. 简介 为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程.用产品的话说就是: 云信 IM 小程序 SDK 的能力 ...

随机推荐

  1. 花式求解 LeetCode 279题-Perfect Squares

    原文地址 https://www.jianshu.com/p/2925f4d7511b 迫于就业的压力,不得不先放下 iOS 开发的学习,开始走上漫漫刷题路. 今天我想聊聊 LeetCode 上的第2 ...

  2. 聊聊mysql中的int(1)

    昨天有个读者问了我这样一个问题在mysql中建表的时候,我设置一个字段为int类型,长度为1,但是我发现这个字段却可以存储任意长度的数字,这是什么情况?这个问题在我刚接触数据库的时候也遇到过,我觉得有 ...

  3. 【POJ2728】Desert King - 01分数规划

    Description David the Great has just become the king of a desert country. To win the respect of his ...

  4. 笔记:Linux用户管理(补充)、权限管理、内存管理、网络管理、渗透常用命令

    一.用户管理(补充) 添加用户:useradd [选项] 用户名 useradd -u 5000 -g demogroup -G root -d /home/demo -s /bin/bash dem ...

  5. Scala的安装和配置

    1.Windows下搭建Scala开发环境 1)Scala需要Java运行时库,安装Scala需要首先安装JVM虚拟机并配置好,推荐安装JDK1.8 2)在http://www.scala-lang. ...

  6. Jmeter系列(56)- 详解 Weighted Switch Controller 权重控制器

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 简单介绍 它能分配其子项目(Child ...

  7. 介绍 golang json数据的处理

    原文链接:https://blog.csdn.net/weixin_43223076/article/details/83550229 demo1: package main import ( &qu ...

  8. 结对项目:四则运算题目生成器(Java)

    目录 一.需求分析 二.开发计划 三.实现方案 3.1 项目结构 3.2 代码说明 3.2.1 出题功能代码 3.2.3 批卷功能代码 3.2.3 四则运算功能代码 四.效能分析 4.1 程序效能 4 ...

  9. 第四篇Scrum冲刺博客--Interesting-Corps

    第四篇Scrum冲刺博客 站立式会议 1.会议照片 2.队友完成情况 团队成员 昨日完成 今日计划 鲍鱼铭 搜索页面跳转.设计及布局实现 音乐详情页面跳转.设计及布局实现设计 叶学涛 编写设置页面 编 ...

  10. 访问github太慢?我写了一个开源小工具一键变快

    前言 GitHub应该是广大开发者最常去的站点,这里面有大量的优秀项目,是广大开发者寻找资源,交友学习的好地方.尤其是前段时间GitHub公布了一项代码存档计划--Arctic Code Vault, ...