大屏21解决数据问题python-tesseract-ocr的安装及使用
大屏21解决数据问题python-tesseract-ocr的安装及使用
Python+Selenium+PIL+Tesseract真正自动识别验证码进行一键登录
0.0312016.08.06 10:59:14字数 2,097阅读 11,932
Python 2.7
IDE Pycharm 5.0.3
Selenium:Selenium的介绍及使用,强烈推荐@ Eastmount的博客
PIL :
Pillow-3.3.0-cp27-cp27m-win_amd64.whl PIL第三方库的下载
win下安装whl文件
Pytesser:依赖于PIL ,Tesseract 了解pytesser及基本使用
Tesseract:3.0.2 tesseract下载及安装
Firefox浏览器:47.0.1
我有个理想,就是把
TMD
教务系统弄崩溃,我港真的!
扯淡
我相信每个脚本都有自己的故事,我这个脚本来源于自己GRD教务系统,每次进行登录时,即使我输入全部正确,第一次登录一定是登不上去的!我不知道设计人员什么想法?悲催的没有人搭理,想到一个粗暴的方法,就是截屏,再用Image.crop
目的
自动识别验证码模拟登陆,注意是自动,一键登录,不是那种扫出验证码,然后手动输入登录!
首先来代码实现吧!
# -*- coding: utf-8 -*-
#Author:哈士奇说喵
fromselenium
importwebdriver
import os
import pytesser
importsys
,time
fromPIL
importImage
,ImageEnhance
#shift+tab多行缩进(左)
reload(sys
)
PostUrl
="http://yjsymis.hrbeu.edu.cn/gsmis/indexAction.do"
driver
=webdriver
.Firefox
()
driver
.get
(PostUrl
)
i
=0
while1:#sb登录系统,即使输对所有消息还是登不进去的,需要登录两次及以上
i
=i
+1
try:
elem_user
=driver
.find_element_by_name
('id')
elem_psw
=driver
.find_element_by_name
('password')
elem_code
=driver
.find_element_by_name
('checkcode')
except:
break
#-------------------对验证码进行区域截图,好吧,这方法有点low------------------
driver
.get_screenshot_as_file
('C:\Users\MrLevo\image1.jpg')#比较好理解
im
=Image
.open('C:\Users\MrLevo\image1.jpg')
box
=(516,417,564,437)
#设置要裁剪的区域
region
=im
.crop
(box
)#此时,region是一个新的图像对象。
#region.show()#显示的话就会被占用,所以要注释掉
region
.save
("e:/image_code.jpg")
#-------------------------------------------------------------------
#--------------ImageGrab.grab()直接可以区域截图,但是有bug,截图不全-------
'''
bbox = (780, 0, 1020, 800)
img = ImageGrab.grab()
img.save("E:\image_code.jpg")
img.show()
'''
#-------------------------手动输入验证码:适用范围更广,但不够方便------------------------------
'''
response = opener.open(CaptchaUrl)
picture = response.read()
with open('e:/image.jpg', 'wb') as local:
local.write(picture)
# 保存验证码到本地
#------------对于不能用pytesser+ocr进行识别,手动打开图片手动输入--------
# 打开保存的验证码图片 输入
#SecretCode = raw_input('please enter the code: ')
#----------------------------------------------------------------------
'''
#--------------------图片增强+自动识别简单验证码-----------------------------
#time.sleep(3)防止由于网速,可能图片还没保存好,就开始识别
def
image_file_to_string(file):
cwd
=os
.getcwd
()
try
:
os
.chdir
("C:\Users\MrLevo\Anaconda2\Lib")
return
pytesser
.image_file_to_string
(file)
finally:
os
.chdir
(cwd
)
im
=Image
.open("E:\\image_code.jpg")
imgry
=im
.convert
('L')#图像加强,二值化
sharpness
=ImageEnhance
.Contrast
(imgry
)#对比度增强
sharp_img
=sharpness
.enhance
(2.0)
sharp_img
.save
("E:\\image_code.jpg")
#http://www.cnblogs.com/txw1958/archive/2012/02/21/2361330.html
#imgry.show()#这是分布测试时候用的,整个程序使用需要注释掉
#imgry.save("E:\\image_code.jpg")
code
=pytesser
.image_file_to_string
("E:\\image_code.jpg")#code即为识别出的图片数字str类型
code
#打印code观察是否识别正确
#----------------------------------------------------------------------
if
i
<=2:
# 根据自己登录特性,我这里是验证码失败一次,重填所有,失败两次,重填验证码
elem_user
.send_keys
('S315080092')
elem_psw
.send_keys
('xxxxxxxxxx')
elem_code
.send_keys
(code
)
click_login
=driver
.find_element_by_xpath
("//img[@src='main_images/images/loginbutton.gif']")
click_login
.click
()
#time.sleep(5)#搜索结果页面停留片刻
#driver.save_screenshot('C:\Users\MrLevo\image.jpg')
#driver.close()
#driver.quit()
第一次放动图,心理还有点小激动~
实现登陆
遇到问题及解决方法
1:验证码取得问题,因为每次刷新之后验证码动态刷新,所以如果不采用cookie的话(我还不太会用cookie),根本捉不到元素,这个我在下篇文章中采用cookie来登录的,但不是调用浏览器,这个跑远了,下次说。
1:解决方案:用了driver.get_screenshot_as_file
方法,机智的进行全截图,然后采用PIL中的crop进行再截图操作,可能有人会说,为什么不采用ImageGrab.grab()
函数来做,好吧,因为这个函数在win10上尽然!截不了全图!!自己试了才知道,btw,我的分辨率1920x1080,难道和分辨率有关?反正这个我截了好久都没有成功,到最后才想到,截全部看看,结果,tmd只有一半,我说怎么都找不到要截图的部分!
2:验证码验证错误率高问题
2:解决方案,采用PIL强大的图像处理功能,我先将图片二值化,本来是蓝色字体的,,然后再进行对比度强化来锐化图片,然后再调用Tesseract.exe进行处理,提高的识别精度不是一点两点:看图比较,左1是用cookie抓的原图,右边是全景截图,再定位截图,再进行二值化和锐化处理的图,本来我想着用matlab做图像识别的,但是想想还要调用,感觉有点麻烦。。。
对比图
3:调用Tesseract.exe问题
3:解决方案因为程序执行图像识别需要调用Tesseract.exe,所以必须把路径切到有这个exe的路径下,刚开始,以为和包依赖,结果根本没有识别出任何图!折腾一个多小时才写好验证码识别的问题----单独测试的确很重要,记一笔!
这里写图片描述
4:登录失败问题--mdzz学校教务系统二次验证
4:解决方案,写了一个while循环,把主程序很大部分都扔进去了,目的也很明确,如果第一次登录失败,再重复进行登录,注意采用try试探元素是否仍然存在,except来抛出break结束循环,因为登录成功后,比如说driver.find_element_by_name('id')
是不存在的!所以当这个元素在登陆后的界面找不到时,那就说明登录成功,ok,跳出循环,进行下一步操作。
5:明明图片已截取,为什么没有识别
5:解决方案,这个我真的没想到,我一直以为可能因为save时候还没下载好,导致库中没有这张图,那就不能识别,但是我用time.sleep函数让它停下来缓缓,还是不行,我就很无语了,想了半天,可能是因为图片被占用!因为我有一个img.show()函数,为了检测有没有截取到标准的图,然后show之后这个图像就被占用了!就像你在编辑word时候,是无法删除word文档一样!果然在注释掉show之后,一切可行,真是差错查了小半天啊!!
这里写图片描述
6:元素一切就位,为什么不执行操作
6:解决方案,这个有点脑残了,不过的确是我遇到的,还是记上一笔,然后骂自己一遍sb,没有click()你让它怎么处理!!!就像用cookie登录时候还有个ENTRY呢!
7:两次验证失败后,用户名重复累加
7:解决方案,直接加了个变量,计数循环次数,观察到只要超过两次没有登录上,就会累加登录名和用户密码,直接写了个if进行判断,完事!
8:im.crop(box)裁剪区域选择困难症
8:解决方案,多试几次,反正我是试出来的。。。。当然,你点击图片进行审查元素时候,可以看到图片大小,那么,你就可以知道横纵坐标差值多少,但是大范围区域还得自己试,如有更好的办法,请告知,以下为我截图实验次数,次数30+
这里写图片描述
9:导入不了Image,ImageEnhance
9:解决方案,因为PIL用的是第三方库,所以,采用的导入方式是这样的,多看看官方文档就可以,官方描述如下
Use
from PIL import Imageinstead of
import Image.
10:找不到应该键入的元素
10:这个问题,请单击要输入的空白处右键,审查元素,就可以看到,然后根据driver.find_element_by_
各种方法来定位元素,如果输入进行了隐藏,在当前页面找不到怎么办,就像如下图,需要先点击我的图书馆,才能看到输入的账户和密码,那么先找我的图书馆的元素,进行click操作,之后再找元素,一句话,把自己想成浏览器,阿不,把python想成浏览器。。。。。
登陆图书馆
上图的代码我也放上,大同小异,比有验证码的简单,但是多了一个click操作。
# -*- coding: utf-8 -*-
#Author:哈士奇说喵
fromselenium
importwebdriver
import time
import sys
#shift+tab多行缩进(左)
reload(sys
)
PostUrl
="http://lib.hrbeu.edu.cn/#"
driver
=webdriver
.Firefox
()
driver
.get
(PostUrl
)
elem_user
=driver
.find_element_by_name
('number')
elem_psw
=driver
.find_element_by_name
('passwd')
#选择我的图书馆,点击后才能看到输入账号密码
click_first
=driver
.find_element_by_xpath
("//ul[@id='imgmenu']/li[4]")
click_first
.click
()
elem_user
.send_keys
('S315080092')
elem_psw
.send_keys
('xxxxxxxx')
#点击登录
click_second
=driver
.find_element_by_name
('submit')
click_second
.click
()
time
.sleep
(5)
#登陆后选择
click_third
=driver
.find_element_by_xpath
("//*[@id='mainbox']/div/div/ul/li/a")
click_third
.click
()
time
.sleep
(5)#搜索结果页面停留片刻
#driver.save_screenshot('C:\Users\MrLevo\image.jpg')
driver
.close
()
driver
.quit
()
最后
(虽然我知道以后肯定会再补充):断断续续差不多两天时间来实现这个操作,虽然对大家来说应该不算难,但是对自己还是有蛮大提升的,对selenium有了基本的概念和操作,对PIL也进行了使用,还有ocr的调用,虽然调用firefox来执行操作表面上看起来很酷炫,但是执行效率和占用内存是很大的内伤,但作为可视化的模拟浏览器登录,这点做的还是十分绚丽的。
Tesseract-OCR 字符识别---样本训练
yasi_xi 2013-04-06 09:53:59 91291 收藏 11
转自:http://blog.csdn.net/feihu521a/article/details/8433077
Tesseract是一个开源的OCR(Optical Character Recognition,光学字符识别)引擎,可以识别多种格式的图像文件并将其转换成文本,目前已支持60多种语言(包括中文)。 Tesseract最初由HP公司开发,后来由Google维护,目前发布在Googel Project上。地址为http://code.google.com/p/tesseract-ocr/。
使用默认的语言库识别
1.安装Tesseract
从 http://code.google.com/p/tesseract-ocr/downloads/list下载Tesseract,目前版本为Tesseract3.02。因为只是测试使用,这里直接下载winodws下的安装文件tesseract-ocr-setup-3.02.02.exe。安装成功后会在相应磁盘上生成一个Tesseract-OCR目录。通过目录下的tesseract.exe程序就可以对图像字符进行识别了。
2.准备一副待识别的图像,这里用画图工具随便写了一串数字,保存为number.jpg,如下图所示:
3. 打开命令行,定位到Tesseract-OCR目录,输入命令:
[plain] view plain copy
- tesseract.exe number.jpg result -l eng
其中result表示输出结果文件txt名称,eng表示用以识别的语言文件为英文。
3. 打开Tesseract-OCR目录下的result.txt文件,看到识别的结果为7542315857,有3个字符识别错误,识别率还不是很高,那有没有什么方法来提供识别率呢?Tesseract提供了一套训练样本的方法,用以生成自己所需的识别语言库。下面介绍一下具体训练样本的方法。
训练样本
关于如何训练样本,Tesseract-OCR官网有详细的介绍 http://code.google.com/p/tesseract-ocr/wiki/TrainingTesseract3。这里通过一个简单的例子来介绍一下如何进行样本训练。
1.下载工具jTessBoxEditor. http://sourceforge.net/projects/vietocr/files/jTessBoxEditor/,这个工具是用来训练样本用的,由于该工具是用JAVA开发的,需要安装JAVA虚拟机才能运行。
2. 获取样本图像。用画图工具绘制了5张0-9的文样本图像(当然样本越多越好),如下图所示:
3.合并样本图像。运行jTessBoxEditor工具,在点击菜单栏中Tools--->Merge TIFF。在弹出的对话框中选择样本图像(按Shift选择多张),合并成num.font.exp0.tif文件。
4.生成Box File文件。打开命令行,执行命令:
[plain] view plain copy
- tesseract.exe num.font.exp0.tif num.font.exp0 batch.nochop makebox
生成的BOX文件为num.font.exp0.box,BOX文件为Tessercat识别出的文字和其坐标。
注:Make Box File 文件名有一定的格式,不能随便乱取名字,命令格式为:
[plain] view plain copy
- tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox
其中lang为语言名称,fontname为字体名称,num为序号,可以随便定义。
【Yasi】:先前自己定义了tessdata的环境变量 TESSDATA_PREFIX 值为 E:\tesseract\tessdata,但没有从tesseract源文件目录中将tessdata子目录中的内容copy到 E:\tesseract\tessdata 中,造成上面的命令报错,说找不到batch.nochop 和 makebox。解决办法:将 tesseract 源文件目录中所有文件和子文件夹(可能充分但非必要,先不管这些啦)copy到 E:\tesseract\tessdata 中。
5.文字校正。运行jTessBoxEditor工具,打开num.font.exp0.tif文件(必须将上一步生成的.box和.tif样本文件放在同一目录),如下图所示。可以看出有些字符识别的不正确,可以通过该工具手动对每张图片中识别错误的字符进行校正。校正完成后保存即可。
【Yasi】这里必须修改识别错误的字符,否则做出来的traineddata文件也是错的。可以在下面的界面中修改并保存,也可以直接在traineddata文件中修改。
6.定义字体特征文件。Tesseract-OCR3.01以上的版本在训练之前需要创建一个名称为font_properties的字体特征文件。
font_properties不含有BOM头,文件内容格式如下:
[plain] view plain copy
- <fontname> <italic> <bold> <fixed> <serif> <fraktur>
其中fontname为字体名称,必须与[lang].[fontname].exp[num].box中的名称保持一致。<italic> 、<bold> 、<fixed> 、<serif>、 <fraktur>的取值为1或0,表示字体是否具有这些属性。
这里在样本图片所在目录下创建一个名称为font_properties的文件,用记事本打开,输入以下下内容:
[plain] view plain copy
- font 0 0 0 0 0
这里全取值为0,表示字体不是粗体、斜体等等。
7.生成语言文件。在样本图片所在目录下创建一个批处理文件,输入如下内容。
[plain] view plain copy
- rem 执行改批处理前先要目录下创建font_properties文件
- echo Run Tesseract for Training..
- tesseract.exe num.font.exp0.tif num.font.exp0 nobatch box.train
- echo Compute the Character Set..
- unicharset_extractor.exe num.font.exp0.box
- mftraining -F font_properties -U unicharset -O num.unicharset num.font.exp0.tr
10. echo Clustering..
11. cntraining.exe num.font.exp0.tr
- 12.
13. echo Rename Files..
14. rename normproto num.normproto
15. rename inttemp num.inttemp
16. rename pffmtable num.pffmtable
17. rename shapetable num.shapetable
- 18.
19. echo Create Tessdata..
20. combine_tessdata.exe num.
将批处理通过命令行执行。执行后的结果如下:
需确认打印结果中的Offset 1、3、4、5、13这些项不是-1。这样,一个新的语言文件就生成了。
num.traineddata便是最终生成的语言文件,将生成的num.traineddata拷贝到Tesseract-OCR-->tessdata目录下。可以用它来进行字符识别了。
使用训练后的语言库识别
用训练后的语言库识别number.jpg文件, 打开命令行,定位到Tesseract-OCR目录,输入命令:
[plain] view plain copy
- tesseract.exe number.jpg result -l eng
识别结果如如图所示,可以看到识别率提高了不少。通过自定义训练样本,可以进行图形验证码、车牌号码识别等。感兴趣的朋友可以研究研究。
【Yasi】试验结果如下:
下面是num-yasi.png
将生成的num.traineddata拷贝到E:\tesseract\tessdata,即环境变量TESSDATA_PREFIX 设置的路径下,执行下面的命令( 注意第二条命令结尾是num,即新加的traineddata,而不是eng)
E:\
tesseract\
tesseract-svn\
vs2008\
LIB_Debug\
tesseractd.exenum-yasi.png
result-eng
-l
eng
E:\
tesseract\
tesseract-svn\
vs2008\
LIB_Debug\
tesseractd.exenum-yasi.png
result-num
-l
num
下图是两次识别结果对比
使用eng traineddata的结果完全不靠谱;使用了自己的traineddata,识别出来的当然都是数字,但正确率实在糟糕。可能是我自己手写的字体和用来做traineddata的手写数字的字体差别太大了吧。
- 微软Azure 图像识别:https://azure.microsoft.com/z...
- 有道智云文字识别:http://aidemo.youdao.com/ocrdemo
- 阿里云图文识别:https://www.aliyun.com/produc...
- 腾讯OCR文字识别: https://cloud.tencent.com/pro...
C:\Users\Administrator.Windwos 10YKMNH>doskey /history
D:\anaconda3python3\tesseract4ocr\tesseract.exe
D:\anaconda3python3\tesseract4ocr\tesseract.exe -v
tesseract.exe -v
tesseract -v
doskey /history
tesseract-ocr的安装及使用
版权
1、下载安装包
根据https://github.com/tesseract-ocr/tesseract/wiki,我找到非官方的安装包,好像我只看到64位的安装包http://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-4.00.00dev.exe,下载后直接安装即可,但是要记得你的安装目录,我们等会配置环境变量要用。
win10添加完tesseract_prefix后一定要重启!
如果不是做英文的图文识别,还需要下载其他语言的识别包https://github.com/tesseract-ocr/tesseract/wiki/Data-Files。
简体字识别包:https://raw.githubusercontent.com/tesseract-ocr/tessdata/4.00/chi_sim.traineddata
繁体字识别包:https://github.com/tesseract-ocr/tessdata/raw/4.0/chi_tra.traineddata
或者直接我的百度云盘:链接:tesseract 密码:tmdm
We've Moved!
These wiki pages are no longer maintained.
All pages were moved to tesseract-ocr/tessdoc.
The latest documentation is available at https://tesseract-ocr.github.io/.
Please find this page in its new home: https://tesseract-ocr.github.io/tessdoc/Data-Files
第二步:安装
直接执行下载好的tesseract-ocr-setup-4.0.0-alpha.20180109.exe,下一步、下一步安装。安装过程中,会让你安装额外的语言包,可根据选择下载。
第三步:配置环境变量
我的是安装在C:\Program Files (x86)\Tesseract-OCR,界面如下:
将“F:\Tesseract-OCR”添加到环境变量中。如图:
增加一个TESSDATA_PREFIX变量名,变量值还是我的安装路径F:\Tesseract-OCR\tessdata这是将语言字库文件夹添加到变量中;
使用
打开命令终端,输入:tesseract -v,可以看到版本信息
用命令tesseract --list-langs来查看Tesseract-OCR支持语言。
将命令行切换至目标图像文件目录,比如我们转换文件为test.png(图片文件允许多种格式),位于C:\Users\Lian\Desktop\test;然后在命令行中输入
tesseract test.png output_1 –l eng
【语法】: tesseract imagename outputbase [-l lang] [-psm pagesegmode] [configfile…]
imagename为目标图片文件名,需加格式后缀;outputbase是转换结果文件名;lang是语言名称(在Tesseract-OCR中tessdata文件夹可看到以eng开头的语言文件eng.traineddata),如不标-l eng则默认为eng。
打开文件output_1.txt,发现tesseract成功的将图像转换成152408。
遇到的问题:
问题1:
没有配置环境变量,按上面情况将环境变量配置好
问题2:
E:\testdir>tesseract ttest1.png test1 -l eng
Error opening data file \Program Files (x86)\Tesseract-OCR\tessdata/eng.traineddata
Please make sure the TESSDATA_PREFIX environment variable is set to the parent directory of your "tessdata" directory.
Failed loading language 'eng'
Tesseract couldn't load any languages!
Could not initialize tesseract.
错误信息的关键词是tesseract_prefix的环境变量设置。
解决办法: 找到testData所在的目录,默认情况下是在tesseract安装的目录,在环境变量中设置TESSDATA_PREFIX的环境变量为testdata所在的目录即可。 重新运行命令即可正常使用。
————————————————
版权声明:本文为CSDN博主「褶皱的包子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37193537/article/details/81335165
自动化在一些场景给人带来方便,但是也有一些技术上的难题,比如登录时候会输入验证码。这篇就写一下关于验证码的处理。
如果是测试环境,就很简单了,常用的两种办法:
1.让开发把验证码注释掉。
2.让开发设置一个万能验证码,只要输入这个验证码就能通过。(感觉这个比较靠谱)
如果是生产环境,再用上面的办法就不太好了,不过还有另外两种办法(如果不嫌麻烦,测试环境也可以用):
1.使用cookie跳过登录。
2.使用验证码识别技术。
看第一种办法,点这里。
第二种研究验证码识别的时间比较长了,遇到的一些坑记得不太清了,就写一下正常的流程,细心一些应该都不会遇到坑。
注意(敲黑板):这是python3能实现的,python2不能用。我这种实现方法仅能识别特别清楚的验证码,如果验证码图片干扰很多,就别看了,实现不了。我用的是个实验的网址,验证码能识别一小部分,下面先放两张识别效果。
第一张现实和理想差距有点大,我最多在代码里去掉特殊符号,剩下识别错了真是没办法了。
仍然想试的可以继续往下走,我这是生产环境, 可以在这里试验,如果能注册一下就更好了。(关注微信公众号,周五可能会有特价机票哦)打了一个广告。
首先得装环境,识别验证码已经不是selenium自己能办到的了。cmd下输入下面命令:
pip install Pillow(如果报错,输入:pip.exe install Pillow)
pip install pytesseract(如果报错,输入:pip.exe install pytesseract)
第一个是对图片处理的包,第二个是识别验证码的包,还需要下载个包,百度搜索:Tesseract-OCR,下载解压到电脑,可以不放在C盘,这个好像也没有位数限制。
解压到电脑以后需要加上环境变量,在path里加上Tesseract-OCR的路径,然后在pycharm里(我只用这个,别的工具什么情况我不知道),External Libraries->Python 3.x->Lib->site-packages->pytesseract->pytesseract.py里面修改一段代码:
由于斜杠是转义字符,我就用了双斜杠,一定要看清不是只加到环境变量的那个路径,后面要加到tesseract.exe,我只记得这一个坑,执行脚本总是提示我未安装或者没配置环境变量。准备工作就这么多,下面我放上我的代码,供参考。
# -*- coding: utf-8 -*-
# python 3.7.0
#
import re
import requests
import pytesseract
from selenium import webdriver
from PIL import Image, ImageEnhance
import time
#
driver=webdriver.Chrome()
driver.maximize_window()
driver.get("https://higo.flycua.com/hp/html/login.html")
driver.implicitly_wait(30)
#下面用户名和密码涉及到我个人信息,所以隐藏
driver.find_element_by_name('memberId').send_keys('xxxxxx')
driver.find_element_by_name('password').send_keys('xxxxxx')
#因为验证码不能一次就正确识别,我加了循环,一直识别,直到登录成功
while True:
#清空验证码输入框,因为可能已经识别过一次了,里面有之前识别的错的验证码
driver.find_element_by_name("verificationCode").clear()
# 截图或验证码图片保存地址
screenImg = "H:\screenImg.png"
# 浏览器页面截屏
driver.get_screenshot_as_file(screenImg)
# 定位验证码位置及大小
location = driver.find_element_by_name('authImage').location
size = driver.find_element_by_name('authImage').size
#下面四行我都在后面加了数字,理论上是不用加的,但是不加我这截的不是验证码那一块的图,可以看保存的截图,根据截图修改截图位置
left = location['x']+530
top = location['y']+175
right = location['x'] + size['width']+553
bottom = location['y'] + size['height']+200
# 从文件读取截图,截取验证码位置再次保存
img = Image.open(screenImg).crop((left, top, right, bottom))
#下面对图片做了一些处理,能更好识别一些,相关处理再百度看吧
img = img.convert('RGBA') # 转换模式:L | RGB
img = img.convert('L') # 转换模式:L | RGB
img = ImageEnhance.Contrast(img) # 增强对比度
img = img.enhance(2.0) # 增加饱和度
img.save(screenImg)
# 再次读取识别验证码
img = Image.open(screenImg)
code = pytesseract.image_to_string(img)
#打印识别的验证码
#print(code.strip())
#识别出来验证码去特殊符号,用到了正则表达式,这是我第一次用,之前也没研究过,所以用的可能粗糙,请见谅
b=''
for i in code.strip():
pattern = re.compile(r'[a-zA-Z0-9]')
m = pattern.search(i)
if m!=None:
b+=i
#输出去特殊符号以后的验证码
print (b)
#把b的值输入验证码输入框
driver.find_element_by_name("verificationCode").send_keys(b)
#点击登录按钮
driver.find_element_by_class_name('login-form-btn-submit').click()
#定时等待5秒,如果验证码识别错误,提示验证码错误需要等一会儿才能继续操作
time.sleep(5)
#获取cookie,并把cookie转化为字符串格式
cookie1= str(driver.get_cookies())
print (cookie1)
#第二次用正则表达式,同样有点粗糙,代码实现的功能就是看cookie里是否有tokenId这个词,如果有说明登录成功,跳出循环,可以进行后面的自动化操作,如果没有,则表示登录失败,继续识别验证码
matchObj = re.search(r'tokenId', cookie1, re.M | re.I)
if matchObj:
print (matchObj.group())
break
else:
print ("No match!!")
print ('结束')
大概就是这些, 希望能有所帮助。
————————————————
版权声明:本文为CSDN博主「宇文诸」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhu940923/article/details/81264542
深度学习入门——基于Python的理论和实现》的第N天,这本书,教你如何利用python,不用机器学习第三方库,自己去实现那些高大上的机器学习能实现的功能。
是的它会涉及到很多数学知识,尤其是矩阵的处理,还有微分等等,但是作者写的真的很细心,真厉害的人物。
在看这种类型书的时候,不知道你们会不会有这种情况,上一次看的内容很容易忘记(可能是我每次看隔的时间都太长了,没有一口气把它看完,但是这真的很难做到),特别是很多的函数在后面的实例调用的时候,可能我还能记得这个函数是干嘛用的,却很难想起来它是怎么实现的…所以,我们需要做总结,要多做总结,总结,结。
好了言归正传,你是否很好奇,程序是如何看懂一张图片上的手写数字到底是几呢?没有天才的头脑,我根本想不出可能用程序实现计算机视觉的方法,但是神奇的是,像识别数字这样的技术,技术上甚至可以达到99%的正确率。那么到底是如何实现的呢,看了前四章,我似乎明白了,哦!原来是这样,真**的牛逼!
让我们来看看自己如何编写一个能识别数字图片的Python程序(专业的部分真的没把握讲清楚,有兴趣的一定要去看看这本书)
1.
首先,我们知道计算机可以识别图片中的数字,是通过从大量的图片中找规律(似乎可以这么认为,其实是通过不断调节所谓的神经网络中的参数的方法),从而找到图片像素和标签之间的某种关系,以达到识别的目的。简单说就是这样:
给一个图片
机器随机初始化参数(其实若按照正态分布初始化将取得较好的结果)
机器:这是0
修改参数
机器调节下自己的神经网络参数:这是5
修改参数
机器再调节下自己的神经网络参数:这是3
修改参数
…(不停重复)
(不知道结果怎么知道如何修改参数呢?很简单,人工来标注好正确结果)
2.
所以,我们要实现这么几个步骤
(1)我要大量的数据来让我学习和测试结果。可以用MNIST(一个有60000数字图片且已经人工标注好的数据集)
(2)我要写一个函数用于判断这个图片是数字几
(3)我要写一个函数,用来告诉我我的结果和正确结果差多少(我们先管这个值叫loss),我通过调节参数应该让这个值不断降低
(4)我要写一个函数来调节神经网络的参数。这块还要注意,参数调节可不是随便调节的,我们要想方法让参数的调节使得loss减小,而且是减小的最快的那个方向(这块用一个叫做梯度法的方法,涉及微分,其实花点时间你可以搞明白的)
(5)最后就是循环,不停的修正我们的参数,到了后面,我们的识别正确率也就越来越高了
来看代码实现,第一部分是主要函数的实现,第二部分是识别的流程:
#功能
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
import random
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def softmax(x):
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0)
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T
x = x - np.max(x) # 溢出对策
return np.exp(x) / np.sum(np.exp(x))
def cross_entropy_error(y, t):
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
# 监督数据是one-hot-vector的情况下,转换为正确解标签的索引
if t.size == y.size:
t = t.argmax(axis=1)
batch_size = y.shape[0]
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size
def numerical_gradient(f, x):
h = 1e-4 # 0.0001
grad = np.zeros_like(x)
it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
while not it.finished:
idx = it.multi_index
tmp_val = x[idx]
x[idx] = float(tmp_val) + h
fxh1 = f(x) # f(x+h)
x[idx] = tmp_val - h
fxh2 = f(x) # f(x-h)
grad[idx] = (fxh1 - fxh2) / (2 * h)
x[idx] = tmp_val # 还原值
it.iternext()
return grad
def sigmoid_grad(x):
return (1.0 - sigmoid(x)) * sigmoid(x)
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
# 初始化权重
self.params = {}
self.params['W1'] = weight_init_std * np.random.randn(input_size, hidden_size)
self.params['b1'] = np.zeros(hidden_size)
self.params['W2'] = weight_init_std * np.random.randn(hidden_size, output_size)
self.params['b2'] = np.zeros(output_size)
def predict(self, x):
W1, W2 = self.params['W1'], self.params['W2']
b1, b2 = self.params['b1'], self.params['b2']
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)
return y
# x:输入数据, t:监督数据
def loss(self, x, t):
y = self.predict(x)
return cross_entropy_error(y, t)
def accuracy(self, x, t):
y = self.predict(x)
y = np.argmax(y, axis=1)
t = np.argmax(t, axis=1)
accuracy = np.sum(y == t) / float(x.shape[0])
return accuracy
# x:输入数据, t:监督数据
def numerical_gradient(self, x, t):
loss_W = lambda W: self.loss(x, t)
grads = {}
grads['W1'] = numerical_gradient(loss_W, self.params['W1'])
grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
grads['W2'] = numerical_gradient(loss_W, self.params['W2'])
grads['b2'] = numerical_gradient(loss_W, self.params['b2'])
return grads
def gradient(self, x, t):
W1, W2 = self.params['W1'], self.params['W2']
b1, b2 = self.params['b1'], self.params['b2']
grads = {}
batch_num = x.shape[0]
# forward
a1 = np.dot(x, W1) + b1
z1 = sigmoid(a1)
a2 = np.dot(z1, W2) + b2
y = softmax(a2)
# backward
dy = (y - t) / batch_num
grads['W2'] = np.dot(z1.T, dy)
grads['b2'] = np.sum(dy, axis=0)
da1 = np.dot(dy, W2.T)
dz1 = sigmoid_grad(a1) * da1
grads['W1'] = np.dot(x.T, dz1)
grads['b1'] = np.sum(dz1, axis=0)
return grads
128
# coding: utf-8
#测试
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from chapter4.allfun import TwoLayerNet
import random
# 读入数据,分别表示 用于训练的数据 用于训练的数据对应的标签 用于测试的数据 用于测试的数据对应的标签
#暂时没必要知道它是怎么加载的,你知道知道他们表示什么就可以了
# #另外,图片数据是(28*28)像素的矩阵,修改load_mnist的参数也可以把(28*28)转换成(784,)这样的形状
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
#这个network 就是我们的神经网络
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
iters_num = 5000 # 适当设定循环的次数
#每次从所有训练数据中抽出100个来学习 这个叫做mini-batch学习
batch_size = 100
#一共多少个训练数据 60000个
train_size = x_train.shape[0]
#学习率,这个影响每次修正神经网络中参数时的力度
learning_rate = 0.1
#训练开始
for i in range(iters_num):
#mini - batch学习,随机抽取 batch_size 个数据
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
# 计算梯度 下面是两种方法,还记得梯度是干嘛的吗,它告诉我如何能让我的loss减小的最快
# 第一种方法较慢,叫做数值微分,就是用python计算微分结果
# 第二种方法快 叫做误差反向传播,我觉得自己无法解释清楚,它是一种利用"计算图"来快速求微分的方法
# 返回的这个值,用于更新神经网络的参数
# grad = network.numerical_gradient(x_batch, t_batch)
grad = network.gradient(x_batch, t_batch)
# 更新参数,一共4个参数,每层神经网络2个,一个2个神经网络层
for key in ('W1', 'b1', 'W2', 'b2'):
network.params[key] -= learning_rate * grad[key]
print('模型训练完成')
# 修改这个值,测试不同图片
whtch = 101
y = network.predict(x_test[whtch])
y = np.argmax(y)
print('y', y)
mytestone = np.array(x_test[whtch])
mytestone = mytestone.reshape(28, 28)
plt.imshow(mytestone)
plt.title(str(y))
plt.show()
#MNIST数据集加载部分
# coding: utf-8
try:
import urllib.request
except ImportError:
raise ImportError('You should use Python 3.x')
import os.path
import gzip
import pickle
import os
import numpy as np
url_base = 'http://yann.lecun.com/exdb/mnist/'
key_file = {
'train_img':'train-images-idx3-ubyte.gz',
'train_label':'train-labels-idx1-ubyte.gz',
'test_img':'t10k-images-idx3-ubyte.gz',
'test_label':'t10k-labels-idx1-ubyte.gz'
}
dataset_dir = os.path.dirname(os.path.abspath(__file__))
save_file = dataset_dir + "/mnist.pkl"
train_num = 60000
test_num = 10000
img_dim = (1, 28, 28)
img_size = 784
def _download(file_name):
file_path = dataset_dir + "/" + file_name
if os.path.exists(file_path):
return
print("Downloading " + file_name + " ... ")
urllib.request.urlretrieve(url_base + file_name, file_path)
print("Done")
def download_mnist():
for v in key_file.values():
_download(v)
def _load_label(file_name):
file_path = dataset_dir + "/" + file_name
print("Converting " + file_name + " to NumPy Array ...")
with gzip.open(file_path, 'rb') as f:
labels = np.frombuffer(f.read(), np.uint8, offset=8)
print("Done")
return labels
def _load_img(file_name):
file_path = dataset_dir + "/" + file_name
print("Converting " + file_name + " to NumPy Array ...")
with gzip.open(file_path, 'rb') as f:
data = np.frombuffer(f.read(), np.uint8, offset=16)
data = data.reshape(-1, img_size)
print("Done")
return data
def _convert_numpy():
dataset = {}
dataset['train_img'] = _load_img(key_file['train_img'])
dataset['train_label'] = _load_label(key_file['train_label'])
dataset['test_img'] = _load_img(key_file['test_img'])
dataset['test_label'] = _load_label(key_file['test_label'])
return dataset
def init_mnist():
download_mnist()
dataset = _convert_numpy()
print("Creating pickle file ...")
with open(save_file, 'wb') as f:
pickle.dump(dataset, f, -1)
print("Done!")
def _change_one_hot_label(X):
T = np.zeros((X.size, 10))
for idx, row in enumerate(T):
row[X[idx]] = 1
return T
def load_mnist(normalize=True, flatten=True, one_hot_label=False):
"""读入MNIST数据集
Parameters
----------
normalize : 将图像的像素值正规化为0.0~1.0
one_hot_label :
one_hot_label为True的情况下,标签作为one-hot数组返回
one-hot数组是指[0,0,1,0,0,0,0,0,0,0]这样的数组
flatten : 是否将图像展开为一维数组
Returns
-------
(训练图像, 训练标签), (测试图像, 测试标签)
"""
if not os.path.exists(save_file):
init_mnist()
with open(save_file, 'rb') as f:
dataset = pickle.load(f)
if normalize:
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].astype(np.float32)
dataset[key] /= 255.0
if one_hot_label:
dataset['train_label'] = _change_one_hot_label(dataset['train_label'])
dataset['test_label'] = _change_one_hot_label(dataset['test_label'])
if not flatten:
for key in ('train_img', 'test_img'):
dataset[key] = dataset[key].reshape(-1, 1, 28, 28)
return (dataset['train_img'], dataset['train_label']), (dataset['test_img'], dataset['test_label'])
if __name__ == '__main__':
init_mnist()
我们把测试图片和识别结果打印出来看看,我们可以得到这样的结果:
世界上就是有那些牛逼的人,能想出方法。
————————————————
版权声明:本文为CSDN博主「阿大古 古古古」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42718004/article/details/105330935
识别图片中的文字 - Tesseract 和 百度云OCR的对比
betacat发布于 2018-01-16
当今时代人工智能都已经是烂大街的词了,OCR应该也很多人都知道。
OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程。
本文主要记录了通过Python使用OCR的两次尝试。
Tesseract
Tesseract,一款由HP实验室开发由Google维护的开源OCR(Optical Character Recognition , 光学字符识别)引擎,特点是开源,免费,支持多语言,多平台。
项目地址:https://github.com/tesseract-...
安装使用
Tesseract的安装比较简单,在mac可以通过brew安装。
brew install --with-training-tools tesseract
在windows可以通过exe安装包安装,下载地址可以从GitHub项目中的wiki找到。安装完成后记得将Tesseract 执行文件的目录加入到PATH中,方便后续调用。
另外,默认安装会包含英文语言训练包,如果需要支持简体中文或者繁体中文,需要在安装时勾选。
或者安装结束后到项目地址下载:https://github.com/tesseract-...
下载好的语言包放入到安装目录中的testdata下即可。在windows系统你还需要将testdata目录也加入环境变量。
TESSDATA_PREFIX=C:
\Program Files (x86)
\Tesseract-OCR
\tessdata
如果一切就绪,你在命令行中就可以使用Tesseract命令。
# tesseract
Usage:
tesseract --help | --help-psm | --help-oem | --
version
tesseract --list-langs [--tessdata-dir PATH]
tesseract --print-parameters [options...] [configfile...]
tesseract imagename|stdin outputbase|stdout [options...] [configfile...]
OCR options:
--tessdata-dir PATH Specify the
locationof
tessdata path.
--user-words PATH Specify the
locationof
user
words
file.
--user-patterns PATH Specify the
locationof
user
patterns
file.
-l LANG[+LANG] Specify language(s) used for OCR.
-c
VAR=VALUE Set value for config variables.
Multiple -c arguments are allowed.
--psm NUM Specify page segmentation mode.
--oem NUM Specify OCR Engine mode.
NOTE: These options must occur before any configfile.
通过命令行你就可以完成简单的图片文字识别任务。
tesseract
test.png
outfile-
lchi_sim
通过Python调用
Tesseract安装完成后可以很方便的被Python调用,你需要安装两个包。
pip
installpillow
pip
installpytesseract
一个简单的图片转文字的函数实现如下。
fromPIL
importImage
import pytesseract
class Languages:
CHS =
'chi_sim'
CHT =
'chi_tra'
ENG =
'eng'
def img_to_str(image_path, lang=Languages.ENG):
return
pytesseract.image_to_string(Image.
open(image_path), lang)
(img_to_str(
'image/test1.png', lang=Languages.CHS))
(img_to_str(
'image/test2.png', lang=Languages.CHS))
测试图片- test1.png
:
识别结果:
processimage
file"image/test1.png"
in
1.4782530478747697
seconds
8
所
调
人
,
在
-
方
。
深
从
久
,
定
中
央
。
所
澈
伊
人
,
圭
水
淳
。
淇
渡
从
之
,
定
圭
北
中
坂
。
。
所
澈
伊人
,
圭
水
浩
从
丿
,
定
圭
水
中
沥
。
测试图片 - test2.png
识别结果:
processimage
file"image/test2.png"
in
1.2131140296607923
seconds
清
明
时
节
雨
纷
纷
,
路
上
行
人
欲
断
魂
信
问
酒
家
何
处
有
,
牧
奕
通
指
枪
花
村
。
小结
Tesseract在识别清晰的标准中文字体效果还行,稍微复杂的情况就很糟糕,而且花费的时间也很多,我个人觉得唯一的优点就是免费了。如果你不介意多花时间,可以考虑使用它提供的训练功能自定义你的语言库,那样在特定场景下识别率应该能上一个台阶。
百度云OCR
这是偶然的发现,百度云提供了一定额度的免费的OCR API,目前是每日500次,做做研究或者小应用还勉强够用,本文主要为了测试其效果。
文档地址:https://cloud.baidu.com/doc/O...
安装使用
首先你需要注册一个百度云BCE账号,然后从控制面板新建一个文字识别应用。
之后你就可以获得调用API需要的 AppID,API Key 和 Secret Key。后面只要根据官方文档一步一步走就可以了。
pip
installbaidu-aip
封装和调用
参考文档: https://cloud.baidu.com/doc/O...
fromaip
importAipOcr
config = {
'appId'
:
'your-id',
'apiKey'
:
'your-key',
'secretKey'
:
'your-secret-key'
}
client = AipOcr(**config)
def get_file_content(file):
with
open
(file,
'rb')
asfp:
return
fp.read()
def img_to_str(image_path):
image = get_file_content(image_path)
result = client.basicGeneral(image)
if
'words_result'
in
result:
return
'\n'
.join([w[
'words']
forw
inresult[
'words_result']])
测试图片- test1.png
:
识别结果:
processimage
file"image/test1.png"
in
0.6331169034812572
seconds
蒹葭
先秦
:
佚名
蒹葭苍苍
,
白露为霜。所谓伊人
,
在水一方。
溯洄从之
,
道阻且长。溯游从之
,
宛在水中央。
蒹葭萋萋
,
白露未晞。所谓伊人
,
在水之湄。
溯洄从之
,
道阳且跻。溯游从之
,
宛在水中坻。
蒹葭采采
,
白露未已。所谓伊人
,
在水之涘。
溯洄从之
,
道阻且右。溯游从之
,
宛在水中沚。
测试图片 - test2.png
识别结果:
processimage
file"image/test2.png"
in
0.6621812639450142
seconds
清明时节雨纷纷
,
路上行人欲断魂。
借问酒家何处有
,
牧童遥指杏花村。
小结
测试结果很明显,我只能说百度云这个OCR真是挺厉害的,一个错别字都没有,不服不行。论中文,还是百度比谷歌更懂一点。而且百度OCR提供了更多的参数让你更灵活的处理图片,比如自定义旋转,返回可信度,特定类型证件识别等等。
更多的OCR
除了本文提到的OCR,其实还是有不少其他选择。有一些直接提供Demo页面,你直接上传一张图片就可以直接看到识别效果,比如:
- 微软Azure 图像识别:https://azure.microsoft.com/z...
- 有道智云文字识别:http://aidemo.youdao.com/ocrdemo
- 阿里云图文识别:https://www.aliyun.com/produc...
- 腾讯OCR文字识别: https://cloud.tencent.com/pro...
你有没有发现所有的大公司都有这样的服务?以后我们买买买就行