因为研究生毕业项目须要完毕一个基于移动终端的场景文字识别系统。尽管离毕业尚早,但出于兴趣的缘故,近一段抽时间完毕了这样一套系统。

主要的架构例如以下:

client:Android应用实现拍摄场景图片,大致划出感兴趣文字区域,通过socket通信上传server端识别;

服务器端:Python server进行socket通信监听,连通后调用文字识别引擎(exe可运行程序),将识别结果返回;

以下是系统执行演示样例图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2VhbndhbmdfMjU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" align="top" height="420" width="680">

1. client

包括两个Activity,: MainActivity主界面如上图左1,选择拍摄后调用系统内部的拍照服务如上图左2;拍照完毕进入KernelActivity如上图左3,大致划出感兴趣文字区域后上传server端,获取识别结果如上图左4。

client拍照和建立网络通信须要注意在AndroidManifestxml文件里声明权限

    <!-- 授权使用相机 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 在SD卡中创建与删除文件的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 向SD卡中写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 授权訪问互联网 -->
<uses-permission android:name="android.permission.INTERNET" />

clientAndroid编程时连接server端利用socket进行通信,在编程过程中有几点须要注意的问题。不然非常easy导致出错:

1.1 主线程中不能直接建立网络连接

为了防止线程堵塞,android 4.0以上的版本号不同意直接在主线程建立网络连接(socket通信须要连接网络)。因此,在须要socket通信时。应新开线程用于网络连接,使用示比例如以下

new Thread(){//主线程不能直接连接网络,需新建子线程
@Override
public void run(){
//TODO
}
}.start();

1.2 clientsocket收发数据流不宜使用close()方法

client须要同一时候接受和发送数据,因此会有例如以下两个对象out和in

							//開始socket通信
Socket socket = new Socket("210.77.27.123", 9058); //此处IP依据自己的server端设定 //写输出(上传)数据
DataOutputStream out = new DataOutputStream(socket.getOutputStream()); //写输入(获得)数据
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "gb2312")); //设置字符编码格式,以便正确读取中文

假设在out向server端发送完数据后,想着out已经不须要了,则可能会想使用 out.close() 关闭对象。假设这样。那么在使用in对象接收数据时便会抛出异常“socket closed”!原因是,in或out对象的close()方法使用后会造成socket的关闭。所以。假设须要关闭,能够考虑使用shutdownInput()和shutdownOutput()方法。或者不处理而待最后socket.close()就可以。

1.3 子线程不能更新UI

获得server端识别结果时。须要使用这个内容更新clientUI(左下角的TextView),假设在上面说到的进行socket通信的子线程中直接使用 text.setText()方法试图更新UI的话。结论是不可行的。

所以,为了更新UI须要借助Handler对象。在其handleMessage()方法内更新UI。

子线程中将server端结果存入message并向提前定义的handler对象发送消息

							String response = in.readLine();
Message msg = handler.obtainMessage();//子线程中不能更新UI。需借助handler
msg.obj = response;
handler.sendMessage(msg);

紧接着handler会调用其 handleMessage()方法更新UI,handleMessage()定义例如以下

		handler = new Handler(){
@Override
public void handleMessage(Message msg){
String message = (String)msg.obj;
if(message != null)
text.setText(message);
else
text.setText("抱歉,未能识别");
super.handleMessage(msg);//这一句必需要有! 不然无法更新UI
}
};



2.server端

服务器端主要部署python脚本进行socket监听,一旦建立连接则调用开发好的场景文字识别引擎(STREngine.exe),并将结果返回client。

python server脚本内容例如以下

#####################################
# #
# STC Recognition Server #
# #
##################################### import socket
import os s = socket.socket() host = socket.gethostname()
port = 9058
s.bind((host, port)) s.listen(5)
while True:
c, addr = s.accept()
print 'Got connection from' , addr #get uploaded params
params = c.recv(19)
lst = params.split(' ')
if len(lst) < 4:
c.close()
continue
print 'x=%d, y=%d, w=%d, h=%d' % (int(lst[0]),int(lst[1]),int(lst[2]),int(lst[3])) #get uploaded image size info
size = int(c.recv(4)) #save uploaded image
f = open('.\\upload\\tmp.jpg', 'wb')
for i in range(size):
f.write(c.recv(1024))
f.close()
print 'Image received, size %dKB' % size #execute STREngine on server and send back the result
result = os.popen('STREngine ./upload/tmp.jpg ' + params).read()
print 'Recognition result:', result
c.send(result + '\n') print 'Close connection with', addr, '\n'
c.close()

文字识别引擎的内部代码不便分享。但会将可运行文件分享给感兴趣的朋友。

server端有一点非常重要的地方。不注意的话可能会给你带来无尽的烦恼,我就花了两个晚上才发现这个非常小的问题,在此分享以免再浪费别人的时间:

在server端返回识别结果给client时,一定要在字符串后面加换行符‘\n’结尾!

假设不加,则client in.readline()方法会因找不到行末而一直堵塞。则无法利用返回结果更新clientUI。这个问题很恼人,由于假设你在服务端返回不加‘\n'的话,在本地电脑上利用android虚拟机是没问题的,虚拟机上正常更新UI,可是一旦换到手机上就没反应了(不更新UI)。

总结:

事实上。client手动划取感兴趣文字上传后。这个区域位置在ImageView和实际图像中是须要细致换算的。这里就不细说了。有须要的朋友直接看代码吧。

或者强烈建议自己分析推导一番,自己找出这个关系。会对加深对ImageView和Bitmap的理解有极大帮助。

此外。因为不是做产品。对效率的考虑并没有在意。如今的话是将手机拍照后的整幅图片上传,尽管进行了压缩,但一副图仍有几百KB大小。这对流量实在太过浪费。解决的话也简单。仅仅要将划取的文字区域单独取出来上传就可以(但四周须要一定程度的扩展),大小应该减小几十倍。

