文档章节

PHP OCR实战:用Tesseract从图像中读取文字

snowing1990
 snowing1990
发布于 2016/04/08 11:43
字数 2306
阅读 544
收藏 0

Optical Character Recognition (OCR)即光学字符辨识是把打印文本转换成一个数字表示的过程。它有各种各样的实际应用–从数字化印刷书籍、创建收据的电子记录,到车牌识别甚至破解基于图像的验证码。

Robotic eye

Tesseract是一个能实现OCR的开源项目。你能在*Nix系统,Mac系统和Windows系统上运行这个项目,但是只要使用一个库,我们就能在PHP项目中使用它了。本教程的目的是教你如何使用。

安装

准备

为了让事情变得简单和一致的, 我们将使用虚拟机(本文使用Vagrant)来运行应用程序,这会涉及到安装PHP和Nginx,我们将安装 Tesseract来分别演示过程。如果你想自己基于现有Debian-based系统安装Tesseract,你可以跳过下一部分—或者查看 the README来获得在其他*nix上,Mac系统或者Windows的安装指导.

配置Vagrant

为了配置Vagrant以跟上本教程,完成如下步骤。或者你也可以简单的从Github获得代码。

输入以下命令来下载Homestead Improved Vagrant配置到一个名为orc的文件夹:

git clone https://github.com/Swader/homestead_improved ocr

将Nginx配置文件Homestead.yml中的以下代码:

sites:     - map: homestead.app       to: /home/vagrant/Code/Project/public

修改成:

sites:     - map: homestead.app       to: /home/vagrant/Code/public

同样要在hosts文件中添加

192.168.10.10       homestead.app

安装Tesseract

下一步是安装Tesseract

因为Homestead Improved 使用debian,我们可以在使用vagrant ssh登陆虚拟机后使用apt-get 来安装它,简单运行如下命令:

sudo apt-get install tesseract-ocr

正如上文提到的,在the README中有其他的操作系统对应教程。

测试并定制安装

我们将使用PHP包装,但是之前我们可以在命令行测试Tesseract。

首先保存这个图片sign.png

在虚拟机中,执行如下命令来从图片中读取文字

tesseract sign.png out

这将在当前文件夹创建一个文件:out.txt里面应该有单词:CAUTION

现在尝试sign2.jpg

tesseract sign2.jpg out

这次产生单词Einbahnstral’ie。很接近但不正确—虽然图像中的文字相当清晰,它没能识别字符ß。

为了获使Tesseract正常读取字符串,我们需要安装一些新的语言文件—就本例来说,德语。

这里有一个全面的可用语言文件列表,但我们直接下载所需的文件:

wget https://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.deu.tar.gz

解压:

tar zxvf tesseract-ocr-3.02.deu.tar.gz

然后把文件复制到如下目录:

/usr/share/tesseract-ocr/tessdata

例如

cp deu-frak.traineddata /usr/share/tesseract-ocr/tessdata cp deu.traineddata /usr/share/tesseract-ocr/tessdata

现在我们再次执行原来的命令但是要用 –l

tesseract sign2.jpg out -l deu      “deu” 是德语的 ISO 639-3码.

这次,文字应该是Einbahnstraße(正确的)。

可以通过重复上述过程来使用任意语言。

配置应用程序

我们将使用这个库来用PHP使用Tesseract。

我们将建立一个极简的web应用:用户上传图片,并查看OCR处理结果。我们将使用Silex microframework 来实现。不要担心你不熟悉它,这个应用本身很简单。

记住这篇教程的所有代码都能在Github上获得。

第一步是用Composer来安装依赖文件:

composer require silex/silex twig/twig thiagoalessio/tesseract_ocr:dev-master

然后建立三个文件夹:

- public - uploads - views

我们需要上传表单(views\index.twig):

<html>   <head>     <title>OCR</title>   </head>   <body>      <form action="" method="post" enctype="multipart/form-data">       <input type="file" name="upload">       <input type="submit">     </form>    </body> </html>

需要一个结果展示页面(views\results.twig)::

<html>   <head>     <title>OCR</title>   </head>   <body>      <h2>Results</h2>      <textarea cols="50" rows="10">{{ text }}</textarea>      <hr>      <a href="/">← Go back</a>    </body> </html>

现在建立skeleton Silex app (public\index.php):

