zoukankan      html  css  js  c++  java
  • opencv+python 车牌识别

      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()
  • 相关阅读:
    一步一步学EF系列【4、升级篇 实体与数据库的映射】live writer真坑,第4次补发
    一步一步学EF系列3【升级篇 实体与数据库的映射】
    一步一步学EF系列2【最简单的一个实例】
    一步一步学EF系列1【Fluent API的方式来处理实体与数据表之间的映射关系】
    MVC5 Entity Framework学习之创建复杂的数据模型
    Demo源码放送:打通B/S与C/S !让HTML5 WebSocket与.NET Socket公用同一个服务端!
    动手写一个Remoting接口测试工具(附源码下载)
    通信服务器群集——跨服务器通信Demo(源码)
    轻量级通信引擎StriveEngine —— C/S通信demo(2) —— 使用二进制协议 (附源码)
    PAT A1011 World Cup Betting(20)
  • 原文地址:https://www.cnblogs.com/kekexxr/p/11574589.html
Copyright © 2011-2022 走看看