這篇文章主要介紹了Python識別快遞條形碼及Tesseract-OCR怎么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

識別快遞單號
這次跟老師做項目,這項目大概是流水線上識別快遞上的快遞單號。首先我嘗試了解條形碼的基本知識
百度百科:條形碼
條形碼(barcode)是將寬度不等的多個黑條和空白,按照一定的編碼規(guī)則排列,用以表達一組信息的圖形標識符。常見的條形碼是由反射率相差很大的黑條(簡稱條)和白條(簡稱空)排成的平行線圖案。條形碼可以標出物品的生產(chǎn)國、制造廠家、商品名稱、生產(chǎn)日期、圖書分類號、郵件起止地點、類別、日期等許多信息,因而在商品流通、圖書管理、郵政管理、銀行系統(tǒng)等許多領域都得到廣泛的應用。
條形碼有多種,在我國廣泛流傳的是EAN13條形碼(以下簡稱條形碼),所以主要研究該種條形碼的識別。
條形碼位數(shù)說明:
條形碼一共有13位
前2位或者前3位稱為前綴,表示國家、地區(qū)或者某種特定的商品類型
中國區(qū)條形碼開頭:690~699
圖書類條形碼開頭:978~979
前綴后的4位或者5位稱為廠商代碼,表示產(chǎn)品制造商
廠商代碼后5位稱為商品代碼,表示具體的商品項目
最后1位是校驗碼,根據(jù)前12位計算而出,可以用來防偽以及識別校驗
條形碼編碼說明
條形碼一共有8個區(qū)域:左側(cè)空白區(qū)->起始符->左側(cè)數(shù)據(jù)符->中間分隔符->右側(cè)數(shù)據(jù)符->校驗符->終止符->右側(cè)空白區(qū)

字符為0~9
除空白區(qū)外的區(qū)域和字符都采用二進制編碼表示,1表示bar(黑條),0表示space(白條)
起始符,終止符編碼為101,分隔符編碼為01010
0~9每種字符有3種編碼方式,AB為左側(cè)數(shù)據(jù)奇偶編碼,C為右側(cè)數(shù)據(jù)偶編碼

左側(cè)數(shù)據(jù)的奇偶性由前置符決定(就是說,第一個支付是幾就按下面的排列開始)

還有這么一種理解編碼方法
以寬度為編碼,去掉起始碼,終止碼,中間分隔碼,不管白條還是黑條都算一個編碼,最窄一節(jié)為1(最窄的為單位寬度),兩個單位寬度就是2,三單位長度為3,四單位寬度為4
四條(不管黑條還是白條都算條)代表一個數(shù)字
| 四條長度 | 數(shù)字 |
|---|---|
| 3211 | 0 |
| 2221 | 1 |
| 2122 | 2 |
| 1411 | 3 |
| 1132 | 4 |
| 1231 | 5 |
| 1114 | 6 |
| 1312 | 7 |
| 1213 | 8 |
| 3112 | 9 |
兩種編碼的圖示

這就代表為 數(shù)字 1
校驗
EAN13條形碼一共有13位,最后1位是校驗位,該位是通過前12位按照一定的步驟計算出來的。
如果按照一定的步驟處理識別出的前12位數(shù)據(jù),如果計算結(jié)果和識別出的結(jié)果相等,識別正確;
如果不相等,則重新識別或糾錯再校驗或提示識別失敗。
校驗碼計算方法
以下圖所示的條形碼舉例說明:

