基于Python實(shí)現(xiàn)條形碼圖片識(shí)別程序
本系列推文案例中,建議Python采用3.10及以上版本,NumPy采用1.22.3及以上版本,Matplotlib采用3.5.1及以上版本,Pandas采用1.4.2及以上版本。Python從3.10這個(gè)版本開始,標(biāo)準(zhǔn)發(fā)行版本中自帶的IDLE交互式環(huán)境中輸入提示符>>>單獨(dú)放在左側(cè),不能隨輸入語句一起復(fù)制。為了清晰區(qū)分實(shí)例在交互環(huán)境中的輸入和輸出,本系列推文在每個(gè)輸入語句的開頭依然保留輸入提示符>>>。
01、應(yīng)用實(shí)例背景
有位朋友開了一家淘寶商店,每天都會(huì)發(fā)出很多快遞,并拍照記錄,于是就有很多快遞單的圖片。每晚有個(gè)重復(fù)性的工作,就是把圖片一張張打開,摘錄其中條形碼的編號(hào),將其保存在Excel中,并把圖片的名稱改為“條形碼編號(hào).jpg”保存,如圖1所示。
圖1 快遞單條形碼識(shí)別
這位朋友的生意越來越好,所以這個(gè)工作量就變得越來越大(每天可能有幾百張圖片需要識(shí)別)。他希望開發(fā)一個(gè)能自動(dòng)識(shí)別條形碼并修改文件名的應(yīng)用程序。
圖片都是jpg格式的,但快遞單因?yàn)樵醋圆煌目爝f公司,所以樣子千奇百怪。拍照片的人也不同,所以拍出的照片不一定工整。唯一可以確定的是,每張照片都有條形碼,且有良好的清晰度。
02、條形碼識(shí)別程序
該應(yīng)用的難點(diǎn)在于條形碼識(shí)別,若從頭開發(fā),則工作量太大。我們找到了可以識(shí)別條形碼和二維碼的開源軟件zbar(http://zbar.sourceforge.net/,大家當(dāng)然也可以選擇其他軟件)。下載、安裝后,就可以打開命令行,在軟件安裝目錄的bin下輸入zbarimg -h,得到如下結(jié)果:
C: work Python barcodes ZBar bin>zbarimg -h
usage: zbarimgoptions] <image >...
scan and decode bar codes from one or more image files
options:
h--help display this help text
--version display version information and exit
-q,-- quiet minimal output,only print decoded symbol data
-V,--verbose increase debug output level
-- verbose=N set specific debug output level
-d,-- display enable display of following images to the screen
-D,--nodisplay disable display of following images (default)
--xml,--nodisplay enable/disable XML output format-- noxm]
-- raw output decoded symbol data without symbology prefix
--S < CONFIG>=< VALUE >],
-set < CONFIG>=< VALUE >],
set decoder/scanner < CONFIG> to < VALUE> (or 1)
這就說明安裝成功了。用手機(jī)拍下一本書的ISBN條形碼,如圖2所示,保存為isbn.jpg。
圖2 ISBN條形碼的圖片
在操作系統(tǒng)的命令行窗口中運(yùn)行以下代碼,即可成功識(shí)別出圖2所示的條形碼所對應(yīng)的ISBN編號(hào)。
EAN-13:9780521865715
C: work Python barcodes ZBar bin>zbarimg isbn.jpg
scanned 1 barcode symbols from 1 images
識(shí)別的關(guān)鍵問題解決了,接著就可以編寫GUI界面了,然后通過調(diào)用zbar來解決問題。
03、界面設(shè)計(jì)
前期工作準(zhǔn)備完畢后,就是正式的軟件設(shè)計(jì)編碼了。構(gòu)思GUI,有以下要求。
(1) 有一個(gè)“打開”按鈕,可以選擇需要識(shí)別的圖片;一個(gè)導(dǎo)出數(shù)據(jù)按鈕。
(2) 數(shù)據(jù)展示窗口,可以以表格的形式呈現(xiàn)。
(3) 一個(gè)多行文本框,用于輸出一些調(diào)試數(shù)據(jù),如錯(cuò)誤反饋、無法識(shí)別等信息。
利用wxFormBuilder來設(shè)計(jì)GUI。在如圖3所示的GUI設(shè)計(jì)界面中,先創(chuàng)建一個(gè)Frame窗口。添加一個(gè)垂直的BoxSizer,加入一個(gè)ToolBar工具條和一個(gè)1行2列的GridSizer。在ToolBar工具條中,添加兩個(gè)Tool按鈕,選擇合適的圖標(biāo)(source選Load From Art Provider,id選wxART_FILE_OPEN和wxART_FILE_SAVE)。在界面的左下部添加一個(gè)DataViewListCtrl用于顯示數(shù)據(jù),右下部添加一個(gè)TextCtrl用于輸出調(diào)試信息。軟件運(yùn)行結(jié)果如圖4所示。
圖3 設(shè)計(jì)軟件界面
圖4 軟件運(yùn)行結(jié)果
04、完整代碼
程序保存在barcodes.py文件中,全部代碼如下:
#-*- coding:utf-8 -* import wx import wx.xrc import wx.dataview import os import csv from datetime import datetime class MyFramel (wx.Frame): definit (self,parent) : wx.Frame.__init__(self,parent,id= wx.ID_ANY,title= u"條形碼識(shí)別程序"pos = wx.DefaultPosition,size = wx.Size866,302)style = WX.DEFAULT FRAME STYLEWX.TAB TRAVERSAL)self.SetSizeHints(wx.DefaultSize,wx.DefaultSize)bSizer5 = wx.BoxSizer(wx.VERTICAL)self.m toolBar2 = wx,ToolBar(self,WX.ID ANY,wx,DefaultPosition,wx.DefaultSize,wX.TB HORIZONTAL)self.m_open = self.m toolBar2.AddTool(wx.ID ANY,u"打開” wx.ArtProvider.GetBitmap(wx.ART FILE OPEN WX.ART TOOLBAR),wx.NullBitmap,wX.ITEM NORMAL, wx.EmptyString,wx.EmptyString,None) self.m_export = self.m toolBar2.AddTool(wx.ID ANY,u"導(dǎo)出”wX.ArtProvider.GetBitmap(wx.ART FILE SAVEWX.ART TOOLBAR),wX.NullBitmap,wX.ITEM NORMALwx.EmptyString,wx.EmptyString,None)self.m toolBar2.Realize()bSizer5.Add(self.m toolBar2,0,WX.EXPAND,5)gSizer1 = wx.GridSizer(1,2,0,0)self.m dvc = wx.dataview.DataViewListCtrl(self,wx.ID ANY wx.DefaultPosition,wx.DefaultSize, wx.dataview.DV MULTIPLE wx.dataview.DV ROW LINES) qSizer1.Add(self.m dvc,0,wx.EXPAND,5)self.m out = wx.TextCtrl(self,wX.ID ANY,wx.EmptyString, wx.DefaultPosition,wx.DefaultSize, WX.TE MULTILINE) 0,WX.EXPAND,5)gSizer1.Add(self.m out,bSizer5.Add(gSizer1,1,WX.EXPAND,5) self.SetSizer(bSizer5) self.Layout( self.Centre(wx.BOTH) # Connect Events self.Bind(wx.EVT_TOOL,self.openimgs,id = self.m open.GetId())self.Bind(wx.EVT TOOL,self.export2csv,id= self.m export.GetId())#Mycode self.m dvc.AppendTextColumn(u'日期 self.m dvc.AppendTextColumn(u'條形碼',width = 120)self.m_dvc.AppendTextColumn(u'文件地址 width = 400) del (self):def pass #Virtual event handlersdef openimgs(self,event)dlg = wx.FileDialog( self,message =“Choose some images" defaultDir = os.getcwd() defaultFile =n wildcard=wildcard style = Wx.FD OPENWX.FD MULTIPLE WX.FD CHANGE DIR if dlq.ShowModal() == wx.ID OK: self.m out.WriteText( Recognizing!n')paths = dlg.GetPaths() for path in paths: tmp = os.popen%s -- raw %s'%(cmd,path)).readlines()barN while barNum == and i< len(tmp)barNum = tmp[i].strip() i +=1 if barNum == . self.m out.WriteText('% s recognize fails! n'% path)continuenewname ='%sss' (os.path.dirname(path),barNum,os.path.splitext(path)[ -1:][0]) try: os.rename(path,newname)item = [datetime.now().strftime('%Y-%m-%d'),s” barNum,newname]self.m dvc.AppendItem( item) csvdata.append( item) self.m out.WriteText( %s Recognize Done! n'% barNumexcept Exception as e:self.m out.WriteText( %s rename fails! n' path)self.m out.WriteText(str(e)) dlg.Destroy() def export2csv(self,event): dlg = wx.FileDialog(self,message ="Save file as ...",defaultDir = os.getcwd()defaultFile=wildcard = wildcard2,style = wx.FD SAVE dlg.SetFilterIndex(2) if dlg.ShowModal() == wX.ID OK: self.m out.WriteText(Exporting! n')path = dlg.GetPath() try:with open(path,w',newline =) as csvfile:writer = csv.writer(csvfile,dialect =excel',quoting = csV.OUOTE ALL)for row in csvdata:writer.writerow(row) self.m out.WriteText( s Export Done! n' path)except Exception as e: self.m out.WriteText(str(e)) dlg.Destroy() wildcard = "Pictures ( *.jpg,*.png)*.jpg;*.png All files (*.*)*.*" wildcard2 ="CSV files (*.csv) *.csv" cmd = os.path.realpath('Zbar/bin/zbarimq.exe') csvdata = [] app= wX.App() win = MyFramel(None) win.Show() app.MainLoop()
說明: 由于以上代碼中的某些行過長,所以在代碼的前端加上了數(shù)字表示行號(hào)。
注意事項(xiàng):
(1) zbar軟件安裝在上述程序的當(dāng)前目錄下,可以通過Zbar\bin\zbarimg.exe運(yùn)行。
(2) 目錄中有中文可能會(huì)出錯(cuò)。
(3) 用FileDialog打開文件時(shí)會(huì)改變當(dāng)前目錄,所以在最初就要保存zbar命令的絕對路徑。
(4) 由于條形碼有以0開頭的數(shù)字,用Excel打開時(shí)會(huì)自動(dòng)省略,所以在數(shù)字前加了一個(gè)“'”符號(hào)。
以上就是基于Python實(shí)現(xiàn)條形碼圖片識(shí)別程序的詳細(xì)內(nèi)容,更多關(guān)于Python條形碼識(shí)別的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python入門教程2. 字符串基本操作【運(yùn)算、格式化輸出、常用函數(shù)】
這篇文章主要介紹了Python字符串基本操作,結(jié)合實(shí)例形式總結(jié)分析了Python字符串的基本表示、運(yùn)算、格式化輸出、常用函數(shù)等,注釋包含較為詳盡的說明,便于理解,需要的朋友可以參考下2018-10-10python 高效去重復(fù) 支持GB級(jí)別大文件的示例代碼
今天小編就為大家分享一篇python 高效去重復(fù) 支持GB級(jí)別大文件的示例代碼,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11python如何實(shí)現(xiàn)lazy segment tree惰性段樹算法
LazySegmentTree(惰性段樹)算法是一種數(shù)據(jù)結(jié)構(gòu),專門用于高效處理區(qū)間查詢和更新操作,它利用延遲更新技術(shù)(LazyPropagation),僅在必要時(shí)執(zhí)行實(shí)際更新,以提升效率,此結(jié)構(gòu)將數(shù)組表達(dá)為二叉樹,每個(gè)節(jié)點(diǎn)表示一個(gè)數(shù)組區(qū)間2024-10-10使用python對excle和json互相轉(zhuǎn)換的示例
今天小編就為大家分享一篇使用python對excle和json互相轉(zhuǎn)換的示例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10Python實(shí)現(xiàn)的直接插入排序算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的直接插入排序算法,結(jié)合實(shí)例形式分析了Python直接插入排序算法的定義與使用相關(guān)操作技巧,代碼備有較為詳盡的注釋便于理解,需要的朋友可以參考下2018-04-04Python讀取及保存mat文件的注意事項(xiàng)說明
這篇文章主要介紹了Python讀取及保存mat文件的注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12