当前位置:脚本大全 > > 正文

opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)

时间:2022-04-01 00:40:47类别:脚本大全

opencv 图像匹配python

OpenCV+Python识别车牌和字符分割的实现

本篇文章主要基于python语言和opencv库(cv2)进行车牌区域识别和字符分割,开篇之前针对在python中安装opencv的环境这里不做介绍,可以自行安装配置!

车牌号检测需要大致分为四个部分:

1.车辆图像获取

2.车牌定位、

3.车牌字符分割

4.车牌字符识别

具体介绍

车牌定位需要用到的是图片二值化为黑白后进canny边缘检测后多次进行开运算与闭运算用于消除小块的区域,保留大块的区域,后用cv2.rectangle选取矩形框,从而定位车牌位置

车牌字符的分割前需要准备的是只保留车牌部分,将其他部分均变为黑色背景。这里我采用cv2.grabcut方法,可将图像分割成前景与背景。分割完成后,再经过二值化为黑白图后即可进行字符分割。由于图像中只有黑色和白色像素,因此我们需要通过图像的白色像素和黑色像素来分割开字符。即分别通过判断每一行每一列的黑色白色像素值的位置,来定位出字符。

具体步骤如下:

1.灰度转换:将彩色图片转换为灰度图像,常见的r=g=b=像素平均值。

2.高斯平滑和中值滤波:去除噪声。

3.sobel算子:提取图像边缘轮廓,x方向和y方向平方和开跟。

4.二值化处理:图像转换为黑白两色,通常像素大于127设置为255,小于设置为0。

5.膨胀和细化:放大图像轮廓,转换为一个个区域,这些区域内包含车牌。

6.通过算法选择合适的车牌位置,通常将较小的区域过滤掉或寻找蓝色底的区域。

7.标注车牌位置

8.图像切割和识别