<php  require __DIR__.'/../vendor/autoload.php';  use Symfony\Component\HttpFoundation\Request;  $app = new Silex\Application();  $app->register(new Silex\Provider\TwigServiceProvider(), [   'twig.path' => __DIR__.'/../views', ]);  $app['debug'] = true;  $app->get('/', function() use ($app) {    return $app['twig']->render('index.twig');  });  $app->post('/', function(Request $request) use ($app) {      // TODO  });  $app->run();

如果你在浏览器访问这个应用,你应该能看到一个文件上传表单。如果你在使用Homestead Improved Vagrant,你可以通过如下链接访问该应用。

http://homestead.app/

下一步是实现文件上传。Silex使得这项工作非常简单;$request包含一个files组件,我们可以通过它来获得任意上传的文件,代码:

// Grab the uploaded file $file = $request->files->get('upload');  // Extract some information about the uploaded file $info = new SplFileInfo($file->getClientOriginalName());  // Create a quasi-random filename $filename = sprintf('%d.%s', time(), $info->getExtension());  // Copy the file $file->move(__DIR__.'/../uploads', $filename);

如你所见,我们产生随机文件名来减少文件名冲突—但在本应用中,我们怎么命名文件是不重要的。一旦我们在本地有一份文件拷贝,我们就可以产生一个Tessearct库的实例,然后进行分析:

// Instantiate the Tessearct library $tesseract = new TesseractOCR(__DIR__ . '/../uploads/' . $filename);

在图像上实现OCR相当简单,我们只需调用方法recognize()。

// Perform OCR on the uploaded image $text = $tesseract->recognize();

最后我们把结果展示到结果页面:

return $app['twig']->render(     'results.twig',     [         'text'  =>  $text,     ] );

在一些图片上尝试,看看它效果怎样。如果你有困难,可以参考这个

一个实际的例子

让我们来看OCR一个更实用的例子。在本例中,我们尝试在图像中找到一个格式化的电话号码。

看看下面一幅图,上传到你的应用:

结果应该如下:

:ii‘i Customer Service Helplines  British Airways Helpline  09040 490 541

它没有挑出正文文本,这是我们能料到的,因为图片质量太差。虽然识别了号码但是也有一些“噪声”。

为了提取相关信息,有如下几件事我们可以做。

你可以让Tesseract 把它的结果限制在一定的字符集内,所以我们告诉它只返回数字型的内容代码如下:

$tesseract->setWhitelist(range(0,9));

但这样有个问题。它常常把非数字字符解释成数字而非忽略它们。比如“Bob”可能被解释称数字“808”。

所以我们采用两步处理。

  1. 尝试提取可能是电话号码的数字串。

  2. 用一个库轮流评估每一个候选字符,一旦找到一个有效电话号码则停止。

第一步,我们可以用一个基本的正则表达式。可以用谷歌电话库来确定一个数字串是否是合法电话号码。

备注:我已在Sitepoint 写过关于谷歌电话库的内容

让我们给谷歌电话库添加一个PHP 端口,修改composer.json,添加:

"giggsey/libphonenumber-for-php": "~7.0"

别忘了升级:

composer update

现在我们可以写一个函数,输入为一个字符串,尝试提取一个合法的电话号码

/** * Parse a string, trying to find a valid telephone number. As soon as it finds a * valid number, it'll return it in E1624 format. If it can't find any, it'll * simply return NULL. * * @param  string   $text           The string to parse * @param  string   $country_code   The two digit country code to use as a "hint" * @return string | NULL */ function findPhoneNumber($text, $country_code = 'GB') {    // Get an instance of Google's libphonenumber   $phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();    // Use a simple regular expression to try and find candidate phone numbers   preg_match_all('/(\+\d+)?\s*(\(\d+\))?([\s-]?\d+)+/', $text, $matches);    // Iterate through the matches   foreach ($matches as $match) {      foreach ($match as $value) {        try {          // Attempt to parse the number         $number = $phoneUtil->parse(trim($value), $country_code);             // Just because we parsed it successfully, doesn't make it vald - so check it         if ($phoneUtil->isValidNumber($number)) {            // We've found a telephone number. Format using E.164, and exit           return $phoneUtil->format($number, \libphonenumber\PhoneNumberFormat::E164);          }        } catch (\libphonenumber\NumberParseException $e) {          // Ignore silently; getting here simply means we found something that isn't a phone number        }      }   }    return null;  }

希望注释能解释这个函数在干什么。注意如果这个库没能从字符串中解析出一个合法的电话号码它会抛出一个异常。这不是什么问题;我们直接忽略它并继续下一个候选字符。

如果我们找到一个电话号码,我们以E.164的形式返回它。这提供了一个国际化的号码,我们可以用来打电话或者发送SMS。

现在我们可以如下使用:

$text = $tesseract->recognize(); $number = findPhoneNumber($text, 'GB');

我们需要给谷歌电话库提供一个提示来说明这个号码是哪个国家的。你也可以改成你自己的国家。

我们把所有的这些打包在一个新的路由中:

$app->post('/identify-telephone-number', function(Request $request) use ($app) {    // Grab the uploaded file   $file = $request->files->get('upload');    // Extract some information about the uploaded file   $info = new SplFileInfo($file->getClientOriginalName());    // Create a quasi-random filename   $filename = sprintf('%d.%s', time(), $info->getExtension());    // Copy the file   $file->move(__DIR__.'/../uploads', $filename);    // Instantiate the Tessearct library   $tesseract = new TesseractOCR(__DIR__ . '/../uploads/' . $filename);    // Perform OCR on the uploaded image   $text = $tesseract->recognize();    $number = findPhoneNumber($text, 'GB');    return $app->json(     [       'number'     =>  $number,     ]   );  });

我们现在有简单的API的基础—-也就是JSON响应-—我们可以用来作为一个简单的移动应用的后端,这款应用可以用来从一幅图中添加联系人,打电话。

总结

OCR有许多应用——并且很容易整合进你的应用(超过你的预期)。本文中,我们安装了开源OCR包;并使用一个包装器库,把它整合进一个非常简单的PHP应用。我们只是触及到了所有可能性的表面,希望这能给你一些想法,帮你想想怎么在你自己的应用中使用OCR。


本文转载自:http://developer.51cto.com/art/201601/504121.htm

共有 人打赏支持
snowing1990
粉丝 4
博文 90
码字总数 2952
作品 0
程序员
深入学习使用ocr算法识别图片中文字的方法

  公司有个需求,简单点说需要从一张图片中识别出中文,通过python来实现,当然其他程序也行,只要能实现,而小编主要学习python,所以就提了python。一个小白在网上遨游了一天,终于找到一...

战争热诚
08/08
0
0
python3+tesseract获取美股PEG图像上的数据

1. 缘起 投资了一点美股,总要参考个股资料的(虽然巴菲特老人家觉得分析技术资料没有用),发现一个一个查找,效率太低了。于是想起来用Python写个爬虫程序。话说,不偷懒的码农不是好的码农...

干土
06/10
0
0
tesseract OCR识别工具及pytesseract

简介 可以使用pytesseract库从图像中提取文本。Tesseract是一款由Google赞助的开源OCR。 pytesseract是python包装器,它为可执行文件提供了pythonic API。 Tesseract(/'tesərækt/) 这个词的...

人工智能python自动化测试
08/22
0
0
​Tesseract-OCR 3.0.1训练自己的语言库之图像文字识别

关于印刷文字识别依然是图像领域的难点问题,还有很多的单位或个人希望拥有自己的语言识别模型。近来,在各大论坛、学习交流群、后台私信等还会看到仍然有同种志群的人才再不断的加入这个领域...

m0epnwstyk4
2017/12/24
0
0
Python外部模块介绍- pyocr 光学字符串识别 验证码破解相关

Python外部模块介绍- pyocr光学字符串识别 2013-05-24磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq 37391319 博客:http://blog.csdn.net/oychw #版权所有,转载刊登...

长平狐
2013/12/25
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

原型模式

1、原型模式-定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象 克隆(浅度克隆->拷贝值类型或者引用,深度克隆->创建新的对象,开辟新的内存) 例如客户端知道抽象Pro...

阿元
今天
6
0
awk命令扩展使用操作

awk 中使用外部shell变量 示例1 [root@centos01 t1022]# A=888[root@centos01 t1022]# echo "" | awk -v GET_A=$A '{print GET_A}'888[root@centos01 t1022]# echo "aaaaaaaaaaaaa" | aw......

野雪球
今天
13
0
深入解析MySQL视图VIEW

Q:什么是视图?视图是干什么用的? A:视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。   通过视图,可以展现基表的部分数据;...

IT--小哥
今天
18
0
虚拟机学习之二:垃圾收集器和内存分配策略

1.对象是否可回收 1.1引用计数算法 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时候计数器值为0的对象就是不可能...

贾峰uk
今天
12
0
smart-doc功能使用介绍

smart-doc从8月份底开始开源发布到目前为止已经迭代了几个版本。在这里非常感谢那些敢于用smart-doc去做尝试并积极提出建议的社区用户。因此决定在本博客中重要说明下smart-doc的功能,包括使...

上官胡闹
昨天
22
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部