代碼格式問題見諒呼巷,csdn寫好粘過來的,想看起來直觀的請移步我的csdn赎瑰,個人簡介有~
昨天我姐問我有沒有軟件可以批量識別圖片上的文字王悍,她在幫客戶做資料整理,但是用的方法只能一張一張上傳識別餐曼,不僅效率低還浪費時間压储。
?我就找了找批量識別的軟件,下載下來覺得:嗯源譬?不錯渠脉,界面也挺好,小東西做的還挺別致瓶佳。但是,識別三張就停止了鳞青,提示非最新版本要聯(lián)系客服升級之類的霸饲,妥妥的套路,果斷刪除臂拓。又找了一個厚脉,嗯?界面更加好看一點兒胶惰,人家就很直接傻工,三張之后提示購買會員,還顯示了幾種VIP的費用孵滞,很“人性”嘛中捆。
?但是,在這個萬物開源的互聯(lián)網(wǎng)時代坊饶,讓程序員掏腰包買軟件是不可能滴泄伪,反正我是不會,啊哈哈匿级。我首想到了反編譯蟋滴,把三張的限制取消,之前看過一些ios逆向工程的東西痘绎,這些應(yīng)該都是通的津函。搜索了一番之后,有這么個方法孤页,下載一個軟件尔苦,把exe拖進去,就能顯示源碼了。又讓我下東西蕉堰,我就覺得很煩了凌净,畢竟還是占空間的嘛。
?so屋讶,我寫寫就好了嘛冰寻,畢竟也是一名程序員,怎么能忘了呢皿渗。16年公司項目中身份證識別用到了OCR做身份證掃描斩芭,當(dāng)時還在做iOS開發(fā),好像用的一個第三方乐疆,細節(jié)嘛忘得差不多了(而且做app的話划乖,我姐又不是iOS系統(tǒng))。這次就用python的GUI然后打包成exe吧挤土,翻翻我的筆記琴庵,對的19年12月份學(xué)習(xí)到的python打包那些剛好用上。要考慮到客戶需求以及易用性仰美,哈哈迷殿,然后就開始了。
批量庆寺、圖片文字識別、導(dǎo)出文本诉字、操作便捷懦尝、圖形化界面
1壤圃、百度AI開放平臺的通用文字識別SDK(沒有廣告成分陵霉,搜到什么用什么,免費調(diào)用量足夠了)埃唯,我的代碼中用的是“網(wǎng)絡(luò)圖片文字識別”撩匕,可根據(jù)需求,自行調(diào)整墨叛;
2止毕、python的tklinker模塊、打包工具pyinstaller漠趁;
3扁凛、也可以直接寫入txt;
前一天的代碼谨朝,第二天優(yōu)化改改改之后,再用新圖片來識別發(fā)現(xiàn)不行了,一度以為是哪里寫錯了字币,各種找原因则披,以為是獲取文件夾路徑方式不對,就自己復(fù)制了路徑進來洗出,發(fā)現(xiàn)報錯了士复。
坑1:圖片路徑——轉(zhuǎn)義
運行報錯:SyntaxError: (unicode error) ‘unicodeescape’ codec can’t decode bytes in position 2-3: tr
我文件夾中復(fù)制來的路徑:C:\Users\78755\Desktop\test\1.pngfilePath='C:\Users\78755\Desktop\test\1.png'報錯原因:在windows系統(tǒng)當(dāng)中讀取文件路徑可以使用\,但是在python字符串中\(zhòng)有轉(zhuǎn)義的含義,如\t可代表TAB翩活,\n代表換行阱洪,所以我們需要采取一些方式使得\不被解讀為轉(zhuǎn)義字符。解決方案:1菠镇、在路徑前面加r冗荸,保持字符原始值的意思。filePath=r'C:\Users\78755\Desktop\test\1.png’2利耍、替換為雙反斜杠filePath='C:\\Users\\78755\\Desktop\\test\\1.png’3蚌本、替換為正斜杠filePath=‘C:/Users/78755/Desktop/test/1.png’
坑2:后綴——python批量修改指定文件夾下圖片后綴
import os# 此處我是將test文件夾下全部.jpg后綴修改了成了.png并給圖片重新命名os.chdir(r'C:\Users\78755\Desktop\test');# 指定文件夾路徑count=1;# 初始序號# os.listdir(path) 方法用于返回指定的文件夾(path)包含的文件或文件夾的名字的列表,如果path=None隘梨,則使用path="."foritem in[xforx in os.listdir(".")]:# os.path.isfile( )判斷某一對象(需提供絕對路徑)是否為文件# 并且后綴以.jpg結(jié)尾ifos.path.isfile(item)and os.path.splitext(item)[1]=='.jpg':os.rename(item,'%s.png'%(count));count+=1;print(item);
1、安裝OCR Python SDK
OCR Python SDK目錄結(jié)構(gòu)├── README.md├── aip//SDK目錄│? ├── __init__.py//導(dǎo)出類│? ├── base.py//aip基類│? ├── http.py//http請求│? └── ocr.py//OCR└── setup.py//setuptools安裝
支持Python版本:2.7.+ ,3.+
安裝使用Python SDK有如下方式:
如果已安裝pip出嘹,執(zhí)行pip install baidu-aip即可。
如果已安裝setuptools咬崔,執(zhí)行python setup.py install即可税稼。
2、新建AipOcr
AipOcr是OCR的Python SDK客戶端垮斯,為使用OCR的開發(fā)人員提供了一系列的交互方法郎仆。
參考如下代碼新建一個AipOcr:
from aip import AipOcr""" 你的 APPID AK SK """APP_ID='你的 App ID'API_KEY='你的 Api Key'SECRET_KEY='你的 Secret Key'client=AipOcr(APP_ID,API_KEY,SECRET_KEY)
在上面代碼中,常量APP_ID在百度智能云控制臺中創(chuàng)建兜蠕,常量API_KEY與SECRET_KEY是在創(chuàng)建完畢應(yīng)用后扰肌,系統(tǒng)分配給用戶的,均為字符串熊杨,用于標(biāo)識用戶曙旭,為訪問做簽名驗證,可在AI服務(wù)控制臺中的應(yīng)用列表中查看晶府。
3桂躏、單張識別:
# 單張圖片識別i=open(r'C:\Users\78755\Desktop\test\1.png','rb')image=i.read()result=client.basicGeneral(image)#將所有的文字都合并到一起foritem in result['words_result']:print(item['words'])
4、批量識別:
# 圖片批量識別filePath=r'C:\Users\78755\Desktop\test'defget_file_content(filePath):withopen(filePath,'rb')as fp:returnfp.read()forroot,dirs,files in os.walk(".",topdown=False):forname in files:if'png'in name:filePath=os.path.join(root,name)[2:]options={'detect_direction':'true','language_type':'CHN_ENG',}result=aipOcr.webImage(get_file_content(filePath),options)print(result)fori in result['words_result']:print(i['words'])
5川陆、寫入txt文件:
# 寫入txt? ? f=open("文件名.txt","a")#a 打開一個文件用于追加剂习。如果該文件已存在,文件指針將會放在文件的結(jié)尾。也就是說鳞绕,新的內(nèi)容將會被寫入到已有內(nèi)容之后失仁。如果該文件不存在,創(chuàng)建新文件進行寫入们何。? ? f.write('要寫入的內(nèi)容')f.close()
6萄焦、Python GUI之tkinter窗口視窗的創(chuàng)建,并實現(xiàn)選擇文件夾路徑并展示路徑的功能:
import tkinter as tk? # 使用Tkinter前需要先導(dǎo)入from tkinter import*from tkinter.filedialog import askdirectory# GUI# 第1步垂蜗,實例化object楷扬,建立窗口windowwindow=tk.Tk()# 第2步,給窗口的可視化起名字window.title('批量識別圖片文字')# 第3步贴见,設(shè)定窗口的大小(長*寬)window.geometry('1000x700')# 這里的乘是小x# 選擇文件夾路徑方法defselectPath():path_=askdirectory()path.set(path_)path=StringVar()# 第4步烘苹,在窗口界面設(shè)置放置Button按鍵selectedButton=tk.Button(window,text='選擇文件夾',font=('Arial',12),width=10,height=1,command=selectPath).place(x=50,y=20)# 第5步,在圖形界面上設(shè)定標(biāo)簽展示選擇好的文件夾路徑var=tk.StringVar()# 將label標(biāo)簽的內(nèi)容設(shè)置為字符類型片部,用var來接收hit_me函數(shù)的傳出內(nèi)容用以顯示在標(biāo)簽上pathLabel=tk.Label(window,textvariable=path,bg='gray',fg='white',font=('Arial',12),width=30,height=2).place(x=180,y=20)# 說明: bg為背景镣衡,fg為字體顏色,font為字體档悠,width為長廊鸥,height為高,這里的長和高是字符的長和高辖所,比如height=2,就是標(biāo)簽有2個字符這么高# 第6步惰说,主窗口循環(huán)顯示window.mainloop()
7、完整代碼:
(1)缘回、融合圖片識別和圖形化界面吆视,可自定通過窗口進行選擇圖片文件夾進行識別(將要識別的圖片放到同一文件夾下即可,此處以.png后綴為例)酥宴;
(2)啦吧、識別結(jié)果的展示用到了tklinker的scrolledtext;
(3)拙寡、窗口大小及各控件樣式可調(diào)整授滓;
# encoding:utf-8# author:笑胖仔from aip import AipOcrimport osimport tkinter as tk? # 使用Tkinter前需要先導(dǎo)入from tkinter import*from tkinter.filedialog import askdirectoryfrom tkinter import scrolledtext""" 你的 APPID AK SK """APP_ID='你的 App ID'API_KEY='你的 Api Key'SECRET_KEY='你的 Secret Key'client=AipOcr(APP_ID,API_KEY,SECRET_KEY)# GUI# 第1步,實例化object肆糕,建立窗口windowwindow=tk.Tk()# 第2步般堆,給窗口的可視化起名字window.title('批量識別圖片文字')# 第3步,設(shè)定窗口的大小(長*寬)window.geometry('1000x700')# 這里的乘是小x# 選擇文件夾路徑方法defselectPath():path_=askdirectory()path.set(path_)path=StringVar()# 第4步诚啃,在窗口界面設(shè)置放置Button按鍵selectedButton=tk.Button(window,text='選擇文件夾',font=('Arial',12),width=10,height=1,command=selectPath).place(x=50,y=20)# selectedButton.pack()# 第5步郁妈,在圖形界面上設(shè)定標(biāo)簽var=tk.StringVar()# 將label標(biāo)簽的內(nèi)容設(shè)置為字符類型,用var來接收hit_me函數(shù)的傳出內(nèi)容用以顯示在標(biāo)簽上pathLabel=tk.Label(window,textvariable=path,bg='gray',fg='white',font=('Arial',12),width=30,height=2).place(x=180,y=20)# 說明: bg為背景绍申,fg為字體顏色噩咪,font為字體顾彰,width為長,height為高胃碾,這里的長和高是字符的長和高涨享,比如height=2,就是標(biāo)簽有2個字符這么高# pathLabel.pack()# 第6步,展示識別結(jié)果resourceScrolledtext=scrolledtext.ScrolledText(window,width=80,height=23,font=("隸書",18))#滾動文本框(寬仆百,高(這里的高應(yīng)該是以行數(shù)為單位)厕隧,字體樣式)resourceScrolledtext.place(x=20,y=100)#滾動文本框在頁面的位置# 識別文字方法defscanPics():filePath=path.get()# 讀取圖片? ? defget_file_content(filePath):withopen(filePath,'rb')as fp:returnfp.read()forroot,dirs,files in os.walk(".",topdown=False):forname in files:if'png'in name:filePath=os.path.join(root,name)[2:]options={'detect_direction':'true','language_type':'CHN_ENG',}result=client.webImage(get_file_content(filePath),options)print(result)resourceScrolledtext.insert("insert",'\n\n')# 在scrolledtext插入間隔,使每張圖片識別內(nèi)容中間有間隔fori in result['words_result']:print(i['words'])# # 如果需要寫入txt俄周,將此段解注釋即可# f = open("文件名.txt", "a") #a 打開一個文件用于追加吁讨。如果該文件已存在,文件指針將會放在文件的結(jié)尾峦朗。也就是說建丧,新的內(nèi)容將會被寫入到已有內(nèi)容之后。如果該文件不存在波势,創(chuàng)建新文件進行寫入翎朱。# f.write(i['words'] + '\n')# f.close()# 將識別結(jié)果插入scrolledtext,在窗口試圖中顯示? ? ? ? ? ? ? ? ? ? resourceScrolledtext.insert("insert",i['words']+'\n')# 第7步尺铣,識別文字按鈕scanButton=tk.Button(window,text='開始識別',font=('Arial',12),command=scanPics).place(x=800,y=20)# scanButton.pack()# 第8步拴曲,主窗口循環(huán)顯示window.mainloop()
8、將python打包成.exe文件:
(1)凛忿、安裝pyinstaller:pip install pyinstaller
(2)澈灼、打包:cd 到文件目錄下,如test.py文件店溢,pyinstaller -F test.py
(3)蕉汪、執(zhí)行完之后,會多出一個.spec文件以及build逞怨、dist兩個目錄,dist中的.exe文件直接運行即可福澡;
9叠赦、測試:
10、后續(xù)測試:
按之前步驟進行打包成exe后革砸,反復(fù)測試都識別不成功除秀,且命令行沒有返回任何結(jié)果,而程序內(nèi)運行正常算利。開始尋找可能的原因册踩,并進行測試。
預(yù)測原因:“打包后exe程序不能發(fā)送網(wǎng)絡(luò)請求”
測試1(無果):
以為是打包后的exe程序沒有進行網(wǎng)絡(luò)請求效拭,網(wǎng)上有說是使用了第三方庫的話暂吉,用pyinstaller打包前胖秒,需要把\Lib\site-packages下相應(yīng)的包復(fù)制到同要打包的.py文件同一目錄,經(jīng)反復(fù)測試無用慕的。
測試2(成功):
新建一文件requestTest.py阎肝,用request做單張圖片識別請求并打印結(jié)果,測試打包成exe之后能否成功調(diào)用接口肮街。運行打包后的exe风题,報錯:FileNotFoundError:
[Errno 2] No such file or directory: ‘呢呢呢.png’
嘗試將資源圖片復(fù)制到打包好的exe程序同目錄下,即為dist目錄下嫉父。此時再打開exe程序沛硅,點擊識別,成功打印出結(jié)果(但是绕辖,此時已不關(guān)乎GUI中選擇路徑的功能摇肌,直接點擊識別即可識別,不知其中緣由引镊,但是解除了我“打包后exe程序不能發(fā)送網(wǎng)絡(luò)請求”的猜測)朦蕴。
測試3(成功):
仍然換回ocr.py進行打包,打包成功后弟头,選擇文件夾吩抓,開始識別,果然還是無打印結(jié)果赴恨。把要識別的文件夾放入dist文件夾下疹娶,再打開exe,直接點擊開始識別伦连,識別成功雨饺。
11、補充:
pyinstaller打包惑淳,一些可選參數(shù):
使用順序:pyinstall -i 圖標(biāo)名稱.ico -n 打包后程序名稱 -w -F 要打包的文件名.py
先圖標(biāo)路徑额港,再程序路徑
(1)、打包單文件模式:-F
(2)歧焦、打包成文件夾:-D
(3)移斩、修改icon(圖標(biāo)后綴.ico,不可自行修改绢馍,網(wǎng)上有轉(zhuǎn).ico格式的方法):-i xxx.ico
(4)向瓷、修改打包后的程序名稱:-n
(5)、不彈出命令行行:-w
如我的程序:pyinstaller -i 笑胖仔.ico -n 批量識別圖片中文字 -w -F ocr.py