700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Python-OpenCV车牌识别系统

Python-OpenCV车牌识别系统

时间:2019-01-24 16:31:48

相关推荐

Python-OpenCV车牌识别系统

Python-OpenCV车牌识别系统

本系统虽然完成了整个系统,但对车牌图像有要求,首先本系统只能识别蓝底白字的车牌,其次车牌所在图像区域应在图像中下部分(因为第一步要进行裁剪,可以看一下展示的车牌),其次,我制作的模板较少,每个字符做了3-4个。

原始图像

文章目录

Python-OpenCV车牌识别系统第一次处理识别效果测试的车牌制作的车牌字符识别模板源码识别过程中保存的图片

第一次处理

并进行初次裁剪处理,因为车牌一般都在图片的中下部分。

# 统一尺寸宽、高为600*300def first(path):image = cv2.imread(path)height_1 = image.shape[0] # 高width_1 = image.shape[1] # 宽sign = 0 # 是否进行了缩放处理while((height_1 < 300) or (width_1 < 600)):sign = 1height_1 = int(height_1 * 1.2)width_1 = int(width_1 *1.2)if sign == 1:image = cv2.resize(image,(width_1,height_1))global heightheight = 300 # 高global widthwidth = 600 # 宽# 裁剪h = int((height_1 - height)*2/3)w = int((width_1 - width)/2)img = image[h:h + height,w:w + width]cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\1.jpg',img)# cv2.imshow('1',img)# cv2.waitKey(0)return img

处理后效果

识别效果

测试的车牌

这些车牌都能进行识别,这里就不一一演示了。

制作的车牌字符识别模板

车牌识别数据集下载-数据集

源码

