[Python爬虫] 九、机器视觉与机器图像识别之Tesseract
往期内容提要:
- [Python爬虫] 一、爬虫原理之HTTP和HTTPS的请求与响应
- [Python爬虫] 二、爬虫原理之定义、分类、流程与编码格式
- [Python爬虫] 三、数据抓取之Requests HTTP 库
- [Python爬虫] 四、数据抓取之HTTP/HTTPS抓包工具Fiddler
- [Python爬虫] 五、数据提取之正则表达式re模块
- [Python爬虫] 六、数据提取之XPath与lxml类库
- [Python爬虫] 七、结构化数据提取之JSON与JsonPATH
- [Python爬虫] 八、动态HTML处理之Selenium与PhantomJS
另:感谢大家一直以来对我的关注和支持,我已于今日(2020年2月17日)认证为博客专家,距19年3月14日第一次发文,已经11个月了,感谢CSDN官方对我博文的认可,博客专家是对我的莫大的激励,自己会继续努力写出更多更有质量的博文,在研究领域不断探索和进步。
一、机器视觉
从 Google 的无人驾驶汽车到可以识别假钞的自动售卖机,机器视觉一直都是一个应用广 泛且具有深远的影响和雄伟的愿景的领域。
我们将重点介绍机器视觉的一个分支:文字识别,介绍如何用一些 Python库来识别和使用在线图片中的文字。
我们可以很轻松的阅读图片里的文字,但是机器阅读这些图片就会非常困难,利用这种人类用户可以正常读取但是大多数机器人都没法读取的图片,验证码 (CAPTCHA)就出现了。验证码读取的难易程度也大不相同,有些验证码比其他的更加难读。
将图像翻译成文字一般被称为光学文字识别(Optical Character Recognition, OCR)。可以实现OCR的底层库并不多,目前很多库都是使用共同的几个底层 OCR 库,或者是在上面 进行定制。在读取和处理图像、图像相关的机器学习以及创建图像等任务中,Python 一直都是非常出色的语言。虽然有很多库可以进行图像处理,但在这里我们只重点介绍:Tesseract
二、Tesseract 安装
Tesseract 是一个 OCR 库,目前由 Google 赞助(Google 也是一家以 OCR 和机器学习技术闻名于世的公司)。Tesseract 是目前公认最优秀、最精确的开源 OCR 系统,除了极高的精确度,Tesseract 也具有很高的灵活性。它可以通过训练识别出任何字体,也可以识别出任何 Unicode 字符。
(1) 安装Tesseract
- Windows系统:下载可执行安装文件https://code.google.com/p/tesseract-ocr/downloads/list安装。
- Linux 系统:可以通过 apt-get 安装: $sudo apt-get tesseract-ocr
- Mac OS X系统:用Homebrew(http://brew.sh/)等第三方库可以很方便地安装
(2) 安装pytesseract
Tesseract 是一个 Python 的命令行工具,不是通过 import 语句导入的库。安装之后,要用 tesseract 命令在 Python 的外面运行,但我们可以通过 pip 安装支持Python 版本的 Tesseract库:
pip install pytesseract
三、处理格式规范文字
处理的大多数文字最好都是比较干净、格式规范的。格式规范的文字通常可以满足一些需求,通常格式规范的文字具有以下特点:
- 使用一个标准字体(不包含手写体、草书,或者十分“花哨的”字体)
- 即使被复印或拍照,字体还是很清晰,没有多余的痕迹或污点
- 排列整齐,没有歪歪斜斜的字
- 没有超出图片范围,也没有残缺不全,或紧紧贴在图片的边缘
文字的一些格式问题在图片预处理时可以进行解决。例如,可以把图片转换成灰度图,调整亮度和对比度,还可以根据需要进行裁剪和旋转(详情需要了解图像与信号处理)等。
(1) 格式规范文字的理想示例
通过下面的命令运行 Tesseract,读取文件并把结果写到一个文本文件中: tesseract test.jpg text
cat text.txt
即可显示结果。识别结果很准确,不过符号^和*分别被表示成了双引号和单引号。大体上可以让你很舒服地阅读。
(2) 通过Python代码实现
import pytesseract
from PIL import Imageimage = Image.open('test.jpg')
text = pytesseract.image_to_string(image)
print text
运行结果:
This is some text, written in Arial, that will be read by
Tesseract. Here are some symbols: !@#$%"&*()
(3) 对图片进行阈值过滤和降噪处理
很多时候我们在网上会看到这样的图片:
Tesseract 不能完整处理这个图片,主要是因为图片背景色是渐变的,最终结果是这样:
随着背景色从左到右不断加深,文字变得越来越难以识别,Tesseract 识别出的 每一行的最后几个字符都是错的。遇到这类问题,可以先用 Python 脚本对图片进行清理。利用 PIL 库,我们可以创建一个阈值过滤器来去掉渐变的背景色,只把文字留下来,从而让图片更加清晰,便于 Tesseract 读取:
from PIL import Image
import subprocessdef cleanFile(filePath, newFilePath):image = Image.open(filePath)# 对图片进行阈值过滤(低于143的置为黑色,否则为白色)image = image.point(lambda x: 0 if x < 143 else 255)# 重新保存图片image.save(newFilePath)# 调用系统的tesseract命令对图片进行OCR识别 subprocess.call(["tesseract", newFilePath, "output"])# 打开文件读取结果with open("output.txt", 'r') as f:print(f.read())if __name__ == "__main__":cleanFile("text2.png", "text2clean.png")
通过一个阈值对前面的“模糊”图片进行过滤的结果:
除了一些标点符号不太清晰或丢失了,大部分文字都被读出来了。Tesseract 给出了最好的 结果:
(4) 从网站图片中抓取文字
用 Tesseract 读取硬盘里图片上的文字,可能不怎么令人兴奋,但当我们把它和网络爬虫组合使用时,就能成为一个强大的工具。
网站上的图片可能并不是故意把文字做得很花哨 (就像餐馆菜单的 JPG 图片上的艺术字),但它们上面的文字对网络爬虫来说就是隐藏起来 了,举个例子:
虽然亚马逊的 robots.txt 文件允许抓取网站的产品页面,但是图书的预览页通常不让网络机 器人采集。
图书的预览页是通过用户触发 Ajax 脚本进行加载的,预览图片隐藏在 div 节点 下面;其实,普通的访问者会觉得它们看起来更像是一个 Flash 动画,而不是一个图片文 件。当然,即使我们能获得图片,要把它们读成文字也没那么简单。
下面的程序就解决了这个问题:首先导航到托尔斯泰的《战争与和平》的大字号印刷版 1, 打开阅读器,收集图片的 URL 链接,然后下载图片,识别图片,最后打印每个图片的文 字。因为这个程序很复杂,利用了前面几章的多个程序片段,所以我增加了一些注释以让 每段代码的目的更加清晰:
import time
from urllib.request import urlretrieve
import subprocess
from selenium import webdriver
#创建新的Selenium driver
driver = webdriver.PhantomJS()# 用Selenium试试Firefox浏览器:
# driver = webdriver.Firefox()driver.get("http://www.amazon.com/War-Peace-Leo-Nikolayevich-Tolstoy/dp/1427030200")
# 单击图书预览按钮 driver.find_element_by_id("sitbLogoImg").click() imageList = set()
# 等待页面加载完成
time.sleep(5)
# 当向右箭头可以点击时,开始翻页
while "pointer" in driver.find_element_by_id("sitbReaderRightPageTurner").get_attribute("style"):driver.find_element_by_id("sitbReaderRightPageTurner").click()time.sleep(2)# 获取已加载的新页面(一次可以加载多个页面,但是重复的页面不能加载到集合中)pages = driver.find_elements_by_xpath("//div[@class='pageImage']/div/img")for page in pages:image = page.get_attribute("src")imageList.add(image)
driver.quit()# 用Tesseract处理我们收集的图片URL链接
for image in sorted(imageList):# 保存图片urlretrieve(image, "page.jpg")p = subprocess.Popen(["tesseract", "page.jpg", "page"], stdout=subprocess.PIPE,stderr=subprocess.PIPE)f = open("page.txt", "r")p.wait() print(f.read())
和我们前面使用 Tesseract 读取的效果一样,这个程序也会完美地打印书中很多长长的段落,第六页的预览如下所示:
6"A word of friendly advice, moncher. Be off as soon as you can,that's all I have to tell you. Happyhe who has ears to hear. Good-by,my dear fellow. Oh, by the by!" heshouted through the doorway afterPierre, "is it true that the countesshas fallen into the clutches of theholy fathers of the Society of je-sus?"Pierre did not answer and left Ros-topchin's room more sullen and an-gry than he had ever before shownhimself.
但是当文字出现在彩色封面上时,结果就不那么完美了:
WEI' nrrd PeaceLen Nlkelayevldu IolfluyReadmg shmdd be axwlnvame asnossxble Wenfleran mm m our cram: Llhvary- Leo Tmsloy was a Russian rwovelwstI and moval phflmopher med lurA ms Ideas 01 nonviolenx reswslance m 5 We range 0, "and"
如果想把文字加工成普通人可以看懂的效果,还需要花很多时间去处理。
比如,通过给 Tesseract 提供大量已知的文字与图片映射集,经过训练 Tesseract 就可以“学会”识别同一种字体,而且可以达到极高的精确率和准确率,甚至可以忽略图片中文字的背景色和相对位置等问题。
四、处理验证码
(1) 尝试对知乎网验证码进行处理:
当前许多流行的内容管理系统加了验证码模块,那么我们如何识别验证码呢?
大多数网站生成的验证码图片都具有以下属性。
- 它们是服务器端的程序动态生成的图片。验证码图片的 src 属性可能和普通图片不太一 样,比如
<img src="WebForm.aspx?id=8AP85CQKE9TJ">
,但是可以和其他图片一样进行 下载和处理。 - 图片的答案存储在服务器端的数据库里。
- 很多验证码都有时间限制,如果你太长时间没解决就会失效。
- 常用的处理方法就是,首先把验证码图片下载到硬盘里,清理干净,然后用 Tesseract 处理 图片,最后返回符合网站要求的识别结果。
#!/usr/bin/env python
# -*- coding:utf-8 -*-import requests
import time
import pytesseract
from PIL import Image
from bs4 import BeautifulSoupdef captcha(data):with open('captcha.jpg','wb') as fp:fp.write(data)time.sleep(1)image = Image.open("captcha.jpg")text = pytesseract.image_to_string(image)print "机器识别后的验证码为:" + textcommand = raw_input("请输入Y表示同意使用,按其他键自行重新输入:")if (command == "Y" or command == "y"):return textelse:return raw_input('输入验证码:')def zhihuLogin(username,password):# 构建一个保存Cookie值的session对象sessiona = requests.Session()headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0'}# 先获取页面信息,找到需要POST的数据(并且已记录当前页面的Cookie)html = sessiona.get('https://www.zhihu.com/#signin', headers=headers).content# 找到 name 属性值为 _xsrf 的input标签,取出value里的值_xsrf = BeautifulSoup(html ,'lxml').find('input', attrs={'name':'_xsrf'}).get('value')# 取出验证码,r后面的值是Unix时间戳,time.time()captcha_url = 'https://www.zhihu.com/captcha.gif?r=%d&type=login' % (time.time() * 1000)response = sessiona.get(captcha_url, headers = headers)data = {"_xsrf":_xsrf,"email":username,"password":password,"remember_me":True,"captcha": captcha(response.content)}response = sessiona.post('https://www.zhihu.com/login/email', data = data, headers=headers)print response.textresponse = sessiona.get('https://www.zhihu.com/people/maozhaojun/activities', headers=headers)print response.textif __name__ == "__main__":zhihuLogin('xxxx@qq.com','ALAxxxxIME')
(2) 尝试处理中文字符
如果手头上有中文的训练数据,也可以尝试对中文进行识别。
命令:tesseract --list-langs
可以查看当前支持的语言,chi_sim
表示支持简体中文。
那么在使用时候,可以指定某个语言来进行识别,如:
tesseract -l chi_sim paixu.png paixu
表现在程序里,则可以这么写:
#!/usr/bin/env python
# -*- coding:utf-8 -*-from PIL import Image
import subprocessdef cleanFile(filePath)image = Image.open(filePath)# 调用系统的tesseract命令, 对图片进行OCR中文识别subprocess.call(["tesseract", "-l", "chi_sim", filePath, "paixu"])# 打开文件读取结果with open("paixu.txt", 'r') as f:print(f.read())if __name__ == "__main__":cleanFile("paixu.png")
结果如下:
五、训练Tesseract
要使用 Tesseract 的功能,比如后面的示例中训练程序识别字母,要先在系统中设置一 个新的环境变量 $TESSDATA_PREFIX
,让 Tesseract 知道训练的数据文件存储在哪里,然后搞一份 tessdata
数据文件,放到Tesseract目录下。
在大多数 Linux 系统和 Mac OS X 系统上,你可以这么设置:
$export TESSDATA_PREFIX=/usr/local/share/Tesseract
在 Windows 系统上也类似,你可以通过下面这行命令设置环境变量:
#setx TESSDATA_PREFIX C:\Program Files\Tesseract OCR\Tesseract
用下面的代码运行 Tesseract 识别图片:
tesseract captchaExample.png output
大多数其他的验证码都是比较简单的。例如,流行的 PHP 内容管理系统 Drupal 有一个著名的验证码模块 https://www.drupal.org/project/captcha,可以生成不同难度的验证码。
影响验证码识别难度因素 | 影响原因 |
---|---|
大小 | 过小字体需要进行额外的训练才能识别 |
字体种类 | 种类越多越难以识别 |
倾斜程度 | 随机的倾斜程度迷惑 OCR 软件识别 |
字母和数字是否混用 | 增加待搜索字符的数量 |
叠加,交叉 | 在每一个字母外面画一个方框时,如重叠在一起识别难度加大 |
背景色、线条 | 产生对 OCR 程序产生干扰的噪点 |
背景与字体颜色对比度 | 对比度越小越难识别 |
创建样本库训练Tesseract
要训练 Tesseract 识别一种文字,无论是晦涩难懂的字体还是验证码,你都需要向 Tesseract 提供每个字符不同形式的样本。
首先要收集大量的验证码样本,样本的数量和复杂程度,会决定训练的效果。第二步是准确地告诉 Tesseract 一张图片中的每个字符是什么,以及每个字符的具体位置。
这里需要创建一些矩形定位文件(box file),一个验证码图片生成一个矩形定位文件,也可以通过jTessBoxEditor软件来修改矩形的定位。
一个图片的矩形定位文件如下所示:
4 15 26 33 55 0M 38 13 67 45 0m 79 15 101 26 0C 111 33 136 60 03 147 17 176 45 0
第一列符号是图片中的每个字符,后面的 4 个数字分别是包围这个字符的最小矩形的坐标 (图片左下角是原点 (0,0),4 个数字分别对应每个字符的左下角 x 坐标、左下角 y 坐标、右上角 x 坐标和右上角 y 坐标),最后一个数字“0”表示图片样本的编号。
矩形定位文件必须保存在一个 .box 后缀的文本文件中,(例如 4MmC3.box)。
博客园的一篇不错的训练教程:http://www.cnblogs.com/mjorcen/p/3800739.html?utm_source=tuicool&utm_medium=referral
前面的内容只是对 Tesseract 库的字体训练和识别能力的一个简略概述。如果你对 Tesseract 的其他训练方法感兴趣,甚至打算建立自己的验证码训练文件库,推荐阅读 Tesseract 官方文档:https://github.com/tesseract-ocr/tesseract/wiki,加油!
后期内容提要:
- [Python爬虫] 十、Scrapy 框架
如果您有任何疑问或者好的建议,期待你的留言与评论!
[Python爬虫] 九、机器视觉与机器图像识别之Tesseract相关推荐
- Python爬虫(九)_案例:使用正则表达式的爬虫
现在拥有了正则表达式这把神兵利器,我们就可以进行对爬取到的全部网页源代码进行筛选了. 下面我们一起尝试一下爬取内涵段子网站: http://www.neihan8.com/article/list_5 ...
- [Python爬虫] 一、爬虫原理之HTTP和HTTPS的请求与响应
一.HTTP和HTTPS HTTP协议(HyperText Transfer Protocol,超文本传输协议):是一种发布和接收 HTML页面的方法. HTTPS(Hypertext Transfe ...
- [Python爬虫] 三、数据抓取之Requests HTTP 库
往期内容提要: [Python爬虫] 一.爬虫原理之HTTP和HTTPS的请求与响应 [Python爬虫] 二.爬虫原理之定义.分类.流程与编码格式 一.urllib 模块 所谓网页抓取,就是把URL ...
- [Python爬虫] 四、数据抓取之HTTP/HTTPS抓包工具Fiddler
往期内容提要: [Python爬虫] 一.爬虫原理之HTTP和HTTPS的请求与响应 [Python爬虫] 二.爬虫原理之定义.分类.流程与编码格式 [Python爬虫] 三.数据抓取之Request ...
- [Python爬虫] 二、爬虫原理之定义、分类、流程与编码格式
往期内容提要: [Python爬虫] 一.爬虫原理之HTTP和HTTPS的请求与响应 一.爬虫的定义.分类和流程 爬虫定义 网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟浏览器发送网络请求,接收请求 ...
- [Python爬虫] 六、数据提取之XPath与lxml类库
往期内容提要: [Python爬虫] 一.爬虫原理之HTTP和HTTPS的请求与响应 [Python爬虫] 二.爬虫原理之定义.分类.流程与编码格式 [Python爬虫] 三.数据抓取之Request ...
- 如何自学python爬虫-python爬虫学习过程:
1.掌握python的基本语法知识 2.学会如何抓取HTML页面: HTTP请求的处理:urlib.urlib2 及requests(reqests对urllib和urllib2进行了封装 ,功能相当 ...
- Python爬虫(九)——京东比价定向爬虫
文章目录 Python爬虫(九)--京东比价定向爬虫 判断可行性 查看链接 查看robots协议 程序的设计 步骤 方法 def getHTMLText(url) parsePage(ilt, htm ...
- Python爬虫初探(九)——爬虫之Beautifulsoup4实战(爬取豆瓣信息)
前面两章咱们介绍了Beautifuisoup4模块的简单使用,今天就用它来爬取豆瓣信息.话不多说,咱们开始吧. 一.拿到url地址 二.获取豆瓣数据 三.保存文件 需求: 爬取标题.评分.详情页的地址 ...
最新文章
- framebuffer的入门介绍-实现程序分析【转】
- 为什么static成员必须在类外初始化
- c#_foreach遍历
- 服务器跑python程序_远程编写+调试服务器上的Python程序
- 在bash脚本中进行浮点运算
- 2021年度总结——做好事不留名·CSDN中的【雷锋】
- win32窗口机制之CreateWindow
- ppp协议pap验证过程状态转移图_电脑网络知识:TCP协议的高级特性,你所不知道的TCP...
- 现在做Android开发有前途吗?社招面试心得
- ffmpeg结构体SpecifierOpt说明文档
- 【ElasticSearch】Es 源码之 RerouteService 源码解读
- 面试要15K,HR说你只值10K,怎么斗得过?
- shell 第六次作业(grep正则、sed)
- [RL 13] VDN (201706, DeepMind)
- 解决macOS idea启动web服务dock回自动打开Java图标
- CentOS7 安装 Oracle 11g rac(7) —— 安装 grid 软件前的准备工作
- 使用 字蛛 对ttf字体文件进行压缩
- 湘潭大学数据库考试(郭云飞)
- 按关键字采集淘特商品列表API接口H5
- Linux系统搭建gitit wiki