1 # -*- coding: utf-8 -*-
2 """
3 Created on Tue Oct 23 20:46:45 2018
4
5 @author: Administrator
6 """
7
8 from cv2 import cv2
9 import numpy as np
10
11
12 def stretch(img):
13 \'\'\'
14 图像拉伸函数
15 \'\'\'
16 maxi=float(img.max())
17 mini=float(img.min())
18
19 for i in range(img.shape[0]):
20 for j in range(img.shape[1]):
21 img[i,j]=(255/(maxi-mini)*img[i,j]-(255*mini)/(maxi-mini))
22
23 return img
24
25 def dobinaryzation(img):
26 \'\'\'
27 二值化处理函数
28 \'\'\'
29 maxi=float(img.max())
30 mini=float(img.min())
31
32 x=maxi-((maxi-mini)/2)
33 #二值化,返回阈值ret 和 二值化操作后的图像thresh
34 ret,thresh=cv2.threshold(img,x,255,cv2.THRESH_BINARY)
35 #返回二值化后的黑白图像
36 return thresh
37
38 def find_rectangle(contour):
39 \'\'\'
40 寻找矩形轮廓
41 \'\'\'
42 y,x=[],[]
43
44 for p in contour:
45 y.append(p[0][0])
46 x.append(p[0][1])
47
48 return [min(y),min(x),max(y),max(x)]
49
50 def locate_license(img,afterimg):
51 \'\'\'
52 定位车牌号
53 \'\'\'
54 contours,hierarchy=cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
55
56 #找出最大的三个区域
57 block=[]
58 for c in contours:
59 #找出轮廓的左上点和右下点,由此计算它的面积和长度比
60 r=find_rectangle(c)
61 a=(r[2]-r[0])*(r[3]-r[1]) #面积
62 s=(r[2]-r[0])*(r[3]-r[1]) #长度比
63
64 block.append([r,a,s])
65 #选出面积最大的3个区域
66 block=sorted(block,key=lambda b: b[1])[-3:]
67
68 #使用颜色识别判断找出最像车牌的区域
69 maxweight,maxindex=0,-1
70 for i in range(len(block)):
71 b=afterimg[block[i][0][1]:block[i][0][3],block[i][0][0]:block[i][0][2]]
72 #BGR转HSV
73 hsv=cv2.cvtColor(b,cv2.COLOR_BGR2HSV)
74 #蓝色车牌的范围
75 lower=np.array([100,50,50])
76 upper=np.array([140,255,255])
77 #根据阈值构建掩膜
78 mask=cv2.inRange(hsv,lower,upper)
79 #统计权值
80 w1=0
81 for m in mask:
82 w1+=m/255
83
84 w2=0
85 for n in w1:
86 w2+=n
87
88 #选出最大权值的区域
89 if w2>maxweight:
90 maxindex=i
91 maxweight=w2
92
93 return block[maxindex][0]
94
95 def find_license(img):
96 \'\'\'
97 预处理函数
98 \'\'\'
99 m=400*img.shape[0]/img.shape[1]
100
101 #压缩图像
102 img=cv2.resize(img,(400,int(m)),interpolation=cv2.INTER_CUBIC)
103
104 #BGR转换为灰度图像
105 gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
106
107 #灰度拉伸
108 stretchedimg=stretch(gray_img)
109
110 \'\'\'进行开运算,用来去除噪声\'\'\'
111 r=16
112 h=w=r*2+1
113 kernel=np.zeros((h,w),np.uint8)
114 cv2.circle(kernel,(r,r),r,1,-1)
115 #开运算
116 openingimg=cv2.morphologyEx(stretchedimg,cv2.MORPH_OPEN,kernel)
117 #获取差分图,两幅图像做差 cv2.absdiff(\'图像1\',\'图像2\')
118 strtimg=cv2.absdiff(stretchedimg,openingimg)
119
120 #图像二值化
121 binaryimg=dobinaryzation(strtimg)
122
123 #canny边缘检测
124 canny=cv2.Canny(binaryimg,binaryimg.shape[0],binaryimg.shape[1])
125
126 \'\'\'消除小的区域,保留大块的区域,从而定位车牌\'\'\'
127 #进行闭运算
128 kernel=np.ones((5,19),np.uint8)
129 closingimg=cv2.morphologyEx(canny,cv2.MORPH_CLOSE,kernel)
130
131 #进行开运算
132 openingimg=cv2.morphologyEx(closingimg,cv2.MORPH_OPEN,kernel)
133
134 #再次进行开运算
135 kernel=np.ones((11,5),np.uint8)
136 openingimg=cv2.morphologyEx(openingimg,cv2.MORPH_OPEN,kernel)
137
138 #消除小区域,定位车牌位置
139 rect=locate_license(openingimg,img)
140
141 return rect,img
142
143 def cut_license(afterimg,rect):
144 \'\'\'
145 图像分割函数
146 \'\'\'
147 #转换为宽度和高度
148 rect[2]=rect[2]-rect[0]
149 rect[3]=rect[3]-rect[1]
150 rect_copy=tuple(rect.copy())
151 rect=[0,0,0,0]
152 #创建掩膜
153 mask=np.zeros(afterimg.shape[:2],np.uint8)
154 #创建背景模型 大小只能为13*5,行数只能为1,单通道浮点型
155 bgdModel=np.zeros((1,65),np.float64)
156 #创建前景模型
157 fgdModel=np.zeros((1,65),np.float64)
158 #分割图像
159 cv2.grabCut(afterimg,mask,rect_copy,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)
160 mask2=np.where((mask==2)|(mask==0),0,1).astype(\'uint8\')
161 img_show=afterimg*mask2[:,:,np.newaxis]
162
163 return img_show
164
165 def deal_license(licenseimg):
166 \'\'\'
167 车牌图片二值化
168 \'\'\'
169 #车牌变为灰度图像
170 gray_img=cv2.cvtColor(licenseimg,cv2.COLOR_BGR2GRAY)
171
172 #均值滤波 去除噪声
173 kernel=np.ones((3,3),np.float32)/9
174 gray_img=cv2.filter2D(gray_img,-1,kernel)
175
176 #二值化处理
177 ret,thresh=cv2.threshold(gray_img,120,255,cv2.THRESH_BINARY)
178
179 return thresh
180
181
182 def find_end(start,arg,black,white,width,black_max,white_max):
183 end=start+1
184 for m in range(start+1,width-1):
185 if (black[m] if arg else white[m])>(0.98*black_max if arg else 0.98*white_max):
186 end=m
187 break
188 return end
189
190
191 if __name__==\'__main__\':
192 img=cv2.imread(\'car.jpg\',cv2.IMREAD_COLOR)
193 #预处理图像
194 rect,afterimg=find_license(img)
195
196 #框出车牌号
197 cv2.rectangle(afterimg,(rect[0],rect[1]),(rect[2],rect[3]),(0,255,0),2)
198 cv2.imshow(\'afterimg\',afterimg)
199
200 #分割车牌与背景
201 cutimg=cut_license(afterimg,rect)
202 cv2.imshow(\'cutimg\',cutimg)
203
204 #二值化生成黑白图
205 thresh=deal_license(cutimg)
206 cv2.imshow(\'thresh\',thresh)
207 cv2.waitKey(0)
208
209 #分割字符
210 \'\'\'
211 判断底色和字色
212 \'\'\'
213 #记录黑白像素总和
214 white=[]
215 black=[]
216 height=thresh.shape[0] #263
217 width=thresh.shape[1] #400
218 #print(\'height\',height)
219 #print(\'width\',width)
220 white_max=0
221 black_max=0
222 #计算每一列的黑白像素总和
223 for i in range(width):
224 line_white=0
225 line_black=0
226 for j in range(height):
227 if thresh[j][i]==255:
228 line_white+=1
229 if thresh[j][i]==0:
230 line_black+=1
231 white_max=max(white_max,line_white)
232 black_max=max(black_max,line_black)
233 white.append(line_white)
234 black.append(line_black)
235 print(\'white\',white)
236 print(\'black\',black)
237 #arg为true表示黑底白字,False为白底黑字
238 arg=True
239 if black_max<white_max:
240 arg=False
241
242 n=1
243 start=1
244 end=2
245 while n<width-2:
246 n+=1
247 #判断是白底黑字还是黑底白字 0.05参数对应上面的0.95 可作调整
248 if(white[n] if arg else black[n])>(0.02*white_max if arg else 0.02*black_max):
249 start=n
250 end=find_end(start,arg,black,white,width,black_max,white_max)
251 n=end
252 if end-start>5:
253 cj=thresh[1:height,start:end]
254 cv2.imshow(\'cutlicense\',cj)
255 cv2.waitKey(0)
256
257
258 cv2.waitKey(0)
259 cv2.destroyAllWindows()