import cv2import numpy as npimport mathfrom scipy import ndimageimport osimport timefrom tkinter import *from PIL import Image, ImageTk# 统一尺寸宽、高为600*300def first(path):image = cv2.imread(path)height_1 = image.shape[0] # 高width_1 = image.shape[1] # 宽sign = 0while((height_1 < 300) or (width_1 < 600)):sign = 1height_1 = int(height_1 * 1.2)width_1 = int(width_1 *1.2)if sign == 1:image = cv2.resize(image,(width_1,height_1))global heightheight = 300global widthwidth = 600h = int((height_1 - height)*2/3)w = int((width_1 - width)/2)img = image[h:h + height,w:w + width]cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\1.jpg',img)# cv2.imshow('1',img)# cv2.waitKey(0)return img# 图像预处理def image_Preprocessing(img):img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)img = cv2.GaussianBlur(img, (5, 5), 1) # 高斯平滑img_median = cv2.medianBlur(img, 3) # 中值滤波img_gray = cv2.cvtColor(img_median, cv2.COLOR_BGR2GRAY)# cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\2.jpg', img_gray)binary = cv2.Canny(img_gray, 100, 200)kerne = np.ones((5, 5), np.uint8)img_1 = cv2.morphologyEx(binary, cv2.MORPH_CLbOSE, kerne, iterations=2)img_2 = cv2.morphologyEx(img_1, cv2.MORPH_OPEN, kerne, iterations=1)img_3 = cv2.morphologyEx(img_2, cv2.MORPH_CLOSE, kerne, iterations=1)# cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\3.jpg', img_3)# cv2.imshow('1', img_3)# cv2.waitKey(0)return img_3# 基于颜色特征辅助定位车牌def fun(img):Blue = 138Green = 63Red = 23THRESHOLD = 50# 高斯平滑img_aussian = cv2.GaussianBlur(img, (5, 5), 1)# 中值滤波img_median = cv2.medianBlur(img_aussian, 3)img_B = cv2.split(img_median)[0]img_G = cv2.split(img_median)[1]img_R = cv2.split(img_median)[2]for i in range(img_median.shape[:2][0]):for j in range(img_median.shape[:2][1]):if abs(img_B[i, j] - Blue) < THRESHOLD and \abs(img_G[i, j] - Green) < THRESHOLD and \abs(img_R[i, j] - Red) < THRESHOLD:img_median[i][j][0] = 255img_median[i][j][1] = 255img_median[i][j][2] = 255else:img_median[i][j][0] = 0img_median[i][j][1] = 0img_median[i][j][2] = 0kernel = np.ones((3, 3), np.uint8)img_dilate = cv2.dilate(img_median, kernel, iterations=5) # 膨胀操作img_erosion = cv2.erode(img_dilate, kernel, iterations=5) # 腐蚀操作# cv2.imshow('2',img_erosion)# cv2.waitKey(0)return img_erosion# 基于轮廓定位车牌def license_Plate_Positioning(img,img_1):img_1 = cv2.cvtColor(img_1, cv2.COLOR_BGR2GRAY)contours, hierarchy = cv2.findContours(img_1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)cv_contours = []for contour in contours:area = cv2.contourArea(contour)if area >= 90000 or area <= 1400:cv_contours.append(contour)else:continuecv2.fillPoly(img_1, cv_contours, (0))contours_1, hierarchy = cv2.findContours(img_1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)cv_contours_null = []for contour in contours_1:x, y, w, h = cv2.boundingRect(contour)if ((w < h) and (w < (h * 2) or (w > (h * 5)))):cv_contours_null.append(contour)cv2.fillPoly(img_1, cv_contours_null, (0))contours_2, _ = cv2.findContours(img_1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)img_s = []index = 4for cont in contours_2:# 外接矩形x, y, w, h = cv2.boundingRect(cont)if((w * h < 7000) or (w < 10) or (h < 50)):continueimg_l = img[y:y + h, x :x + w ]img_s.append(img_l)cv2.imwrite("C:\\Users\\lenovo\\Desktop\\demo_1\\" + f"{index}" + ".jpg", img_s[0])return img_s[0]## return img_l# img_1 = cv2.cvtColor(img_1, cv2.COLOR_BGR2GRAY)# contours, hierarchy = cv2.findContours(img_1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# # 筛选面积小的# cv_contours = []# for contour in contours:#area = cv2.contourArea(contour)#if area >= 17000 or area <= 1400:# cv_contours.append(contour)#else:# continue# cv2.fillPoly(img_1, cv_contours, (0))# # cv2.imshow('img1', img)# # cv2.waitKey(0)# contours_1, hierarchy = cv2.findContours(img_1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# # 处理面积差别不大# cv_contours_null = []# for contour in contours_1:#x, y, w, h = cv2.boundingRect(contour)#if ((w < h) and (w < (h * 2) or (w > (h * 5)))):# cv_contours_null.append(contour)# cv2.fillPoly(img_1, cv_contours_null, (0))# cv2.imshow('3', img)# cv2.waitKey(0)# contours_2, _ = cv2.findContours(img_1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)## index = 4# img_2 = None# for cont in contours_2:## 外接矩形#x, y, w, h = cv2.boundingRect(cont)#if (w * h < 2000):# continue#img_2 = img[y - 5:y + h + 5, x - 5:x + w + 5]#cv2.imwrite("C:\\Users\\lenovo\\Desktop\\demo_1\\" + f"{index}" + ".jpg", img_2)#index += 1# print('查找轮廓完毕')### #return img_2# 车牌矫正def correction(img):# 二值化gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 边缘检测edges = cv2.Canny(gray, 50, 150, 3) # apertureSize 卷积大小# 霍夫变换lines = cv2.HoughLines(edges, 1, np.pi / 180, 0)for rho, theta in lines[0]:a = np.cos(theta)b = np.sin(theta)x0 = a * rhoy0 = b * rhox1 = int(x0 + 1000 * (-b))y1 = int(y0 + 1000 * (a))x2 = int(x0 - 1000 * (-b))y2 = int(y0 - 1000 * (a))if x1 == x2 or y1 == y2:continuet = float(y2 - y1) / (x2 - x1)# 得到角度后rotate_angle = math.degrees(math.atan(t))if rotate_angle > 45:rotate_angle = -90 + rotate_angleelif rotate_angle < -45:rotate_angle = 90 + rotate_angle# 图像根据角度进行校正rotate_img = ndimage.rotate(img, rotate_angle)# 输出图像cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\5.jpg', rotate_img)return rotate_img# 去除边框和铆钉def remove(img):# 改变车牌号大小height = img.shape[0] # 高width = img.shape[1] # 宽while(width < 500):height = int(height * 1.2) # 高width = int(width * 1.2) # 宽image = cv2.resize(img, (width, height))# 高斯模糊blurerd = cv2.GaussianBlur(image, (3, 3), 0, 0, cv2.BORDER_DEFAULT)# 图像转灰度gray = cv2.cvtColor(blurerd, cv2.COLOR_BGR2GRAY)# 图像二值化ret, img_thre = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # cv2.THRESH_BINARY_INV# 展示# cv2.imwrite("C:\\Users\\lenovo\\Desktop\\demo_1\\20.jpg", img_thre)white = [] # 记录每一列的白色像素总和black = [] # 记录每一列的黑色像素的总和height = img_thre.shape[0] # 高width = img_thre.shape[1] # 宽# 计算每一行的黑白像素的总和for i in range(height):s = 0 # 这一行白色总数t = 0 # 这一行黑色总数for j in range(width):if img_thre[i][j] == 255:s = s + 1if img_thre[i][j] == 0:t = t + 1white.append(s)black.append(t)# 去除上# 从车牌中间开始,向上向下找第一个不为0且大于50mid = int(height / 2)while ((white[mid] != 0) & (white[mid] > 50) & (mid > 1)):mid = mid - 1start = midmid = int(height / 2)while ((white[mid] != 0) & (white[mid] > 50) & (mid < height - 1)):mid = mid + 1end = mid + 1img_cut = img_thre[start: end, 3: width - 3]cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\6.jpg', img_cut)return img_cut# 字符分割辅助函数def get_vvList(list_data):# 取出list中像素存在的区间vv_list=[]v_list=[]for index,i in enumerate(list_data):if i > 10 :v_list.append(index)else:if v_list: # 如果v_list里有数据则执行下面代码vv_list.append(v_list)#list的clear与[]有区别v_list=[]# 分开字符处理,如在第一个字符所以保险起见考虑前3个切割的字符,川字符还未作处理index = -1for i in range(3):j = i + 1if vv_list[j][0] - vv_list[i][-1] > 5:continueelse: # 如果两个字符之间间距小于5,判断为同一字符index = ibreakif index != -1:list = [vv_list[index][0],vv_list[index + 1][-1]]vv_list[index] = listvv_list.pop(index + 1)# 川字符index = -1for i in range(3):j = i + 1if vv_list[j][0] - vv_list[i][-1] > 5:continueelse: # 如果两个字符之间间距小于5,判断为同一字符index = ibreakif index != -1:list = [vv_list[index][0], vv_list[index + 1][-1]]vv_list[index] = listvv_list.pop(index + 1)return vv_list# 字符分割def cut(img):# grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将BGR图转为灰度图# ret, binary = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY) # 将图片进行二值化(130,255)之间的点均变为255(背景)# ret, img_thre = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)rows, cols = img.shapever_list = [0] * colsfor j in range(cols):for i in range(rows):if img.item(i, j) == 255:ver_list[j] = ver_list[j] + 1ver_arr = np.array(ver_list)ver_arr[np.where(ver_arr < 1)] = 0ver_list = ver_arr.tolist()# 切割单一字符vv_list = get_vvList(ver_list)name = 7x = 1imgs = []for i in vv_list:if (i[-1] - i[0] > 12):img_ver = img[:, i[0] - 1:i[-1] + 1] # i[-1]取列表最后一个元素else:continueimg_i = cv2.resize(img_ver, (25, 50))imgs.append(img_i)name += 1x += 1if len(imgs) == 9:imgs.pop(0)imgs.pop(2)name = 7for img_i in imgs:cv2.imwrite('C:\\Users\\lenovo\\Desktop\\demo_1\\' + f'{name}' + '.jpg', img_i)name += 1return imgs# 字符识别#模版匹配# 准备模板(template[0-9]为数字模板;)template = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','藏','川','鄂','甘','赣','贵','桂','黑','沪','吉','冀','津','晋','京','辽','鲁','蒙','闽','宁','青','琼','陕','苏','皖','湘','新','渝','豫','粤','云','浙'] # 一共有65个# 读取一个文件夹下的所有图片,输入参数是文件名,返回模板文件地址列表# 返回列表def read_directory(directory_name):referImg_list = []for filename in os.listdir(directory_name):referImg_list.append(directory_name + "\\" + filename)return referImg_list # 模板照片地址列表# 获得中文模板列表(只匹配车牌的第一个字符)# 返回列表def get_chinese_words_list():chinese_words_list = []for i in range(34,64):#将模板存放在字典中c_word = read_directory('C:\\Users\\lenovo\\Desktop\\template\\'+ template[i]) # read_directory调用上一个函数chinese_words_list.append(c_word)return chinese_words_listchinese_words_list = get_chinese_words_list() # chinese_words_list=[[],[],[]]# 获得英文模板列表(只匹配车牌的第二个字符)# 返回列表def get_eng_words_list():eng_words_list = []for i in range(10,34):e_word = read_directory('C:\\Users\\lenovo\\Desktop\\template\\'+ template[i])eng_words_list.append(e_word)return eng_words_listeng_words_list = get_eng_words_list() #eng_words_list = [[],[],[]]# 获得英文和数字模板列表(匹配车牌后面的字符)# 返回列表def get_eng_num_words_list():eng_num_words_list = []for i in range(0,34):word = read_directory('C:\\Users\\lenovo\\Desktop\\template\\'+ template[i])eng_num_words_list.append(word)return eng_num_words_listeng_num_words_list = get_eng_num_words_list() # eng_num_words_list = [[],[],[]]# 读取一个模板地址与图片进行匹配,返回得分def template_score(template,image): # 参数:read_directory--模板照片 image--待检测照片#将模板进行格式转换template_img=cv2.imdecode(np.fromfile(template,dtype=np.uint8),1) # imdecode-内存缓存中读取图像数据并将其转换为图像格式 np.fromfile--一种读取具有已知数据类型的二进制数据以及解析简单格式文本文件的高效方法 1--按照int读取数据template_img = cv2.cvtColor(template_img, cv2.COLOR_RGB2GRAY)#模板图像阈值化处理——获得黑白图ret, template_img = cv2.threshold(template_img, 0, 255, cv2.THRESH_OTSU)image_ = image.copy()#获得待检测图片的尺寸height, width = image_.shape# 将模板resize至与图像一样大小template_img = cv2.resize(template_img, (width, height))# 模板匹配,返回匹配得分result = cv2.matchTemplate(image_, template_img, cv2.TM_CCOEFF)return result[0][0]# 对分割得到的字符逐一匹配def template_matching(word_images): # 参数word_images--待检测图片列表results = []for index,word_image in enumerate(word_images): # enumerate() 函数用于将一个可遍历的数据对象,返回索引和对象if index==0: # 匹配中文字符best_score = []for chinese_words in chinese_words_list:score = []for chinese_word in chinese_words: # chinese_word--模板照片地址result = template_score(chinese_word,word_image) # 得分score.append(result)best_score.append(max(score)) # 最大得分i = best_score.index(max(best_score)) # 最大得分的索引,就是这个模板的从34开始之后的索引# print(template[34+i])r = template[34+i]results.append(r)continueif index==1: # 匹配车牌第二个英文字符best_score = []for eng_word_list in eng_words_list:score = []for eng_word in eng_word_list:result = template_score(eng_word,word_image)score.append(result)best_score.append(max(score))i = best_score.index(max(best_score))# print(template[10+i])r = template[10+i]results.append(r)continueelse: # 匹配英文和数字字符best_score = []for eng_num_word_list in eng_num_words_list:score = []for eng_num_word in eng_num_word_list:result = template_score(eng_num_word,word_image)score.append(result)best_score.append(max(score))i = best_score.index(max(best_score))# print(template[i])r = template[i]results.append(r)continuereturn results# 字符识别def character_Recognition(imgs):global result_lastword_images = imgs.copy() # 切割后的照片# 调用函数获得结果result = template_matching(word_images)# "".join(result)函数将列表转换为拼接好的字符串,方便结果显示result_last = "".join(result)# 调用所有的函数def run():global img# 要识别的图像# 指定路径path = 'C:\\Users\\lenovo\\Desktop\\demo\\'# 返回指定路径的文件夹名称dirs = os.listdir(path)# 拼接字符串pa = path + dirs[0]img = first(pa)# 预处理后的图像,二值图img_1 = fun(img)img_2 = license_Plate_Positioning(img,img_1)img_3 = correction(img_2)img_4 = remove(img_3)imgs = cut(img_4)character_Recognition(imgs)# 窗口函数def gui():# 全局变量global rootglobal img# 关闭原来的窗口root.destroy()# 创建新窗口 设定大小并命名window = Tk()window.title('车牌识别系统')window.geometry('1200x500')var = StringVar() # 文字变量储存器var_1 = StringVar()var_2 = StringVar()var_3 = StringVar()img_jpg = ImageTk.PhotoImage(img)var.set('要识别图像')label_Img = Label(window, image=img_jpg)label_Img.place(x=10, y=20, width=600, height=300)text_Show = Label(window, textvariable=var, fg='black', font=("黑体", 12), width=10)text_Show.place(x=75, y=330, width=350, height=20)# 点击按钮式执行的命令btn_Run_1 = Button(window, text='开始识别', fg='red', width=15, height=5)btn_Run_1.place(x=200, y=360, width=100, height=70) # 按钮位置img_1 = Image.open('C:\\Users\\lenovo\\Desktop\\demo_1\\4.jpg')img_jpg_1 = ImageTk.PhotoImage(img_1)label_Img = Label(window, image=img_jpg_1)label_Img.place(x=650, y=20, width=500, height=100)var_1.set('定位到的车牌')text_Show_1 = Label(window, textvariable=var_1, fg='black', font=("黑体", 12), width=10)text_Show_1.place(x=800, y=130, width=170, height=20)var_2.set('识别结果:')text_Show_2 = Label(window, textvariable=var_2, fg='black', font=("黑体", 20), width=10)text_Show_2.place(x=700, y=200, width=170, height=40)var_3.set(result_last)text_Show_3 = Label(window, textvariable=var_3, fg='red', font=("黑体", 20), width=10)text_Show_3.place(x=700, y=250, width=200, height=40)# 运行整体窗口window.mainloop()# 主函数if __name__ == '__main__':# 开始识别run()# 程序停一秒time.sleep(1)# 新建窗口root = Tk()root.title('车牌识别系统')root.geometry('1200x500')# 文字变量储存器var = StringVar()var_1 = StringVar()var_2 = StringVar()# 只能显示gif格式,需要借助其他库img = Image.open('C:\\Users\\lenovo\\Desktop\\demo_1\\1.jpg')img_jpg = ImageTk.PhotoImage(img)# 显示要识别的图像,自定义位置label_Img = Label(root, image=img_jpg)label_Img.place(x=10, y=20, width=600, height=300)# 显示"要识别的图像"字符串var.set('要识别图像')text_Show = Label(root, textvariable=var, fg='black', font=("黑体", 12), width=10)text_Show.place(x=75, y=330, width=350, height=20)# 点击按钮式执行的命令,关闭这个窗口,新建一个窗口btn_Run_1 = Button(root, text='开始识别', fg='red', width=15, height=5, command=gui)btn_Run_1.place(x=200, y=360, width=100, height=70) # 按钮位置# # 运行整体窗口root.mainloop()

要运行本系统,要先创建相关的文件夹。

识别过程中保存的图片

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。