赞
踩
本文尚有很多不足的地方,例如车牌字符的定位,车牌种类的不同,复杂环境下车牌识别的问题等等。。。
不足之处请多指教
(1)color_change(picture)函数
对输入的图片,现进行阈值的设定,不同颜色的车牌有不同的阈值,一般为蓝色,黄色和绿色。然后通过掩模运算突出二值化车牌的位置,极大的降低了其他背景对识别的干扰。然后在进行按位运算回复车牌原有的颜色,并返回处理过的图像。
(2)binaryzation(value)函数
把color_change(picture)返回的结果转化为和灰度图并进行二值化,然后进行边缘检测,并对检测后的图像进行开运算和开运算,将车牌区域的轮廓连为一个整体。然后通过cv2.findContours()函数找出图像中单独的轮廓并返回。
cv2.findContours()参数说明:img为寻找轮廓的图像,且为二值图(黑白图)。
mode为轮廓的检索模式,有四种:cv2.RETR_EXTERNAL只检测外轮廓。cv2.RETR_LIST检测的轮廓不建立等级关系。cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。cv2.RETR_TREE建立一个等级树结构的轮廓。
method为轮廓的近似方法。cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1)) == 1。cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
返回值contours表示图像中的所有轮廓的list,np.array类型。
开闭运算输出的轮廓:
函数画出的轮廓:
(3)cut_out(value1,value2)函数
函数接收 binaryzation(value)返回的结果,利用cv2.minAreaRect(contour)函数计算识别轮廓的长宽比,确定车牌的位置。然后利用v2.boxPoints(rect)函数找出车牌四个角的坐标,最后切割车牌。
切割出的车牌:
(4)car_binaryzation_cut(value)函数
将cut_out(value1,value2)函数返回的图像进行二值化,然后获取图像行方向和列方向上字符的分布图,确定字符的分布位置。然后根据位置进行字符的分割。最后将分割后的字符和保存的字符库进行匹配,找出匹配度最高的图像,最后输出匹配结果。
车牌二值化的图像:
字符行列像素分布图:
字符分割后的图像:
(5)show(value,picture)函数
该函数主要用于在原始图像上添加识别后的结果,因为有汉字,所以运用PIL库进行输出。其参数为原始图像和识别后的字符串结果。
import cv2 import numpy as np import matplotlib.pyplot as plt from PIL import Image,ImageDraw,ImageFont def color_change(picture): ''' 将图片转化到HSV空间,并按位取反,突出车牌区域 ''' hsv=cv2.cvtColor(picture,cv2.COLOR_BGR2HSV) #转化为HSV颜色空间 lower_blue=np.array([100,43,46]) #蓝色阈值 upper_blue=np.array([124,255,255]) mask1=cv2.inRange(hsv,lower_blue,upper_blue) #构建掩模 res1=cv2.bitwise_and(image,image,mask=mask1) #按位运算 cv2.imwrite('111.jpg',res1) return res1 def binaryzation(value): ''' 把图象进行二值化,并进行开闭运算,最后找到可能存在的区域,并返回区域信息 ''' gray=cv2.cvtColor(value,cv2.COLOR_BGR2GRAY) #转化为灰度图 ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY) #图像二值化 canny = cv2.Canny(thresh, 100, 200) #边缘检测 kernel1 = np.ones((12,40), np.uint8) img_edge1 = cv2.morphologyEx(canny, cv2.MORPH_CLOSE, kernel1) # 闭运算 img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel1) # 开运算 cv2.imwrite('222.jpg',img_edge2) contours ,hierarchy = cv2.findContours(img_edge2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) #c=cv2.drawContours(image, contours, -1, (0, 255, 0), 3) return contours def cut_out(value1,value2): ''' 通过长宽比判断车牌的位置,并截取 ''' for contour in value1: rect = cv2.minAreaRect(contour) #找出最小外接矩形 中心点、宽和高、角度 if rect[1][1]>rect[1][0]: k=rect[1][1]/rect[1][0] else: k=rect[1][0]/rect[1][1] if (k>2.5)&(k<5): #判断车牌的轮廓 a=cv2.boxPoints(rect) #获取外接矩形的四个点 box = np.int0(a) aa=cv2.drawContours(value2, [box], -1, (0, 255, 0), 3) #找出车牌的位置 cv2.imwrite('aa.jpg',aa) x=[] y=[] for i in range(4): x.append(box[i][1]) y.append(box[i][0]) min_x=min(x) max_x=max(x) min_y=min(y) max_y=max(y) cut=image[min_x:max_x,min_y:max_y] cv2.imwrite('333.jpg',cut) return cut def car_binaryzation_cut(value): ''' 截取车牌的二值化并切割 ''' # RGB转GARY change_size= cv2.resize(value, (440, 140)) gray_img = cv2.cvtColor(change_size, cv2.COLOR_BGR2GRAY) ret,thresh=cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY) #图像二值化 cv2.imwrite('444.jpg', thresh) x=list(range(440)) y=[] for i in range(440): #获取列方向上的字符像素分布图 n=0 for j in range(140): if thresh[j,i]==255: n=n+1 y.append(n) plt.subplot(1,2,1) plt.plot(x,y) x1=list(range(140)) y1=[] for i in range(140): #获取行方向上的字符像素分布图 n=0 for j in range(440): if thresh[i,j]==255: n=n+1 y1.append(n) plt.subplot(1,2,2) plt.plot(x1,y1) plt.show() p1=thresh[15:120,12:63] p2=thresh[15:120,65:117] p3=thresh[20:120,142:197] p4=thresh[20:120,200:260] p5=thresh[20:120,260:317] p6=thresh[20:120,320:365] p7=thresh[20:120,370:425] cv2.imshow('1',p1) cv2.imshow('2',p2) cv2.imshow('3',p3) cv2.imshow('4',p4) cv2.imshow('5',p5) cv2.imshow('6',p6) cv2.imshow('7',p7) p=[p1,p2,p3,p4,p5,p6,p7] tem=['0.jpg','5.jpg','6.jpg','7.jpg','8.jpg','9.jpg','B.jpg','C.jpg','E.jpg','J.jpg','K.jpg','M.jpg','Q.jpg','T.jpg','U.jpg','jin.jpg','chuan.jpg','yu.jpg','lu.jpg','su.jpg','ee.jpg'] a=['0','5','6','7','8','9','B','C','E','J','K','M','Q','T','U','晋','川','豫','鲁','苏','鄂'] ss=[] for i in range(7): #模板匹配 s=[] for j in range(len(tem)): image1=cv2.imread(tem[j],0) #读入图像 __,aaa=cv2.threshold(image1,127,255,cv2.THRESH_BINARY) bbb= cv2.resize(aaa, (50, 100)) result=cv2.matchTemplate(p[i],bbb,cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) s.append(max_val) ss.append(a[s.index(max(s))]) car=ss[0]+ss[1]+'.'+ss[2]+ss[3]+ss[4]+ss[5]+ss[6] print(car) return car def show(value,picture): cv2img = cv2.cvtColor(picture, cv2.COLOR_BGR2RGB) # cv2和PIL中颜色的hex码的储存顺序不同 pilimg = Image.fromarray(cv2img) # PIL图片上打印汉字 draw = ImageDraw.Draw(pilimg) # 图片上打印 font = ImageFont.truetype("simhei.ttf", 40, encoding="utf-8") # 参数1:字体文件路径,参数2:字体大小 draw.text((200, 200), value, (255, 0, 0), font=font) # 参数1:打印坐标,参数2:文本,参数3:字体颜色,参数4:字体 # PIL图片转cv2 图片 cv2charimg = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR) cv2.imshow("result", cv2charimg) cv2.imwrite('555.jpg',cv2charimg) if __name__=='__main__': image=cv2.imread('bbb.jpg') #读入图像 image = cv2.resize(image, (570, 430)) res=color_change(image) #转化到HSV,并大致取出车牌位置 a=binaryzation(res) #对颜色识别过的区域进行二值化,并进行开闭运算识别轮廓 b=cut_out(a,image) #找到符合条件的区域,并进行切割 c=car_binaryzation_cut(b) show(c,image) while(1): k=cv2.waitKey(5)&0xFF if k==27: cv2.destroyAllWindows() break
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。