-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathid_templeate_match.py
166 lines (144 loc) · 5.13 KB
/
id_templeate_match.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import cv2
import utils
import numpy as np
import argparse
from imutils import contours
#设置参数
ap=argparse.ArgumentParser()
ap.add_argument("-i","-image",required=True,help="path to input images")
ap.add_argument("-t","--template",required=True,help="path to temlate OCR-A image")
args=vars(ap.parse_args())
#指定信用卡类型
FIRST_NUMBER={
"3":"American Express",
"4":"Visa",
"5":"MasterCard",
"6":"Discover Card"
}
#绘图展示
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#读取一个模板文件
img=cv2.imread(args["template"])
cv_show("img",img)
#灰度图
ref=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv_show('ref',ref)
#二值图像
ref=cv2.threshold(ref,10,255,cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)
#计算轮廓
#cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图)
#cv2.RETR_EXTERNAL只检测外轮廓,cv2.CHAIN_APPROX_SIMPLE只保留终点坐标
#返回的list中每个元素都是图像中的一个轮廓
ref_,refCnts,hierarchy=cv2.findContours(ref.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,refCnts,-1,(0,0,255),3)
cv_show('img',img)
print(np.array(refCnts).shape)
refCnts=utils.sort_contours(refCnts,method="left-to-right")[0]#排序从左到右,从上到下
digits={}
'''
第一个参数:img是原图
第二个参数:(x,y)是矩阵的左上点坐标
第三个参数:(x+w,y+h)是矩阵的右下点坐标
第四个参数:(0,255,0)是画线对应的rgb颜色
'''
#遍历每一个轮廓
for(i,c) in enumerate(refCnts):
#计算外接矩形并且resize成合适大小
(x,y,w,h)=cv2.boundingRect(c)
roi=ref[y:y+h,x:x+w]
roi=cv2.resize(roi,(57,58))
#每一个数字对应一个模板
digits[i]=roi
#初始化卷积核
rectKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(9,3))
sqKernel=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#读取输入图像,预处理
image=cv2.imread(args["image"])
cv_show('image',image)
image=utils.resize(image,width=300)
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv_show('gray',gray)
#礼帽操作,突出更明亮的区域
tophat=cv2.morphologyEx(gray,cv2.MORPH_TOPHAT,rectKernel)
cv_show('tophat',tophat)
#计算
gradX=cv2.Sobel(tophat,ddepth=cv2.CV_32F,dx=1,dy=0,ksize=1)
gradX=np.absolute(gradX)
(minVal,maxVal)=(np.min(gradX),np.max(gradX))
gradX=(255*((gradX-minVal)/(maxVal-minVal)))
gradX=gradX.astype("uint8")
print(np.array(gradX).shape)
cv_show('gradX',gradX)
#通过闭操作,(先膨胀,在腐蚀)将数字连在一起
gradX=cv2.morphologyEx(gradX,cv2.MORPH_CLOSE,rectKernel)
cv_show('gradX',gradX)
#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh=cv2.threshold(gradX,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
cv_show('thresh',thresh)
#再来一个闭操作
thresh=cv2.morphologyEx(thresh,cv2.MORPH_CLOSE,sqKernel)
cv_show('thresh',thresh)
#计算轮廓
thresh_,threshCnts,hierarchy=cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts=threshCnts
cur_img=image.copy()
cv2.drawContours(cur_img,cnts,-1,(0,0,255),3)
cv_show('img',cur_img)
locs=[]
#遍历轮廓
for (i,c) in enumerate(cnts):
#计算矩形
(x,y,w,h)=cv2.boundingRect(c)
ar=w/float(h)
#适合合适的区域,根据实际任务来,这里的基本是四个数字一组
if ar>2.5 and ar <4.0:
if(w>40 and w<55) and (h>10 and h<20):
#符合的留下来
locs.append((x,y,w,h))
#将符合的轮廓从左到右排序
locs=sorted(locs,key=lambda x:x[0])
output=[]
#遍历每一个轮廓中的数字
for (i,(gX,gY,gW,gH)) in enumerate(locs):
#initialize the list of group digits
groupOutput=[]
#根据坐标提取每一个组
group=gray[gY-5:gY+gH+5,gX-5:gX+gW+5]
cv_show('group',group)
#预处理
group=cv2.threshold(group,0,255,cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1]
cv_show('group',group)
#计算每一个轮廓
group_,digitCnts,hierarchy=cv2.findContours(group.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
digitCnts=contours.sort_contours(digitCnts,method="left-to-right")[0]
#计算每一组总的每一个数值
for c in digitCnts:
#找到当前数值的轮廓,resize成合适的大小
(x,y,w,h)=cv2.boundingRect(c)
roi=group[y:y+h,x:x+w]
roi=cv2.resize(roi,(57,58))
cv_show('roi',roi)
#计算匹配得分
scores=[]
#在模板章中计算每一个得分
for(digit,digiROI) in digits.items():
#模板匹配
result=cv2.matchTemplate(roi,digiROI,cv2.TM_CCOEFF)
(_,score,_,_)=cv2.minMaxLoc(result)
scores.append(score)
#得到合适的数字
groupOutput.append(str(np.argmax(scores)))
#画出来
cv2.rectangle(image,(gX-5,gY-5),(gX+gW+5,gY+gH+5),(0,0,255),1)
cv2.putText(image,"".join(groupOutput),(gX,gY-15),cv2.FONT_HERSHEY_SIMPLEX,0.65,(0,0,255),2)
#得到结果
output.extend(groupOutput)
# 打印结果
print("Credit Card Type: {}".format(FIRST_NUMBER[output[0]]))
print("Credit Card #: {}".format("".join(output)))
cv2.imshow("Image", image)
cv2.waitKey(0)