通过代码实现:

  • ?
  • 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
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • # -*- coding: utf-8 -*-
  • """
  • @email:cuiran2001@163.com
  • @author: cuiran
  • """
  • import cv2
  • import numpy as np
  • from pil import image
  • import os.path
  • from skimage import io,data
  • def stretch(img):
  •  '''
  •  图像拉伸函数
  •  '''
  •  maxi=float(img.max())
  •  mini=float(img.min())
  •  
  •  for i in range(img.shape[0]):
  •   for j in range(img.shape[1]):
  •    img[i,j]=(255/(maxi-mini)*img[i,j]-(255*mini)/(maxi-mini))
  •  
  •  return img
  •  
  • def dobinaryzation(img):
  •  '''
  •  二值化处理函数
  •  '''
  •  maxi=float(img.max())
  •  mini=float(img.min())
  •  
  •  x=maxi-((maxi-mini)/2)
  •  #二值化,返回阈值ret 和 二值化操作后的图像thresh
  •  ret,thresh=cv2.threshold(img,x,255,cv2.thresh_binary)
  •  #返回二值化后的黑白图像
  •  return thresh
  •  
  • def find_rectangle(contour):
  •  '''
  •  寻找矩形轮廓
  •  '''
  •  y,x=[],[]
  •  
  •  for p in contour:
  •   y.append(p[0][0])
  •   x.append(p[0][1])
  •  
  •  return [min(y),min(x),max(y),max(x)]
  •  
  • def locate_license(img,afterimg):
  •  '''
  •  定位车牌号
  •  '''
  •  img,contours,hierarchy=cv2.findcontours(img,cv2.retr_external,cv2.chain_approx_simple)
  •  
  •  #找出最大的三个区域
  •  block=[]
  •  for c in contours:
  •   #找出轮廓的左上点和右下点,由此计算它的面积和长度比
  •   r=find_rectangle(c)
  •   a=(r[2]-r[0])*(r[3]-r[1]) #面积
  •   s=(r[2]-r[0])*(r[3]-r[1]) #长度比
  •  
  •   block.append([r,a,s])
  •  #选出面积最大的3个区域
  •  block=sorted(block,key=lambda b: b[1])[-3:]
  •  
  •  #使用颜色识别判断找出最像车牌的区域
  •  maxweight,maxindex=0,-1
  •  for i in range(len(block)):
  •   b=afterimg[block[i][0][1]:block[i][0][3],block[i][0][0]:block[i][0][2]]
  •   #bgr转hsv
  •   hsv=cv2.cvtcolor(b,cv2.color_bgr2hsv)
  •   #蓝色车牌的范围
  •   lower=np.array([100,50,50])
  •   upper=np.array([140,255,255])
  •   #根据阈值构建掩膜
  •   mask=cv2.inrange(hsv,lower,upper)
  •   #统计权值
  •   w1=0
  •   for m in mask:
  •    w1+=m/255
  •  
  •   w2=0
  •   for n in w1:
  •    w2+=n
  •  
  •   #选出最大权值的区域
  •   if w2>maxweight:
  •    maxindex=i
  •    maxweight=w2
  •  
  •  return block[maxindex][0]
  •  
  • def find_license(img):
  •  '''
  •  预处理函数
  •  '''
  •  m=400*img.shape[0]/img.shape[1]
  •  
  •  #压缩图像
  •  img=cv2.resize(img,(400,int(m)),interpolation=cv2.inter_cubic)
  •  
  •  #bgr转换为灰度图像
  •  gray_img=cv2.cvtcolor(img,cv2.color_bgr2gray)
  •  
  •  #灰度拉伸
  •  stretchedimg=stretch(gray_img)
  •  
  •  '''进行开运算,用来去除噪声'''
  •  r=16
  •  h=w=r*2+1
  •  kernel=np.zeros((h,w),np.uint8)
  •  cv2.circle(kernel,(r,r),r,1,-1)
  •  #开运算
  •  openingimg=cv2.morphologyex(stretchedimg,cv2.morph_open,kernel)
  •  #获取差分图,两幅图像做差 cv2.absdiff('图像1','图像2')
  •  strtimg=cv2.absdiff(stretchedimg,openingimg)
  •  
  •  #图像二值化
  •  binaryimg=dobinaryzation(strtimg)
  •  
  •  #canny边缘检测
  •  canny=cv2.canny(binaryimg,binaryimg.shape[0],binaryimg.shape[1])
  •  
  •  '''消除小的区域,保留大块的区域,从而定位车牌'''
  •  #进行闭运算
  •  kernel=np.ones((5,19),np.uint8)
  •  closingimg=cv2.morphologyex(canny,cv2.morph_close,kernel)
  •  
  •  #进行开运算
  •  openingimg=cv2.morphologyex(closingimg,cv2.morph_open,kernel)
  •  
  •  #再次进行开运算
  •  kernel=np.ones((11,5),np.uint8)
  •  openingimg=cv2.morphologyex(openingimg,cv2.morph_open,kernel)
  •  
  •  #消除小区域,定位车牌位置
  •  rect=locate_license(openingimg,img)
  •  
  •  return rect,img
  •  
  • def cut_license(afterimg,rect):
  •  '''
  •  图像分割函数
  •  '''
  •  #转换为宽度和高度
  •  rect[2]=rect[2]-rect[0]
  •  rect[3]=rect[3]-rect[1]
  •  rect_copy=tuple(rect.copy())
  •  rect=[0,0,0,0]
  •  #创建掩膜
  •  mask=np.zeros(afterimg.shape[:2],np.uint8)
  •  #创建背景模型 大小只能为13*5,行数只能为1,单通道浮点型
  •  bgdmodel=np.zeros((1,65),np.float64)
  •  #创建前景模型
  •  fgdmodel=np.zeros((1,65),np.float64)
  •  #分割图像
  •  cv2.grabcut(afterimg,mask,rect_copy,bgdmodel,fgdmodel,5,cv2.gc_init_with_rect)
  •  mask2=np.where((mask==2)|(mask==0),0,1).astype('uint8')
  •  img_show=afterimg*mask2[:,:,np.newaxis]
  •  
  •  return img_show
  •  
  • def deal_license(licenseimg):
  •  '''
  •  车牌图片二值化
  •  '''
  •  #车牌变为灰度图像
  •  gray_img=cv2.cvtcolor(licenseimg,cv2.color_bgr2gray)
  •  
  •  #均值滤波 去除噪声
  •  kernel=np.ones((3,3),np.float32)/9
  •  gray_img=cv2.filter2d(gray_img,-1,kernel)
  •  
  •  #二值化处理
  •  ret,thresh=cv2.threshold(gray_img,120,255,cv2.thresh_binary)
  •  
  •  return thresh
  •  
  •  
  • def find_end(start,arg,black,white,width,black_max,white_max):
  •  end=start+1
  •  for m in range(start+1,width-1):
  •   if (black[m] if arg else white[m])>(0.98*black_max if arg else 0.98*white_max):
  •    end=m
  •    break
  •  return end
  •  
  •  
  • if __name__=='__main__':
  •  img=cv2.imread('test_images/car001.jpg" alt="opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)" border="0" />,cv2.imread_color)
  •  #预处理图像
  •  rect,afterimg=find_license(img)
  •  
  •  #框出车牌号
  •  cv2.rectangle(afterimg,(rect[0],rect[1]),(rect[2],rect[3]),(0,255,0),2)
  •  cv2.imshow('afterimg',afterimg)
  •  
  •  #分割车牌与背景
  •  cutimg=cut_license(afterimg,rect)
  •  cv2.imshow('cutimg',cutimg)
  •  
  •  #二值化生成黑白图
  •  thresh=deal_license(cutimg)
  •  cv2.imshow('thresh',thresh)
  •  cv2.waitkey(0)
  •  
  •  #分割字符
  •  '''
  •  判断底色和字色
  •  '''
  •  #记录黑白像素总和
  •  white=[]
  •  black=[]
  •  height=thresh.shape[0] #263
  •  width=thresh.shape[1] #400
  •  #print('height',height)
  •  #print('width',width)
  •  white_max=0
  •  black_max=0
  •  #计算每一列的黑白像素总和
  •  for i in range(width):
  •   line_white=0
  •   line_black=0
  •   for j in range(height):
  •    if thresh[j][i]==255:
  •     line_white+=1
  •    if thresh[j][i]==0:
  •     line_black+=1
  •   white_max=max(white_max,line_white)
  •   black_max=max(black_max,line_black)
  •   white.append(line_white)
  •   black.append(line_black)
  •   print('white',white)
  •   print('black',black)
  •  #arg为true表示黑底白字,false为白底黑字
  •  arg=true
  •  if black_max<white_max:
  •   arg=false
  •  
  •  n=1
  •  start=1
  •  end=2
  •  s_width=28
  •  s_height=28
  •  while n<width-2:
  •   n+=1
  •   #判断是白底黑字还是黑底白字 0.05参数对应上面的0.95 可作调整
  •   if(white[n] if arg else black[n])>(0.02*white_max if arg else 0.02*black_max):
  •    start=n
  •    end=find_end(start,arg,black,white,width,black_max,white_max)
  •    n=end
  •    if end-start>5:
  •     cj=thresh[1:height,start:end]
  •  
  •     # new_image = cj.resize((s_width,s_height),image.bilinear)
  •     # cj=cj.reshape(28, 28)
  •     print("result/%s.jpg" alt="opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)" border="0" /> % (n))
  •     #保存分割的图片 by cayden
  •     # cj.save("result/%s.jpg" alt="opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)" border="0" />
  •     infile="result/%s.jpg" alt="opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)" border="0" /> % (n)
  •     io.imsave(infile,cj)
  •  
  •     # im = image.open(infile)
  •     # out=im.resize((s_width,s_height),image.bilinear)
  •     # out.save(infile)
  •  
  •     cv2.imshow('cutlicense',cj)
  •     cv2.waitkey(0)
  •  
  •  
  •  cv2.waitkey(0)
  •  cv2.destroyallwindows()
  • 运行效果如图所示

    车牌定位并进行处理

    opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)

    车牌分割如图所示

    opencv 图像匹配python(OpenCV+Python识别车牌和字符分割的实现)

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持开心学习网。

    原文链接:https://blog.csdn.net/cuiran/article/details/86706441

    上一篇下一篇

    猜您喜欢

    热门推荐