大屏21解决数据问题python-tesseract-ocr的安装及使用 Python+Selenium+PIL+Tesseract真正自动识别验证码进行一键登录 Tesseract-OCR 字符识别---样本训练 识别图片中的文字 - Tesseract 和 百度云OCR的对比

大屏21解决数据问题python-tesseract-ocr的安装及使用

mrlevo520关注

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:哈士奇说喵
from selenium import webdriver
import os
import pytesser
import sys,time
from PIL import Image,ImageEnhance
 
#shift+tab多行缩进(左)
reload(sys)
PostUrl = "http://yjsymis.hrbeu.edu.cn/gsmis/indexAction.do"
 
driver=webdriver.Firefox()
driver.get(PostUrl)
 
 
i=0
while 1:#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:UsersMrLevoimage1.jpg')#比较好理解
    im =Image.open('C:UsersMrLevoimage1.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:UsersMrLevoAnaconda2Lib")
            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类型
    print 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:UsersMrLevoimage.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用的是第三方库,所以,采用的导入方式是这样的,多看看官方文档就可以,官方描述如下
Usefrom PIL import Imageinstead ofimport Image.


10:找不到应该键入的元素
10:这个问题,请单击要输入的空白处右键,审查元素,就可以看到,然后根据driver.find_element_by_各种方法来定位元素,如果输入进行了隐藏,在当前页面找不到怎么办,就像如下图,需要先点击我的图书馆,才能看到输入的账户和密码,那么先找我的图书馆的元素,进行click操作,之后再找元素,一句话,把自己想成浏览器,阿不,把python想成浏览器。。。。。

 

登陆图书馆

上图的代码我也放上,大同小异,比有验证码的简单,但是多了一个click操作。

# -*- coding: utf-8 -*-
#Author:哈士奇说喵
from selenium import webdriver
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:UsersMrLevoimage.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

  1. 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

  1. 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

  1. tesseract [lang].[fontname].exp[num].tif [lang].[fontname].exp[num] batch.nochop makebox  

其中lang为语言名称,fontname为字体名称,num为序号,可以随便定义。

Yasi:先前自己定义了tessdata的环境变量 TESSDATA_PREFIX 值为 E: esseract essdata,但没有从tesseract源文件目录中将tessdata子目录中的内容copy到 E: esseract essdata 中,造成上面的命令报错,说找不到batch.nochop makebox。解决办法: tesseract 源文件目录中所有文件和子文件夹(可能充分但非必要,先不管这些啦)copy E: esseract essdata

5.文字校正。运行jTessBoxEditor工具,打开num.font.exp0.tif文件(必须将上一步生成的.box和.tif样本文件放在同一目录),如下图所示。可以看出有些字符识别的不正确,可以通过该工具手动对每张图片中识别错误的字符进行校正。校正完成后保存即可。

Yasi】这里必须修改识别错误的字符,否则做出来的traineddata文件也是错的。可以在下面的界面中修改并保存,也可以直接在traineddata文件中修改。



6.定义字体特征文件。Tesseract-OCR3.01以上的版本在训练之前需要创建一个名称为font_properties的字体特征文件。

font_properties不含有BOM头,文件内容格式如下:

[plain]  view plain copy

  1. <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

  1. font 0 0 0 0 0  

这里全取值为0,表示字体不是粗体、斜体等等。

7.生成语言文件。在样本图片所在目录下创建一个批处理文件,输入如下内容。

[plain]  view plain copy

  1. rem 执行改批处理前先要目录下创建font_properties文件  
  2.   
  3. echo Run Tesseract for Training..  
  4. tesseract.exe num.font.exp0.tif num.font.exp0 nobatch box.train  
  5.   
  6. echo Compute the Character Set..  
  7. unicharset_extractor.exe num.font.exp0.box  
  8. mftraining -F font_properties -U unicharset -O num.unicharset num.font.exp0.tr  
  9.   

10. echo Clustering..  

11. cntraining.exe num.font.exp0.tr  

  1. 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   

  1. 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

  1. tesseract.exe number.jpg result -l eng  

识别结果如如图所示,可以看到识别率提高了不少。通过自定义训练样本,可以进行图形验证码、车牌号码识别等。感兴趣的朋友可以研究研究。

【Yasi】试验结果如下:

下面是num-yasi.png 

 将生成的num.traineddata拷贝到E: esseract essdata,即环境变量TESSDATA_PREFIX 设置的路径下,执行下面的命令( 注意第二条命令结尾是num,即新加的traineddata,而不是eng

E:tesseracttesseract-svnvs2008LIB_Debugtesseractd.exe num-yasi.png result-eng -l eng
E:tesseracttesseract-svnvs2008LIB_Debugtesseractd.exe num-yasi.png result-num -l num

下图是两次识别结果对比

使用eng traineddata的结果完全不靠谱;使用了自己的traineddata,识别出来的当然都是数字,但正确率实在糟糕。可能是我自己手写的字体和用来做traineddata的手写数字的字体差别太大了吧。

C:UsersAdministrator.Windwos 10YKMNH>doskey /history

D:anaconda3python3 esseract4ocr esseract.exe

D:anaconda3python3 esseract4ocr esseract.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 essdata这是将语言字库文件夹添加到变量中;

使用

打开命令终端,输入:tesseract -v,可以看到版本信息

用命令tesseract --list-langs来查看Tesseract-OCR支持语言。

将命令行切换至目标图像文件目录,比如我们转换文件为test.png(图片文件允许多种格式),位于C:UsersLianDesktop est;然后在命令行中输入

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: estdir>tesseract ttest1.png test1 -l eng 

Error opening data file Program Files (x86)Tesseract-OCR essdata/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	essdata

如果一切就绪,你在命令行中就可以使用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 location of tessdata path.
  --user-words PATH     Specify the location of user words file.
  --user-patterns PATH  Specify the location of 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 -l chi_sim

通过Python调用

Tesseract安装完成后可以很方便的被Python调用,你需要安装两个包。

pip install pillow
pip install pytesseract

一个简单的图片转文字的函数实现如下。

from PIL import Image
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)
  
print(img_to_str('image/test1.png', lang=Languages.CHS))
print(img_to_str('image/test2.png', lang=Languages.CHS))

测试图片- test1.png

识别结果:

process image file "image/test1.png" in 1.4782530478747697 seconds
 
8    ,  -  
   ,   
     ,   
     ,      
   伊人 ,   
 丿 ,      

测试图片 - test2.png

识别结果:

process image 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 install baidu-aip

封装和调用

参考文档: https://cloud.baidu.com/doc/O...

from aip import AipOcr
 
config = {
    'appId': 'your-id',
    'apiKey': 'your-key',
    'secretKey': 'your-secret-key'
}
 
client = AipOcr(**config)
 
def get_file_content(file):
    with open(file, 'rb') as fp:
        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 '
'.join([w['words'] for w in result['words_result']])

测试图片- test1.png

识别结果:

process image file "image/test1.png" in 0.6331169034812572 seconds
 
蒹葭
先秦:佚名
蒹葭苍苍,白露为霜。所谓伊人,在水一方。
溯洄从之,道阻且长。溯游从之,宛在水*。
蒹葭萋萋,白露未晞。所谓伊人,在水之湄。
溯洄从之,道阳且跻。溯游从之,宛在水中坻。
蒹葭采采,白露未已。所谓伊人,在水之涘。
溯洄从之,道阻且右。溯游从之,宛在水中沚。

测试图片 - test2.png

识别结果:

process image file "image/test2.png" in 0.6621812639450142 seconds
 
清明时节雨纷纷,路上行人欲断魂。
借问酒家何处有,牧童遥指杏花村。

小结

测试结果很明显,我只能说百度云这个OCR真是挺厉害的,一个错别字都没有,不服不行。论中文,还是百度比谷歌更懂一点。而且百度OCR提供了更多的参数让你更灵活的处理图片,比如自定义旋转,返回可信度,特定类型证件识别等等。

更多的OCR

除了本文提到的OCR,其实还是有不少其他选择。有一些直接提供Demo页面,你直接上传一张图片就可以直接看到识别效果,比如:

你有没有发现所有的大公司都有这样的服务?以后我们买买买就行