client和服务端源码(包含识别引擎可运行程序)已分享至CSDN,有问题欢迎随时随时交流指正。

Android应用开发进阶篇-场景文字识别的更多相关文章

  1. Android JNI开发提高篇

    有关JNI的开发技术,我们继续围绕Android平台进行,JNI可以支持C或C++,从目前为止我们写过的JNI代码均为C实现的,即文件名为.C而C++的和这些有什么不同呢? Android平台上的JN ...

  2. [转]抢先Mark!微信公众平台开发进阶篇资源集锦

    FROM : http://www.csdn.net/article/2014-08-01/2820986 由CSDN和<程序员>杂志联合主办的 2014年微信开发者大会 将于8月23日在 ...

  3. Android应用开发基础篇(1)-----Button

    Android应用开发基础篇(1)-----Button   一.概述        Button,顾名思义就是按钮的意思,它主要的功能是响应用户按下按钮时的动作. 二.应用      新建一个工程, ...

  4. Android应用开发提高篇(1)-----获取本地IP

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/02/21/2361802.html 一.概述 习惯了Linux下的网络编程,在还没用智能机之前就一直想 ...

  5. 浅析点对点(End-to-End)的场景文字识别(图片文字)

    一.背景 随着智能手机的广泛普及和移动互联网的迅速发展,通过手机等移动终端的摄像头获取.检索和分享资讯已经逐步成为一种生活方式.基于摄像头的 (Camera-based)的应用更加强调对拍摄场景的理解 ...

  6. android 串口开发第二篇:利用jni实现android和串口通信

    一:串口通信简介 由于串口开发涉及到jni,所以开发环境需要支持ndk开发,如果未配置ndk配置的朋友,或者对jni不熟悉的朋友,请查看上一篇文章,android 串口开发第一篇:搭建ndk开发环境以 ...

  7. mysql 开发进阶篇系列 55 权限与安全(安全事项 )

    一. 操作系统层面安全 对于数据库来说,安全很重要,本章将从操作系统和数据库两个层面对mysql的安全问题进行了解. 1. 严格控制操作系统账号和权限 在数据库服务器上要严格控制操作系统的账号和权限, ...

  8. mysql 开发进阶篇系列 47 物理备份与恢复(xtrabackup 的完全备份恢复,恢复后重启失败总结)

    一. 完全备份恢复说明 xtrabackup二进制文件有一个xtrabackup --copy-back选项,它将备份复制到服务器的datadir目录下.下面是通过 --target-dir 指定完全 ...

  9. mysql 开发进阶篇系列 46 物理备份与恢复( xtrabackup的 选项说明,增加备份用户,完全备份案例)

    一. xtrabackup 选项说明 在操作xtrabackup备份与恢复之前,先看下该工具的选项,下面记录了xtrabackup二进制文件的部分命令行选项,后期把常用的选项在补上.点击查看xtrab ...

随机推荐

  1. Python 2:str.title()(使字符串每个单词首字母大写)

    name = "hello,world! hello,python!" print(name.title()) #单词首字母大写 运行结果将会是:Hello,World!Hello ...

  2. Halcon学习笔记之支持向量机(二)

    例程:classify_halogen_bulbs.hdev 在Halcon中模式匹配最成熟最常用的方式该署支持向量机了,在本例程中展示了使用支持向量机对卤素灯的质量检测方法.通过这个案例,相信大家可 ...

  3. 联想VIBE Shot(Z90-7/全网通) 解锁BootLoader

    工具下载链接: http://pan.baidu.com/s/1dF7zGTb 备用下载链接: http://pan.baidu.com/s/1i4UHP4L 本篇教程教你如何傻瓜式解锁BootLoa ...

  4. Linux通信之异步通知模式

    [参考]韦东山 教学笔记 为了使设备支持异步通知机制,驱动程序中涉及以下3项工作:1. 支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID. 不过此项工 ...

  5. 使用curl 上传文件,multipart/form-data

    使用curl 上传文件,multipart/form-data 1. 不使用-F,curl内置multipart/form-data功能: 2. 文件内容与真实数据无关,用abc代替数据,依然可以上传 ...

  6. sql server 数据库优化--显示执行计划

      刚开始用SQL Server的时候,我没有用显示执行计划来对查询进行分析.我曾经一直认为我递交的SQL查询都是最优的,而忽略了查询性能究竟如何,从而对“执行计划”重视不够.在我职业初期,我只要能获 ...

  7. 【SQL】联合语句

    一.UNION操作符 UNION 操作符用于合并两个结果集,在合并的同时去掉重复行,并按合并后结果的第一列升序排列.合并后结果集的列名由第一个结果集的列名确定. UINON连接的两个结果集必须具有相同 ...

  8. ionic + cordova开发APP遇到的一些坑

    ionic1时期接触了这套体系,做了一个APP之后就放置了,最近又要开发一个APP,但时间不足以让我重头了解typescripts,于是又把之前做过的东西翻了出来,一边做一边掉坑里,爬上来再掉坑里,所 ...

  9. Net.Json 常用例子

    #JsonConvert 例子 内容主要都是官方的例子,加上一些中文注释而已. 主要方便自己查询,分享一份出来. 参考文档: https://www.newtonsoft.com/json/help/ ...

  10. 三维重建面试0:*SLAM滤波方法的串联综述

    知乎上的提问,高翔作了回答:能否简单并且易懂地介绍一下多个基于滤波方法的SLAM算法原理? 写的比较通顺,抄之.如有异议,请拜访原文.如有侵权,请联系删除. 我怎么会写得那么长--如果您有兴趣可以和我 ...