條形碼的位數(shù)起始位為最右一位,即校驗位,檢驗碼計算方法如下:
偶位數(shù)數(shù)值相加乘3((0+2+0+8+1+9)*3=60)
不含校驗位的奇位數(shù)相加(7+4+7+9+3+6=36)
將前兩步的結(jié)果相加(60+36=96)
用10減去上一步結(jié)果的個位數(shù)數(shù)值(10-6=4)
上一步結(jié)果的個位數(shù)即為校驗碼(4)
源碼
#創(chuàng)建:2016/01/26
#文件:BarCodeIdentification.py
#作者:moverzp
#功能:識別條形碼
import sys
import cv2
DECODING_TABLE = {
'0001101': 0, '0100111': 0, '1110010': 0,
'0011001': 1, '0110011': 1, '1100110': 1,
'0010011': 2, '0011011': 2, '1101100': 2,
'0111101': 3, '0100001': 3, '1000010': 3,
'0100011': 4, '0011101': 4, '1011100': 4,
'0110001': 5, '0111001': 5, '1001110': 5,
'0101111': 6, '0000101': 6, '1010000': 6,
'0111011': 7, '0010001': 7, '1000100': 7,
'0110111': 8, '0001001': 8, '1001000': 8,
'0001011': 9, '0010111': 9, '1110100': 9,
}
EDGE_TABLE = {
2:{2:6,3:0,4:4,5:3},
3:{2:9,3:'33',4:'34',5:5},
4:{2:9,3:'43',4:'44',5:5},
5:{2:6,3:0,4:4,5:3},
}
INDEX_IN_WIDTH = (0, 4, 8, 12, 16, 20, 24, 33, 37, 41, 45, 49, 53)
def get_bar_space_width(img):
row = img.shape[0] *1/2
currentPix = -1
lastPix = -1
pos = 0
width = []
for i in range(img.shape[1]):#遍歷一整行
currentPix = img[row][i]
if currentPix != lastPix:
if lastPix == -1:
lastPix = currentPix
pos = i
else:
width.append( i - pos )
pos = i
lastPix = currentPix
return width
def divide(t, l):
if float(t) / l < 0.357:
return 2
elif float(t) / l < 0.500:
return 3
elif float(t) / l < 0.643:
return 4
else:
return 5
def cal_similar_edge(data):
similarEdge = []
#先判斷起始符
limit = float(data[1] + data[2] + data[3] ) / 3 * 1.5
if data[1] >= limit or data[2] >= limit or data[3] >= limit:
return -1#寬度提取失敗
index = 4
while index < 54:
#跳過分隔符區(qū)間
if index==28 or index==29 or index==30 or index==31 or index==32:
index +=1
continue
#字符檢測
T1 = data[index] + data[index+1]
T2 = data[index+1] + data[index+2]
L = data[index] + data[index+1] + data[index+2] + data[index+3]
similarEdge.append( divide(T1, L) )
similarEdge.append( divide(T2, L) )
index += 4
return similarEdge
def decode_similar_edge(edge):
barCode = [6]#第一個字符一定是6,中國區(qū)
for i in range (0, 24, 2):#每個字符兩個相似邊,共12個字符
barCode.append( EDGE_TABLE[edge[i]][edge[i+1]] )
return barCode
def decode_sharp(barCode, barSpaceWidth):
for i in range(0, 13):
if barCode[i] == '44':
index = INDEX_IN_WIDTH[i]
c3 = barSpaceWidth[index+2]
c4 = barSpaceWidth[index+3]
if c3 > c4:
barCode[i] = 1
else:
barCode[i] = 7
elif barCode[i] == '33':
index = INDEX_IN_WIDTH[i]
c1 = barSpaceWidth[index]
c2 = barSpaceWidth[index+1]
if c1 > c2:
barCode[i] = 2
else:
barCode[i] = 8
elif barCode[i] == '34':
index = INDEX_IN_WIDTH[i]
c1 = barSpaceWidth[index]
c2 = barSpaceWidth[index+1]
if c1 > c2:
barCode[i] = 7
else:
barCode[i] = 1
elif barCode[i] == '43':
index = INDEX_IN_WIDTH[i]
c2 = barSpaceWidth[index+1]
c3 = barSpaceWidth[index+2]
if c2 > c3:
barCode[i] = 2
else:
barCode[i] = 8
def check_bar_code(barCode):
evens = barCode[11]+barCode[9]+barCode[7]+barCode[5]+barCode[3]+barCode[1]
odds = barCode[10]+barCode[8]+barCode[6]+barCode[4]+barCode[2]+barCode[0]
sum = evens * 3 + odds
if barCode[12] == (10 - sum % 10) % 10:
return True
else:
return False
#載入圖像
img = cv2.imread('res\google6.jpg')
grayImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#轉(zhuǎn)換成單通道圖像
ret, grayImg = cv2.threshold(grayImg, 200, 255, cv2.THRESH_BINARY)#二值化
grayImg = cv2.medianBlur(grayImg, 3)#中值濾波
#提取條空寬度
barSpaceWidth = get_bar_space_width(grayImg)
print 'bar & space\'s numbers:', len(barSpaceWidth)#只有60是正確的
print barSpaceWidth
#計算相似邊數(shù)值
similarEdge = cal_similar_edge(barSpaceWidth)
if similarEdge == -1:
print 'barSpaceWidth error!'
sys.exit()
print 'similarEdge\'s numbers:', len(similarEdge)
print similarEdge
#相似邊譯碼
barCode = decode_similar_edge(similarEdge)
#針對‘#'譯碼
decode_sharp(barCode, barSpaceWidth)
#校驗
valid = check_bar_code(barCode)
valid = 1
print 'barcode:\n', barCode if valid else 'Check barcode error!'
height = img.shape[0]
width = img.shape[1]
cv2.line(grayImg, (0, height/2), (width, height/2),(0, 255, 0), 2)#畫出掃描的行
#顯示圖像
cv2.imshow("origin", img)
cv2.imshow("result", grayImg)
key = cv2.waitKey(0)
if key == 27:
cv2.destroyAllWindows()第二種編碼的程序
#-*- coding:utf-8 -*-
from PIL import Image
def clean(img):
A = img.load()
print A
ss = ''
for x in xrange(img.size[0]):
ss += str(A[x, img.size[1]/2])
print ss
ls = []
while len(ss) > 0:
start = ss[0]
j = 1
while j < len(ss) and ss[j] == start :
j += 1
ls.append(j)
ss = ss[j:]
print ls
return ls
#print ls
def GetUPC_A(t):
#print t
t = t[4:-4]
print len(t)
for i in xrange(len(t)):
t[i] = (t[i] + 1) / 4
t = t[:24] + t[29:]
s = ''
for i in xrange(len(t)):
s += str(t[i])
upca = ''
for i in range(0, len(s) / 4):
n = i * 4
upca += dic[s[n:n + 4]]
print upca
dic = {'3211':'0', '2221':'1', '2122':'2', '1411':'3', '1132':'4', '1231':'5', '1114':'6', '1312':'7', '1213':'8', '3112':'9'}
img = Image.open('7.png')
GetUPC_A(clean(img))可惜這次遇到的是快遞單上的條形碼,非標準的EAN13條形碼,暫時還不清楚這條形碼的編碼方式,所以換一個思路來識別快遞單號,直接識別快遞單上的數(shù)字快遞單號
這里我用OCR引擎來識別,用的是Tesseract-OCR引擎
Tesseract-OCR引擎簡介
OCR(Optical Character Recognition):光學字符識別,是指對圖片文件中的文字進行分析識別,獲取的過程。Tesseract的OCR引擎最先由HP實驗室于1985年開始研發(fā),至1995年時已經(jīng)成為OCR業(yè)內(nèi)最準確的三款識別引擎之一。然而,HP不久便決定放棄OCR業(yè)務,Tesseract也從此塵封。
數(shù)年以后,HP意識到,與其將Tesseract束之高閣,不如貢獻給開源軟件業(yè),讓其重煥新生--2005年,Tesseract由美國內(nèi)華達州信息技術(shù)研究所獲得,并求諸于Google對Tesseract進行改進、消除Bug、優(yōu)化工作。
(由Google管理,所以下載地址“被墻”了,這里就不貼了)
還有一個模塊就是 pytesseract 這包是對Google Tesseract的一層python封裝需要配合 PIL 模塊使用
所以此次識別快遞單號,用到三個
Tesseract-OCR ——(直接下載一個exe文件一路”next”即可安裝完成)
pytesseract模塊——(直接 pip install pytesseract 安裝即可)
PIL模塊——(由于我的是win7_64bit的系統(tǒng),原PIL不支持,所以用pillow模塊,直接pip install pillow即可)
源代碼
#-*- coding:utf-8 -*-
from PIL import Image
import pytesseract
import time
start = time.clock()#開始計時
#---------主要代碼------------
im = Image.open('66.png')
code = pytesseract.image_to_string(im)
print u'驗證碼:' + str(code)
#---------------------------------
end = time.clock()#結(jié)束計時
print u'運行時間:' + str(end-start)有坑
在有 Git Bash調(diào)試時遇到了
Traceback (most recent call last): File "111.py", line 10, in <module> print u'驗證碼:' + str(code) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
這一看就有事編碼的坑了,我用的是python2.7 估計生3就沒沒坑了
但目前還是要解決這問題,對于這編碼的問題有兩種解決方法:
1.一個解決的方案在程序中加入以下代碼:
import sys
reload(sys)
sys.setdefaultencoding('utf8')2.是在python的Lib\site-packages文件夾下新建一個sitecustomize.py,內(nèi)容為:
# encoding=utf8
import sys
reload(sys)
sys.setdefaultencoding('utf8')此時重啟python解釋器,執(zhí)行sys.getdefaultencoding(),發(fā)現(xiàn)編碼已經(jīng)被設置為utf8的了,多次重啟之后,效果相同,這是因為系統(tǒng)在python啟動的時候,自行調(diào)用該文件,設置系統(tǒng)的默認編碼,而不需要每次都手動的加上解決代碼,屬于一勞永逸的解決方法。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Python識別快遞條形碼及Tesseract-OCR怎么用”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關知識等著你來學習!
本文標題:Python識別快遞條形碼及Tesseract-OCR怎么用-創(chuàng)新互聯(lián)
網(wǎng)址分享:http://www.chinadenli.net/article44/dcjgee.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供響應式網(wǎng)站、網(wǎng)站策劃、品牌網(wǎng)站建設、定制開發(fā)、網(wǎng)站設計、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容