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()